Hide keyboard shortcuts

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 

24 

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) 

33 

34 

35"""Classes to build network packets programmatically. 

36 

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. 

40 

41All objects can be turned back into a raw buffer ready to be sent over 

42the wire (see method get_packet). 

43""" 

44 

45class ImpactPacketException(Exception): 

46 def __init__(self, value): 

47 self.value = value 

48 def __str__(self): 

49 return repr(self.value) 

50 

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. 

54 

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 """ 

59 

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') 

66 

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) 

70 

71 def get_buffer_as_string(self): 

72 "Returns the packet buffer as a string object" 

73 return array_tobytes(self.__bytes) 

74 

75 def get_bytes(self): 

76 "Returns the packet buffer as an array" 

77 return self.__bytes 

78 

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()) 

83 

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 

88 

89 def get_byte(self, index): 

90 "Return byte at 'index'" 

91 index = self.__validate_index(index, 1) 

92 return self.__bytes[index] 

93 

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 

102 

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 

112 

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 

121 

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 

131 

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 

140 

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 

150 

151 

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)) 

160 

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) 

170 

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)) 

174 

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) 

187 

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 

194 

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 """ 

200 

201 orig_index = index 

202 

203 curlen = len(self.__bytes) 

204 if index < 0: 

205 index = curlen + index 

206 

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 

212 

213 return orig_index 

214 

215class ProtocolLayer(): 

216 "Protocol Layer Manager for insertion and removal of protocol layers." 

217 

218 __child = None 

219 __parent = None 

220 

221 def contains(self, aHeader): 

222 "Set 'aHeader' as the child of this protocol layer" 

223 self.__child = aHeader 

224 aHeader.set_parent(self) 

225 

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 

229 

230 def child(self): 

231 "Return the child of this protocol layer" 

232 return self.__child 

233 

234 def parent(self): 

235 "Return the parent of this protocol layer" 

236 return self.__parent 

237 

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 

243 

244class ProtocolPacket(ProtocolLayer): 

245 __HEADER_SIZE = 0 

246 __BODY_SIZE = 0 

247 __TAIL_SIZE = 0 

248 

249 __header = None 

250 __body = None 

251 __tail = None 

252 

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) 

259 

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) 

266 

267 def __get_header(self): 

268 return self.__header 

269 

270 header = property(__get_header) 

271 

272 def __get_body(self): 

273 self.__update_body_from_child() 

274 return self.__body 

275 

276 body = property(__get_body) 

277 

278 def __get_tail(self): 

279 return self.__tail 

280 

281 tail = property(__get_tail) 

282 

283 def get_header_size(self): 

284 "Return frame header size" 

285 return self.__HEADER_SIZE 

286 

287 def get_tail_size(self): 

288 "Return frame tail size" 

289 return self.__TAIL_SIZE 

290 

291 def get_body_size(self): 

292 "Return frame body size" 

293 self.__update_body_from_child() 

294 return self.__BODY_SIZE 

295 

296 def get_size(self): 

297 "Return frame total size" 

298 return self.get_header_size()+self.get_body_size()+self.get_tail_size() 

299 

300 def load_header(self, aBuffer): 

301 self.__HEADER_SIZE=len(aBuffer) 

302 self.__header.set_bytes_from_string(aBuffer) 

303 

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) 

310 

311 def load_tail(self, aBuffer): 

312 self.__TAIL_SIZE=len(aBuffer) 

313 self.__tail.set_bytes_from_string(aBuffer) 

314 

315 def __extract_header(self, aBuffer): 

316 self.load_header(aBuffer[:self.__HEADER_SIZE]) 

317 

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]) 

325 

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:]) 

333 

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() 

338 

339 self.__extract_header(aBuffer) 

340 self.__extract_body(aBuffer) 

341 self.__extract_tail(aBuffer) 

342 

343 def get_header_as_string(self): 

344 return self.__header.get_buffer_as_string() 

345 

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) 

350 

