root/umpa/branches/protocols/umit/umpa/protocols/ICMP.py @ 5804

Revision 5804, 24.1 kB (checked in by kosma, 3 years ago)

ICMP: load_raw support; tests for get_raw and load_raw

Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# Copyright (C) 2010 Adriano Monteiro Marques.
5#
6# Author: Kosma Moczek <kosma at kosma dot pl>
7#
8# This library is free software; you can redistribute it and/or modify
9# it under the terms of the GNU Lesser General Public License as published
10# by the Free Software Foundation; either version 2.1 of the License, or
11# (at your option) any later version.
12#
13# This library is distributed in the hope that it will be useful, but
14# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16# License for more details.
17#
18# You should have received a copy of the GNU Lesser General Public License
19# along with this library; if not, write to the Free Software Foundation,
20# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22"""
23ICMP (Internet Control Message Protocol) implementation.
24"""
25
26import struct
27
28from umit.umpa.protocols import _consts
29from umit.umpa.protocols import _fields
30from umit.umpa.protocols import _protocols
31from umit.umpa.protocols import _layer4
32import umit.umpa.utils.net as _net
33import umit.umpa.utils.bits as _bits
34
35__all__ = [ "ICMP", ]
36
37class _HType(_fields.EnumField):
38    """
39    This field contains the ICMP message type.
40    """
41
42    bits = 8
43    auto = False
44    enumerable = {
45        "ADDRESS_MASK_REPLY" : _consts.ICMP_TYPE_ADDRESS_MASK_REPLY,
46        "ADDRESS_MASK_REQUEST" : _consts.ICMP_TYPE_ADDRESS_MASK_REQUEST,
47        "ALTERNATE_HOST_ADDRESS" : _consts.ICMP_TYPE_ALTERNATE_HOST_ADDRESS,
48        "DATAGRAM_CONVERSION_ERROR" : _consts.ICMP_TYPE_DATAGRAM_CONVERSION_ERROR,
49        "DESTINATION_UNREACHABLE" : _consts.ICMP_TYPE_DESTINATION_UNREACHABLE,
50        "DOMAIN_NAME_REPLY" : _consts.ICMP_TYPE_DOMAIN_NAME_REPLY,
51        "DOMAIN_NAME_REQUEST" : _consts.ICMP_TYPE_DOMAIN_NAME_REQUEST,
52        "ECHO" : _consts.ICMP_TYPE_ECHO,
53        "ECHO_REPLY" : _consts.ICMP_TYPE_ECHO_REPLY,
54        "ICMP_MESSAGES_UTILIZED" : _consts.ICMP_TYPE_ICMP_MESSAGES_UTILIZED,
55        "INFORMATION_REPLY" : _consts.ICMP_TYPE_INFORMATION_REPLY,
56        "INFORMATION_REQUEST" : _consts.ICMP_TYPE_INFORMATION_REQUEST,
57        "IPV6_I_AM_HERE" : _consts.ICMP_TYPE_IPV6_I_AM_HERE,
58        "IPV6_WHERE_ARE_YOU" : _consts.ICMP_TYPE_IPV6_WHERE_ARE_YOU,
59        "MOBILE_HOST_REDIRECT" : _consts.ICMP_TYPE_MOBILE_HOST_REDIRECT,
60        "MOBILE_REGISTRATION_REPLY" : _consts.ICMP_TYPE_MOBILE_REGISTRATION_REPLY,
61        "MOBILE_REGISTRATION_REQUEST" : _consts.ICMP_TYPE_MOBILE_REGISTRATION_REQUEST,
62        "PARAMETER_PROBLEM" : _consts.ICMP_TYPE_PARAMETER_PROBLEM,
63        "PHOTURIS" : _consts.ICMP_TYPE_PHOTURIS,
64        "REDIRECT" : _consts.ICMP_TYPE_REDIRECT,
65        "RESERVED_ROBUSTNESS" : _consts.ICMP_TYPE_RESERVED_ROBUSTNESS,
66        "RESERVED_SECURITY" : _consts.ICMP_TYPE_RESERVED_SECURITY,
67        "ROUTER_ADVERTISEMENT" : _consts.ICMP_TYPE_ROUTER_ADVERTISEMENT,
68        "ROUTER_SOLICITATION" : _consts.ICMP_TYPE_ROUTER_SOLICITATION,
69        "SKIP" : _consts.ICMP_TYPE_SKIP,
70        "SOURCE_QUENCH" : _consts.ICMP_TYPE_SOURCE_QUENCH,
71        "TIME_EXCEEDED" : _consts.ICMP_TYPE_TIME_EXCEEDED,
72        "TIMESTAMP" : _consts.ICMP_TYPE_TIMESTAMP,
73        "TIMESTAMP_REPLY" : _consts.ICMP_TYPE_TIMESTAMP_REPLY,
74        "TRACEROUTE" : _consts.ICMP_TYPE_TRACEROUTE,
75        "1" : _consts.ICMP_TYPE_UNASSIGNED1,
76        "2" : _consts.ICMP_TYPE_UNASSIGNED2,
77        "7" : _consts.ICMP_TYPE_UNASSIGNED7,
78        "42" : _consts.ICMP_TYPE_RESERVED42,
79        "43" : _consts.ICMP_TYPE_RESERVED43,
80        "44" : _consts.ICMP_TYPE_RESERVED44,
81        "45" : _consts.ICMP_TYPE_RESERVED45,
82        "46" : _consts.ICMP_TYPE_RESERVED46,
83        "47" : _consts.ICMP_TYPE_RESERVED47,
84        "48" : _consts.ICMP_TYPE_RESERVED48,
85        "49" : _consts.ICMP_TYPE_RESERVED49,
86        "50" : _consts.ICMP_TYPE_RESERVED50,
87        "51" : _consts.ICMP_TYPE_RESERVED51,
88        "52" : _consts.ICMP_TYPE_RESERVED52,
89        "53" : _consts.ICMP_TYPE_RESERVED53,
90        "54" : _consts.ICMP_TYPE_RESERVED54,
91        "55" : _consts.ICMP_TYPE_RESERVED55,
92        "56" : _consts.ICMP_TYPE_RESERVED56,
93        "57" : _consts.ICMP_TYPE_RESERVED57,
94        "58" : _consts.ICMP_TYPE_RESERVED58,
95        "59" : _consts.ICMP_TYPE_RESERVED59,
96        "60" : _consts.ICMP_TYPE_RESERVED60,
97        "61" : _consts.ICMP_TYPE_RESERVED61,
98        "62" : _consts.ICMP_TYPE_RESERVED62,
99        "63" : _consts.ICMP_TYPE_RESERVED63,
100        "64" : _consts.ICMP_TYPE_RESERVED64,
101        "65" : _consts.ICMP_TYPE_RESERVED65,
102        "66" : _consts.ICMP_TYPE_RESERVED66,
103        "67" : _consts.ICMP_TYPE_RESERVED67,
104        "68" : _consts.ICMP_TYPE_RESERVED68,
105        "69" : _consts.ICMP_TYPE_RESERVED69,
106        "70" : _consts.ICMP_TYPE_RESERVED70,
107        "71" : _consts.ICMP_TYPE_RESERVED71,
108        "72" : _consts.ICMP_TYPE_RESERVED72,
109        "73" : _consts.ICMP_TYPE_RESERVED73,
110        "74" : _consts.ICMP_TYPE_RESERVED74,
111        "75" : _consts.ICMP_TYPE_RESERVED75,
112        "76" : _consts.ICMP_TYPE_RESERVED76,
113        "77" : _consts.ICMP_TYPE_RESERVED77,
114        "78" : _consts.ICMP_TYPE_RESERVED78,
115        "79" : _consts.ICMP_TYPE_RESERVED79,
116        "80" : _consts.ICMP_TYPE_RESERVED80,
117        "81" : _consts.ICMP_TYPE_RESERVED81,
118        "82" : _consts.ICMP_TYPE_RESERVED82,
119        "83" : _consts.ICMP_TYPE_RESERVED83,
120        "84" : _consts.ICMP_TYPE_RESERVED84,
121        "85" : _consts.ICMP_TYPE_RESERVED85,
122        "86" : _consts.ICMP_TYPE_RESERVED86,
123        "87" : _consts.ICMP_TYPE_RESERVED87,
124        "88" : _consts.ICMP_TYPE_RESERVED88,
125        "89" : _consts.ICMP_TYPE_RESERVED89,
126        "90" : _consts.ICMP_TYPE_RESERVED90,
127        "91" : _consts.ICMP_TYPE_RESERVED91,
128        "92" : _consts.ICMP_TYPE_RESERVED92,
129        "93" : _consts.ICMP_TYPE_RESERVED93,
130        "94" : _consts.ICMP_TYPE_RESERVED94,
131        "95" : _consts.ICMP_TYPE_RESERVED95,
132        "96" : _consts.ICMP_TYPE_RESERVED96,
133        "97" : _consts.ICMP_TYPE_RESERVED97,
134        "98" : _consts.ICMP_TYPE_RESERVED98,
135        "99" : _consts.ICMP_TYPE_RESERVED99,
136        "100" : _consts.ICMP_TYPE_RESERVED100,
137        "101" : _consts.ICMP_TYPE_RESERVED101,
138        "102" : _consts.ICMP_TYPE_RESERVED102,
139        "103" : _consts.ICMP_TYPE_RESERVED103,
140        "104" : _consts.ICMP_TYPE_RESERVED104,
141        "105" : _consts.ICMP_TYPE_RESERVED105,
142        "106" : _consts.ICMP_TYPE_RESERVED106,
143        "107" : _consts.ICMP_TYPE_RESERVED107,
144        "108" : _consts.ICMP_TYPE_RESERVED108,
145        "109" : _consts.ICMP_TYPE_RESERVED109,
146        "110" : _consts.ICMP_TYPE_RESERVED110,
147        "111" : _consts.ICMP_TYPE_RESERVED111,
148        "112" : _consts.ICMP_TYPE_RESERVED112,
149        "113" : _consts.ICMP_TYPE_RESERVED113,
150        "114" : _consts.ICMP_TYPE_RESERVED114,
151        "115" : _consts.ICMP_TYPE_RESERVED115,
152        "116" : _consts.ICMP_TYPE_RESERVED116,
153        "117" : _consts.ICMP_TYPE_RESERVED117,
154        "118" : _consts.ICMP_TYPE_RESERVED118,
155        "119" : _consts.ICMP_TYPE_RESERVED119,
156        "120" : _consts.ICMP_TYPE_RESERVED120,
157        "121" : _consts.ICMP_TYPE_RESERVED121,
158        "122" : _consts.ICMP_TYPE_RESERVED122,
159        "123" : _consts.ICMP_TYPE_RESERVED123,
160        "124" : _consts.ICMP_TYPE_RESERVED124,
161        "125" : _consts.ICMP_TYPE_RESERVED125,
162        "126" : _consts.ICMP_TYPE_RESERVED126,
163        "127" : _consts.ICMP_TYPE_RESERVED127,
164        "128" : _consts.ICMP_TYPE_RESERVED128,
165        "129" : _consts.ICMP_TYPE_RESERVED129,
166        "130" : _consts.ICMP_TYPE_RESERVED130,
167        "131" : _consts.ICMP_TYPE_RESERVED131,
168        "132" : _consts.ICMP_TYPE_RESERVED132,
169        "133" : _consts.ICMP_TYPE_RESERVED133,
170        "134" : _consts.ICMP_TYPE_RESERVED134,
171        "135" : _consts.ICMP_TYPE_RESERVED135,
172        "136" : _consts.ICMP_TYPE_RESERVED136,
173        "137" : _consts.ICMP_TYPE_RESERVED137,
174        "138" : _consts.ICMP_TYPE_RESERVED138,
175        "139" : _consts.ICMP_TYPE_RESERVED139,
176        "140" : _consts.ICMP_TYPE_RESERVED140,
177        "141" : _consts.ICMP_TYPE_RESERVED141,
178        "142" : _consts.ICMP_TYPE_RESERVED142,
179        "143" : _consts.ICMP_TYPE_RESERVED143,
180        "144" : _consts.ICMP_TYPE_RESERVED144,
181        "145" : _consts.ICMP_TYPE_RESERVED145,
182        "146" : _consts.ICMP_TYPE_RESERVED146,
183        "147" : _consts.ICMP_TYPE_RESERVED147,
184        "148" : _consts.ICMP_TYPE_RESERVED148,
185        "149" : _consts.ICMP_TYPE_RESERVED149,
186        "150" : _consts.ICMP_TYPE_RESERVED150,
187        "151" : _consts.ICMP_TYPE_RESERVED151,
188        "152" : _consts.ICMP_TYPE_RESERVED152,
189        "153" : _consts.ICMP_TYPE_RESERVED153,
190        "154" : _consts.ICMP_TYPE_RESERVED154,
191        "155" : _consts.ICMP_TYPE_RESERVED155,
192        "156" : _consts.ICMP_TYPE_RESERVED156,
193        "157" : _consts.ICMP_TYPE_RESERVED157,
194        "158" : _consts.ICMP_TYPE_RESERVED158,
195        "159" : _consts.ICMP_TYPE_RESERVED159,
196        "160" : _consts.ICMP_TYPE_RESERVED160,
197        "161" : _consts.ICMP_TYPE_RESERVED161,
198        "162" : _consts.ICMP_TYPE_RESERVED162,
199        "163" : _consts.ICMP_TYPE_RESERVED163,
200        "164" : _consts.ICMP_TYPE_RESERVED164,
201        "165" : _consts.ICMP_TYPE_RESERVED165,
202        "166" : _consts.ICMP_TYPE_RESERVED166,
203        "167" : _consts.ICMP_TYPE_RESERVED167,
204        "168" : _consts.ICMP_TYPE_RESERVED168,
205        "169" : _consts.ICMP_TYPE_RESERVED169,
206        "170" : _consts.ICMP_TYPE_RESERVED170,
207        "171" : _consts.ICMP_TYPE_RESERVED171,
208        "172" : _consts.ICMP_TYPE_RESERVED172,
209        "173" : _consts.ICMP_TYPE_RESERVED173,
210        "174" : _consts.ICMP_TYPE_RESERVED174,
211        "175" : _consts.ICMP_TYPE_RESERVED175,
212        "176" : _consts.ICMP_TYPE_RESERVED176,
213        "177" : _consts.ICMP_TYPE_RESERVED177,
214        "178" : _consts.ICMP_TYPE_RESERVED178,
215        "179" : _consts.ICMP_TYPE_RESERVED179,
216        "180" : _consts.ICMP_TYPE_RESERVED180,
217        "181" : _consts.ICMP_TYPE_RESERVED181,
218        "182" : _consts.ICMP_TYPE_RESERVED182,
219        "183" : _consts.ICMP_TYPE_RESERVED183,
220        "184" : _consts.ICMP_TYPE_RESERVED184,
221        "185" : _consts.ICMP_TYPE_RESERVED185,
222        "186" : _consts.ICMP_TYPE_RESERVED186,
223        "187" : _consts.ICMP_TYPE_RESERVED187,
224        "188" : _consts.ICMP_TYPE_RESERVED188,
225        "189" : _consts.ICMP_TYPE_RESERVED189,
226        "190" : _consts.ICMP_TYPE_RESERVED190,
227        "191" : _consts.ICMP_TYPE_RESERVED191,
228        "192" : _consts.ICMP_TYPE_RESERVED192,
229        "193" : _consts.ICMP_TYPE_RESERVED193,
230        "194" : _consts.ICMP_TYPE_RESERVED194,
231        "195" : _consts.ICMP_TYPE_RESERVED195,
232        "196" : _consts.ICMP_TYPE_RESERVED196,
233        "197" : _consts.ICMP_TYPE_RESERVED197,
234        "198" : _consts.ICMP_TYPE_RESERVED198,
235        "199" : _consts.ICMP_TYPE_RESERVED199,
236        "200" : _consts.ICMP_TYPE_RESERVED200,
237        "201" : _consts.ICMP_TYPE_RESERVED201,
238        "202" : _consts.ICMP_TYPE_RESERVED202,
239        "203" : _consts.ICMP_TYPE_RESERVED203,
240        "204" : _consts.ICMP_TYPE_RESERVED204,
241        "205" : _consts.ICMP_TYPE_RESERVED205,
242        "206" : _consts.ICMP_TYPE_RESERVED206,
243        "207" : _consts.ICMP_TYPE_RESERVED207,
244        "208" : _consts.ICMP_TYPE_RESERVED208,
245        "209" : _consts.ICMP_TYPE_RESERVED209,
246        "210" : _consts.ICMP_TYPE_RESERVED210,
247        "211" : _consts.ICMP_TYPE_RESERVED211,
248        "212" : _consts.ICMP_TYPE_RESERVED212,
249        "213" : _consts.ICMP_TYPE_RESERVED213,
250        "214" : _consts.ICMP_TYPE_RESERVED214,
251        "215" : _consts.ICMP_TYPE_RESERVED215,
252        "216" : _consts.ICMP_TYPE_RESERVED216,
253        "217" : _consts.ICMP_TYPE_RESERVED217,
254        "218" : _consts.ICMP_TYPE_RESERVED218,
255        "219" : _consts.ICMP_TYPE_RESERVED219,
256        "220" : _consts.ICMP_TYPE_RESERVED220,
257        "221" : _consts.ICMP_TYPE_RESERVED221,
258        "222" : _consts.ICMP_TYPE_RESERVED222,
259        "223" : _consts.ICMP_TYPE_RESERVED223,
260        "224" : _consts.ICMP_TYPE_RESERVED224,
261        "225" : _consts.ICMP_TYPE_RESERVED225,
262        "226" : _consts.ICMP_TYPE_RESERVED226,
263        "227" : _consts.ICMP_TYPE_RESERVED227,
264        "228" : _consts.ICMP_TYPE_RESERVED228,
265        "229" : _consts.ICMP_TYPE_RESERVED229,
266        "230" : _consts.ICMP_TYPE_RESERVED230,
267        "231" : _consts.ICMP_TYPE_RESERVED231,
268        "232" : _consts.ICMP_TYPE_RESERVED232,
269        "233" : _consts.ICMP_TYPE_RESERVED233,
270        "234" : _consts.ICMP_TYPE_RESERVED234,
271        "235" : _consts.ICMP_TYPE_RESERVED235,
272        "236" : _consts.ICMP_TYPE_RESERVED236,
273        "237" : _consts.ICMP_TYPE_RESERVED237,
274        "238" : _consts.ICMP_TYPE_RESERVED238,
275        "239" : _consts.ICMP_TYPE_RESERVED239,
276        "240" : _consts.ICMP_TYPE_RESERVED240,
277        "241" : _consts.ICMP_TYPE_RESERVED241,
278        "242" : _consts.ICMP_TYPE_RESERVED242,
279        "243" : _consts.ICMP_TYPE_RESERVED243,
280        "244" : _consts.ICMP_TYPE_RESERVED244,
281        "245" : _consts.ICMP_TYPE_RESERVED245,
282        "246" : _consts.ICMP_TYPE_RESERVED246,
283        "247" : _consts.ICMP_TYPE_RESERVED247,
284        "248" : _consts.ICMP_TYPE_RESERVED248,
285        "249" : _consts.ICMP_TYPE_RESERVED249,
286        "250" : _consts.ICMP_TYPE_RESERVED250,
287        "251" : _consts.ICMP_TYPE_RESERVED251,
288        "252" : _consts.ICMP_TYPE_RESERVED252,
289        "253" : _consts.ICMP_TYPE_RESERVED253,
290        "254" : _consts.ICMP_TYPE_RESERVED254,
291        "255" : _consts.ICMP_TYPE_RESERVED255,
292    }
293
294class _HCode(_fields.IntField):
295    """
296    This field contains the ICMP message code.
297    """
298
299    bits = 8
300    auto = False
301
302    # TODO: support the enums
303
304class _HIdent(_fields.IntField):
305    """
306    This field contains the ICMP identifier value.
307    """
308
309    bits = 16
310
311class _HSeq(_fields.IntField):
312    """
313    This field contains the ICMP sequence value.
314    """
315
316    bits = 16
317
318class _HPointer(_fields.IntField):
319    """
320    This field contains the ICMP pointer value.
321    """
322
323    bits = 8
324
325class _HPointerUnused(_fields.IntField):
326    """
327    This field is unused.
328    """
329
330    bits = 24
331
332class _HUnused(_fields.IntField):
333    """
334    This field is unused.
335    """
336
337    bits = 32
338
339class _HTimestamp(_fields.IntField):
340    """
341    This field holds a timestamp expressed as milliseconds since midnight UT.
342    See RFC 792 for details.
343    """
344
345    bits = 32
346
347class ICMP(_protocols.Protocol):
348    """
349    ICMP (Internet Control Message Protocol) implementation.
350
351    This protocol provides error reporting and problem diagnostics for IP
352    networks. ICMP packets are typically sent in response to corrupted and/or
353    misdirected packets.
354
355    Note: ICMP header structure changes depending on the type of the packet.
356          To see field names available for a specific ICMP type, create an
357          instance with that type and print it. Example:
358
359          >>> from umit.umpa.protocols import ICMP
360          >>> print ICMP(type='ECHO')
361    """
362
363    layer = 4
364    protocol_id = _consts.PROTOCOL_ICMP
365    payload_fieldname = None
366    name = "ICMP"
367
368    # The ICMP packet consists of three parts:
369    # +----+----+---------+
370    # |type|code| checksum| <= fixed header
371    # +----+----+---------+
372    # |    (4 bytes)      | <= type-dependent header
373    # +-------------------+
374    # | (variable length) | <= type-dependent data
375    # +-------------------+
376    # While the first part is fixed, the other two require changing the packet
377    # structure depending on the `type' field.
378    _ordered_fields = (# fixed header
379                       'type', 'code', '_checksum',
380                       # variable headers, one per line
381                       'ident', 'seq',
382                       'redir_gw',
383                       'pointer', 'pointer_unused',
384                       'unused',
385                       # data part, one per line
386                       'originate', 'receive', 'transmit',
387                       'addressmask',
388                       'data',
389                       )
390
391    def __init__(self, **kwargs):
392        """
393        Create a new ICMP().
394        """
395
396        fields_list = [ ### Fixed header part:
397                        _HType("Type"),
398                        _HCode("Code", 0),
399                        _layer4.Layer4ChecksumField("Checksum"),
400                        ### Variable header part:
401                        # Ping, Timestamp, etc.
402                        _HIdent("Identifier", 0, active=False),
403                        _HSeq("Sequence Number", 0, active=False),
404                        # Redirect
405                        _fields.IPv4AddrField("Gateway Internet Address",
406                                              '0.0.0.0', active=False),
407                        # Parameter Problem
408                        _HPointer("Pointer", active=False),
409                        _HPointerUnused("Unused", 0, active=False),
410                        # generic/unknown header
411                        _HUnused("Unused", 0),
412                        ### Data part:
413                        # Timestamp
414                        _HTimestamp("Originate Timestamp", 0, active=False),
415                        _HTimestamp("Receive Timestamp", 0, active=False),
416                        _HTimestamp("Transmit Timestamp", 0, active=False),
417                        # Address Mask
418                        _fields.IPv4AddrField("Address Mask",
419                                              '0.0.0.0', active=False),
420                        # generic/unknown data
421                        _fields.DataField("Data", ''),
422                        ]
423
424        # we call super.__init__ after prepared necessary data
425        super(ICMP, self).__init__(fields_list, **kwargs)
426
427        # set __doc__ for fields - it's important if you want to get hints
428        # in some frontends. E.g. Umit Project provides one...
429        self.get_field('_checksum').set_doc("Checksum of ICMP packet. "
430            "See RFC 792 for more info.")
431        self.get_field('redir_gw').set_doc("ICMP Redirect destination. "
432            "See RFC 792 for more info.")
433        self.get_field('addressmask').set_doc("Address Mask."
434            "See RFC 950 for more info.")
435
436    def __setattr__(self, attr, value):
437        """
438        When changing the 'type' field, reflect the changes in the structure
439        of the packet.
440        """
441
442        super(ICMP, self).__setattr__(attr, value)
443
444        if attr == 'type':
445            # disable all variable fields initially
446            self.disable_fields('unused', 'ident', 'seq', 'redir_gw', 'pointer',
447                                'pointer_unused',
448                                'originate', 'receive', 'transmit',
449                                'addressmask', 'data')
450
451            # activate dynamic header fields depending on the type
452            if self.type in (_consts.ICMP_TYPE_ADDRESS_MASK_REQUEST,
453                             _consts.ICMP_TYPE_ADDRESS_MASK_REPLY,
454                             _consts.ICMP_TYPE_ECHO,
455                             _consts.ICMP_TYPE_ECHO_REPLY,
456                             _consts.ICMP_TYPE_INFORMATION_REQUEST,
457                             _consts.ICMP_TYPE_INFORMATION_REPLY,
458                             _consts.ICMP_TYPE_TIMESTAMP,
459                             _consts.ICMP_TYPE_TIMESTAMP_REPLY,):
460                self.enable_fields('ident', 'seq')
461            elif self.type in (_consts.ICMP_TYPE_REDIRECT, ):
462                self.enable_fields('redir_gw')
463            elif self.type in (_consts.ICMP_TYPE_PARAMETER_PROBLEM, ):
464                self.enable_fields('pointer', 'pointer_unused')
465            else:
466                # insert a dummy 4-byte field by default
467                self.enable_fields('unused')
468
469            # activate data fields depending on the type
470            if self.type in (_consts.ICMP_TYPE_ADDRESS_MASK_REQUEST,
471                             _consts.ICMP_TYPE_ADDRESS_MASK_REPLY,):
472                self.enable_fields('addressmask')
473            elif self.type in (_consts.ICMP_TYPE_TIMESTAMP,
474                               _consts.ICMP_TYPE_TIMESTAMP_REPLY,):
475                self.enable_fields('originate', 'receive', 'transmit')
476            else:
477                # unknown/generic data
478                self.enable_fields('data')
479
480    def _pre_raw(self, raw_value, bit, protocol_container, protocol_bits):
481        """
482        Handle with fields before calling fillout() for them.
483
484        Store temp value of protocols bits for checksum field.
485
486        @type raw_value: C{int}
487        @param raw_value: currently raw value for the packet.
488
489        @type bit: C{int}
490        @param bit: currently length of the protocol.
491
492        @type protocol_container: C{tuple}
493        @param protocol_container: tuple of protocols included in the packet.
494
495        @type protocol_bits: C{int}
496        @param protocol_bits: currently length of the packet.
497
498        @return: C{raw_value, bit}
499        """
500
501        # Length
502        self.get_field('_checksum')._tmp_value = protocol_bits
503
504        return raw_value, bit
505
506    def _post_raw(self, raw_value, bit, protocol_container, protocol_bits):
507        """
508        Handle with fields after calling fillout() for them.
509
510        Calculate header checksum with new instance of PseudoHeader object.
511
512        @type raw_value: C{int}
513        @param raw_value: currently raw value for the packet.
514
515        @type bit: C{int}
516        @param bit: currently length of the protocol.
517
518        @type protocol_container: C{tuple}
519        @param protocol_container: tuple of protocols included in the packet.
520
521        @type protocol_bits: C{int}
522        @param protocol_bits: currently length of the packet.
523
524        @return: C{raw_value, bit}
525        """
526
527        # Fill checksum only if it's zero (not supplied by user)
528        cksum_offset = bit - self.get_offset('_checksum') - \
529                       self.get_field('_checksum').bits
530
531        if _bits.get_bits(raw_value,
532                        self.get_field('_checksum').bits,
533                        cksum_offset,
534                        rev_offset=True) == 0:
535
536            # TODO: what about payload?
537
538            # calculate checksum and place it at the correct offset in raw_value
539            cksum = _net.in_cksum(raw_value)
540            raw_value |= cksum << cksum_offset
541
542        return raw_value, bit
543
544    def load_raw(self, buffer):
545        """
546        Load raw and update a protocol's fields.
547
548        @return: raw payload
549        """
550
551        header_size = 8
552        header_format = '!BBHI'
553        fields = struct.unpack(header_format, buffer[:header_size])
554        buffer = buffer[header_size:]
555
556        self.type = fields[0]
557        self.code = fields[1]
558        self._checksum = fields[2]
559
560        # fill in dynamic header fields depending on the type
561        if self.type in (_consts.ICMP_TYPE_ADDRESS_MASK_REQUEST,
562                         _consts.ICMP_TYPE_ADDRESS_MASK_REPLY,
563                         _consts.ICMP_TYPE_ECHO,
564                         _consts.ICMP_TYPE_ECHO_REPLY,
565                         _consts.ICMP_TYPE_INFORMATION_REQUEST,
566                         _consts.ICMP_TYPE_INFORMATION_REPLY,
567                         _consts.ICMP_TYPE_TIMESTAMP,
568                         _consts.ICMP_TYPE_TIMESTAMP_REPLY,):
569            self.ident = fields[3] >> 16
570            self.seq   = fields[3] & 0x0000FFFF
571        elif self.type in (_consts.ICMP_TYPE_REDIRECT, ):
572            self.redir_gw = ( (fields[3]>>24) & 0xff,
573                              (fields[3]>>16) & 0xff,
574                              (fields[3]>> 8) & 0xff,
575                              (fields[3]    ) & 0xff, )
576        elif self.type in (_consts.ICMP_TYPE_PARAMETER_PROBLEM, ):
577            self.pointer = fields[3] >> 24
578            self.pointer_unused = fields[3] & 0x00ffffff
579        else:
580            self.unused = fields[3]
581
582        # fill in data fields depending on the type
583        if self.type in (_consts.ICMP_TYPE_ADDRESS_MASK_REQUEST,
584                         _consts.ICMP_TYPE_ADDRESS_MASK_REPLY,):
585            data_size = 4
586            data_format = "!4B"
587            fields = struct.unpack(data_format, buffer[:data_size])
588            buffer = buffer[data_size:]
589
590            self.addressmask = fields[0:4]
591        elif self.type in (_consts.ICMP_TYPE_TIMESTAMP,
592                           _consts.ICMP_TYPE_TIMESTAMP_REPLY,):
593            data_size = 12
594            data_format = "!3I"
595            fields = struct.unpack(data_format, buffer[:data_size])
596            buffer = buffer[data_size:]
597
598            self.originate = fields[0]
599            self.receive = fields[1]
600            self.transmit = fields[2]
601        else:
602            # unknown/generic data
603            self.data = buffer
604
605        return buffer
606
607protocols = [ ICMP, ]
Note: See TracBrowser for help on using the browser.