Coverage for /root/GitHubProjects/impacket/impacket/ImpactPacket.py : 55%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# Impacket - Collection of Python classes for working with network protocols.
2#
3# SECUREAUTH LABS. Copyright (C) 2018 SecureAuth Corporation. All rights reserved.
4#
5# This software is provided under a slightly modified version
6# of the Apache Software License. See the accompanying LICENSE file
7# for more information.
8#
9# Description:
10# Network packet codecs basic building blocks.
11# Low-level packet codecs for various Internet protocols.
12#
13# Author:
14# Javier Burroni (javier)
15# Bruce Leidl (brl)
16# Javier Kohen (jkohen)
17#
19from __future__ import division
20from __future__ import print_function
21import array
22import struct
23import socket
24import string
25import sys
26from binascii import hexlify
27from functools import reduce
29# Alias function for compatibility with both Python <3.2 `tostring` and `fromstring` methods, and
30# Python >=3.2 `tobytes` and `tostring`
31if sys.version_info[0] >= 3 and sys.version_info[1] >= 2: 31 ↛ 35line 31 didn't jump to line 35, because the condition on line 31 was never false
32 array_tobytes = lambda array_object: array_object.tobytes()
33 array_frombytes = lambda array_object, bytes: array_object.frombytes(bytes)
34else:
35 array_tobytes = lambda array_object: array_object.tostring()
36 array_frombytes = lambda array_object, bytes: array_object.fromstring(bytes)
39"""Classes to build network packets programmatically.
41Each protocol layer is represented by an object, and these objects are
42hierarchically structured to form a packet. This list is traversable
43in both directions: from parent to child and vice versa.
45All objects can be turned back into a raw buffer ready to be sent over
46the wire (see method get_packet).
47"""
49class ImpactPacketException(Exception):
50 def __init__(self, value):
51 self.value = value
52 def __str__(self):
53 return repr(self.value)
55class PacketBuffer(object):
56 """Implement the basic operations utilized to operate on a
57 packet's raw buffer. All the packet classes derive from this one.
59 The byte, word, long and ip_address getters and setters accept
60 negative indexes, having these the a similar effect as in a
61 regular Python sequence slice.
62 """
64 def __init__(self, length = None):
65 "If 'length' is specified the buffer is created with an initial size"
66 if length:
67 self.__bytes = array.array('B', b'\0' * length)
68 else:
69 self.__bytes = array.array('B')
71 def set_bytes_from_string(self, data):
72 "Sets the value of the packet buffer from the string 'data'"
73 self.__bytes = array.array('B', data)
75 def get_buffer_as_string(self):
76 "Returns the packet buffer as a string object"
77 return array_tobytes(self.__bytes)
79 def get_bytes(self):
80 "Returns the packet buffer as an array"
81 return self.__bytes
83 def set_bytes(self, bytes):
84 "Set the packet buffer from an array"
85 # Make a copy to be safe
86 self.__bytes = array.array('B', bytes.tolist())
88 def set_byte(self, index, value):
89 "Set byte at 'index' to 'value'"
90 index = self.__validate_index(index, 1)
91 self.__bytes[index] = value
93 def get_byte(self, index):
94 "Return byte at 'index'"
95 index = self.__validate_index(index, 1)
96 return self.__bytes[index]
98 def set_word(self, index, value, order = '!'):
99 "Set 2-byte word at 'index' to 'value'. See struct module's documentation to understand the meaning of 'order'."
100 index = self.__validate_index(index, 2)
101 ary = array.array("B", struct.pack(order + 'H', value))
102 if -2 == index: 102 ↛ 103line 102 didn't jump to line 103, because the condition on line 102 was never true
103 self.__bytes[index:] = ary
104 else:
105 self.__bytes[index:index+2] = ary
107 def get_word(self, index, order = '!'):
108 "Return 2-byte word at 'index'. See struct module's documentation to understand the meaning of 'order'."
109 index = self.__validate_index(index, 2)
110 if -2 == index: 110 ↛ 111line 110 didn't jump to line 111, because the condition on line 110 was never true
111 bytes = self.__bytes[index:]
112 else:
113 bytes = self.__bytes[index:index+2]
114 (value,) = struct.unpack(order + 'H', array_tobytes(bytes))
115 return value
117 def set_long(self, index, value, order = '!'):
118 "Set 4-byte 'value' at 'index'. See struct module's documentation to understand the meaning of 'order'."
119 index = self.__validate_index(index, 4)
120 ary = array.array("B", struct.pack(order + 'L', value))
121 if -4 == index:
122 self.__bytes[index:] = ary
123 else:
124 self.__bytes[index:index+4] = ary
126 def get_long(self, index, order = '!'):
127 "Return 4-byte value at 'index'. See struct module's documentation to understand the meaning of 'order'."
128 index = self.__validate_index(index, 4)
129 if -4 == index:
130 bytes = self.__bytes[index:]
131 else:
132 bytes = self.__bytes[index:index+4]
133 (value,) = struct.unpack(order + 'L', array_tobytes(bytes))
134 return value
136 def set_long_long(self, index, value, order = '!'):
137 "Set 8-byte 'value' at 'index'. See struct module's documentation to understand the meaning of 'order'."
138 index = self.__validate_index(index, 8)
139 ary = array.array("B", struct.pack(order + 'Q', value))
140 if -8 == index: 140 ↛ 141line 140 didn't jump to line 141, because the condition on line 140 was never true
141 self.__bytes[index:] = ary
142 else:
143 self.__bytes[index:index+8] = ary
145 def get_long_long(self, index, order = '!'):
146 "Return 8-byte value at 'index'. See struct module's documentation to understand the meaning of 'order'."
147 index = self.__validate_index(index, 8)
148 if -8 == index: 148 ↛ 149line 148 didn't jump to line 149, because the condition on line 148 was never true
149 bytes = self.__bytes[index:]
150 else:
151 bytes = self.__bytes[index:index+8]
152 (value,) = struct.unpack(order + 'Q', array_tobytes(bytes))
153 return value
156 def get_ip_address(self, index):
157 "Return 4-byte value at 'index' as an IP string"
158 index = self.__validate_index(index, 4)
159 if -4 == index: 159 ↛ 160line 159 didn't jump to line 160, because the condition on line 159 was never true
160 bytes = self.__bytes[index:]
161 else:
162 bytes = self.__bytes[index:index+4]
163 return socket.inet_ntoa(array_tobytes(bytes))
165 def set_ip_address(self, index, ip_string):
166 "Set 4-byte value at 'index' from 'ip_string'"
167 index = self.__validate_index(index, 4)
168 raw = socket.inet_aton(ip_string)
169 (b1,b2,b3,b4) = struct.unpack("BBBB", raw)
170 self.set_byte(index, b1)
171 self.set_byte(index + 1, b2)
172 self.set_byte(index + 2, b3)
173 self.set_byte(index + 3, b4)
175 def set_checksum_from_data(self, index, data):
176 "Set 16-bit checksum at 'index' by calculating checksum of 'data'"
177 self.set_word(index, self.compute_checksum(data))
179 def compute_checksum(self, anArray):
180 "Return the one's complement of the one's complement sum of all the 16-bit words in 'anArray'"
181 nleft = len(anArray)
182 sum = 0
183 pos = 0
184 while nleft > 1:
185 sum = anArray[pos] * 256 + (anArray[pos + 1] + sum)
186 pos = pos + 2
187 nleft = nleft - 2
188 if nleft == 1:
189 sum = sum + anArray[pos] * 256
190 return self.normalize_checksum(sum)
192 def normalize_checksum(self, aValue):
193 sum = aValue
194 sum = (sum >> 16) + (sum & 0xFFFF)
195 sum += (sum >> 16)
196 sum = (~sum & 0xFFFF)
197 return sum
199 def __validate_index(self, index, size):
200 """This method performs two tasks: to allocate enough space to
201 fit the elements at positions index through index+size, and to
202 adjust negative indexes to their absolute equivalent.
203 """
205 orig_index = index
207 curlen = len(self.__bytes)
208 if index < 0:
209 index = curlen + index
211 diff = index + size - curlen
212 if diff > 0:
213 array_frombytes(self.__bytes, b'\0' * diff)
214 if orig_index < 0: 214 ↛ 215line 214 didn't jump to line 215, because the condition on line 214 was never true
215 orig_index -= diff
217 return orig_index
219class ProtocolLayer():
220 "Protocol Layer Manager for insertion and removal of protocol layers."
222 __child = None
223 __parent = None
225 def contains(self, aHeader):
226 "Set 'aHeader' as the child of this protocol layer"
227 self.__child = aHeader
228 aHeader.set_parent(self)
230 def set_parent(self, my_parent):
231 "Set the header 'my_parent' as the parent of this protocol layer"
232 self.__parent = my_parent
234 def child(self):
235 "Return the child of this protocol layer"
236 return self.__child
238 def parent(self):
239 "Return the parent of this protocol layer"
240 return self.__parent
242 def unlink_child(self):
243 "Break the hierarchy parent/child child/parent"
244 if self.__child:
245 self.__child.set_parent(None)
246 self.__child = None
248class ProtocolPacket(ProtocolLayer):
249 __HEADER_SIZE = 0
250 __BODY_SIZE = 0
251 __TAIL_SIZE = 0
253 __header = None
254 __body = None
255 __tail = None
257 def __init__(self, header_size, tail_size):
258 self.__HEADER_SIZE = header_size
259 self.__TAIL_SIZE = tail_size
260 self.__header=PacketBuffer(self.__HEADER_SIZE)
261 self.__body=PacketBuffer()
262 self.__tail=PacketBuffer(self.__TAIL_SIZE)
264 def __update_body_from_child(self):
265 # Update child raw packet in my body
266 if self.child():
267 body=self.child().get_packet()
268 self.__BODY_SIZE=len(body)
269 self.__body.set_bytes_from_string(body)
271 def __get_header(self):
272 return self.__header
274 header = property(__get_header)
276 def __get_body(self):
277 self.__update_body_from_child()
278 return self.__body
280 body = property(__get_body)
282 def __get_tail(self):
283 return self.__tail
285 tail = property(__get_tail)
287 def get_header_size(self):
288 "Return frame header size"
289 return self.__HEADER_SIZE
291 def get_tail_size(self):
292 "Return frame tail size"
293 return self.__TAIL_SIZE
295 def get_body_size(self):
296 "Return frame body size"
297 self.__update_body_from_child()
298 return self.__BODY_SIZE
300 def get_size(self):
301 "Return frame total size"
302 return self.get_header_size()+self.get_body_size()+self.get_tail_size()
304 def load_header(self, aBuffer):
305 self.__HEADER_SIZE=len(aBuffer)
306 self.__header.set_bytes_from_string(aBuffer)
308 def load_body(self, aBuffer):
309 "Load the packet body from string. "\
310 "WARNING: Using this function will break the hierarchy of preceding protocol layer"
311 self.unlink_child()
312 self.__BODY_SIZE=len(aBuffer)
313 self.__body.set_bytes_from_string(aBuffer)
315 def load_tail(self, aBuffer):
316 self.__TAIL_SIZE=len(aBuffer)
317 self.__tail.set_bytes_from_string(aBuffer)
319 def __extract_header(self, aBuffer):
320 self.load_header(aBuffer[:self.__HEADER_SIZE])
322 def __extract_body(self, aBuffer):
323 if self.__TAIL_SIZE<=0:
324 end=None
325 else:
326 end=-self.__TAIL_SIZE
327 self.__BODY_SIZE=len(aBuffer[self.__HEADER_SIZE:end])
328 self.__body.set_bytes_from_string(aBuffer[self.__HEADER_SIZE:end])
330 def __extract_tail(self, aBuffer):
331 if self.__TAIL_SIZE<=0:
332 # leave the array empty
333 return
334 else:
335 start=-self.__TAIL_SIZE
336 self.__tail.set_bytes_from_string(aBuffer[start:])
338 def load_packet(self, aBuffer):
339 "Load the whole packet from a string" \
340 "WARNING: Using this function will break the hierarchy of preceding protocol layer"
341 self.unlink_child()
343 self.__extract_header(aBuffer)
344 self.__extract_body(aBuffer)
345 self.__extract_tail(aBuffer)
347 def get_header_as_string(self):
348 return self.__header.get_buffer_as_string()
350 def get_body_as_string(self):
351 self.__update_body_from_child()
352 return self.__body.get_buffer_as_string()
353 body_string = property(get_body_as_string)
355 def get_tail_as_string(self):
356 return self.__tail.get_buffer_as_string()
357 tail_string = property(get_tail_as_string)
359 def get_packet(self):
360 self.__update_body_from_child()
362 ret = b''
364 header = self.get_header_as_string()
365 if header:
366 ret += header
368 body = self.get_body_as_string()
369 if body:
370 ret += body
372 tail = self.get_tail_as_string()
373 if tail:
374 ret += tail
376 return ret
378class Header(PacketBuffer,ProtocolLayer):
379 "This is the base class from which all protocol definitions extend."
381 packet_printable = [c for c in string.printable if c not in string.whitespace] + [' ']
383 ethertype = None
384 protocol = None
385 def __init__(self, length = None):
386 PacketBuffer.__init__(self, length)
387 self.auto_checksum = 1
389 def get_data_as_string(self):
390 "Returns all data from children of this header as string"
392 if self.child():
393 return self.child().get_packet()
394 else:
395 return None
397 def get_packet(self):
398 """Returns the raw representation of this packet and its
399 children as a string. The output from this method is a packet
400 ready to be transmitted over the wire.
401 """
402 self.calculate_checksum()
404 data = self.get_data_as_string()
405 if data:
406 return self.get_buffer_as_string() + data
407 else:
408 return self.get_buffer_as_string()
410 def get_size(self):
411 "Return the size of this header and all of it's children"
412 tmp_value = self.get_header_size()
413 if self.child():
414 tmp_value = tmp_value + self.child().get_size()
415 return tmp_value
417 def calculate_checksum(self):
418 "Calculate and set the checksum for this header"
419 pass
421 def get_pseudo_header(self):
422 "Pseudo headers can be used to limit over what content will the checksums be calculated."
423 # default implementation returns empty array
424 return array.array('B')
426 def load_header(self, aBuffer):
427 "Properly set the state of this instance to reflect that of the raw packet passed as argument."
428 self.set_bytes_from_string(aBuffer)
429 hdr_len = self.get_header_size()
430 if(len(aBuffer) < hdr_len): #we must do something like this 430 ↛ 431line 430 didn't jump to line 431, because the condition on line 430 was never true
431 diff = hdr_len - len(aBuffer)
432 for i in range(0, diff):
433 aBuffer += '\x00'
434 self.set_bytes_from_string(aBuffer[:hdr_len])
436 def get_header_size(self):
437 "Return the size of this header, that is, not counting neither the size of the children nor of the parents."
438 raise RuntimeError("Method %s.get_header_size must be overridden." % self.__class__)
440 def list_as_hex(self, aList):
441 if len(aList):
442 ltmp = []
443 line = []
444 count = 0
445 for byte in aList:
446 if not (count % 2):
447 if (count % 16):
448 ltmp.append(' ')
449 else:
450 ltmp.append(' '*4)
451 ltmp.append(''.join(line))
452 ltmp.append('\n')
453 line = []
454 if chr(byte) in Header.packet_printable:
455 line.append(chr(byte))
456 else:
457 line.append('.')
458 ltmp.append('%.2x' % byte)
459 count += 1
460 if (count%16):
461 left = 16 - (count%16)
462 ltmp.append(' ' * (4+(left // 2) + (left*2)))
463 ltmp.append(''.join(line))
464 ltmp.append('\n')
465 return ltmp
466 else:
467 return []
469 def __str__(self):
470 ltmp = self.list_as_hex(self.get_bytes().tolist())
472 if self.child():
473 ltmp.append(['\n', str(self.child())])
475 if len(ltmp)>0:
476 return ''.join(ltmp)
477 else:
478 return ''
482class Data(Header):
483 """This packet type can hold raw data. It's normally employed to
484 hold a packet's innermost layer's contents in those cases for
485 which the protocol details are unknown, and there's a copy of a
486 valid packet available.
488 For instance, if all that's known about a certain protocol is that
489 a UDP packet with its contents set to "HELLO" initiate a new
490 session, creating such packet is as simple as in the following code
491 fragment:
492 packet = UDP()
493 packet.contains('HELLO')
494 """
496 def __init__(self, aBuffer = None):
497 Header.__init__(self)
498 if aBuffer:
499 self.set_data(aBuffer)
501 def set_data(self, data):
502 self.set_bytes_from_string(data)
504 def get_size(self):
505 return len(self.get_bytes())
508class EthernetTag(PacketBuffer):
509 """Represents a VLAN header specified in IEEE 802.1Q and 802.1ad.
510 Provides methods for convenient manipulation with header fields."""
512 def __init__(self, value=0x81000000):
513 PacketBuffer.__init__(self, 4)
514 self.set_long(0, value)
516 def get_tpid(self):
517 """Returns Tag Protocol Identifier"""
518 return self.get_word(0)
520 def set_tpid(self, value):
521 """Sets Tag Protocol Identifier"""
522 return self.set_word(0, value)
524 def get_pcp(self):
525 """Returns Priority Code Point"""
526 return (self.get_byte(2) & 0xE0) >> 5
528 def set_pcp(self, value):
529 """Sets Priority Code Point"""
530 orig_value = self.get_byte(2)
531 self.set_byte(2, (orig_value & 0x1F) | ((value & 0x07) << 5))
533 def get_dei(self):
534 """Returns Drop Eligible Indicator"""
535 return (self.get_byte(2) & 0x10) >> 4
537 def set_dei(self, value):
538 """Sets Drop Eligible Indicator"""
539 orig_value = self.get_byte(2)
540 self.set_byte(2, orig_value | 0x10 if value else orig_value & 0xEF)
542 def get_vid(self):
543 """Returns VLAN Identifier"""
544 return self.get_word(2) & 0x0FFF
546 def set_vid(self, value):
547 """Sets VLAN Identifier"""
548 orig_value = self.get_word(2)
549 self.set_word(2, (orig_value & 0xF000) | (value & 0x0FFF))
551 def __str__(self):
552 priorities = (
553 'Best Effort',
554 'Background',
555 'Excellent Effort',
556 'Critical Applications',
557 'Video, < 100 ms latency and jitter',
558 'Voice, < 10 ms latency and jitter',
559 'Internetwork Control',
560 'Network Control')
562 pcp = self.get_pcp()
563 return '\n'.join((
564 '802.1Q header: 0x{0:08X}'.format(self.get_long(0)),
565 'Priority Code Point: {0} ({1})'.format(pcp, priorities[pcp]),
566 'Drop Eligible Indicator: {0}'.format(self.get_dei()),
567 'VLAN Identifier: {0}'.format(self.get_vid())))
570class Ethernet(Header):
571 def __init__(self, aBuffer = None):
572 Header.__init__(self, 14)
573 self.tag_cnt = 0
574 if(aBuffer): 574 ↛ exitline 574 didn't return from function '__init__', because the condition on line 574 was never false
575 self.load_header(aBuffer)
577 def set_ether_type(self, aValue):
578 "Set ethernet data type field to 'aValue'"
579 self.set_word(12 + 4*self.tag_cnt, aValue)
581 def get_ether_type(self):
582 "Return ethernet data type field"
583 return self.get_word(12 + 4*self.tag_cnt)
585 def get_tag(self, index):
586 """Returns an EthernetTag initialized from index-th VLAN tag.
587 The tags are numbered from 0 to self.tag_cnt-1 as they appear in the frame.
588 It is possible to use negative indexes as well."""
589 index = self.__validate_tag_index(index)
590 return EthernetTag(self.get_long(12+4*index))
592 def set_tag(self, index, tag):
593 """Sets the index-th VLAN tag to contents of an EthernetTag object.
594 The tags are numbered from 0 to self.tag_cnt-1 as they appear in the frame.
595 It is possible to use negative indexes as well."""
596 index = self.__validate_tag_index(index)
597 pos = 12 + 4*index
598 for i,val in enumerate(tag.get_bytes()):
599 self.set_byte(pos+i, val)
601 def push_tag(self, tag, index=0):
602 """Inserts contents of an EthernetTag object before the index-th VLAN tag.
603 Index defaults to 0 (the top of the stack)."""
604 if index < 0: 604 ↛ 605line 604 didn't jump to line 605, because the condition on line 604 was never true
605 index += self.tag_cnt
606 pos = 12 + 4*max(0, min(index, self.tag_cnt))
607 data = self.get_bytes()
608 data[pos:pos] = tag.get_bytes()
609 self.set_bytes(data)
610 self.tag_cnt += 1
612 def pop_tag(self, index=0):
613 """Removes the index-th VLAN tag and returns it as an EthernetTag object.
614 Index defaults to 0 (the top of the stack)."""
615 index = self.__validate_tag_index(index)
616 pos = 12 + 4*index
617 tag = self.get_long(pos)
618 data = self.get_bytes()
619 del data[pos:pos+4]
620 self.set_bytes(data)
621 self.tag_cnt -= 1
622 return EthernetTag(tag)
624 def load_header(self, aBuffer):
625 self.tag_cnt = 0
626 while aBuffer[12+4*self.tag_cnt:14+4*self.tag_cnt] in (b'\x81\x00', b'\x88\xa8', b'\x91\x00'):
627 self.tag_cnt += 1
629 hdr_len = self.get_header_size()
630 diff = hdr_len - len(aBuffer)
631 if diff > 0: 631 ↛ 632line 631 didn't jump to line 632, because the condition on line 631 was never true
632 aBuffer += b'\x00'*diff
633 self.set_bytes_from_string(aBuffer[:hdr_len])
635 def get_header_size(self):
636 "Return size of Ethernet header"
637 return 14 + 4*self.tag_cnt
639 def get_packet(self):
641 if self.child(): 641 ↛ 642line 641 didn't jump to line 642, because the condition on line 641 was never true
642 try:
643 self.set_ether_type(self.child().ethertype)
644 except:
645 " an Ethernet packet may have a Data() "
646 pass
647 return Header.get_packet(self)
649 def get_ether_dhost(self):
650 "Return 48 bit destination ethernet address as a 6 byte array"
651 return self.get_bytes()[0:6]
653 def set_ether_dhost(self, aValue):
654 "Set destination ethernet address from 6 byte array 'aValue'"
655 for i in range(0, 6):
656 self.set_byte(i, aValue[i])
658 def get_ether_shost(self):
659 "Return 48 bit source ethernet address as a 6 byte array"
660 return self.get_bytes()[6:12]
662 def set_ether_shost(self, aValue):
663 "Set source ethernet address from 6 byte array 'aValue'"
664 for i in range(0, 6):
665 self.set_byte(i + 6, aValue[i])
667 @staticmethod
668 def as_eth_addr(anArray):
669 tmp_list = [x > 15 and '%x'%x or '0%x'%x for x in anArray]
670 return '' + reduce(lambda x, y: x+':'+y, tmp_list)
672 def __str__(self):
673 tmp_str = 'Ether: ' + self.as_eth_addr(self.get_ether_shost()) + ' -> '
674 tmp_str += self.as_eth_addr(self.get_ether_dhost())
675 if self.child():
676 tmp_str += '\n' + str( self.child())
677 return tmp_str
679 def __validate_tag_index(self, index):
680 """Adjusts negative indices to their absolute equivalents.
681 Raises IndexError when out of range <0, self.tag_cnt-1>."""
682 if index < 0:
683 index += self.tag_cnt
684 if index < 0 or index >= self.tag_cnt:
685 raise IndexError("Tag index out of range")
686 return index
688# Linux "cooked" capture encapsulation.
689# Used, for instance, for packets returned by the "any" interface.
690class LinuxSLL(Header):
691 type_descriptions = [
692 "sent to us by somebody else",
693 "broadcast by somebody else",
694 "multicast by somebody else",
695 "sent to somebody else to somebody else",
696 "sent by us",
697 ]
699 def __init__(self, aBuffer = None):
700 Header.__init__(self, 16)
701 if (aBuffer):
702 self.load_header(aBuffer)
704 def set_type(self, type):
705 "Sets the packet type field to type"
706 self.set_word(0, type)
708 def get_type(self):
709 "Returns the packet type field"
710 return self.get_word(0)
712 def set_arphdr(self, value):
713 "Sets the ARPHDR value for the link layer device type"
714 self.set_word(2, type)
716 def get_arphdr(self):
717 "Returns the ARPHDR value for the link layer device type"
718 return self.get_word(2)
720 def set_addr_len(self, len):
721 "Sets the length of the sender's address field to len"
722 self.set_word(4, len)
724 def get_addr_len(self):
725 "Returns the length of the sender's address field"
726 return self.get_word(4)
728 def set_addr(self, addr):
729 "Sets the sender's address field to addr. Addr must be at most 8-byte long."
730 if (len(addr) < 8):
731 addr += b'\0' * (8 - len(addr))
732 self.get_bytes()[6:14] = addr
734 def get_addr(self):
735 "Returns the sender's address field"
736 return array_tobytes(self.get_bytes()[6:14])
738 def set_ether_type(self, aValue):
739 "Set ethernet data type field to 'aValue'"
740 self.set_word(14, aValue)
742 def get_ether_type(self):
743 "Return ethernet data type field"
744 return self.get_word(14)
746 def get_header_size(self):
747 "Return size of packet header"
748 return 16
750 def get_packet(self):
751 if self.child():
752 self.set_ether_type(self.child().ethertype)
753 return Header.get_packet(self)
755 def get_type_desc(self):
756 type = self.get_type()
757 if type < len(LinuxSLL.type_descriptions):
758 return LinuxSLL.type_descriptions[type]
759 else:
760 return "Unknown"
762 def __str__(self):
763 ss = []
764 alen = self.get_addr_len()
765 addr = hexlify(self.get_addr()[0:alen])
766 ss.append("Linux SLL: addr=%s type=`%s'" % (addr, self.get_type_desc()))
767 if self.child():
768 ss.append(str(self.child()))
770 return '\n'.join(ss)
773class IP(Header):
774 ethertype = 0x800
775 def __init__(self, aBuffer = None):
776 Header.__init__(self, 20)
777 self.set_ip_v(4)
778 self.set_ip_hl(5)
779 self.set_ip_ttl(255)
780 self.__option_list = []
781 if(aBuffer):
782 # When decoding, checksum shouldn't be modified
783 self.auto_checksum = 0
784 self.load_header(aBuffer)
786 if sys.platform.count('bsd'): 786 ↛ 787line 786 didn't jump to line 787, because the condition on line 786 was never true
787 self.is_BSD = True
788 else:
789 self.is_BSD = False
792 def get_packet(self):
793 # set protocol
794 if self.get_ip_p() == 0 and self.child(): 794 ↛ 795line 794 didn't jump to line 795, because the condition on line 794 was never true
795 self.set_ip_p(self.child().protocol)
797 # set total length
798 if self.get_ip_len() == 0:
799 self.set_ip_len(self.get_size())
801 child_data = self.get_data_as_string()
803 if self.auto_checksum:
804 self.reset_ip_sum()
806 my_bytes = self.get_bytes()
808 for op in self.__option_list: 808 ↛ 809line 808 didn't jump to line 809, because the loop on line 808 never started
809 my_bytes.extend(op.get_bytes())
811 # Pad to a multiple of 4 bytes
812 num_pad = (4 - (len(my_bytes) % 4)) % 4
813 if num_pad: 813 ↛ 814line 813 didn't jump to line 814, because the condition on line 813 was never true
814 array_frombytes(my_bytes, b"\0" * num_pad)
816 # only change ip_hl value if options are present
817 if len(self.__option_list): 817 ↛ 818line 817 didn't jump to line 818, because the condition on line 817 was never true
818 self.set_ip_hl(len(my_bytes) // 4)
821 # set the checksum if the user hasn't modified it
822 if self.auto_checksum:
823 self.set_ip_sum(self.compute_checksum(my_bytes))
825 if child_data is None: 825 ↛ 826line 825 didn't jump to line 826, because the condition on line 825 was never true
826 return array_tobytes(my_bytes)
827 else:
828 return array_tobytes(my_bytes) + child_data
832 # def calculate_checksum(self, buffer = None):
833 # tmp_value = self.get_ip_sum()
834 # if self.auto_checksum and (not tmp_value):
835 # if buffer:
836 # tmp_bytes = buffer
837 # else:
838 # tmp_bytes = self.bytes[0:self.get_header_size()]
839 #
840 # self.set_ip_sum(self.compute_checksum(tmp_bytes))
843 def get_pseudo_header(self):
844 pseudo_buf = array.array("B")
845 pseudo_buf.extend(self.get_bytes()[12:20])
846 pseudo_buf.fromlist([0])
847 pseudo_buf.extend(self.get_bytes()[9:10])
848 tmp_size = self.child().get_size()
850 size_str = struct.pack("!H", tmp_size)
852 array_frombytes(pseudo_buf, size_str)
853 return pseudo_buf
855 def add_option(self, option):
856 self.__option_list.append(option)
857 sum = 0
858 for op in self.__option_list:
859 sum += op.get_len()
860 if sum > 40:
861 raise ImpactPacketException("Options overflowed in IP packet with length: %d" % sum)
864 def get_ip_v(self):
865 n = self.get_byte(0)
866 return (n >> 4)
868 def set_ip_v(self, value):
869 n = self.get_byte(0)
870 version = value & 0xF
871 n = n & 0xF
872 n = n | (version << 4)
873 self.set_byte(0, n)
875 def get_ip_hl(self):
876 n = self.get_byte(0)
877 return (n & 0xF)
879 def set_ip_hl(self, value):
880 n = self.get_byte(0)
881 len = value & 0xF
882 n = n & 0xF0
883 n = (n | len)
884 self.set_byte(0, n)
886 def get_ip_tos(self):
887 return self.get_byte(1)
889 def set_ip_tos(self,value):
890 self.set_byte(1, value)
892 def get_ip_len(self):
893 if self.is_BSD: 893 ↛ 894line 893 didn't jump to line 894, because the condition on line 893 was never true
894 return self.get_word(2, order = '=')
895 else:
896 return self.get_word(2)
898 def set_ip_len(self, value):
899 if self.is_BSD: 899 ↛ 900line 899 didn't jump to line 900, because the condition on line 899 was never true
900 self.set_word(2, value, order = '=')
901 else:
902 self.set_word(2, value)
904 def get_ip_id(self):
905 return self.get_word(4)
906 def set_ip_id(self, value):
907 return self.set_word(4, value)
909 def get_ip_off(self):
910 if self.is_BSD: 910 ↛ 911line 910 didn't jump to line 911, because the condition on line 910 was never true
911 return self.get_word(6, order = '=')
912 else:
913 return self.get_word(6)
915 def set_ip_off(self, aValue):
916 if self.is_BSD: 916 ↛ 917line 916 didn't jump to line 917, because the condition on line 916 was never true
917 self.set_word(6, aValue, order = '=')
918 else:
919 self.set_word(6, aValue)
921 def get_ip_offmask(self):
922 return self.get_ip_off() & 0x1FFF
924 def set_ip_offmask(self, aValue):
925 tmp_value = self.get_ip_off() & 0xD000
926 tmp_value |= aValue
927 self.set_ip_off(tmp_value)
929 def get_ip_rf(self):
930 return self.get_ip_off() & 0x8000
932 def set_ip_rf(self, aValue):
933 tmp_value = self.get_ip_off()
934 if aValue: 934 ↛ 935line 934 didn't jump to line 935, because the condition on line 934 was never true
935 tmp_value |= 0x8000
936 else:
937 my_not = 0xFFFF ^ 0x8000
938 tmp_value &= my_not
939 self.set_ip_off(tmp_value)
941 def get_ip_df(self):
942 return self.get_ip_off() & 0x4000
944 def set_ip_df(self, aValue):
945 tmp_value = self.get_ip_off()
946 if aValue: 946 ↛ 947line 946 didn't jump to line 947, because the condition on line 946 was never true
947 tmp_value |= 0x4000
948 else:
949 my_not = 0xFFFF ^ 0x4000
950 tmp_value &= my_not
951 self.set_ip_off(tmp_value)
953 def get_ip_mf(self):
954 return self.get_ip_off() & 0x2000
956 def set_ip_mf(self, aValue):
957 tmp_value = self.get_ip_off()
958 if aValue: 958 ↛ 959line 958 didn't jump to line 959, because the condition on line 958 was never true
959 tmp_value |= 0x2000
960 else:
961 my_not = 0xFFFF ^ 0x2000
962 tmp_value &= my_not
963 self.set_ip_off(tmp_value)
966 def fragment_by_list(self, aList):
967 if self.child():
968 proto = self.child().protocol
969 else:
970 proto = 0
972 child_data = self.get_data_as_string()
973 if not child_data:
974 return [self]
976 ip_header_bytes = self.get_bytes()
977 current_offset = 0
978 fragment_list = []
980 for frag_size in aList:
981 ip = IP()
982 ip.set_bytes(ip_header_bytes) # copy of original header
983 ip.set_ip_p(proto)
986 if frag_size % 8: # round this fragment size up to next multiple of 8
987 frag_size += 8 - (frag_size % 8)
990 ip.set_ip_offmask(current_offset // 8)
991 current_offset += frag_size
993 data = Data(child_data[:frag_size])
994 child_data = child_data[frag_size:]
996 ip.set_ip_len(20 + data.get_size())
997 ip.contains(data)
1000 if child_data:
1002 ip.set_ip_mf(1)
1004 fragment_list.append(ip)
1005 else: # no more data bytes left to add to fragments
1007 ip.set_ip_mf(0)
1009 fragment_list.append(ip)
1010 return fragment_list
1012 if child_data: # any remaining data?
1013 # create a fragment containing all of the remaining child_data
1014 ip = IP()
1015 ip.set_bytes(ip_header_bytes)
1016 ip.set_ip_offmask(current_offset)
1017 ip.set_ip_len(20 + len(child_data))
1018 data = Data(child_data)
1019 ip.contains(data)
1020 fragment_list.append(ip)
1022 return fragment_list
1025 def fragment_by_size(self, aSize):
1026 data_len = len(self.get_data_as_string())
1027 num_frags = data_len // aSize
1029 if data_len % aSize:
1030 num_frags += 1
1032 size_list = []
1033 for i in range(0, num_frags):
1034 size_list.append(aSize)
1035 return self.fragment_by_list(size_list)
1038 def get_ip_ttl(self):
1039 return self.get_byte(8)
1040 def set_ip_ttl(self, value):
1041 self.set_byte(8, value)
1043 def get_ip_p(self):
1044 return self.get_byte(9)
1046 def set_ip_p(self, value):
1047 self.set_byte(9, value)
1049 def get_ip_sum(self):
1050 return self.get_word(10)
1051 def set_ip_sum(self, value):
1052 self.auto_checksum = 0
1053 self.set_word(10, value)
1055 def reset_ip_sum(self):
1056 self.set_ip_sum(0x0000)
1057 self.auto_checksum = 1
1059 def get_ip_src(self):
1060 return self.get_ip_address(12)
1061 def set_ip_src(self, value):
1062 self.set_ip_address(12, value)
1064 def get_ip_dst(self):
1065 return self.get_ip_address(16)
1067 def set_ip_dst(self, value):
1068 self.set_ip_address(16, value)
1070 def get_header_size(self):
1071 op_len = 0
1072 for op in self.__option_list: 1072 ↛ 1073line 1072 didn't jump to line 1073, because the loop on line 1072 never started
1073 op_len += op.get_len()
1075 num_pad = (4 - (op_len % 4)) % 4
1077 return 20 + op_len + num_pad
1079 def load_header(self, aBuffer):
1080 self.set_bytes_from_string(aBuffer[:20])
1081 opt_left = (self.get_ip_hl() - 5) * 4
1082 opt_bytes = array.array('B', aBuffer[20:(20 + opt_left)])
1083 if len(opt_bytes) != opt_left: 1083 ↛ 1084line 1083 didn't jump to line 1084, because the condition on line 1083 was never true
1084 raise ImpactPacketException("Cannot load options from truncated packet")
1087 while opt_left: 1087 ↛ 1088line 1087 didn't jump to line 1088, because the condition on line 1087 was never true
1088 op_type = opt_bytes[0]
1089 if op_type == IPOption.IPOPT_EOL or op_type == IPOption.IPOPT_NOP:
1090 new_option = IPOption(op_type)
1091 op_len = 1
1092 else:
1093 op_len = opt_bytes[1]
1094 if op_len > len(opt_bytes):
1095 raise ImpactPacketException("IP Option length is too high")
1097 new_option = IPOption(op_type, op_len)
1098 new_option.set_bytes(opt_bytes[:op_len])
1100 opt_bytes = opt_bytes[op_len:]
1101 opt_left -= op_len
1102 self.add_option(new_option)
1103 if op_type == IPOption.IPOPT_EOL:
1104 break
1107 def __str__(self):
1108 flags = ' '
1109 if self.get_ip_df():
1110 flags += 'DF '
1111 if self.get_ip_mf():
1112 flags += 'MF '
1113 if self.get_ip_rf():
1114 flags += 'RF '
1115 tmp_str = 'IP%s%s -> %s ' % (flags, self.get_ip_src(),self.get_ip_dst())
1116 for op in self.__option_list:
1117 tmp_str += '\n' + str(op)
1118 if self.child():
1119 tmp_str += '\n' + str(self.child())
1120 return tmp_str
1123class IPOption(PacketBuffer):
1124 IPOPT_EOL = 0
1125 IPOPT_NOP = 1
1126 IPOPT_RR = 7
1127 IPOPT_TS = 68
1128 IPOPT_LSRR = 131
1129 IPOPT_SSRR = 137
1131 def __init__(self, opcode = 0, size = None):
1132 if size and (size < 3 or size > 40):
1133 raise ImpactPacketException("IP Options must have a size between 3 and 40 bytes")
1135 if(opcode == IPOption.IPOPT_EOL):
1136 PacketBuffer.__init__(self, 1)
1137 self.set_code(IPOption.IPOPT_EOL)
1138 elif(opcode == IPOption.IPOPT_NOP):
1139 PacketBuffer.__init__(self, 1)
1140 self.set_code(IPOption.IPOPT_NOP)
1141 elif(opcode == IPOption.IPOPT_RR):
1142 if not size:
1143 size = 39
1144 PacketBuffer.__init__(self, size)
1145 self.set_code(IPOption.IPOPT_RR)
1146 self.set_len(size)
1147 self.set_ptr(4)
1149 elif(opcode == IPOption.IPOPT_LSRR):
1150 if not size:
1151 size = 39
1152 PacketBuffer.__init__(self, size)
1153 self.set_code(IPOption.IPOPT_LSRR)
1154 self.set_len(size)
1155 self.set_ptr(4)
1157 elif(opcode == IPOption.IPOPT_SSRR):
1158 if not size:
1159 size = 39
1160 PacketBuffer.__init__(self, size)
1161 self.set_code(IPOption.IPOPT_SSRR)
1162 self.set_len(size)
1163 self.set_ptr(4)
1165 elif(opcode == IPOption.IPOPT_TS):
1166 if not size:
1167 size = 40
1168 PacketBuffer.__init__(self, size)
1169 self.set_code(IPOption.IPOPT_TS)
1170 self.set_len(size)
1171 self.set_ptr(5)
1172 self.set_flags(0)
1173 else:
1174 if not size:
1175 raise ImpactPacketException("Size required for this type")
1176 PacketBuffer.__init__(self,size)
1177 self.set_code(opcode)
1178 self.set_len(size)
1181 def append_ip(self, ip):
1182 op = self.get_code()
1183 if not (op == IPOption.IPOPT_RR or op == IPOption.IPOPT_LSRR or op == IPOption.IPOPT_SSRR or op == IPOption.IPOPT_TS):
1184 raise ImpactPacketException("append_ip() not support for option type %d" % self.opt_type)
1186 p = self.get_ptr()
1187 if not p:
1188 raise ImpactPacketException("append_ip() failed, option ptr uninitialized")
1190 if (p + 4) > self.get_len():
1191 raise ImpactPacketException("append_ip() would overflow option")
1193 self.set_ip_address(p - 1, ip)
1194 p += 4
1195 self.set_ptr(p)
1198 def set_code(self, value):
1199 self.set_byte(0, value)
1201 def get_code(self):
1202 return self.get_byte(0)
1205 def set_flags(self, flags):
1206 if not (self.get_code() == IPOption.IPOPT_TS):
1207 raise ImpactPacketException("Operation only supported on Timestamp option")
1208 self.set_byte(3, flags)
1210 def get_flags(self, flags):
1211 if not (self.get_code() == IPOption.IPOPT_TS):
1212 raise ImpactPacketException("Operation only supported on Timestamp option")
1213 return self.get_byte(3)
1216 def set_len(self, len):
1217 self.set_byte(1, len)
1220 def set_ptr(self, ptr):
1221 self.set_byte(2, ptr)
1223 def get_ptr(self):
1224 return self.get_byte(2)
1226 def get_len(self):
1227 return len(self.get_bytes())
1230 def __str__(self):
1231 map = {IPOption.IPOPT_EOL : "End of List ",
1232 IPOption.IPOPT_NOP : "No Operation ",
1233 IPOption.IPOPT_RR : "Record Route ",
1234 IPOption.IPOPT_TS : "Timestamp ",
1235 IPOption.IPOPT_LSRR : "Loose Source Route ",
1236 IPOption.IPOPT_SSRR : "Strict Source Route "}
1238 tmp_str = "\tIP Option: "
1239 op = self.get_code()
1240 if op in map:
1241 tmp_str += map[op]
1242 else:
1243 tmp_str += "Code: %d " % op
1245 if op == IPOption.IPOPT_RR or op == IPOption.IPOPT_LSRR or op ==IPOption.IPOPT_SSRR:
1246 tmp_str += self.print_addresses()
1249 return tmp_str
1252 def print_addresses(self):
1253 p = 3
1254 tmp_str = "["
1255 if self.get_len() >= 7: # at least one complete IP address
1256 while 1:
1257 if p + 1 == self.get_ptr():
1258 tmp_str += "#"
1259 tmp_str += self.get_ip_address(p)
1260 p += 4
1261 if p >= self.get_len():
1262 break
1263 else:
1264 tmp_str += ", "
1265 tmp_str += "] "
1266 if self.get_ptr() % 4: # ptr field should be a multiple of 4
1267 tmp_str += "nonsense ptr field: %d " % self.get_ptr()
1268 return tmp_str
1271class UDP(Header):
1272 protocol = 17
1273 def __init__(self, aBuffer = None):
1274 Header.__init__(self, 8)
1275 if(aBuffer): 1275 ↛ 1276line 1275 didn't jump to line 1276, because the condition on line 1275 was never true
1276 self.load_header(aBuffer)
1278 def get_uh_sport(self):
1279 return self.get_word(0)
1280 def set_uh_sport(self, value):
1281 self.set_word(0, value)
1283 def get_uh_dport(self):
1284 return self.get_word(2)
1285 def set_uh_dport(self, value):
1286 self.set_word(2, value)
1288 def get_uh_ulen(self):
1289 return self.get_word(4)
1291 def set_uh_ulen(self, value):
1292 self.set_word(4, value)
1294 def get_uh_sum(self):
1295 return self.get_word(6)
1297 def set_uh_sum(self, value):
1298 self.set_word(6, value)
1299 self.auto_checksum = 0
1301 def calculate_checksum(self):
1302 if self.auto_checksum and (not self.get_uh_sum()):
1303 # if there isn't a parent to grab a pseudo-header from we'll assume the user knows what they're doing
1304 # and won't meddle with the checksum or throw an exception
1305 if not self.parent():
1306 return
1308 buffer = self.parent().get_pseudo_header()
1310 buffer += self.get_bytes()
1311 data = self.get_data_as_string()
1312 if(data):
1313 array_frombytes(buffer, data)
1314 self.set_uh_sum(self.compute_checksum(buffer))
1316 def get_header_size(self):
1317 return 8
1319 def __str__(self):
1320 tmp_str = 'UDP %d -> %d' % (self.get_uh_sport(), self.get_uh_dport())
1321 if self.child():
1322 tmp_str += '\n' + str(self.child())
1323 return tmp_str
1325 def get_packet(self):
1326 # set total length
1327 if(self.get_uh_ulen() == 0):
1328 self.set_uh_ulen(self.get_size())
1329 return Header.get_packet(self)
1331class TCP(Header):
1332 protocol = 6
1333 TCP_FLAGS_MASK = 0x00FF # lowest 16 bits are the flags
1334 def __init__(self, aBuffer = None):
1335 Header.__init__(self, 20)
1336 self.set_th_off(5)
1337 self.__option_list = []
1338 if aBuffer: 1338 ↛ exitline 1338 didn't return from function '__init__', because the condition on line 1338 was never false
1339 self.load_header(aBuffer)
1341 def add_option(self, option):
1342 self.__option_list.append(option)
1344 sum = 0
1345 for op in self.__option_list:
1346 sum += op.get_size()
1348 if sum > 40: 1348 ↛ 1349line 1348 didn't jump to line 1349, because the condition on line 1348 was never true
1349 raise ImpactPacketException("Cannot add TCP option, would overflow option space")
1351 def get_options(self):
1352 return self.__option_list
1354 def swapSourceAndDestination(self):
1355 oldSource = self.get_th_sport()
1356 self.set_th_sport(self.get_th_dport())
1357 self.set_th_dport(oldSource)
1359 #
1360 # Header field accessors
1361 #
1363 def set_th_sport(self, aValue):
1364 self.set_word(0, aValue)
1366 def get_th_sport(self):
1367 return self.get_word(0)
1369 def get_th_dport(self):
1370 return self.get_word(2)
1372 def set_th_dport(self, aValue):
1373 self.set_word(2, aValue)
1375 def get_th_seq(self):
1376 return self.get_long(4)
1378 def set_th_seq(self, aValue):
1379 self.set_long(4, aValue)
1381 def get_th_ack(self):
1382 return self.get_long(8)
1384 def set_th_ack(self, aValue):
1385 self.set_long(8, aValue)
1387 def get_th_flags(self):
1388 return self.get_word(12) & self.TCP_FLAGS_MASK
1390 def set_th_flags(self, aValue):
1391 masked = self.get_word(12) & (~self.TCP_FLAGS_MASK)
1392 nb = masked | (aValue & self.TCP_FLAGS_MASK)
1393 return self.set_word(12, nb, ">")
1395 def get_th_win(self):
1396 return self.get_word(14)
1398 def set_th_win(self, aValue):
1399 self.set_word(14, aValue)
1401 def set_th_sum(self, aValue):
1402 self.set_word(16, aValue)
1403 self.auto_checksum = 0
1405 def get_th_sum(self):
1406 return self.get_word(16)
1408 def get_th_urp(self):
1409 return self.get_word(18)
1411 def set_th_urp(self, aValue):
1412 return self.set_word(18, aValue)
1414 # Flag accessors
1416 def get_th_reserved(self):
1417 tmp_value = self.get_byte(12) & 0x0f
1418 return tmp_value
1421 def get_th_off(self):
1422 tmp_value = self.get_byte(12) >> 4
1423 return tmp_value
1425 def set_th_off(self, aValue):
1426 mask = 0xF0
1427 masked = self.get_byte(12) & (~mask)
1428 nb = masked | ( (aValue << 4) & mask)
1429 return self.set_byte(12, nb)
1431 def get_CWR(self):
1432 return self.get_flag(128)
1433 def set_CWR(self):
1434 return self.set_flags(128)
1435 def reset_CWR(self):
1436 return self.reset_flags(128)
1438 def get_ECE(self):
1439 return self.get_flag(64)
1440 def set_ECE(self):
1441 return self.set_flags(64)
1442 def reset_ECE(self):
1443 return self.reset_flags(64)
1445 def get_URG(self):
1446 return self.get_flag(32)
1447 def set_URG(self):
1448 return self.set_flags(32)
1449 def reset_URG(self):
1450 return self.reset_flags(32)
1452 def get_ACK(self):
1453 return self.get_flag(16)
1454 def set_ACK(self):
1455 return self.set_flags(16)
1456 def reset_ACK(self):
1457 return self.reset_flags(16)
1459 def get_PSH(self):
1460 return self.get_flag(8)
1461 def set_PSH(self):
1462 return self.set_flags(8)
1463 def reset_PSH(self):
1464 return self.reset_flags(8)
1466 def get_RST(self):
1467 return self.get_flag(4)
1468 def set_RST(self):
1469 return self.set_flags(4)
1470 def reset_RST(self):
1471 return self.reset_flags(4)
1473 def get_SYN(self):
1474 return self.get_flag(2)
1475 def set_SYN(self):
1476 return self.set_flags(2)
1477 def reset_SYN(self):
1478 return self.reset_flags(2)
1480 def get_FIN(self):
1481 return self.get_flag(1)
1482 def set_FIN(self):
1483 return self.set_flags(1)
1484 def reset_FIN(self):
1485 return self.reset_flags(1)
1487 # Overridden Methods
1489 def get_header_size(self):
1490 return 20 + len(self.get_padded_options())
1492 def calculate_checksum(self):
1493 if not self.auto_checksum or not self.parent(): 1493 ↛ 1496line 1493 didn't jump to line 1496, because the condition on line 1493 was never false
1494 return
1496 self.set_th_sum(0)
1497 buffer = self.parent().get_pseudo_header()
1498 buffer += self.get_bytes()
1499 buffer += self.get_padded_options()
1501 data = self.get_data_as_string()
1502 if(data):
1503 array_frombytes(buffer, data)
1505 res = self.compute_checksum(buffer)
1507 self.set_th_sum(self.compute_checksum(buffer))
1509 def get_packet(self):
1510 "Returns entire packet including child data as a string. This is the function used to extract the final packet"
1512 # only change th_off value if options are present
1513 if len(self.__option_list): 1513 ↛ 1516line 1513 didn't jump to line 1516, because the condition on line 1513 was never false
1514 self.set_th_off(self.get_header_size() // 4)
1516 self.calculate_checksum()
1518 bytes = self.get_bytes() + self.get_padded_options()
1519 data = self.get_data_as_string()
1521 if data: 1521 ↛ 1522line 1521 didn't jump to line 1522, because the condition on line 1521 was never true
1522 return array_tobytes(bytes) + data
1523 else:
1524 return array_tobytes(bytes)
1526 def load_header(self, aBuffer):
1527 self.set_bytes_from_string(aBuffer[:20])
1528 opt_left = (self.get_th_off() - 5) * 4
1529 opt_bytes = array.array('B', aBuffer[20:(20 + opt_left)])
1530 if len(opt_bytes) != opt_left: 1530 ↛ 1531line 1530 didn't jump to line 1531, because the condition on line 1530 was never true
1531 raise ImpactPacketException("Cannot load options from truncated packet")
1533 while opt_left:
1534 op_kind = opt_bytes[0]
1535 if op_kind == TCPOption.TCPOPT_EOL or op_kind == TCPOption.TCPOPT_NOP:
1536 new_option = TCPOption(op_kind)
1537 op_len = 1
1538 else:
1539 op_len = opt_bytes[1]
1540 if op_len > len(opt_bytes): 1540 ↛ 1541line 1540 didn't jump to line 1541, because the condition on line 1540 was never true
1541 raise ImpactPacketException("TCP Option length is too high")
1542 if op_len < 2: 1542 ↛ 1543line 1542 didn't jump to line 1543, because the condition on line 1542 was never true
1543 raise ImpactPacketException("TCP Option length is too low")
1545 new_option = TCPOption(op_kind)
1546 new_option.set_bytes(opt_bytes[:op_len])
1548 opt_bytes = opt_bytes[op_len:]
1549 opt_left -= op_len
1550 self.add_option(new_option)
1551 if op_kind == TCPOption.TCPOPT_EOL: 1551 ↛ 1552line 1551 didn't jump to line 1552, because the condition on line 1551 was never true
1552 break
1554 #
1555 # Private
1556 #
1558 def get_flag(self, bit):
1559 if self.get_th_flags() & bit:
1560 return 1
1561 else:
1562 return 0
1564 def reset_flags(self, aValue):
1565 tmp_value = self.get_th_flags() & (~aValue)
1566 return self.set_th_flags(tmp_value)
1568 def set_flags(self, aValue):
1569 tmp_value = self.get_th_flags() | aValue
1570 return self.set_th_flags(tmp_value)
1572 def get_padded_options(self):
1573 "Return an array containing all options padded to a 4 byte boundary"
1574 op_buf = array.array('B')
1575 for op in self.__option_list:
1576 op_buf += op.get_bytes()
1577 num_pad = (4 - (len(op_buf) % 4)) % 4
1578 if num_pad: 1578 ↛ 1579line 1578 didn't jump to line 1579, because the condition on line 1578 was never true
1579 array_frombytes(op_buf, "\0" * num_pad)
1580 return op_buf
1582 def __str__(self):
1583 tmp_str = 'TCP '
1584 if self.get_ECE():
1585 tmp_str += 'ece '
1586 if self.get_CWR():
1587 tmp_str += 'cwr '
1588 if self.get_ACK():
1589 tmp_str += 'ack '
1590 if self.get_FIN():
1591 tmp_str += 'fin '
1592 if self.get_PSH():
1593 tmp_str += 'push '
1594 if self.get_RST():
1595 tmp_str += 'rst '
1596 if self.get_SYN():
1597 tmp_str += 'syn '
1598 if self.get_URG():
1599 tmp_str += 'urg '
1600 tmp_str += '%d -> %d' % (self.get_th_sport(), self.get_th_dport())
1601 for op in self.__option_list:
1602 tmp_str += '\n' + str(op)
1604 if self.child():
1605 tmp_str += '\n' + str(self.child())
1606 return tmp_str
1609class TCPOption(PacketBuffer):
1610 TCPOPT_EOL = 0
1611 TCPOPT_NOP = 1
1612 TCPOPT_MAXSEG = 2
1613 TCPOPT_WINDOW = 3
1614 TCPOPT_SACK_PERMITTED = 4
1615 TCPOPT_SACK = 5
1616 TCPOPT_TIMESTAMP = 8
1617 TCPOPT_SIGNATURE = 19
1620 def __init__(self, kind, data = None):
1622 if kind == TCPOption.TCPOPT_EOL: 1622 ↛ 1623line 1622 didn't jump to line 1623, because the condition on line 1622 was never true
1623 PacketBuffer.__init__(self, 1)
1624 self.set_kind(TCPOption.TCPOPT_EOL)
1625 elif kind == TCPOption.TCPOPT_NOP:
1626 PacketBuffer.__init__(self, 1)
1627 self.set_kind(TCPOption.TCPOPT_NOP)
1628 elif kind == TCPOption.TCPOPT_MAXSEG:
1629 PacketBuffer.__init__(self, 4)
1630 self.set_kind(TCPOption.TCPOPT_MAXSEG)
1631 self.set_len(4)
1632 if data: 1632 ↛ 1633line 1632 didn't jump to line 1633, because the condition on line 1632 was never true
1633 self.set_mss(data)
1634 else:
1635 self.set_mss(512)
1636 elif kind == TCPOption.TCPOPT_WINDOW:
1637 PacketBuffer.__init__(self, 3)
1638 self.set_kind(TCPOption.TCPOPT_WINDOW)
1639 self.set_len(3)
1640 if data: 1640 ↛ 1641line 1640 didn't jump to line 1641, because the condition on line 1640 was never true
1641 self.set_shift_cnt(data)
1642 else:
1643 self.set_shift_cnt(0)
1644 elif kind == TCPOption.TCPOPT_TIMESTAMP:
1645 PacketBuffer.__init__(self, 10)
1646 self.set_kind(TCPOption.TCPOPT_TIMESTAMP)
1647 self.set_len(10)
1648 if data: 1648 ↛ 1649line 1648 didn't jump to line 1649, because the condition on line 1648 was never true
1649 self.set_ts(data)
1650 else:
1651 self.set_ts(0)
1652 elif kind == TCPOption.TCPOPT_SACK_PERMITTED: 1652 ↛ 1657line 1652 didn't jump to line 1657, because the condition on line 1652 was never false
1653 PacketBuffer.__init__(self, 2)
1654 self.set_kind(TCPOption.TCPOPT_SACK_PERMITTED)
1655 self.set_len(2)
1657 elif kind == TCPOption.TCPOPT_SACK:
1658 PacketBuffer.__init__(self, 2)
1659 self.set_kind(TCPOption.TCPOPT_SACK)
1661 def set_left_edge(self, aValue):
1662 self.set_long (2, aValue)
1664 def set_right_edge(self, aValue):
1665 self.set_long (6, aValue)
1667 def set_kind(self, kind):
1668 self.set_byte(0, kind)
1671 def get_kind(self):
1672 return self.get_byte(0)
1675 def set_len(self, len):
1676 if self.get_size() < 2: 1676 ↛ 1677line 1676 didn't jump to line 1677, because the condition on line 1676 was never true
1677 raise ImpactPacketException("Cannot set length field on an option having a size smaller than 2 bytes")
1678 self.set_byte(1, len)
1680 def get_len(self):
1681 if self.get_size() < 2:
1682 raise ImpactPacketException("Cannot retrieve length field from an option having a size smaller than 2 bytes")
1683 return self.get_byte(1)
1685 def get_size(self):
1686 return len(self.get_bytes())
1689 def set_mss(self, len):
1690 if self.get_kind() != TCPOption.TCPOPT_MAXSEG: 1690 ↛ 1691line 1690 didn't jump to line 1691, because the condition on line 1690 was never true
1691 raise ImpactPacketException("Can only set MSS on TCPOPT_MAXSEG option")
1692 self.set_word(2, len)
1694 def get_mss(self):
1695 if self.get_kind() != TCPOption.TCPOPT_MAXSEG:
1696 raise ImpactPacketException("Can only retrieve MSS from TCPOPT_MAXSEG option")
1697 return self.get_word(2)
1699 def set_shift_cnt(self, cnt):
1700 if self.get_kind() != TCPOption.TCPOPT_WINDOW: 1700 ↛ 1701line 1700 didn't jump to line 1701, because the condition on line 1700 was never true
1701 raise ImpactPacketException("Can only set Shift Count on TCPOPT_WINDOW option")
1702 self.set_byte(2, cnt)
1704 def get_shift_cnt(self):
1705 if self.get_kind() != TCPOption.TCPOPT_WINDOW:
1706 raise ImpactPacketException("Can only retrieve Shift Count from TCPOPT_WINDOW option")
1707 return self.get_byte(2)
1709 def get_ts(self):
1710 if self.get_kind() != TCPOption.TCPOPT_TIMESTAMP:
1711 raise ImpactPacketException("Can only retrieve timestamp from TCPOPT_TIMESTAMP option")
1712 return self.get_long(2)
1714 def set_ts(self, ts):
1715 if self.get_kind() != TCPOption.TCPOPT_TIMESTAMP: 1715 ↛ 1716line 1715 didn't jump to line 1716, because the condition on line 1715 was never true
1716 raise ImpactPacketException("Can only set timestamp on TCPOPT_TIMESTAMP option")
1717 self.set_long(2, ts)
1719 def get_ts_echo(self):
1720 if self.get_kind() != TCPOption.TCPOPT_TIMESTAMP:
1721 raise ImpactPacketException("Can only retrieve timestamp from TCPOPT_TIMESTAMP option")
1722 return self.get_long(6)
1724 def set_ts_echo(self, ts):
1725 if self.get_kind() != TCPOption.TCPOPT_TIMESTAMP:
1726 raise ImpactPacketException("Can only set timestamp on TCPOPT_TIMESTAMP option")
1727 self.set_long(6, ts)
1729 def __str__(self):
1730 map = { TCPOption.TCPOPT_EOL : "End of List ",
1731 TCPOption.TCPOPT_NOP : "No Operation ",
1732 TCPOption.TCPOPT_MAXSEG : "Maximum Segment Size ",
1733 TCPOption.TCPOPT_WINDOW : "Window Scale ",
1734 TCPOption.TCPOPT_TIMESTAMP : "Timestamp " }
1736 tmp_str = "\tTCP Option: "
1737 op = self.get_kind()
1738 if op in map:
1739 tmp_str += map[op]
1740 else:
1741 tmp_str += " kind: %d " % op
1742 if op == TCPOption.TCPOPT_MAXSEG:
1743 tmp_str += " MSS : %d " % self.get_mss()
1744 elif op == TCPOption.TCPOPT_WINDOW:
1745 tmp_str += " Shift Count: %d " % self.get_shift_cnt()
1746 elif op == TCPOption.TCPOPT_TIMESTAMP:
1747 pass # TODO
1748 return tmp_str
1750class ICMP(Header):
1751 protocol = 1
1752 ICMP_ECHOREPLY = 0
1753 ICMP_UNREACH = 3
1754 ICMP_UNREACH_NET = 0
1755 ICMP_UNREACH_HOST = 1
1756 ICMP_UNREACH_PROTOCOL = 2
1757 ICMP_UNREACH_PORT = 3
1758 ICMP_UNREACH_NEEDFRAG = 4
1759 ICMP_UNREACH_SRCFAIL = 5
1760 ICMP_UNREACH_NET_UNKNOWN = 6
1761 ICMP_UNREACH_HOST_UNKNOWN = 7
1762 ICMP_UNREACH_ISOLATED = 8
1763 ICMP_UNREACH_NET_PROHIB = 9
1764 ICMP_UNREACH_HOST_PROHIB = 10
1765 ICMP_UNREACH_TOSNET = 11
1766 ICMP_UNREACH_TOSHOST = 12
1767 ICMP_UNREACH_FILTERPROHIB = 13
1768 ICMP_UNREACH_HOST_PRECEDENCE = 14
1769 ICMP_UNREACH_PRECEDENCE_CUTOFF = 15
1770 ICMP_SOURCEQUENCH = 4
1771 ICMP_REDIRECT = 5
1772 ICMP_REDIRECT_NET = 0
1773 ICMP_REDIRECT_HOST = 1
1774 ICMP_REDIRECT_TOSNET = 2
1775 ICMP_REDIRECT_TOSHOST = 3
1776 ICMP_ALTHOSTADDR = 6
1777 ICMP_ECHO = 8
1778 ICMP_ROUTERADVERT = 9
1779 ICMP_ROUTERSOLICIT = 10
1780 ICMP_TIMXCEED = 11
1781 ICMP_TIMXCEED_INTRANS = 0
1782 ICMP_TIMXCEED_REASS = 1
1783 ICMP_PARAMPROB = 12
1784 ICMP_PARAMPROB_ERRATPTR = 0
1785 ICMP_PARAMPROB_OPTABSENT = 1
1786 ICMP_PARAMPROB_LENGTH = 2
1787 ICMP_TSTAMP = 13
1788 ICMP_TSTAMPREPLY = 14
1789 ICMP_IREQ = 15
1790 ICMP_IREQREPLY = 16
1791 ICMP_MASKREQ = 17
1792 ICMP_MASKREPLY = 18
1794 def __init__(self, aBuffer = None):
1795 Header.__init__(self, 8)
1796 if aBuffer:
1797 self.load_header(aBuffer)
1799 def get_header_size(self):
1800 anamolies = { ICMP.ICMP_TSTAMP : 20, ICMP.ICMP_TSTAMPREPLY : 20, ICMP.ICMP_MASKREQ : 12, ICMP.ICMP_MASKREPLY : 12 }
1801 if self.get_icmp_type() in anamolies: 1801 ↛ 1802line 1801 didn't jump to line 1802, because the condition on line 1801 was never true
1802 return anamolies[self.get_icmp_type()]
1803 else:
1804 return 8
1806 def get_icmp_type(self):
1807 return self.get_byte(0)
1809 def set_icmp_type(self, aValue):
1810 self.set_byte(0, aValue)
1812 def get_icmp_code(self):
1813 return self.get_byte(1)
1815 def set_icmp_code(self, aValue):
1816 self.set_byte(1, aValue)
1818 def get_icmp_cksum(self):
1819 return self.get_word(2)
1821 def set_icmp_cksum(self, aValue):
1822 self.set_word(2, aValue)
1823 self.auto_checksum = 0
1825 def get_icmp_gwaddr(self):
1826 return self.get_ip_address(4)
1828 def set_icmp_gwaddr(self, ip):
1829 self.set_ip_address(4, ip)
1831 def get_icmp_id(self):
1832 return self.get_word(4)
1834 def set_icmp_id(self, aValue):
1835 self.set_word(4, aValue)
1837 def get_icmp_seq(self):
1838 return self.get_word(6)
1840 def set_icmp_seq(self, aValue):
1841 self.set_word(6, aValue)
1843 def get_icmp_void(self):
1844 return self.get_long(4)
1846 def set_icmp_void(self, aValue):
1847 self.set_long(4, aValue)
1850 def get_icmp_nextmtu(self):
1851 return self.get_word(6)
1853 def set_icmp_nextmtu(self, aValue):
1854 self.set_word(6, aValue)
1856 def get_icmp_num_addrs(self):
1857 return self.get_byte(4)
1859 def set_icmp_num_addrs(self, aValue):
1860 self.set_byte(4, aValue)
1862 def get_icmp_wpa(self):
1863 return self.get_byte(5)
1865 def set_icmp_wpa(self, aValue):
1866 self.set_byte(5, aValue)
1868 def get_icmp_lifetime(self):
1869 return self.get_word(6)
1871 def set_icmp_lifetime(self, aValue):
1872 self.set_word(6, aValue)
1874 def get_icmp_otime(self):
1875 return self.get_long(8)
1877 def set_icmp_otime(self, aValue):
1878 self.set_long(8, aValue)
1880 def get_icmp_rtime(self):
1881 return self.get_long(12)
1883 def set_icmp_rtime(self, aValue):
1884 self.set_long(12, aValue)
1886 def get_icmp_ttime(self):
1887 return self.get_long(16)
1889 def set_icmp_ttime(self, aValue):
1890 self.set_long(16, aValue)
1892 def get_icmp_mask(self):
1893 return self.get_ip_address(8)
1895 def set_icmp_mask(self, mask):
1896 self.set_ip_address(8, mask)
1899 def calculate_checksum(self):
1900 if self.auto_checksum and (not self.get_icmp_cksum()):
1901 buffer = self.get_buffer_as_string()
1902 data = self.get_data_as_string()
1903 if data: 1903 ↛ 1906line 1903 didn't jump to line 1906, because the condition on line 1903 was never false
1904 buffer += data
1906 tmp_array = array.array('B', buffer)
1907 self.set_icmp_cksum(self.compute_checksum(tmp_array))
1909 def get_type_name(self, aType):
1910 tmp_type = {0:'ECHOREPLY', 3:'UNREACH', 4:'SOURCEQUENCH',5:'REDIRECT', 6:'ALTHOSTADDR', 8:'ECHO', 9:'ROUTERADVERT', 10:'ROUTERSOLICIT', 11:'TIMXCEED', 12:'PARAMPROB', 13:'TSTAMP', 14:'TSTAMPREPLY', 15:'IREQ', 16:'IREQREPLY', 17:'MASKREQ', 18:'MASKREPLY', 30:'TRACEROUTE', 31:'DATACONVERR', 32:'MOBILE REDIRECT', 33:'IPV6 WHEREAREYOU', 34:'IPV6 IAMHERE', 35:'MOBILE REGREQUEST', 36:'MOBILE REGREPLY', 39:'SKIP', 40:'PHOTURIS'}
1911 answer = tmp_type.get(aType, 'UNKNOWN')
1912 return answer
1914 def get_code_name(self, aType, aCode):
1915 tmp_code = {3:['UNREACH NET', 'UNREACH HOST', 'UNREACH PROTOCOL', 'UNREACH PORT', 'UNREACH NEEDFRAG', 'UNREACH SRCFAIL', 'UNREACH NET UNKNOWN', 'UNREACH HOST UNKNOWN', 'UNREACH ISOLATED', 'UNREACH NET PROHIB', 'UNREACH HOST PROHIB', 'UNREACH TOSNET', 'UNREACH TOSHOST', 'UNREACH FILTER PROHIB', 'UNREACH HOST PRECEDENCE', 'UNREACH PRECEDENCE CUTOFF', 'UNKNOWN ICMP UNREACH']}
1916 tmp_code[5] = ['REDIRECT NET', 'REDIRECT HOST', 'REDIRECT TOSNET', 'REDIRECT TOSHOST']
1917 tmp_code[9] = ['ROUTERADVERT NORMAL', None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,'ROUTERADVERT NOROUTE COMMON']
1918 tmp_code[11] = ['TIMXCEED INTRANS ', 'TIMXCEED REASS']
1919 tmp_code[12] = ['PARAMPROB ERRATPTR ', 'PARAMPROB OPTABSENT', 'PARAMPROB LENGTH']
1920 tmp_code[40] = [None, 'PHOTURIS UNKNOWN INDEX', 'PHOTURIS AUTH FAILED', 'PHOTURIS DECRYPT FAILED']
1921 if aType in tmp_code:
1922 tmp_list = tmp_code[aType]
1923 if ((aCode + 1) > len(tmp_list)) or (not tmp_list[aCode]):
1924 return 'UNKNOWN'
1925 else:
1926 return tmp_list[aCode]
1927 else:
1928 return 'UNKNOWN'
1930 def __str__(self):
1931 tmp_type = self.get_icmp_type()
1932 tmp_code = self.get_icmp_code()
1933 tmp_str = 'ICMP type: ' + self.get_type_name(tmp_type)
1934 tmp_str+= ' code: ' + self.get_code_name(tmp_type, tmp_code)
1935 if self.child():
1936 tmp_str += '\n' + str( self.child() )
1937 return tmp_str
1939 def isDestinationUnreachable(self):
1940 return self.get_icmp_type() == 3
1942 def isError(self):
1943 return not self.isQuery()
1945 def isHostUnreachable(self):
1946 return self.isDestinationUnreachable() and (self.get_icmp_code() == 1)
1948 def isNetUnreachable(self):
1949 return self.isDestinationUnreachable() and (self.get_icmp_code() == 0)
1951 def isPortUnreachable(self):
1952 return self.isDestinationUnreachable() and (self.get_icmp_code() == 3)
1954 def isProtocolUnreachable(self):
1955 return self.isDestinationUnreachable() and (self.get_icmp_code() == 2)
1957 def isQuery(self):
1958 tmp_dict = {8:'', 9:'', 10:'', 13:'', 14:'', 15:'', 16:'', 17:'', 18:''}
1959 return self.get_icmp_type() in tmp_dict
1961class IGMP(Header):
1962 protocol = 2
1963 def __init__(self, aBuffer = None):
1964 Header.__init__(self, 8)
1965 if aBuffer:
1966 self.load_header(aBuffer)
1968 def get_igmp_type(self):
1969 return self.get_byte(0)
1971 def set_igmp_type(self, aValue):
1972 self.set_byte(0, aValue)
1974 def get_igmp_code(self):
1975 return self.get_byte(1)
1977 def set_igmp_code(self, aValue):
1978 self.set_byte(1, aValue)
1980 def get_igmp_cksum(self):
1981 return self.get_word(2)
1983 def set_igmp_cksum(self, aValue):
1984 self.set_word(2, aValue)
1986 def get_igmp_group(self):
1987 return self.get_long(4)
1989 def set_igmp_group(self, aValue):
1990 self.set_long(4, aValue)
1992 def get_header_size(self):
1993 return 8
1995 def get_type_name(self, aType):
1996 tmp_dict = {0x11:'HOST MEMBERSHIP QUERY ', 0x12:'v1 HOST MEMBERSHIP REPORT ', 0x13:'IGMP DVMRP ', 0x14:' PIM ', 0x16:'v2 HOST MEMBERSHIP REPORT ', 0x17:'HOST LEAVE MESSAGE ', 0x1e:'MTRACE REPLY ', 0X1f:'MTRACE QUERY '}
1997 answer = tmp_dict.get(aType, 'UNKNOWN TYPE OR VERSION ')
1998 return answer
2000 def calculate_checksum(self):
2001 if self.auto_checksum and (not self.get_igmp_cksum()):
2002 self.set_igmp_cksum(self.compute_checksum(self.get_bytes()))
2004 def __str__(self):
2005 tmp_str = 'IGMP: ' + self.get_type_name(self.get_igmp_type())
2006 tmp_str += 'Group: ' + socket.inet_ntoa(struct.pack('!L',self.get_igmp_group()))
2007 if self.child():
2008 tmp_str += '\n' + str(self.child())
2009 return tmp_str
2013class ARP(Header):
2014 ethertype = 0x806
2015 def __init__(self, aBuffer = None):
2016 Header.__init__(self, 7)
2017 if aBuffer: 2017 ↛ exitline 2017 didn't return from function '__init__', because the condition on line 2017 was never false
2018 self.load_header(aBuffer)
2020 def get_ar_hrd(self):
2021 return self.get_word(0)
2023 def set_ar_hrd(self, aValue):
2024 self.set_word(0, aValue)
2026 def get_ar_pro(self):
2027 return self.get_word(2)
2029 def set_ar_pro(self, aValue):
2030 self.set_word(2, aValue)
2032 def get_ar_hln(self):
2033 return self.get_byte(4)
2035 def set_ar_hln(self, aValue):
2036 self.set_byte(4, aValue)
2038 def get_ar_pln(self):
2039 return self.get_byte(5)
2041 def set_ar_pln(self, aValue):
2042 self.set_byte(5, aValue)
2044 def get_ar_op(self):
2045 return self.get_word(6)
2047 def set_ar_op(self, aValue):
2048 self.set_word(6, aValue)
2050 def get_ar_sha(self):
2051 tmp_size = self.get_ar_hln()
2052 return self.get_bytes().tolist()[8: 8 + tmp_size]
2054 def set_ar_sha(self, aValue):
2055 for i in range(0, self.get_ar_hln()):
2056 self.set_byte(i + 8, aValue[i])
2058 def get_ar_spa(self):
2059 tmp_size = self.get_ar_pln()
2060 return self.get_bytes().tolist()[8 + self.get_ar_hln(): 8 + self.get_ar_hln() + tmp_size]
2062 def set_ar_spa(self, aValue):
2063 for i in range(0, self.get_ar_pln()):
2064 self.set_byte(i + 8 + self.get_ar_hln(), aValue[i])
2066 def get_ar_tha(self):
2067 tmp_size = self.get_ar_hln()
2068 tmp_from = 8 + self.get_ar_hln() + self.get_ar_pln()
2069 return self.get_bytes().tolist()[tmp_from: tmp_from + tmp_size]
2071 def set_ar_tha(self, aValue):
2072 tmp_from = 8 + self.get_ar_hln() + self.get_ar_pln()
2073 for i in range(0, self.get_ar_hln()):
2074 self.set_byte(i + tmp_from, aValue[i])
2076 def get_ar_tpa(self):
2077 tmp_size = self.get_ar_pln()
2078 tmp_from = 8 + ( 2 * self.get_ar_hln()) + self.get_ar_pln()
2079 return self.get_bytes().tolist()[tmp_from: tmp_from + tmp_size]
2081 def set_ar_tpa(self, aValue):
2082 tmp_from = 8 + (2 * self.get_ar_hln()) + self.get_ar_pln()
2083 for i in range(0, self.get_ar_pln()):
2084 self.set_byte(i + tmp_from, aValue[i])
2086 def get_header_size(self):
2087 return 8 + (2 * self.get_ar_hln()) + (2 * self.get_ar_pln())
2089 def get_op_name(self, ar_op):
2090 tmp_dict = {1:'REQUEST', 2:'REPLY', 3:'REVREQUEST', 4:'REVREPLY', 8:'INVREQUEST', 9:'INVREPLY'}
2091 answer = tmp_dict.get(ar_op, 'UNKNOWN')
2092 return answer
2094 def get_hrd_name(self, ar_hrd):
2095 tmp_dict = { 1:'ARPHRD ETHER', 6:'ARPHRD IEEE802', 15:'ARPHRD FRELAY'}
2096 answer = tmp_dict.get(ar_hrd, 'UNKNOWN')
2097 return answer
2100 def as_hrd(self, anArray):
2101 if not anArray:
2102 return ''
2103 tmp_str = '%x' % anArray[0]
2104 for i in range(1, len(anArray)):
2105 tmp_str += ':%x' % anArray[i]
2106 return tmp_str
2108 def as_pro(self, anArray):
2109 if not anArray:
2110 return ''
2111 tmp_str = '%d' % anArray[0]
2112 for i in range(1, len(anArray)):
2113 tmp_str += '.%d' % anArray[i]
2114 return tmp_str
2116 def __str__(self):
2117 tmp_op = self.get_ar_op()
2118 tmp_str = 'ARP format: ' + self.get_hrd_name(self.get_ar_hrd()) + ' '
2119 tmp_str += 'opcode: ' + self.get_op_name(tmp_op)
2120 tmp_str += '\n' + self.as_hrd(self.get_ar_sha()) + ' -> '
2121 tmp_str += self.as_hrd(self.get_ar_tha())
2122 tmp_str += '\n' + self.as_pro(self.get_ar_spa()) + ' -> '
2123 tmp_str += self.as_pro(self.get_ar_tpa())
2124 if self.child():
2125 tmp_str += '\n' + str(self.child())
2126 return tmp_str
2128def example(): #To execute an example, remove this line
2129 a = Ethernet()
2130 b = ARP()
2131 c = Data('Hola loco!!!')
2132 b.set_ar_hln(6)
2133 b.set_ar_pln(4)
2134 #a.set_ip_dst('192.168.22.6')
2135 #a.set_ip_src('1.1.1.2')
2136 a.contains(b)
2137 b.contains(c)
2138 b.set_ar_op(2)
2139 b.set_ar_hrd(1)
2140 b.set_ar_spa((192, 168, 22, 6))
2141 b.set_ar_tpa((192, 168, 66, 171))
2142 a.set_ether_shost((0x0, 0xe0, 0x7d, 0x8a, 0xef, 0x3d))
2143 a.set_ether_dhost((0x0, 0xc0, 0xdf, 0x6, 0x5, 0xe))
2144 print("beto %s" % a)