351 def get_tail_as_string(self): 

352 return self.__tail.get_buffer_as_string() 

353 tail_string = property(get_tail_as_string) 

354 

355 def get_packet(self): 

356 self.__update_body_from_child() 

357 

358 ret = b'' 

359 

360 header = self.get_header_as_string() 

361 if header: 

362 ret += header 

363 

364 body = self.get_body_as_string() 

365 if body: 

366 ret += body 

367 

368 tail = self.get_tail_as_string() 

369 if tail: 

370 ret += tail 

371 

372 return ret 

373 

374class Header(PacketBuffer,ProtocolLayer): 

375 "This is the base class from which all protocol definitions extend." 

376 

377 packet_printable = [c for c in string.printable if c not in string.whitespace] + [' '] 

378 

379 ethertype = None 

380 protocol = None 

381 def __init__(self, length = None): 

382 PacketBuffer.__init__(self, length) 

383 self.auto_checksum = 1 

384 

385 def get_data_as_string(self): 

386 "Returns all data from children of this header as string" 

387 

388 if self.child(): 

389 return self.child().get_packet() 

390 else: 

391 return None 

392 

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() 

399 

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() 

405 

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 

412 

413 def calculate_checksum(self): 

414 "Calculate and set the checksum for this header" 

415 pass 

416 

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') 

421 

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]) 

431 

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__) 

435 

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 [] 

464 

465 def __str__(self): 

466 ltmp = self.list_as_hex(self.get_bytes().tolist()) 

467 

468 if self.child(): 

469 ltmp.append(['\n', str(self.child())]) 

470 

471 if len(ltmp)>0: 

472 return ''.join(ltmp) 

473 else: 

474 return '' 

475 

476 

477 

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. 

483 

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 """ 

491 

492 def __init__(self, aBuffer = None): 

493 Header.__init__(self) 

494 if aBuffer: 

495 self.set_data(aBuffer) 

496 

497 def set_data(self, data): 

498 self.set_bytes_from_string(data) 

499 

500 def get_size(self): 

501 return len(self.get_bytes()) 

502 

503 

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.""" 

507 

508 def __init__(self, value=0x81000000): 

509 PacketBuffer.__init__(self, 4) 

510 self.set_long(0, value) 

511 

512 def get_tpid(self): 

513 """Returns Tag Protocol Identifier""" 

514 return self.get_word(0) 

515 

516 def set_tpid(self, value): 

517 """Sets Tag Protocol Identifier""" 

518 return self.set_word(0, value) 

519 

520 def get_pcp(self): 

521 """Returns Priority Code Point""" 

522 return (self.get_byte(2) & 0xE0) >> 5 

523 

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)) 

528 

529 def get_dei(self): 

530 """Returns Drop Eligible Indicator""" 

531 return (self.get_byte(2) & 0x10) >> 4 

532 

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) 

537 

538 def get_vid(self): 

539 """Returns VLAN Identifier""" 

540 return self.get_word(2) & 0x0FFF 

541 

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)) 

546 

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') 

557 

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()))) 

564 

565 

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) 

572 

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) 

576 

577 def get_ether_type(self): 

578 "Return ethernet data type field" 

579 return self.get_word(12 + 4*self.tag_cnt) 

580 

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)) 

587 

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) 

596 

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 

607 

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) 

619 

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 

624 

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]) 

630 

631 def get_header_size(self): 

632 "Return size of Ethernet header" 

633 return 14 + 4*self.tag_cnt 

634 

635 def get_packet(self): 

636 

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) 

644 

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] 

648 

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]) 

653 

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] 

657 

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]) 

662 

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) 

667 

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 

674 

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 

683 

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 ] 

694 

695 def __init__(self, aBuffer = None): 

696 Header.__init__(self, 16) 

697 if (aBuffer): 

698 self.load_header(aBuffer) 

699 

700 def set_type(self, type): 

701 "Sets the packet type field to type" 

702 self.set_word(0, type) 

703 

