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# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved.
2#
3# This software is provided under under a slightly modified version
4# of the Apache Software License. See the accompanying LICENSE file
5# for more information.
6#
7# Description:
8# Network packet codecs basic building blocks.
9# Low-level packet codecs for various Internet protocols.
10#
11# Author:
12# Javier Burroni (javier)
13# Bruce Leidl (brl)
14# Javier Kohen (jkohen)
15from __future__ import division
16from __future__ import print_function
17import array
18import struct
19import socket
20import string
21import sys
22from binascii import hexlify
23from functools import reduce
25# Alias function for compatibility with both Python <3.2 `tostring` and `fromstring` methods, and
26# Python >=3.2 `tobytes` and `tostring`
27if sys.version_info[0] >= 3 and sys.version_info[1] >= 2: 27 ↛ 31line 27 didn't jump to line 31, because the condition on line 27 was never false
28 array_tobytes = lambda array_object: array_object.tobytes()
29 array_frombytes = lambda array_object, bytes: array_object.frombytes(bytes)
30else:
31 array_tobytes = lambda array_object: array_object.tostring()
32 array_frombytes = lambda array_object, bytes: array_object.fromstring(bytes)
35"""Classes to build network packets programmatically.
37Each protocol layer is represented by an object, and these objects are
38hierarchically structured to form a packet. This list is traversable
39in both directions: from parent to child and vice versa.
41All objects can be turned back into a raw buffer ready to be sent over
42the wire (see method get_packet).
43"""
45class ImpactPacketException(Exception):
46 def __init__(self, value):
47 self.value = value
48 def __str__(self):
49 return repr(self.value)
51class PacketBuffer(object):
52 """Implement the basic operations utilized to operate on a
53 packet's raw buffer. All the packet classes derive from this one.
55 The byte, word, long and ip_address getters and setters accept
56 negative indexes, having these the a similar effect as in a
57 regular Python sequence slice.
58 """
60 def __init__(self, length = None):
61 "If 'length' is specified the buffer is created with an initial size"
62 if length:
63 self.__bytes = array.array('B', b'\0' * length)
64 else:
65 self.__bytes = array.array('B')
67 def set_bytes_from_string(self, data):
68 "Sets the value of the packet buffer from the string 'data'"
69 self.__bytes = array.array('B', data)
71 def get_buffer_as_string(self):
72 "Returns the packet buffer as a string object"
73 return array_tobytes(self.__bytes)
75 def get_bytes(self):
76 "Returns the packet buffer as an array"
77 return self.__bytes
79 def set_bytes(self, bytes):
80 "Set the packet buffer from an array"
81 # Make a copy to be safe
82 self.__bytes = array.array('B', bytes.tolist())
84 def set_byte(self, index, value):
85 "Set byte at 'index' to 'value'"
86 index = self.__validate_index(index, 1)
87 self.__bytes[index] = value
89 def get_byte(self, index):
90 "Return byte at 'index'"
91 index = self.__validate_index(index, 1)
92 return self.__bytes[index]
94 def set_word(self, index, value, order = '!'):
95 "Set 2-byte word at 'index' to 'value'. See struct module's documentation to understand the meaning of 'order'."
96 index = self.__validate_index(index, 2)
97 ary = array.array("B", struct.pack(order + 'H', value))
98 if -2 == index: 98 ↛ 99line 98 didn't jump to line 99, because the condition on line 98 was never true
99 self.__bytes[index:] = ary
100 else:
101 self.__bytes[index:index+2] = ary
103 def get_word(self, index, order = '!'):
104 "Return 2-byte word at 'index'. See struct module's documentation to understand the meaning of 'order'."
105 index = self.__validate_index(index, 2)
106 if -2 == index: 106 ↛ 107line 106 didn't jump to line 107, because the condition on line 106 was never true
107 bytes = self.__bytes[index:]
108 else:
109 bytes = self.__bytes[index:index+2]
110 (value,) = struct.unpack(order + 'H', array_tobytes(bytes))
111 return value
113 def set_long(self, index, value, order = '!'):
114 "Set 4-byte 'value' at 'index'. See struct module's documentation to understand the meaning of 'order'."
115 index = self.__validate_index(index, 4)
116 ary = array.array("B", struct.pack(order + 'L', value))
117 if -4 == index:
118 self.__bytes[index:] = ary
119 else:
120 self.__bytes[index:index+4] = ary
122 def get_long(self, index, order = '!'):
123 "Return 4-byte value at 'index'. See struct module's documentation to understand the meaning of 'order'."
124 index = self.__validate_index(index, 4)
125 if -4 == index:
126 bytes = self.__bytes[index:]
127 else:
128 bytes = self.__bytes[index:index+4]
129 (value,) = struct.unpack(order + 'L', array_tobytes(bytes))
130 return value
132 def set_long_long(self, index, value, order = '!'):
133 "Set 8-byte 'value' at 'index'. See struct module's documentation to understand the meaning of 'order'."
134 index = self.__validate_index(index, 8)
135 ary = array.array("B", struct.pack(order + 'Q', value))
136 if -8 == index: 136 ↛ 137line 136 didn't jump to line 137, because the condition on line 136 was never true
137 self.__bytes[index:] = ary
138 else:
139 self.__bytes[index:index+8] = ary
141 def get_long_long(self, index, order = '!'):
142 "Return 8-byte value at 'index'. See struct module's documentation to understand the meaning of 'order'."
143 index = self.__validate_index(index, 8)
144 if -8 == index: 144 ↛ 145line 144 didn't jump to line 145, because the condition on line 144 was never true
145 bytes = self.__bytes[index:]
146 else:
147 bytes = self.__bytes[index:index+8]
148 (value,) = struct.unpack(order + 'Q', array_tobytes(bytes))
149 return value
152 def get_ip_address(self, index):
153 "Return 4-byte value at 'index' as an IP string"
154 index = self.__validate_index(index, 4)
155 if -4 == index: 155 ↛ 156line 155 didn't jump to line 156, because the condition on line 155 was never true
156 bytes = self.__bytes[index:]
157 else:
158 bytes = self.__bytes[index:index+4]
159 return socket.inet_ntoa(array_tobytes(bytes))
161 def set_ip_address(self, index, ip_string):
162 "Set 4-byte value at 'index' from 'ip_string'"
163 index = self.__validate_index(index, 4)
164 raw = socket.inet_aton(ip_string)
165 (b1,b2,b3,b4) = struct.unpack("BBBB", raw)
166 self.set_byte(index, b1)
167 self.set_byte(index + 1, b2)
168 self.set_byte(index + 2, b3)
169 self.set_byte(index + 3, b4)
171 def set_checksum_from_data(self, index, data):
172 "Set 16-bit checksum at 'index' by calculating checksum of 'data'"
173 self.set_word(index, self.compute_checksum(data))
175 def compute_checksum(self, anArray):
176 "Return the one's complement of the one's complement sum of all the 16-bit words in 'anArray'"
177 nleft = len(anArray)
178 sum = 0
179 pos = 0
180 while nleft > 1:
181 sum = anArray[pos] * 256 + (anArray[pos + 1] + sum)
182 pos = pos + 2
183 nleft = nleft - 2
184 if nleft == 1:
185 sum = sum + anArray[pos] * 256
186 return self.normalize_checksum(sum)
188 def normalize_checksum(self, aValue):
189 sum = aValue
190 sum = (sum >> 16) + (sum & 0xFFFF)
191 sum += (sum >> 16)
192 sum = (~sum & 0xFFFF)
193 return sum
195 def __validate_index(self, index, size):
196 """This method performs two tasks: to allocate enough space to
197 fit the elements at positions index through index+size, and to
198 adjust negative indexes to their absolute equivalent.
199 """
201 orig_index = index
203 curlen = len(self.__bytes)
204 if index < 0:
205 index = curlen + index
207 diff = index + size - curlen
208 if diff > 0:
209 array_frombytes(self.__bytes, b'\0' * diff)
210 if orig_index < 0: 210 ↛ 211line 210 didn't jump to line 211, because the condition on line 210 was never true
211 orig_index -= diff
213 return orig_index
215class ProtocolLayer():
216 "Protocol Layer Manager for insertion and removal of protocol layers."
218 __child = None
219 __parent = None
221 def contains(self, aHeader):
222 "Set 'aHeader' as the child of this protocol layer"
223 self.__child = aHeader
224 aHeader.set_parent(self)
226 def set_parent(self, my_parent):
227 "Set the header 'my_parent' as the parent of this protocol layer"
228 self.__parent = my_parent
230 def child(self):
231 "Return the child of this protocol layer"
232 return self.__child
234 def parent(self):
235 "Return the parent of this protocol layer"
236 return self.__parent
238 def unlink_child(self):
239 "Break the hierarchy parent/child child/parent"
240 if self.__child:
241 self.__child.set_parent(None)
242 self.__child = None
244class ProtocolPacket(ProtocolLayer):
245 __HEADER_SIZE = 0
246 __BODY_SIZE = 0
247 __TAIL_SIZE = 0
249 __header = None
250 __body = None
251 __tail = None
253 def __init__(self, header_size, tail_size):
254 self.__HEADER_SIZE = header_size
255 self.__TAIL_SIZE = tail_size
256 self.__header=PacketBuffer(self.__HEADER_SIZE)
257 self.__body=PacketBuffer()
258 self.__tail=PacketBuffer(self.__TAIL_SIZE)
260 def __update_body_from_child(self):
261 # Update child raw packet in my body
262 if self.child():
263 body=self.child().get_packet()
264 self.__BODY_SIZE=len(body)
265 self.__body.set_bytes_from_string(body)
267 def __get_header(self):
268 return self.__header
270 header = property(__get_header)
272 def __get_body(self):
273 self.__update_body_from_child()
274 return self.__body
276 body = property(__get_body)
278 def __get_tail(self):
279 return self.__tail
281 tail = property(__get_tail)
283 def get_header_size(self):
284 "Return frame header size"
285 return self.__HEADER_SIZE
287 def get_tail_size(self):
288 "Return frame tail size"
289 return self.__TAIL_SIZE
291 def get_body_size(self):
292 "Return frame body size"
293 self.__update_body_from_child()
294 return self.__BODY_SIZE
296 def get_size(self):
297 "Return frame total size"
298 return self.get_header_size()+self.get_body_size()+self.get_tail_size()
300 def load_header(self, aBuffer):
301 self.__HEADER_SIZE=len(aBuffer)
302 self.__header.set_bytes_from_string(aBuffer)
304 def load_body(self, aBuffer):
305 "Load the packet body from string. "\
306 "WARNING: Using this function will break the hierarchy of preceding protocol layer"
307 self.unlink_child()
308 self.__BODY_SIZE=len(aBuffer)
309 self.__body.set_bytes_from_string(aBuffer)
311 def load_tail(self, aBuffer):
312 self.__TAIL_SIZE=len(aBuffer)
313 self.__tail.set_bytes_from_string(aBuffer)
315 def __extract_header(self, aBuffer):
316 self.load_header(aBuffer[:self.__HEADER_SIZE])
318 def __extract_body(self, aBuffer):
319 if self.__TAIL_SIZE<=0:
320 end=None
321 else:
322 end=-self.__TAIL_SIZE
323 self.__BODY_SIZE=len(aBuffer[self.__HEADER_SIZE:end])
324 self.__body.set_bytes_from_string(aBuffer[self.__HEADER_SIZE:end])
326 def __extract_tail(self, aBuffer):
327 if self.__TAIL_SIZE<=0:
328 # leave the array empty
329 return
330 else:
331 start=-self.__TAIL_SIZE
332 self.__tail.set_bytes_from_string(aBuffer[start:])
334 def load_packet(self, aBuffer):
335 "Load the whole packet from a string" \
336 "WARNING: Using this function will break the hierarchy of preceding protocol layer"
337 self.unlink_child()
339 self.__extract_header(aBuffer)
340 self.__extract_body(aBuffer)
341 self.__extract_tail(aBuffer)
343 def get_header_as_string(self):
344 return self.__header.get_buffer_as_string()
346 def get_body_as_string(self):
347 self.__update_body_from_child()
348 return self.__body.get_buffer_as_string()
349 body_string = property(get_body_as_string)
351 def get_tail_as_string(self):
352 return self.__tail.get_buffer_as_string()
353 tail_string = property(get_tail_as_string)
355 def get_packet(self):
356 self.__update_body_from_child()
358 ret = b''
360 header = self.get_header_as_string()
361 if header:
362 ret += header
364 body = self.get_body_as_string()
365 if body:
366 ret += body
368 tail = self.get_tail_as_string()
369 if tail:
370 ret += tail
372 return ret
374class Header(PacketBuffer,ProtocolLayer):
375 "This is the base class from which all protocol definitions extend."
377 packet_printable = [c for c in string.printable if c not in string.whitespace] + [' ']
379 ethertype = None
380 protocol = None
381 def __init__(self, length = None):
382 PacketBuffer.__init__(self, length)
383 self.auto_checksum = 1
385 def get_data_as_string(self):
386 "Returns all data from children of this header as string"
388 if self.child():
389 return self.child().get_packet()
390 else:
391 return None
393 def get_packet(self):
394 """Returns the raw representation of this packet and its
395 children as a string. The output from this method is a packet
396 ready to be transmitted over the wire.
397 """
398 self.calculate_checksum()
400 data = self.get_data_as_string()
401 if data:
402 return self.get_buffer_as_string() + data
403 else:
404 return self.get_buffer_as_string()
406 def get_size(self):
407 "Return the size of this header and all of it's children"
408 tmp_value = self.get_header_size()
409 if self.child():
410 tmp_value = tmp_value + self.child().get_size()
411 return tmp_value
413 def calculate_checksum(self):
414 "Calculate and set the checksum for this header"
415 pass
417 def get_pseudo_header(self):
418 "Pseudo headers can be used to limit over what content will the checksums be calculated."
419 # default implementation returns empty array
420 return array.array('B')
422 def load_header(self, aBuffer):
423 "Properly set the state of this instance to reflect that of the raw packet passed as argument."
424 self.set_bytes_from_string(aBuffer)
425 hdr_len = self.get_header_size()
426 if(len(aBuffer) < hdr_len): #we must do something like this 426 ↛ 427line 426 didn't jump to line 427, because the condition on line 426 was never true
427 diff = hdr_len - len(aBuffer)
428 for i in range(0, diff):
429 aBuffer += '\x00'
430 self.set_bytes_from_string(aBuffer[:hdr_len])
432 def get_header_size(self):
433 "Return the size of this header, that is, not counting neither the size of the children nor of the parents."
434 raise RuntimeError("Method %s.get_header_size must be overridden." % self.__class__)
436 def list_as_hex(self, aList):
437 if len(aList):
438 ltmp = []
439 line = []
440 count = 0
441 for byte in aList:
442 if not (count % 2):
443 if (count % 16):
444 ltmp.append(' ')
445 else:
446 ltmp.append(' '*4)
447 ltmp.append(''.join(line))
448 ltmp.append('\n')
449 line = []
450 if chr(byte) in Header.packet_printable:
451 line.append(chr(byte))
452 else:
453 line.append('.')
454 ltmp.append('%.2x' % byte)
455 count += 1
456 if (count%16):
457 left = 16 - (count%16)
458 ltmp.append(' ' * (4+(left // 2) + (left*2)))
459 ltmp.append(''.join(line))
460 ltmp.append('\n')
461 return ltmp
462 else:
463 return []
465 def __str__(self):
466 ltmp = self.list_as_hex(self.get_bytes().tolist())
468 if self.child():
469 ltmp.append(['\n', str(self.child())])
471 if len(ltmp)>0:
472 return ''.join(ltmp)
473 else:
474 return ''
478class Data(Header):
479 """This packet type can hold raw data. It's normally employed to
480 hold a packet's innermost layer's contents in those cases for
481 which the protocol details are unknown, and there's a copy of a
482 valid packet available.
484 For instance, if all that's known about a certain protocol is that
485 a UDP packet with its contents set to "HELLO" initiate a new
486 session, creating such packet is as simple as in the following code
487 fragment:
488 packet = UDP()
489 packet.contains('HELLO')
490 """
492 def __init__(self, aBuffer = None):
493 Header.__init__(self)
494 if aBuffer:
495 self.set_data(aBuffer)
497 def set_data(self, data):
498 self.set_bytes_from_string(data)
500 def get_size(self):
501 return len(self.get_bytes())
504class EthernetTag(PacketBuffer):
505 """Represents a VLAN header specified in IEEE 802.1Q and 802.1ad.
506 Provides methods for convenient manipulation with header fields."""
508 def __init__(self, value=0x81000000):
509 PacketBuffer.__init__(self, 4)
510 self.set_long(0, value)
512 def get_tpid(self):
513 """Returns Tag Protocol Identifier"""
514 return self.get_word(0)
516 def set_tpid(self, value):
517 """Sets Tag Protocol Identifier"""
518 return self.set_word(0, value)
520 def get_pcp(self):
521 """Returns Priority Code Point"""
522 return (self.get_byte(2) & 0xE0) >> 5
524 def set_pcp(self, value):
525 """Sets Priority Code Point"""
526 orig_value = self.get_byte(2)
527 self.set_byte(2, (orig_value & 0x1F) | ((value & 0x07) << 5))
529 def get_dei(self):
530 """Returns Drop Eligible Indicator"""
531 return (self.get_byte(2) & 0x10) >> 4
533 def set_dei(self, value):
534 """Sets Drop Eligible Indicator"""
535 orig_value = self.get_byte(2)
536 self.set_byte(2, orig_value | 0x10 if value else orig_value & 0xEF)
538 def get_vid(self):
539 """Returns VLAN Identifier"""
540 return self.get_word(2) & 0x0FFF
542 def set_vid(self, value):
543 """Sets VLAN Identifier"""
544 orig_value = self.get_word(2)
545 self.set_word(2, (orig_value & 0xF000) | (value & 0x0FFF))
547 def __str__(self):
548 priorities = (
549 'Best Effort',
550 'Background',
551 'Excellent Effort',
552 'Critical Applications',
553 'Video, < 100 ms latency and jitter',
554 'Voice, < 10 ms latency and jitter',
555 'Internetwork Control',
556 'Network Control')
558 pcp = self.get_pcp()
559 return '\n'.join((
560 '802.1Q header: 0x{0:08X}'.format(self.get_long(0)),
561 'Priority Code Point: {0} ({1})'.format(pcp, priorities[pcp]),
562 'Drop Eligible Indicator: {0}'.format(self.get_dei()),
563 'VLAN Identifier: {0}'.format(self.get_vid())))
566class Ethernet(Header):
567 def __init__(self, aBuffer = None):
568 Header.__init__(self, 14)
569 self.tag_cnt = 0
570 if(aBuffer): 570 ↛ exitline 570 didn't return from function '__init__', because the condition on line 570 was never false
571 self.load_header(aBuffer)
573 def set_ether_type(self, aValue):
574 "Set ethernet data type field to 'aValue'"
575 self.set_word(12 + 4*self.tag_cnt, aValue)
577 def get_ether_type(self):
578 "Return ethernet data type field"
579 return self.get_word(12 + 4*self.tag_cnt)
581 def get_tag(self, index):
582 """Returns an EthernetTag initialized from index-th VLAN tag.
583 The tags are numbered from 0 to self.tag_cnt-1 as they appear in the frame.
584 It is possible to use negative indexes as well."""
585 index = self.__validate_tag_index(index)
586 return EthernetTag(self.get_long(12+4*index))
588 def set_tag(self, index, tag):
589 """Sets the index-th VLAN tag to contents of an EthernetTag object.
590 The tags are numbered from 0 to self.tag_cnt-1 as they appear in the frame.
591 It is possible to use negative indexes as well."""
592 index = self.__validate_tag_index(index)
593 pos = 12 + 4*index
594 for i,val in enumerate(tag.get_bytes()):
595 self.set_byte(pos+i, val)
597 def push_tag(self, tag, index=0):
598 """Inserts contents of an EthernetTag object before the index-th VLAN tag.
599 Index defaults to 0 (the top of the stack)."""
600 if index < 0: 600 ↛ 601line 600 didn't jump to line 601, because the condition on line 600 was never true
601 index += self.tag_cnt
602 pos = 12 + 4*max(0, min(index, self.tag_cnt))
603 data = self.get_bytes()
604 data[pos:pos] = tag.get_bytes()
605 self.set_bytes(data)
606 self.tag_cnt += 1
608 def pop_tag(self, index=0):
609 """Removes the index-th VLAN tag and returns it as an EthernetTag object.
610 Index defaults to 0 (the top of the stack)."""
611 index = self.__validate_tag_index(index)
612 pos = 12 + 4*index
613 tag = self.get_long(pos)
614 data = self.get_bytes()
615 del data[pos:pos+4]
616 self.set_bytes(data)
617 self.tag_cnt -= 1
618 return EthernetTag(tag)
620 def load_header(self, aBuffer):
621 self.tag_cnt = 0
622 while aBuffer[12+4*self.tag_cnt:14+4*self.tag_cnt] in (b'\x81\x00', b'\x88\xa8', b'\x91\x00'):
623 self.tag_cnt += 1
625 hdr_len = self.get_header_size()
626 diff = hdr_len - len(aBuffer)
627 if diff > 0: 627 ↛ 628line 627 didn't jump to line 628, because the condition on line 627 was never true
628 aBuffer += b'\x00'*diff
629 self.set_bytes_from_string(aBuffer[:hdr_len])
631 def get_header_size(self):
632 "Return size of Ethernet header"
633 return 14 + 4*self.tag_cnt
635 def get_packet(self):
637 if self.child(): 637 ↛ 638line 637 didn't jump to line 638, because the condition on line 637 was never true
638 try:
639 self.set_ether_type(self.child().ethertype)
640 except:
641 " an Ethernet packet may have a Data() "
642 pass
643 return Header.get_packet(self)
645 def get_ether_dhost(self):
646 "Return 48 bit destination ethernet address as a 6 byte array"
647 return self.get_bytes()[0:6]
649 def set_ether_dhost(self, aValue):
650 "Set destination ethernet address from 6 byte array 'aValue'"
651 for i in range(0, 6):
652 self.set_byte(i, aValue[i])
654 def get_ether_shost(self):
655 "Return 48 bit source ethernet address as a 6 byte array"
656 return self.get_bytes()[6:12]
658 def set_ether_shost(self, aValue):
659 "Set source ethernet address from 6 byte array 'aValue'"
660 for i in range(0, 6):
661 self.set_byte(i + 6, aValue[i])
663 @staticmethod
664 def as_eth_addr(anArray):
665 tmp_list = [x > 15 and '%x'%x or '0%x'%x for x in anArray]
666 return '' + reduce(lambda x, y: x+':'+y, tmp_list)
668 def __str__(self):
669 tmp_str = 'Ether: ' + self.as_eth_addr(self.get_ether_shost()) + ' -> '
670 tmp_str += self.as_eth_addr(self.get_ether_dhost())
671 if self.child():
672 tmp_str += '\n' + str( self.child())
673 return tmp_str
675 def __validate_tag_index(self, index):
676 """Adjusts negative indices to their absolute equivalents.
677 Raises IndexError when out of range <0, self.tag_cnt-1>."""
678 if index < 0:
679 index += self.tag_cnt
680 if index < 0 or index >= self.tag_cnt:
681 raise IndexError("Tag index out of range")
682 return index
684# Linux "cooked" capture encapsulation.
685# Used, for instance, for packets returned by the "any" interface.
686class LinuxSLL(Header):
687 type_descriptions = [
688 "sent to us by somebody else",
689 "broadcast by somebody else",
690 "multicast by somebody else",
691 "sent to somebody else to somebody else",
692 "sent by us",
693 ]
695 def __init__(self, aBuffer = None):
696 Header.__init__(self, 16)
697 if (aBuffer):
698 self.load_header(aBuffer)
700 def set_type(self, type):
701 "Sets the packet type field to type"
702 self.set_word(0, type)
704 def get_type(self):
705 "Returns the packet type field"
706 return self.get_word(0)
708 def set_arphdr(self, value):
709 "Sets the ARPHDR value for the link layer device type"
710 self.set_word(2, type)
712 def get_arphdr(self):
713 "Returns the ARPHDR value for the link layer device type"
714 return self.get_word(2)
716 def set_addr_len(self, len):
717 "Sets the length of the sender's address field to len"
718 self.set_word(4, len)
720 def get_addr_len(self):
721 "Returns the length of the sender's address field"
722 return self.get_word(4)
724 def set_addr(self, addr):
725 "Sets the sender's address field to addr. Addr must be at most 8-byte long."
726 if (len(addr) < 8):
727 addr += b'\0' * (8 - len(addr))
728 self.get_bytes()[6:14] = addr
730 def get_addr(self):
731 "Returns the sender's address field"
732 return array_tobytes(self.get_bytes()[6:14])
734 def set_ether_type(self, aValue):
735 "Set ethernet data type field to 'aValue'"
736 self.set_word(14, aValue)
738 def get_ether_type(self):
739 "Return ethernet data type field"
740 return self.get_word(14)
742 def get_header_size(self):
743 "Return size of packet header"
744 return 16
746 def get_packet(self):
747 if self.child():
748 self.set_ether_type(self.child().ethertype)
749 return Header.get_packet(self)
751 def get_type_desc(self):
752 type = self.get_type()
753 if type < len(LinuxSLL.type_descriptions):
754 return LinuxSLL.type_descriptions[type]
755 else:
756 return "Unknown"
758 def __str__(self):
759 ss = []
760 alen = self.get_addr_len()
761 addr = hexlify(self.get_addr()[0:alen])
762 ss.append("Linux SLL: addr=%s type=`%s'" % (addr, self.get_type_desc()))
763 if self.child():
764 ss.append(str(self.child()))
766 return '\n'.join(ss)
769class IP(Header):
770 ethertype = 0x800
771 def __init__(self, aBuffer = None):
772 Header.__init__(self, 20)
773 self.set_ip_v(4)
774 self.set_ip_hl(5)
775 self.set_ip_ttl(255)
776 self.__option_list = []
777 if(aBuffer):
778 # When decoding, checksum shouldn't be modified
779 self.auto_checksum = 0
780 self.load_header(aBuffer)
782 if sys.platform.count('bsd'): 782 ↛ 783line 782 didn't jump to line 783, because the condition on line 782 was never true
783 self.is_BSD = True
784 else:
785 self.is_BSD = False
788 def get_packet(self):
789 # set protocol
790 if self.get_ip_p() == 0 and self.child(): 790 ↛ 791line 790 didn't jump to line 791, because the condition on line 790 was never true
791 self.set_ip_p(self.child().protocol)
793 # set total length
794 if self.get_ip_len() == 0:
795 self.set_ip_len(self.get_size())
797 child_data = self.get_data_as_string()
799 if self.auto_checksum:
800 self.reset_ip_sum()
802 my_bytes = self.get_bytes()
804 for op in self.__option_list: 804 ↛ 805line 804 didn't jump to line 805, because the loop on line 804 never started
805 my_bytes.extend(op.get_bytes())
807 # Pad to a multiple of 4 bytes
808 num_pad = (4 - (len(my_bytes) % 4)) % 4
809 if num_pad: 809 ↛ 810line 809 didn't jump to line 810, because the condition on line 809 was never true
810 array_frombytes(my_bytes, b"\0" * num_pad)
812 # only change ip_hl value if options are present
813 if len(self.__option_list): 813 ↛ 814line 813 didn't jump to line 814, because the condition on line 813 was never true
814 self.set_ip_hl(len(my_bytes) // 4)
817 # set the checksum if the user hasn't modified it
818 if self.auto_checksum:
819 self.set_ip_sum(self.compute_checksum(my_bytes))
821 if child_data is None: 821 ↛ 822line 821 didn't jump to line 822, because the condition on line 821 was never true
822 return array_tobytes(my_bytes)
823 else:
824 return array_tobytes(my_bytes) + child_data
828 # def calculate_checksum(self, buffer = None):
829 # tmp_value = self.get_ip_sum()
830 # if self.auto_checksum and (not tmp_value):
831 # if buffer:
832 # tmp_bytes = buffer
833 # else:
834 # tmp_bytes = self.bytes[0:self.get_header_size()]
835 #
836 # self.set_ip_sum(self.compute_checksum(tmp_bytes))
839 def get_pseudo_header(self):
840 pseudo_buf = array.array("B")
841 pseudo_buf.extend(self.get_bytes()[12:20])
842 pseudo_buf.fromlist([0])
843 pseudo_buf.extend(self.get_bytes()[9:10])
844 tmp_size = self.child().get_size()
846 size_str = struct.pack("!H", tmp_size)
848 array_frombytes(pseudo_buf, size_str)
849 return pseudo_buf
851 def add_option(self, option):
852 self.__option_list.append(option)
853 sum = 0
854 for op in self.__option_list:
855 sum += op.get_len()
856 if sum > 40:
857 raise ImpactPacketException("Options overflowed in IP packet with length: %d" % sum)
860 def get_ip_v(self):
861 n = self.get_byte(0)
862 return (n >> 4)
864 def set_ip_v(self, value):
865 n = self.get_byte(0)
866 version = value & 0xF
867 n = n & 0xF
868 n = n | (version << 4)
869 self.set_byte(0, n)
871 def get_ip_hl(self):
872 n = self.get_byte(0)
873 return (n & 0xF)
875 def set_ip_hl(self, value):
876 n = self.get_byte(0)
877 len = value & 0xF
878 n = n & 0xF0
879 n = (n | len)
880 self.set_byte(0, n)
882 def get_ip_tos(self):
883 return self.get_byte(1)
885 def set_ip_tos(self,value):
886 self.set_byte(1, value)
888 def get_ip_len(self):
889 if self.is_BSD: 889 ↛ 890line 889 didn't jump to line 890, because the condition on line 889 was never true
890 return self.get_word(2, order = '=')
891 else:
892 return self.get_word(2)
894 def set_ip_len(self, value):
895 if self.is_BSD: 895 ↛ 896line 895 didn't jump to line 896, because the condition on line 895 was never true
896 self.set_word(2, value, order = '=')
897 else:
898 self.set_word(2, value)
900 def get_ip_id(self):
901 return self.get_word(4)
902 def set_ip_id(self, value):
903 return self.set_word(4, value)
905 def get_ip_off(self):
906 if self.is_BSD: 906 ↛ 907line 906 didn't jump to line 907, because the condition on line 906 was never true
907 return self.get_word(6, order = '=')
908 else:
909 return self.get_word(6)
911 def set_ip_off(self, aValue):
912 if self.is_BSD: 912 ↛ 913line 912 didn't jump to line 913, because the condition on line 912 was never true
913 self.set_word(6, aValue, order = '=')
914 else:
915 self.set_word(6, aValue)
917 def get_ip_offmask(self):
918 return self.get_ip_off() & 0x1FFF
920 def set_ip_offmask(self, aValue):
921 tmp_value = self.get_ip_off() & 0xD000
922 tmp_value |= aValue
923 self.set_ip_off(tmp_value)
925 def get_ip_rf(self):
926 return self.get_ip_off() & 0x8000
928 def set_ip_rf(self, aValue):
929 tmp_value = self.get_ip_off()
930 if aValue: 930 ↛ 931line 930 didn't jump to line 931, because the condition on line 930 was never true
931 tmp_value |= 0x8000
932 else:
933 my_not = 0xFFFF ^ 0x8000
934 tmp_value &= my_not
935 self.set_ip_off(tmp_value)
937 def get_ip_df(self):
938 return self.get_ip_off() & 0x4000
940 def set_ip_df(self, aValue):
941 tmp_value = self.get_ip_off()
942 if aValue: 942 ↛ 943line 942 didn't jump to line 943, because the condition on line 942 was never true
943 tmp_value |= 0x4000
944 else:
945 my_not = 0xFFFF ^ 0x4000
946 tmp_value &= my_not
947 self.set_ip_off(tmp_value)
949 def get_ip_mf(self):
950 return self.get_ip_off() & 0x2000
952 def set_ip_mf(self, aValue):
953 tmp_value = self.get_ip_off()
954 if aValue: 954 ↛ 955line 954 didn't jump to line 955, because the condition on line 954 was never true
955 tmp_value |= 0x2000
956 else:
957 my_not = 0xFFFF ^ 0x2000
958 tmp_value &= my_not
959 self.set_ip_off(tmp_value)
962 def fragment_by_list(self, aList):
963 if self.child():
964 proto = self.child().protocol
965 else:
966 proto = 0
968 child_data = self.get_data_as_string()
969 if not child_data:
970 return [self]
972 ip_header_bytes = self.get_bytes()
973 current_offset = 0
974 fragment_list = []
976 for frag_size in aList:
977 ip = IP()
978 ip.set_bytes(ip_header_bytes) # copy of original header
979 ip.set_ip_p(proto)
982 if frag_size % 8: # round this fragment size up to next multiple of 8
983 frag_size += 8 - (frag_size % 8)
986 ip.set_ip_offmask(current_offset // 8)
987 current_offset += frag_size
989 data = Data(child_data[:frag_size])
990 child_data = child_data[frag_size:]
992 ip.set_ip_len(20 + data.get_size())
993 ip.contains(data)
996 if child_data:
998 ip.set_ip_mf(1)
1000 fragment_list.append(ip)
1001 else: # no more data bytes left to add to fragments
1003 ip.set_ip_mf(0)
1005 fragment_list.append(ip)
1006 return fragment_list
1008 if child_data: # any remaining data?
1009 # create a fragment containing all of the remaining child_data
1010 ip = IP()
1011 ip.set_bytes(ip_header_bytes)
1012 ip.set_ip_offmask(current_offset)
1013 ip.set_ip_len(20 + len(child_data))
1014 data = Data(child_data)
1015 ip.contains(data)
1016 fragment_list.append(ip)
1018 return fragment_list
1021 def fragment_by_size(self, aSize):
1022 data_len = len(self.get_data_as_string())
1023 num_frags = data_len // aSize
1025 if data_len % aSize:
1026 num_frags += 1
1028 size_list = []
1029 for i in range(0, num_frags):
1030 size_list.append(aSize)
1031 return self.fragment_by_list(size_list)
1034 def get_ip_ttl(self):
1035 return self.get_byte(8)
1036 def set_ip_ttl(self, value):
1037 self.set_byte(8, value)
1039 def get_ip_p(self):
1040 return self.get_byte(9)
1042 def set_ip_p(self, value):
1043 self.set_byte(9, value)
1045 def get_ip_sum(self):
1046 return self.get_word(10)
1047 def set_ip_sum(self, value):
1048 self.auto_checksum = 0
1049 self.set_word(10, value)
1051 def reset_ip_sum(self):
1052 self.set_ip_sum(0x0000)
1053 self.auto_checksum = 1
1055 def get_ip_src(self):
1056 return self.get_ip_address(12)
1057 def set_ip_src(self, value):
1058 self.set_ip_address(12, value)
1060 def get_ip_dst(self):
1061 return self.get_ip_address(16)
1063 def set_ip_dst(self, value):
1064 self.set_ip_address(16, value)
1066 def get_header_size(self):
1067 op_len = 0
1068 for op in self.__option_list: 1068 ↛ 1069line 1068 didn't jump to line 1069, because the loop on line 1068 never started
1069 op_len += op.get_len()
1071 num_pad = (4 - (op_len % 4)) % 4
1073 return 20 + op_len + num_pad
1075 def load_header(self, aBuffer):
1076 self.set_bytes_from_string(aBuffer[:20])
1077 opt_left = (self.get_ip_hl() - 5) * 4
1078 opt_bytes = array.array('B', aBuffer[20:(20 + opt_left)])
1079 if len(opt_bytes) != opt_left: 1079 ↛ 1080line 1079 didn't jump to line 1080, because the condition on line 1079 was never true
1080 raise ImpactPacketException("Cannot load options from truncated packet")
1083 while opt_left: 1083 ↛ 1084line 1083 didn't jump to line 1084, because the condition on line 1083 was never true
1084 op_type = opt_bytes[0]
1085 if op_type == IPOption.IPOPT_EOL or op_type == IPOption.IPOPT_NOP:
1086 new_option = IPOption(op_type)
1087 op_len = 1
1088 else:
1089 op_len = opt_bytes[1]
1090 if op_len > len(opt_bytes):
1091 raise ImpactPacketException("IP Option length is too high")
1093 new_option = IPOption(op_type, op_len)
1094 new_option.set_bytes(opt_bytes[:op_len])
1096 opt_bytes = opt_bytes[op_len:]
1097 opt_left -= op_len
1098 self.add_option(new_option)
1099 if op_type == IPOption.IPOPT_EOL:
1100 break
1103 def __str__(self):
1104 flags = ' '
1105 if self.get_ip_df():
1106 flags += 'DF '
1107 if self.get_ip_mf():
1108 flags += 'MF '
1109 if self.get_ip_rf():
1110 flags += 'RF '
1111 tmp_str = 'IP%s%s -> %s ' % (flags, self.get_ip_src(),self.get_ip_dst())
1112 for op in self.__option_list:
1113 tmp_str += '\n' + str(op)
1114 if self.child():
1115 tmp_str += '\n' + str(self.child())
1116 return tmp_str
1119class IPOption(PacketBuffer):
1120 IPOPT_EOL = 0
1121 IPOPT_NOP = 1
1122 IPOPT_RR = 7
1123 IPOPT_TS = 68
1124 IPOPT_LSRR = 131
1125 IPOPT_SSRR = 137
1127 def __init__(self, opcode = 0, size = None):
1128 if size and (size < 3 or size > 40):
1129 raise ImpactPacketException("IP Options must have a size between 3 and 40 bytes")
1131 if(opcode == IPOption.IPOPT_EOL):
1132 PacketBuffer.__init__(self, 1)
1133 self.set_code(IPOption.IPOPT_EOL)
1134 elif(opcode == IPOption.IPOPT_NOP):
1135 PacketBuffer.__init__(self, 1)
1136 self.set_code(IPOption.IPOPT_NOP)
1137 elif(opcode == IPOption.IPOPT_RR):
1138 if not size:
1139 size = 39
1140 PacketBuffer.__init__(self, size)
1141 self.set_code(IPOption.IPOPT_RR)
1142 self.set_len(size)
1143 self.set_ptr(4)
1145 elif(opcode == IPOption.IPOPT_LSRR):
1146 if not size:
1147 size = 39
1148 PacketBuffer.__init__(self, size)
1149 self.set_code(IPOption.IPOPT_LSRR)
1150 self.set_len(size)
1151 self.set_ptr(4)
1153 elif(opcode == IPOption.IPOPT_SSRR):
1154 if not size:
1155 size = 39
1156 PacketBuffer.__init__(self, size)
1157 self.set_code(IPOption.IPOPT_SSRR)
1158 self.set_len(size)
1159 self.set_ptr(4)
1161 elif(opcode == IPOption.IPOPT_TS):
1162 if not size:
1163 size = 40
1164 PacketBuffer.__init__(self, size)
1165 self.set_code(IPOption.IPOPT_TS)
1166 self.set_len(size)
1167 self.set_ptr(5)
1168 self.set_flags(0)
1169 else:
1170 if not size:
1171 raise ImpactPacketException("Size required for this type")
1172 PacketBuffer.__init__(self,size)
1173 self.set_code(opcode)
1174 self.set_len(size)
1177 def append_ip(self, ip):
1178 op = self.get_code()
1179 if not (op == IPOption.IPOPT_RR or op == IPOption.IPOPT_LSRR or op == IPOption.IPOPT_SSRR or op == IPOption.IPOPT_TS):
1180 raise ImpactPacketException("append_ip() not support for option type %d" % self.opt_type)
1182 p = self.get_ptr()
1183 if not p:
1184 raise ImpactPacketException("append_ip() failed, option ptr uninitialized")
1186 if (p + 4) > self.get_len():
1187 raise ImpactPacketException("append_ip() would overflow option")
1189 self.set_ip_address(p - 1, ip)
1190 p += 4
1191 self.set_ptr(p)
1194 def set_code(self, value):
1195 self.set_byte(0, value)
1197 def get_code(self):
1198 return self.get_byte(0)
1201 def set_flags(self, flags):
1202 if not (self.get_code() == IPOption.IPOPT_TS):
1203 raise ImpactPacketException("Operation only supported on Timestamp option")
1204 self.set_byte(3, flags)
1206 def get_flags(self, flags):
1207 if not (self.get_code() == IPOption.IPOPT_TS):
1208 raise ImpactPacketException("Operation only supported on Timestamp option")
1209 return self.get_byte(3)
1212 def set_len(self, len):
1213 self.set_byte(1, len)
1216 def set_ptr(self, ptr):
1217 self.set_byte(2, ptr)
1219 def get_ptr(self):
1220 return self.get_byte(2)
1222 def get_len(self):
1223 return len(self.get_bytes())
1226 def __str__(self):
1227 map = {IPOption.IPOPT_EOL : "End of List ",
1228 IPOption.IPOPT_NOP : "No Operation ",
1229 IPOption.IPOPT_RR : "Record Route ",
1230 IPOption.IPOPT_TS : "Timestamp ",
1231 IPOption.IPOPT_LSRR : "Loose Source Route ",
1232 IPOption.IPOPT_SSRR : "Strict Source Route "}
1234 tmp_str = "\tIP Option: "
1235 op = self.get_code()
1236 if op in map:
1237 tmp_str += map[op]
1238 else:
1239 tmp_str += "Code: %d " % op
1241 if op == IPOption.IPOPT_RR or op == IPOption.IPOPT_LSRR or op ==IPOption.IPOPT_SSRR:
1242 tmp_str += self.print_addresses()
1245 return tmp_str
1248 def print_addresses(self):
1249 p = 3
1250 tmp_str = "["
1251 if self.get_len() >= 7: # at least one complete IP address
1252 while 1:
1253 if p + 1 == self.get_ptr():
1254 tmp_str += "#"
1255 tmp_str += self.get_ip_address(p)
1256 p += 4
1257 if p >= self.get_len():
1258 break
1259 else:
1260 tmp_str += ", "
1261 tmp_str += "] "
1262 if self.get_ptr() % 4: # ptr field should be a multiple of 4
1263 tmp_str += "nonsense ptr field: %d " % self.get_ptr()
1264 return tmp_str
1267class UDP(Header):
1268 protocol = 17
1269 def __init__(self, aBuffer = None):
1270 Header.__init__(self, 8)
1271 if(aBuffer): 1271 ↛ 1272line 1271 didn't jump to line 1272, because the condition on line 1271 was never true
1272 self.load_header(aBuffer)
1274 def get_uh_sport(self):
1275 return self.get_word(0)
1276 def set_uh_sport(self, value):
1277 self.set_word(0, value)
1279 def get_uh_dport(self):
1280 return self.get_word(2)
1281 def set_uh_dport(self, value):
1282 self.set_word(2, value)
1284 def get_uh_ulen(self):
1285 return self.get_word(4)
1287 def set_uh_ulen(self, value):
1288 self.set_word(4, value)
1290 def get_uh_sum(self):
1291 return self.get_word(6)
1293 def set_uh_sum(self, value):
1294 self.set_word(6, value)
1295 self.auto_checksum = 0
1297 def calculate_checksum(self):
1298 if self.auto_checksum and (not self.get_uh_sum()):
1299 # if there isn't a parent to grab a pseudo-header from we'll assume the user knows what they're doing
1300 # and won't meddle with the checksum or throw an exception
1301 if not self.parent():
1302 return
1304 buffer = self.parent().get_pseudo_header()
1306 buffer += self.get_bytes()
1307 data = self.get_data_as_string()
1308 if(data):
1309 array_frombytes(buffer, data)
1310 self.set_uh_sum(self.compute_checksum(buffer))
1312 def get_header_size(self):
1313 return 8
1315 def __str__(self):
1316 tmp_str = 'UDP %d -> %d' % (self.get_uh_sport(), self.get_uh_dport())
1317 if self.child():
1318 tmp_str += '\n' + str(self.child())
1319 return tmp_str
1321 def get_packet(self):
1322 # set total length
1323 if(self.get_uh_ulen() == 0):
1324 self.set_uh_ulen(self.get_size())
1325 return Header.get_packet(self)
1327class TCP(Header):
1328 protocol = 6
1329 TCP_FLAGS_MASK = 0x00FF # lowest 16 bits are the flags
1330 def __init__(self, aBuffer = None):
1331 Header.__init__(self, 20)
1332 self.set_th_off(5)
1333 self.__option_list = []
1334 if aBuffer: 1334 ↛ exitline 1334 didn't return from function '__init__', because the condition on line 1334 was never false
1335 self.load_header(aBuffer)
1337 def add_option(self, option):
1338 self.__option_list.append(option)
1340 sum = 0
1341 for op in self.__option_list:
1342 sum += op.get_size()
1344 if sum > 40: 1344 ↛ 1345line 1344 didn't jump to line 1345, because the condition on line 1344 was never true
1345 raise ImpactPacketException("Cannot add TCP option, would overflow option space")
1347 def get_options(self):
1348 return self.__option_list
1350 def swapSourceAndDestination(self):
1351 oldSource = self.get_th_sport()
1352 self.set_th_sport(self.get_th_dport())
1353 self.set_th_dport(oldSource)
1355 #
1356 # Header field accessors
1357 #
1359 def set_th_sport(self, aValue):
1360 self.set_word(0, aValue)
1362 def get_th_sport(self):
1363 return self.get_word(0)
1365 def get_th_dport(self):
1366 return self.get_word(2)
1368 def set_th_dport(self, aValue):
1369 self.set_word(2, aValue)
1371 def get_th_seq(self):
1372 return self.get_long(4)
1374 def set_th_seq(self, aValue):
1375 self.set_long(4, aValue)
1377 def get_th_ack(self):
1378 return self.get_long(8)
1380 def set_th_ack(self, aValue):
1381 self.set_long(8, aValue)
1383 def get_th_flags(self):
1384 return self.get_word(12) & self.TCP_FLAGS_MASK
1386 def set_th_flags(self, aValue):
1387 masked = self.get_word(12) & (~self.TCP_FLAGS_MASK)
1388 nb = masked | (aValue & self.TCP_FLAGS_MASK)
1389 return self.set_word(12, nb, ">")
1391 def get_th_win(self):
1392 return self.get_word(14)
1394 def set_th_win(self, aValue):
1395 self.set_word(14, aValue)
1397 def set_th_sum(self, aValue):
1398 self.set_word(16, aValue)
1399 self.auto_checksum = 0
1401 def get_th_sum(self):
1402 return self.get_word(16)
1404 def get_th_urp(self):
1405 return self.get_word(18)
1407 def set_th_urp(self, aValue):
1408 return self.set_word(18, aValue)
1410 # Flag accessors
1412 def get_th_reserved(self):
1413 tmp_value = self.get_byte(12) & 0x0f
1414 return tmp_value
1417 def get_th_off(self):
1418 tmp_value = self.get_byte(12) >> 4
1419 return tmp_value
1421 def set_th_off(self, aValue):
1422 mask = 0xF0
1423 masked = self.get_byte(12) & (~mask)
1424 nb = masked | ( (aValue << 4) & mask)
1425 return self.set_byte(12, nb)
1427 def get_CWR(self):
1428 return self.get_flag(128)
1429 def set_CWR(self):
1430 return self.set_flags(128)
1431 def reset_CWR(self):
1432 return self.reset_flags(128)
1434 def get_ECE(self):
1435 return self.get_flag(64)
1436 def set_ECE(self):
1437 return self.set_flags(64)
1438 def reset_ECE(self):
1439 return self.reset_flags(64)
1441 def get_URG(self):
1442 return self.get_flag(32)
1443 def set_URG(self):
1444 return self.set_flags(32)
1445 def reset_URG(self):
1446 return self.reset_flags(32)
1448 def get_ACK(self):
1449 return self.get_flag(16)
1450 def set_ACK(self):
1451 return self.set_flags(16)
1452 def reset_ACK(self):
1453 return self.reset_flags(16)
1455 def get_PSH(self):
1456 return self.get_flag(8)
1457 def set_PSH(self):
1458 return self.set_flags(8)
1459 def reset_PSH(self):
1460 return self.reset_flags(8)
1462 def get_RST(self):
1463 return self.get_flag(4)
1464 def set_RST(self):
1465 return self.set_flags(4)
1466 def reset_RST(self):
1467 return self.reset_flags(4)
1469 def get_SYN(self):
1470 return self.get_flag(2)
1471 def set_SYN(self):
1472 return self.set_flags(2)
1473 def reset_SYN(self):
1474 return self.reset_flags(2)
1476 def get_FIN(self):
1477 return self.get_flag(1)
1478 def set_FIN(self):
1479 return self.set_flags(1)
1480 def reset_FIN(self):
1481 return self.reset_flags(1)
1483 # Overridden Methods
1485 def get_header_size(self):
1486 return 20 + len(self.get_padded_options())
1488 def calculate_checksum(self):
1489 if not self.auto_checksum or not self.parent(): 1489 ↛ 1492line 1489 didn't jump to line 1492, because the condition on line 1489 was never false
1490 return
1492 self.set_th_sum(0)
1493 buffer = self.parent().get_pseudo_header()
1494 buffer += self.get_bytes()
1495 buffer += self.get_padded_options()
1497 data = self.get_data_as_string()
1498 if(data):
1499 array_frombytes(buffer, data)
1501 res = self.compute_checksum(buffer)
1503 self.set_th_sum(self.compute_checksum(buffer))
1505 def get_packet(self):
1506 "Returns entire packet including child data as a string. This is the function used to extract the final packet"
1508 # only change th_off value if options are present
1509 if len(self.__option_list): 1509 ↛ 1512line 1509 didn't jump to line 1512, because the condition on line 1509 was never false
1510 self.set_th_off(self.get_header_size() // 4)
1512 self.calculate_checksum()
1514 bytes = self.get_bytes() + self.get_padded_options()
1515 data = self.get_data_as_string()
1517 if data: 1517 ↛ 1518line 1517 didn't jump to line 1518, because the condition on line 1517 was never true
1518 return array_tobytes(bytes) + data
1519 else:
1520 return array_tobytes(bytes)
1522 def load_header(self, aBuffer):
1523 self.set_bytes_from_string(aBuffer[:20])
1524 opt_left = (self.get_th_off() - 5) * 4
1525 opt_bytes = array.array('B', aBuffer[20:(20 + opt_left)])
1526 if len(opt_bytes) != opt_left: 1526 ↛ 1527line 1526 didn't jump to line 1527, because the condition on line 1526 was never true
1527 raise ImpactPacketException("Cannot load options from truncated packet")
1529 while opt_left:
1530 op_kind = opt_bytes[0]
1531 if op_kind == TCPOption.TCPOPT_EOL or op_kind == TCPOption.TCPOPT_NOP:
1532 new_option = TCPOption(op_kind)
1533 op_len = 1
1534 else:
1535 op_len = opt_bytes[1]
1536 if op_len > len(opt_bytes): 1536 ↛ 1537line 1536 didn't jump to line 1537, because the condition on line 1536 was never true
1537 raise ImpactPacketException("TCP Option length is too high")
1538 if op_len < 2: 1538 ↛ 1539line 1538 didn't jump to line 1539, because the condition on line 1538 was never true
1539 raise ImpactPacketException("TCP Option length is too low")
1541 new_option = TCPOption(op_kind)
1542 new_option.set_bytes(opt_bytes[:op_len])
1544 opt_bytes = opt_bytes[op_len:]
1545 opt_left -= op_len
1546 self.add_option(new_option)
1547 if op_kind == TCPOption.TCPOPT_EOL: 1547 ↛ 1548line 1547 didn't jump to line 1548, because the condition on line 1547 was never true
1548 break
1550 #
1551 # Private
1552 #
1554 def get_flag(self, bit):
1555 if self.get_th_flags() & bit:
1556 return 1
1557 else:
1558 return 0
1560 def reset_flags(self, aValue):
1561 tmp_value = self.get_th_flags() & (~aValue)
1562 return self.set_th_flags(tmp_value)
1564 def set_flags(self, aValue):
1565 tmp_value = self.get_th_flags() | aValue
1566 return self.set_th_flags(tmp_value)
1568 def get_padded_options(self):
1569 "Return an array containing all options padded to a 4 byte boundary"
1570 op_buf = array.array('B')
1571 for op in self.__option_list:
1572 op_buf += op.get_bytes()
1573 num_pad = (4 - (len(op_buf) % 4)) % 4
1574 if num_pad: 1574 ↛ 1575line 1574 didn't jump to line 1575, because the condition on line 1574 was never true
1575 array_frombytes(op_buf, "\0" * num_pad)
1576 return op_buf
1578 def __str__(self):
1579 tmp_str = 'TCP '
1580 if self.get_ECE():
1581 tmp_str += 'ece '
1582 if self.get_CWR():
1583 tmp_str += 'cwr '
1584 if self.get_ACK():
1585 tmp_str += 'ack '
1586 if self.get_FIN():
1587 tmp_str += 'fin '
1588 if self.get_PSH():
1589 tmp_str += 'push '
1590 if self.get_RST():
1591 tmp_str += 'rst '
1592 if self.get_SYN():
1593 tmp_str += 'syn '
1594 if self.get_URG():
1595 tmp_str += 'urg '
1596 tmp_str += '%d -> %d' % (self.get_th_sport(), self.get_th_dport())
1597 for op in self.__option_list:
1598 tmp_str += '\n' + str(op)
1600 if self.child():
1601 tmp_str += '\n' + str(self.child())
1602 return tmp_str
1605class TCPOption(PacketBuffer):
1606 TCPOPT_EOL = 0
1607 TCPOPT_NOP = 1
1608 TCPOPT_MAXSEG = 2
1609 TCPOPT_WINDOW = 3
1610 TCPOPT_SACK_PERMITTED = 4
1611 TCPOPT_SACK = 5
1612 TCPOPT_TIMESTAMP = 8
1613 TCPOPT_SIGNATURE = 19
1616 def __init__(self, kind, data = None):
1618 if kind == TCPOption.TCPOPT_EOL: 1618 ↛ 1619line 1618 didn't jump to line 1619, because the condition on line 1618 was never true
1619 PacketBuffer.__init__(self, 1)
1620 self.set_kind(TCPOption.TCPOPT_EOL)
1621 elif kind == TCPOption.TCPOPT_NOP:
1622 PacketBuffer.__init__(self, 1)
1623 self.set_kind(TCPOption.TCPOPT_NOP)
1624 elif kind == TCPOption.TCPOPT_MAXSEG:
1625 PacketBuffer.__init__(self, 4)
1626 self.set_kind(TCPOption.TCPOPT_MAXSEG)
1627 self.set_len(4)
1628 if data: 1628 ↛ 1629line 1628 didn't jump to line 1629, because the condition on line 1628 was never true
1629 self.set_mss(data)
1630 else:
1631 self.set_mss(512)
1632 elif kind == TCPOption.TCPOPT_WINDOW:
1633 PacketBuffer.__init__(self, 3)
1634 self.set_kind(TCPOption.TCPOPT_WINDOW)
1635 self.set_len(3)
1636 if data: 1636 ↛ 1637line 1636 didn't jump to line 1637, because the condition on line 1636 was never true
1637 self.set_shift_cnt(data)
1638 else:
1639 self.set_shift_cnt(0)
1640 elif kind == TCPOption.TCPOPT_TIMESTAMP:
1641 PacketBuffer.__init__(self, 10)
1642 self.set_kind(TCPOption.TCPOPT_TIMESTAMP)
1643 self.set_len(10)
1644 if data: 1644 ↛ 1645line 1644 didn't jump to line 1645, because the condition on line 1644 was never true
1645 self.set_ts(data)
1646 else:
1647 self.set_ts(0)
1648 elif kind == TCPOption.TCPOPT_SACK_PERMITTED: 1648 ↛ 1653line 1648 didn't jump to line 1653, because the condition on line 1648 was never false
1649 PacketBuffer.__init__(self, 2)
1650 self.set_kind(TCPOption.TCPOPT_SACK_PERMITTED)
1651 self.set_len(2)
1653 elif kind == TCPOption.TCPOPT_SACK:
1654 PacketBuffer.__init__(self, 2)
1655 self.set_kind(TCPOption.TCPOPT_SACK)
1657 def set_left_edge(self, aValue):
1658 self.set_long (2, aValue)
1660 def set_right_edge(self, aValue):
1661 self.set_long (6, aValue)
1663 def set_kind(self, kind):
1664 self.set_byte(0, kind)
1667 def get_kind(self):
1668 return self.get_byte(0)
1671 def set_len(self, len):
1672 if self.get_size() < 2: 1672 ↛ 1673line 1672 didn't jump to line 1673, because the condition on line 1672 was never true
1673 raise ImpactPacketException("Cannot set length field on an option having a size smaller than 2 bytes")
1674 self.set_byte(1, len)
1676 def get_len(self):
1677 if self.get_size() < 2:
1678 raise ImpactPacketException("Cannot retrieve length field from an option having a size smaller than 2 bytes")
1679 return self.get_byte(1)
1681 def get_size(self):
1682 return len(self.get_bytes())
1685 def set_mss(self, len):
1686 if self.get_kind() != TCPOption.TCPOPT_MAXSEG: 1686 ↛ 1687line 1686 didn't jump to line 1687, because the condition on line 1686 was never true
1687 raise ImpactPacketException("Can only set MSS on TCPOPT_MAXSEG option")
1688 self.set_word(2, len)
1690 def get_mss(self):
1691 if self.get_kind() != TCPOption.TCPOPT_MAXSEG:
1692 raise ImpactPacketException("Can only retrieve MSS from TCPOPT_MAXSEG option")
1693 return self.get_word(2)
1695 def set_shift_cnt(self, cnt):
1696 if self.get_kind() != TCPOption.TCPOPT_WINDOW: 1696 ↛ 1697line 1696 didn't jump to line 1697, because the condition on line 1696 was never true
1697 raise ImpactPacketException("Can only set Shift Count on TCPOPT_WINDOW option")
1698 self.set_byte(2, cnt)
1700 def get_shift_cnt(self):
1701 if self.get_kind() != TCPOption.TCPOPT_WINDOW:
1702 raise ImpactPacketException("Can only retrieve Shift Count from TCPOPT_WINDOW option")
1703 return self.get_byte(2)
1705 def get_ts(self):
1706 if self.get_kind() != TCPOption.TCPOPT_TIMESTAMP:
1707 raise ImpactPacketException("Can only retrieve timestamp from TCPOPT_TIMESTAMP option")
1708 return self.get_long(2)
1710 def set_ts(self, ts):
1711 if self.get_kind() != TCPOption.TCPOPT_TIMESTAMP: 1711 ↛ 1712line 1711 didn't jump to line 1712, because the condition on line 1711 was never true
1712 raise ImpactPacketException("Can only set timestamp on TCPOPT_TIMESTAMP option")
1713 self.set_long(2, ts)
1715 def get_ts_echo(self):
1716 if self.get_kind() != TCPOption.TCPOPT_TIMESTAMP:
1717 raise ImpactPacketException("Can only retrieve timestamp from TCPOPT_TIMESTAMP option")
1718 return self.get_long(6)
1720 def set_ts_echo(self, ts):
1721 if self.get_kind() != TCPOption.TCPOPT_TIMESTAMP:
1722 raise ImpactPacketException("Can only set timestamp on TCPOPT_TIMESTAMP option")
1723 self.set_long(6, ts)
1725 def __str__(self):
1726 map = { TCPOption.TCPOPT_EOL : "End of List ",
1727 TCPOption.TCPOPT_NOP : "No Operation ",
1728 TCPOption.TCPOPT_MAXSEG : "Maximum Segment Size ",
1729 TCPOption.TCPOPT_WINDOW : "Window Scale ",
1730 TCPOption.TCPOPT_TIMESTAMP : "Timestamp " }
1732 tmp_str = "\tTCP Option: "
1733 op = self.get_kind()
1734 if op in map:
1735 tmp_str += map[op]
1736 else:
1737 tmp_str += " kind: %d " % op
1738 if op == TCPOption.TCPOPT_MAXSEG:
1739 tmp_str += " MSS : %d " % self.get_mss()
1740 elif op == TCPOption.TCPOPT_WINDOW:
1741 tmp_str += " Shift Count: %d " % self.get_shift_cnt()
1742 elif op == TCPOption.TCPOPT_TIMESTAMP:
1743 pass # TODO
1744 return tmp_str
1746class ICMP(Header):
1747 protocol = 1
1748 ICMP_ECHOREPLY = 0
1749 ICMP_UNREACH = 3
1750 ICMP_UNREACH_NET = 0
1751 ICMP_UNREACH_HOST = 1
1752 ICMP_UNREACH_PROTOCOL = 2
1753 ICMP_UNREACH_PORT = 3
1754 ICMP_UNREACH_NEEDFRAG = 4
1755 ICMP_UNREACH_SRCFAIL = 5
1756 ICMP_UNREACH_NET_UNKNOWN = 6
1757 ICMP_UNREACH_HOST_UNKNOWN = 7
1758 ICMP_UNREACH_ISOLATED = 8
1759 ICMP_UNREACH_NET_PROHIB = 9
1760 ICMP_UNREACH_HOST_PROHIB = 10
1761 ICMP_UNREACH_TOSNET = 11
1762 ICMP_UNREACH_TOSHOST = 12
1763 ICMP_UNREACH_FILTERPROHIB = 13
1764 ICMP_UNREACH_HOST_PRECEDENCE = 14
1765 ICMP_UNREACH_PRECEDENCE_CUTOFF = 15
1766 ICMP_SOURCEQUENCH = 4
1767 ICMP_REDIRECT = 5
1768 ICMP_REDIRECT_NET = 0
1769 ICMP_REDIRECT_HOST = 1
1770 ICMP_REDIRECT_TOSNET = 2
1771 ICMP_REDIRECT_TOSHOST = 3
1772 ICMP_ALTHOSTADDR = 6
1773 ICMP_ECHO = 8
1774 ICMP_ROUTERADVERT = 9
1775 ICMP_ROUTERSOLICIT = 10
1776 ICMP_TIMXCEED = 11
1777 ICMP_TIMXCEED_INTRANS = 0
1778 ICMP_TIMXCEED_REASS = 1
1779 ICMP_PARAMPROB = 12
1780 ICMP_PARAMPROB_ERRATPTR = 0
1781 ICMP_PARAMPROB_OPTABSENT = 1
1782 ICMP_PARAMPROB_LENGTH = 2
1783 ICMP_TSTAMP = 13
1784 ICMP_TSTAMPREPLY = 14
1785 ICMP_IREQ = 15
1786 ICMP_IREQREPLY = 16
1787 ICMP_MASKREQ = 17
1788 ICMP_MASKREPLY = 18
1790 def __init__(self, aBuffer = None):
1791 Header.__init__(self, 8)
1792 if aBuffer:
1793 self.load_header(aBuffer)
1795 def get_header_size(self):
1796 anamolies = { ICMP.ICMP_TSTAMP : 20, ICMP.ICMP_TSTAMPREPLY : 20, ICMP.ICMP_MASKREQ : 12, ICMP.ICMP_MASKREPLY : 12 }
1797 if self.get_icmp_type() in anamolies: 1797 ↛ 1798line 1797 didn't jump to line 1798, because the condition on line 1797 was never true
1798 return anamolies[self.get_icmp_type()]
1799 else:
1800 return 8
1802 def get_icmp_type(self):
1803 return self.get_byte(0)
1805 def set_icmp_type(self, aValue):
1806 self.set_byte(0, aValue)
1808 def get_icmp_code(self):
1809 return self.get_byte(1)
1811 def set_icmp_code(self, aValue):
1812 self.set_byte(1, aValue)
1814 def get_icmp_cksum(self):
1815 return self.get_word(2)
1817 def set_icmp_cksum(self, aValue):
1818 self.set_word(2, aValue)
1819 self.auto_checksum = 0
1821 def get_icmp_gwaddr(self):
1822 return self.get_ip_address(4)
1824 def set_icmp_gwaddr(self, ip):
1825 self.set_ip_address(4, ip)
1827 def get_icmp_id(self):
1828 return self.get_word(4)
1830 def set_icmp_id(self, aValue):
1831 self.set_word(4, aValue)
1833 def get_icmp_seq(self):
1834 return self.get_word(6)
1836 def set_icmp_seq(self, aValue):
1837 self.set_word(6, aValue)
1839 def get_icmp_void(self):
1840 return self.get_long(4)
1842 def set_icmp_void(self, aValue):
1843 self.set_long(4, aValue)
1846 def get_icmp_nextmtu(self):
1847 return self.get_word(6)
1849 def set_icmp_nextmtu(self, aValue):
1850 self.set_word(6, aValue)
1852 def get_icmp_num_addrs(self):
1853 return self.get_byte(4)
1855 def set_icmp_num_addrs(self, aValue):
1856 self.set_byte(4, aValue)
1858 def get_icmp_wpa(self):
1859 return self.get_byte(5)
1861 def set_icmp_wpa(self, aValue):
1862 self.set_byte(5, aValue)
1864 def get_icmp_lifetime(self):
1865 return self.get_word(6)
1867 def set_icmp_lifetime(self, aValue):
1868 self.set_word(6, aValue)
1870 def get_icmp_otime(self):
1871 return self.get_long(8)
1873 def set_icmp_otime(self, aValue):
1874 self.set_long(8, aValue)
1876 def get_icmp_rtime(self):
1877 return self.get_long(12)
1879 def set_icmp_rtime(self, aValue):
1880 self.set_long(12, aValue)
1882 def get_icmp_ttime(self):
1883 return self.get_long(16)
1885 def set_icmp_ttime(self, aValue):
1886 self.set_long(16, aValue)
1888 def get_icmp_mask(self):
1889 return self.get_ip_address(8)
1891 def set_icmp_mask(self, mask):
1892 self.set_ip_address(8, mask)
1895 def calculate_checksum(self):
1896 if self.auto_checksum and (not self.get_icmp_cksum()):
1897 buffer = self.get_buffer_as_string()
1898 data = self.get_data_as_string()
1899 if data: 1899 ↛ 1902line 1899 didn't jump to line 1902, because the condition on line 1899 was never false
1900 buffer += data
1902 tmp_array = array.array('B', buffer)
1903 self.set_icmp_cksum(self.compute_checksum(tmp_array))
1905 def get_type_name(self, aType):
1906 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'}
1907 answer = tmp_type.get(aType, 'UNKNOWN')
1908 return answer
1910 def get_code_name(self, aType, aCode):
1911 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']}
1912 tmp_code[5] = ['REDIRECT NET', 'REDIRECT HOST', 'REDIRECT TOSNET', 'REDIRECT TOSHOST']
1913 tmp_code[9] = ['ROUTERADVERT NORMAL', None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,'ROUTERADVERT NOROUTE COMMON']
1914 tmp_code[11] = ['TIMXCEED INTRANS ', 'TIMXCEED REASS']
1915 tmp_code[12] = ['PARAMPROB ERRATPTR ', 'PARAMPROB OPTABSENT', 'PARAMPROB LENGTH']
1916 tmp_code[40] = [None, 'PHOTURIS UNKNOWN INDEX', 'PHOTURIS AUTH FAILED', 'PHOTURIS DECRYPT FAILED']
1917 if aType in tmp_code:
1918 tmp_list = tmp_code[aType]
1919 if ((aCode + 1) > len(tmp_list)) or (not tmp_list[aCode]):
1920 return 'UNKNOWN'
1921 else:
1922 return tmp_list[aCode]
1923 else:
1924 return 'UNKNOWN'
1926 def __str__(self):
1927 tmp_type = self.get_icmp_type()
1928 tmp_code = self.get_icmp_code()
1929 tmp_str = 'ICMP type: ' + self.get_type_name(tmp_type)
1930 tmp_str+= ' code: ' + self.get_code_name(tmp_type, tmp_code)
1931 if self.child():
1932 tmp_str += '\n' + str( self.child() )
1933 return tmp_str
1935 def isDestinationUnreachable(self):
1936 return self.get_icmp_type() == 3
1938 def isError(self):
1939 return not self.isQuery()
1941 def isHostUnreachable(self):
1942 return self.isDestinationUnreachable() and (self.get_icmp_code() == 1)
1944 def isNetUnreachable(self):
1945 return self.isDestinationUnreachable() and (self.get_icmp_code() == 0)
1947 def isPortUnreachable(self):
1948 return self.isDestinationUnreachable() and (self.get_icmp_code() == 3)
1950 def isProtocolUnreachable(self):
1951 return self.isDestinationUnreachable() and (self.get_icmp_code() == 2)
1953 def isQuery(self):
1954 tmp_dict = {8:'', 9:'', 10:'', 13:'', 14:'', 15:'', 16:'', 17:'', 18:''}
1955 return self.get_icmp_type() in tmp_dict
1957class IGMP(Header):
1958 protocol = 2
1959 def __init__(self, aBuffer = None):
1960 Header.__init__(self, 8)
1961 if aBuffer:
1962 self.load_header(aBuffer)
1964 def get_igmp_type(self):
1965 return self.get_byte(0)
1967 def set_igmp_type(self, aValue):
1968 self.set_byte(0, aValue)
1970 def get_igmp_code(self):
1971 return self.get_byte(1)
1973 def set_igmp_code(self, aValue):
1974 self.set_byte(1, aValue)
1976 def get_igmp_cksum(self):
1977 return self.get_word(2)
1979 def set_igmp_cksum(self, aValue):
1980 self.set_word(2, aValue)
1982 def get_igmp_group(self):
1983 return self.get_long(4)
1985 def set_igmp_group(self, aValue):
1986 self.set_long(4, aValue)
1988 def get_header_size(self):
1989 return 8
1991 def get_type_name(self, aType):
1992 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 '}
1993 answer = tmp_dict.get(aType, 'UNKNOWN TYPE OR VERSION ')
1994 return answer
1996 def calculate_checksum(self):
1997 if self.auto_checksum and (not self.get_igmp_cksum()):
1998 self.set_igmp_cksum(self.compute_checksum(self.get_bytes()))
2000 def __str__(self):
2001 tmp_str = 'IGMP: ' + self.get_type_name(self.get_igmp_type())
2002 tmp_str += 'Group: ' + socket.inet_ntoa(struct.pack('!L',self.get_igmp_group()))
2003 if self.child():
2004 tmp_str += '\n' + str(self.child())
2005 return tmp_str
2009class ARP(Header):
2010 ethertype = 0x806
2011 def __init__(self, aBuffer = None):
2012 Header.__init__(self, 7)
2013 if aBuffer: 2013 ↛ exitline 2013 didn't return from function '__init__', because the condition on line 2013 was never false
2014 self.load_header(aBuffer)
2016 def get_ar_hrd(self):
2017 return self.get_word(0)
2019 def set_ar_hrd(self, aValue):
2020 self.set_word(0, aValue)
2022 def get_ar_pro(self):
2023 return self.get_word(2)
2025 def set_ar_pro(self, aValue):
2026 self.set_word(2, aValue)
2028 def get_ar_hln(self):
2029 return self.get_byte(4)
2031 def set_ar_hln(self, aValue):
2032 self.set_byte(4, aValue)
2034 def get_ar_pln(self):
2035 return self.get_byte(5)
2037 def set_ar_pln(self, aValue):
2038 self.set_byte(5, aValue)
2040 def get_ar_op(self):
2041 return self.get_word(6)
2043 def set_ar_op(self, aValue):
2044 self.set_word(6, aValue)
2046 def get_ar_sha(self):
2047 tmp_size = self.get_ar_hln()
2048 return self.get_bytes().tolist()[8: 8 + tmp_size]
2050 def set_ar_sha(self, aValue):
2051 for i in range(0, self.get_ar_hln()):
2052 self.set_byte(i + 8, aValue[i])
2054 def get_ar_spa(self):
2055 tmp_size = self.get_ar_pln()
2056 return self.get_bytes().tolist()[8 + self.get_ar_hln(): 8 + self.get_ar_hln() + tmp_size]
2058 def set_ar_spa(self, aValue):
2059 for i in range(0, self.get_ar_pln()):
2060 self.set_byte(i + 8 + self.get_ar_hln(), aValue[i])
2062 def get_ar_tha(self):
2063 tmp_size = self.get_ar_hln()
2064 tmp_from = 8 + self.get_ar_hln() + self.get_ar_pln()
2065 return self.get_bytes().tolist()[tmp_from: tmp_from + tmp_size]
2067 def set_ar_tha(self, aValue):
2068 tmp_from = 8 + self.get_ar_hln() + self.get_ar_pln()
2069 for i in range(0, self.get_ar_hln()):
2070 self.set_byte(i + tmp_from, aValue[i])
2072 def get_ar_tpa(self):
2073 tmp_size = self.get_ar_pln()
2074 tmp_from = 8 + ( 2 * self.get_ar_hln()) + self.get_ar_pln()
2075 return self.get_bytes().tolist()[tmp_from: tmp_from + tmp_size]
2077 def set_ar_tpa(self, aValue):
2078 tmp_from = 8 + (2 * self.get_ar_hln()) + self.get_ar_pln()
2079 for i in range(0, self.get_ar_pln()):
2080 self.set_byte(i + tmp_from, aValue[i])
2082 def get_header_size(self):
2083 return 8 + (2 * self.get_ar_hln()) + (2 * self.get_ar_pln())
2085 def get_op_name(self, ar_op):
2086 tmp_dict = {1:'REQUEST', 2:'REPLY', 3:'REVREQUEST', 4:'REVREPLY', 8:'INVREQUEST', 9:'INVREPLY'}
2087 answer = tmp_dict.get(ar_op, 'UNKNOWN')
2088 return answer
2090 def get_hrd_name(self, ar_hrd):
2091 tmp_dict = { 1:'ARPHRD ETHER', 6:'ARPHRD IEEE802', 15:'ARPHRD FRELAY'}
2092 answer = tmp_dict.get(ar_hrd, 'UNKNOWN')
2093 return answer
2096 def as_hrd(self, anArray):
2097 if not anArray:
2098 return ''
2099 tmp_str = '%x' % anArray[0]
2100 for i in range(1, len(anArray)):
2101 tmp_str += ':%x' % anArray[i]
2102 return tmp_str
2104 def as_pro(self, anArray):
2105 if not anArray:
2106 return ''
2107 tmp_str = '%d' % anArray[0]
2108 for i in range(1, len(anArray)):
2109 tmp_str += '.%d' % anArray[i]
2110 return tmp_str
2112 def __str__(self):
2113 tmp_op = self.get_ar_op()
2114 tmp_str = 'ARP format: ' + self.get_hrd_name(self.get_ar_hrd()) + ' '
2115 tmp_str += 'opcode: ' + self.get_op_name(tmp_op)
2116 tmp_str += '\n' + self.as_hrd(self.get_ar_sha()) + ' -> '
2117 tmp_str += self.as_hrd(self.get_ar_tha())
2118 tmp_str += '\n' + self.as_pro(self.get_ar_spa()) + ' -> '
2119 tmp_str += self.as_pro(self.get_ar_tpa())
2120 if self.child():
2121 tmp_str += '\n' + str(self.child())
2122 return tmp_str
2124def example(): #To execute an example, remove this line
2125 a = Ethernet()
2126 b = ARP()
2127 c = Data('Hola loco!!!')
2128 b.set_ar_hln(6)
2129 b.set_ar_pln(4)
2130 #a.set_ip_dst('192.168.22.6')
2131 #a.set_ip_src('1.1.1.2')
2132 a.contains(b)
2133 b.contains(c)
2134 b.set_ar_op(2)
2135 b.set_ar_hrd(1)
2136 b.set_ar_spa((192, 168, 22, 6))
2137 b.set_ar_tpa((192, 168, 66, 171))
2138 a.set_ether_shost((0x0, 0xe0, 0x7d, 0x8a, 0xef, 0x3d))
2139 a.set_ether_dhost((0x0, 0xc0, 0xdf, 0x6, 0x5, 0xe))
2140 print("beto %s" % a)