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