704 def get_type(self): 

705 "Returns the packet type field" 

706 return self.get_word(0) 

707 

708 def set_arphdr(self, value): 

709 "Sets the ARPHDR value for the link layer device type" 

710 self.set_word(2, type) 

711 

712 def get_arphdr(self): 

713 "Returns the ARPHDR value for the link layer device type" 

714 return self.get_word(2) 

715 

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) 

719 

720 def get_addr_len(self): 

721 "Returns the length of the sender's address field" 

722 return self.get_word(4) 

723 

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 

729 

730 def get_addr(self): 

731 "Returns the sender's address field" 

732 return array_tobytes(self.get_bytes()[6:14]) 

733 

734 def set_ether_type(self, aValue): 

735 "Set ethernet data type field to 'aValue'" 

736 self.set_word(14, aValue) 

737 

738 def get_ether_type(self): 

739 "Return ethernet data type field" 

740 return self.get_word(14) 

741 

742 def get_header_size(self): 

743 "Return size of packet header" 

744 return 16 

745 

746 def get_packet(self): 

747 if self.child(): 

748 self.set_ether_type(self.child().ethertype) 

749 return Header.get_packet(self) 

750 

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" 

757 

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())) 

765 

766 return '\n'.join(ss) 

767 

768 

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) 

781 

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 

786 

787 

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) 

792 

793 # set total length 

794 if self.get_ip_len() == 0: 

795 self.set_ip_len(self.get_size()) 

796 

797 child_data = self.get_data_as_string() 

798 

799 if self.auto_checksum: 

800 self.reset_ip_sum() 

801 

802 my_bytes = self.get_bytes() 

803 

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()) 

806 

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) 

811 

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) 

815 

816 

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)) 

820 

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 

825 

826 

827 

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)) 

837 

838 

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() 

845 

846 size_str = struct.pack("!H", tmp_size) 

847 

848 array_frombytes(pseudo_buf, size_str) 

849 return pseudo_buf 

850 

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) 

858 

859 

860 def get_ip_v(self): 

861 n = self.get_byte(0) 

862 return (n >> 4) 

863 

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) 

870 

871 def get_ip_hl(self): 

872 n = self.get_byte(0) 

873 return (n & 0xF) 

874 

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) 

881 

882 def get_ip_tos(self): 

883 return self.get_byte(1) 

884 

885 def set_ip_tos(self,value): 

886 self.set_byte(1, value) 

887 

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) 

893 

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) 

899 

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) 

904 

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) 

910 

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) 

916 

917 def get_ip_offmask(self): 

918 return self.get_ip_off() & 0x1FFF 

919 

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) 

924 

925 def get_ip_rf(self): 

926 return self.get_ip_off() & 0x8000 

927 

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) 

936 

937 def get_ip_df(self): 

938 return self.get_ip_off() & 0x4000 

939 

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) 

948 

949 def get_ip_mf(self): 

950 return self.get_ip_off() & 0x2000 

951 

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) 

960 

961 

962 def fragment_by_list(self, aList): 

963 if self.child(): 

964 proto = self.child().protocol 

965 else: 

966 proto = 0 

967 

968 child_data = self.get_data_as_string() 

969 if not child_data: 

970 return [self] 

971 

972 ip_header_bytes = self.get_bytes() 

973 current_offset = 0 

974 fragment_list = [] 

975 

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) 

980 

981 

982 if frag_size % 8: # round this fragment size up to next multiple of 8 

983 frag_size += 8 - (frag_size % 8) 

984 

985 

986 ip.set_ip_offmask(current_offset // 8) 

987 current_offset += frag_size 

988 

989 data = Data(child_data[:frag_size]) 

990 child_data = child_data[frag_size:] 

991 

992 ip.set_ip_len(20 + data.get_size()) 

993 ip.contains(data) 

994 

995 

996 if child_data: 

997 

998 ip.set_ip_mf(1) 

999 

1000 fragment_list.append(ip) 

1001 else: # no more data bytes left to add to fragments 

1002 

1003 ip.set_ip_mf(0) 

1004 

1005 fragment_list.append(ip) 

1006 return fragment_list 

1007 

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) 

1017 

1018 return fragment_list 

1019 

1020 

1021 def fragment_by_size(self, aSize): 

1022 data_len = len(self.get_data_as_string()) 

1023 num_frags = data_len // aSize 

1024 

1025 if data_len % aSize: 

1026 num_frags += 1 

1027 

1028 size_list = [] 

1029 for i in range(0, num_frags): 

1030 size_list.append(aSize) 

1031 return self.fragment_by_list(size_list) 

1032 

1033 

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) 

1038 

1039 def get_ip_p(self): 

1040 return self.get_byte(9) 

1041 

1042 def set_ip_p(self, value): 

1043 self.set_byte(9, value) 

1044 

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) 

1050 

1051 def reset_ip_sum(self): 

1052 self.set_ip_sum(0x0000) 

1053 self.auto_checksum = 1 

1054 

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) 

1059 

1060 def get_ip_dst(self): 

1061 return self.get_ip_address(16) 

1062 

1063 def set_ip_dst(self, value): 

1064 self.set_ip_address(16, value) 

1065 

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() 

1070 

1071 num_pad = (4 - (op_len % 4)) % 4 

1072 

1073 return 20 + op_len + num_pad 

1074 

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") 

1081 

1082 

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") 

1092 

1093 new_option = IPOption(op_type, op_len) 

1094 new_option.set_bytes(opt_bytes[:op_len]) 

1095 

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 

1101 

1102 

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 

1117 

1118 

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 

1126 

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") 

1130 

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) 

1144 

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) 

1152 

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) 

1160 

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) 

1175 

1176 

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) 

1181 

1182 p = self.get_ptr() 

1183 if not p: 

1184 raise ImpactPacketException("append_ip() failed, option ptr uninitialized") 

1185 

1186 if (p + 4) > self.get_len(): 

1187 raise ImpactPacketException("append_ip() would overflow option") 

1188 

1189 self.set_ip_address(p - 1, ip) 

1190 p += 4 

1191 self.set_ptr(p) 

1192 

1193 

1194 def set_code(self, value): 

1195 self.set_byte(0, value) 

1196 

1197 def get_code(self): 

1198 return self.get_byte(0) 

1199 

1200 

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) 

1205 

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) 

1210 

1211 

1212 def set_len(self, len): 

1213 self.set_byte(1, len) 

1214 

1215 

1216 def set_ptr(self, ptr): 

1217 self.set_byte(2, ptr) 

1218 

1219 def get_ptr(self): 

1220 return self.get_byte(2) 

1221 

1222 def get_len(self): 

1223 return len(self.get_bytes()) 

1224 

1225 

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 "} 

1233 

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 

1240 

1241 if op == IPOption.IPOPT_RR or op == IPOption.IPOPT_LSRR or op ==IPOption.IPOPT_SSRR: 

1242 tmp_str += self.print_addresses() 

1243 

1244 

1245 return tmp_str 

1246 

1247 

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 

1265 

1266 

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) 

1273 

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) 

1278 

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) 

1283 

1284 def get_uh_ulen(self): 

1285 return self.get_word(4) 

1286 

1287 def set_uh_ulen(self, value): 

1288 self.set_word(4, value) 

1289 

1290 def get_uh_sum(self): 

1291 return self.get_word(6) 

1292 

1293 def set_uh_sum(self, value): 

1294 self.set_word(6, value) 

1295 self.auto_checksum = 0 

1296 

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 

1303 

1304 buffer = self.parent().get_pseudo_header() 

1305 

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)) 

1311 

1312 def get_header_size(self): 

1313 return 8 

1314 

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 

1320 

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) 

1326 

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) 

1336 

1337 def add_option(self, option): 

1338 self.__option_list.append(option) 

1339 

1340 sum = 0 

1341 for op in self.__option_list: 

1342 sum += op.get_size() 

1343 

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") 

1346 

1347 def get_options(self): 

1348 return self.__option_list 

1349 

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) 

1354 

1355 # 

1356 # Header field accessors 

1357 # 

1358 

1359 def set_th_sport(self, aValue): 

1360 self.set_word(0, aValue) 

1361 

1362 def get_th_sport(self): 

1363 return self.get_word(0) 

1364 

1365 def get_th_dport(self): 

1366 return self.get_word(2) 

1367 

1368 def set_th_dport(self, aValue): 

1369 self.set_word(2, aValue) 

1370 

1371 def get_th_seq(self): 

1372 return self.get_long(4) 

1373 

1374 def set_th_seq(self, aValue): 

1375 self.set_long(4, aValue) 

1376 

1377 def get_th_ack(self): 

1378 return self.get_long(8) 

1379 

1380 def set_th_ack(self, aValue): 

1381 self.set_long(8, aValue) 

1382 

1383 def get_th_flags(self): 

1384 return self.get_word(12) & self.TCP_FLAGS_MASK 

1385 

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, ">") 

1390 

1391 def get_th_win(self): 

1392 return self.get_word(14) 

1393 

1394 def set_th_win(self, aValue): 

1395 self.set_word(14, aValue) 

1396 

1397 def set_th_sum(self, aValue): 

1398 self.set_word(16, aValue) 

1399 self.auto_checksum = 0 

1400 

1401 def get_th_sum(self): 

1402 return self.get_word(16) 

1403 

1404 def get_th_urp(self): 

1405 return self.get_word(18) 

1406 

1407 def set_th_urp(self, aValue): 

1408 return self.set_word(18, aValue) 

1409 

1410 # Flag accessors 

1411 

1412 def get_th_reserved(self): 

1413 tmp_value = self.get_byte(12) & 0x0f 

1414 return tmp_value 

1415 

1416 

1417 def get_th_off(self): 

1418 tmp_value = self.get_byte(12) >> 4 

1419 return tmp_value 

1420 

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) 

1426 

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) 

1433 

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) 

1440 

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) 

1447 

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) 

1454 

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) 

1461 

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) 

1468 

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) 

1475 

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) 

1482 

1483 # Overridden Methods 

1484 

1485 def get_header_size(self): 

1486 return 20 + len(self.get_padded_options()) 

1487 

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 

1491 

1492 self.set_th_sum(0) 

1493 buffer = self.parent().get_pseudo_header() 

1494 buffer += self.get_bytes() 

1495 buffer += self.get_padded_options() 

1496 

1497 data = self.get_data_as_string() 

1498 if(data): 

1499 array_frombytes(buffer, data) 

1500 

1501 res = self.compute_checksum(buffer) 

1502 

1503 self.set_th_sum(self.compute_checksum(buffer)) 

1504 

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" 

1507 

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) 

1511 

1512 self.calculate_checksum() 

1513 

1514 bytes = self.get_bytes() + self.get_padded_options() 

1515 data = self.get_data_as_string() 

1516 

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) 

1521 

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") 

1528 

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") 

1540 

1541 new_option = TCPOption(op_kind) 

1542 new_option.set_bytes(opt_bytes[:op_len]) 

1543 

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 

1549 

1550 # 

1551 # Private 

1552 # 

1553 

1554 def get_flag(self, bit): 

1555 if self.get_th_flags() & bit: 

1556 return 1 

1557 else: 

1558 return 0 

1559 

1560 def reset_flags(self, aValue): 

1561 tmp_value = self.get_th_flags() & (~aValue) 

1562 return self.set_th_flags(tmp_value) 

1563 

1564 def set_flags(self, aValue): 

1565 tmp_value = self.get_th_flags() | aValue 

1566 return self.set_th_flags(tmp_value) 

1567 

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 

1577 

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) 

1599 

1600 if self.child(): 

1601 tmp_str += '\n' + str(self.child()) 

1602 return tmp_str 

1603 

1604 

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 

1614 

1615 

1616 def __init__(self, kind, data = None): 

1617 

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) 

1652 

1653 elif kind == TCPOption.TCPOPT_SACK: 

1654 PacketBuffer.__init__(self, 2) 

1655 self.set_kind(TCPOption.TCPOPT_SACK) 

1656 

1657 def set_left_edge(self, aValue): 

1658 self.set_long (2, aValue) 

1659 

1660 def set_right_edge(self, aValue): 

1661 self.set_long (6, aValue) 

1662 

1663 def set_kind(self, kind): 

1664 self.set_byte(0, kind) 

1665 

1666 

1667 def get_kind(self): 

1668 return self.get_byte(0) 

1669 

1670 

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) 

1675 

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) 

1680 

1681 def get_size(self): 

1682 return len(self.get_bytes()) 

1683 

1684 

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) 

1689 

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) 

1694 

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) 

1699 

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) 

1704 

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) 

1709 

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) 

1714 

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) 

1719 

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) 

1724 

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 " } 

1731 

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 

1745 

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 

1789 

1790 def __init__(self, aBuffer = None): 

1791 Header.__init__(self, 8) 

1792 if aBuffer: 

1793 self.load_header(aBuffer) 

1794 

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 

1801 

1802 def get_icmp_type(self): 

1803 return self.get_byte(0) 

1804 

1805 def set_icmp_type(self, aValue): 

1806 self.set_byte(0, aValue) 

1807 

1808 def get_icmp_code(self): 

1809 return self.get_byte(1) 

1810 

1811 def set_icmp_code(self, aValue): 

1812 self.set_byte(1, aValue) 

1813 

1814 def get_icmp_cksum(self): 

1815 return self.get_word(2) 

1816 

1817 def set_icmp_cksum(self, aValue): 

1818 self.set_word(2, aValue) 

1819 self.auto_checksum = 0 

1820 

1821 def get_icmp_gwaddr(self): 

1822 return self.get_ip_address(4) 

1823 

1824 def set_icmp_gwaddr(self, ip): 

1825 self.set_ip_address(4, ip) 

1826 

1827 def get_icmp_id(self): 

1828 return self.get_word(4) 

1829 

1830 def set_icmp_id(self, aValue): 

1831 self.set_word(4, aValue) 

1832 

1833 def get_icmp_seq(self): 

1834 return self.get_word(6) 

1835 

1836 def set_icmp_seq(self, aValue): 

1837 self.set_word(6, aValue) 

1838 

1839 def get_icmp_void(self): 

1840 return self.get_long(4) 

1841 

1842 def set_icmp_void(self, aValue): 

1843 self.set_long(4, aValue) 

1844 

1845 

1846 def get_icmp_nextmtu(self): 

1847 return self.get_word(6) 

1848 

1849 def set_icmp_nextmtu(self, aValue): 

1850 self.set_word(6, aValue) 

1851 

1852 def get_icmp_num_addrs(self): 

1853 return self.get_byte(4) 

1854 

1855 def set_icmp_num_addrs(self, aValue): 

1856 self.set_byte(4, aValue) 

1857 

1858 def get_icmp_wpa(self): 

1859 return self.get_byte(5) 

1860 

1861 def set_icmp_wpa(self, aValue): 

1862 self.set_byte(5, aValue) 

1863 

1864 def get_icmp_lifetime(self): 

1865 return self.get_word(6) 

1866 

1867 def set_icmp_lifetime(self, aValue): 

1868 self.set_word(6, aValue) 

1869 

1870 def get_icmp_otime(self): 

1871 return self.get_long(8) 

1872 

1873 def set_icmp_otime(self, aValue): 

1874 self.set_long(8, aValue) 

1875 

1876 def get_icmp_rtime(self): 

1877 return self.get_long(12) 

1878 

1879 def set_icmp_rtime(self, aValue): 

1880 self.set_long(12, aValue) 

1881 

1882 def get_icmp_ttime(self): 

1883 return self.get_long(16) 

1884 

1885 def set_icmp_ttime(self, aValue): 

1886 self.set_long(16, aValue) 

1887 

1888 def get_icmp_mask(self): 

1889 return self.get_ip_address(8) 

1890 

1891 def set_icmp_mask(self, mask): 

1892 self.set_ip_address(8, mask) 

1893 

1894 

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 

1901 

1902 tmp_array = array.array('B', buffer) 

1903 self.set_icmp_cksum(self.compute_checksum(tmp_array)) 

1904 

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 

1909 

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' 

1925 

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 

1934 

1935 def isDestinationUnreachable(self): 

1936 return self.get_icmp_type() == 3 

1937 

1938 def isError(self): 

1939 return not self.isQuery() 

1940 

1941 def isHostUnreachable(self): 

1942 return self.isDestinationUnreachable() and (self.get_icmp_code() == 1) 

1943 

1944 def isNetUnreachable(self): 

1945 return self.isDestinationUnreachable() and (self.get_icmp_code() == 0) 

1946 

1947 def isPortUnreachable(self): 

1948 return self.isDestinationUnreachable() and (self.get_icmp_code() == 3) 

1949 

1950 def isProtocolUnreachable(self): 

1951 return self.isDestinationUnreachable() and (self.get_icmp_code() == 2) 

1952 

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 

1956 

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) 

1963 

1964 def get_igmp_type(self): 

1965 return self.get_byte(0) 

1966 

1967 def set_igmp_type(self, aValue): 

1968 self.set_byte(0, aValue) 

1969 

1970 def get_igmp_code(self): 

1971 return self.get_byte(1) 

1972 

1973 def set_igmp_code(self, aValue): 

1974 self.set_byte(1, aValue) 

1975 

1976 def get_igmp_cksum(self): 

1977 return self.get_word(2) 

1978 

1979 def set_igmp_cksum(self, aValue): 

1980 self.set_word(2, aValue) 

1981 

1982 def get_igmp_group(self): 

1983 return self.get_long(4) 

1984 

1985 def set_igmp_group(self, aValue): 

1986 self.set_long(4, aValue) 

1987 

1988 def get_header_size(self): 

1989 return 8 

1990 

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 

1995 

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())) 

1999 

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 

2006 

2007 

2008 

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) 

2015 

2016 def get_ar_hrd(self): 

2017 return self.get_word(0) 

2018 

2019 def set_ar_hrd(self, aValue): 

2020 self.set_word(0, aValue) 

2021 

2022 def get_ar_pro(self): 

2023 return self.get_word(2) 

2024 

2025 def set_ar_pro(self, aValue): 

2026 self.set_word(2, aValue) 

2027 

2028 def get_ar_hln(self): 

2029 return self.get_byte(4) 

2030 

2031 def set_ar_hln(self, aValue): 

2032 self.set_byte(4, aValue) 

2033 

2034 def get_ar_pln(self): 

2035 return self.get_byte(5) 

2036 

2037 def set_ar_pln(self, aValue): 

2038 self.set_byte(5, aValue) 

2039 

2040 def get_ar_op(self): 

2041 return self.get_word(6) 

2042 

2043 def set_ar_op(self, aValue): 

2044 self.set_word(6, aValue) 

2045 

2046 def get_ar_sha(self): 

2047 tmp_size = self.get_ar_hln() 

2048 return self.get_bytes().tolist()[8: 8 + tmp_size] 

2049 

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]) 

2053 

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] 

2057 

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]) 

2061 

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] 

2066 

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]) 

2071 

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] 

2076 

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]) 

2081 

2082 def get_header_size(self): 

2083 return 8 + (2 * self.get_ar_hln()) + (2 * self.get_ar_pln()) 

2084 

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 

2089 

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 

2094 

2095 

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 

2103 

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 

2111 

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 

2123 

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)