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

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

## 1455 statements

Hot-keys on this page

r m x p toggle line displays

j k next/prev highlighted chunk

0 (zero) top of page

1 (one) first highlighted chunk

1# Impacket - Collection of Python classes for working with network protocols.

2#

3# SECUREAUTH LABS. Copyright (C) 2018 SecureAuth Corporation. All rights reserved.

4#

5# This software is provided under a slightly modified version

6# of the Apache Software License. See the accompanying LICENSE file

7# for more information.

8#

9# Description:

10# Network packet codecs basic building blocks.

11# Low-level packet codecs for various Internet protocols.

12#

13# Author:

14# Javier Burroni (javier)

15# Bruce Leidl (brl)

16# Javier Kohen (jkohen)

17#

18

19 from __future__ import division

20 from __future__ import print_function

21 import array

22 import struct

23 import socket

24 import string

25 import sys

26 from binascii import hexlify

27 from functools import reduce

28

29# Alias function for compatibility with both Python <3.2 `tostring` and `fromstring` methods, and

30# Python >=3.2 `tobytes` and `tostring`

31 if sys.version_info[0] >= 3 and sys.version_info[1] >= 2: 31 ↛ 35line 31 didn't jump to line 35, because the condition on line 31 was never false

32 array_tobytes = lambda array_object: array_object.tobytes()

33 array_frombytes = lambda array_object, bytes: array_object.frombytes(bytes)

34 else:

35 array_tobytes = lambda array_object: array_object.tostring()

36 array_frombytes = lambda array_object, bytes: array_object.fromstring(bytes)

37

38

39"""Classes to build network packets programmatically.

40

41 Each protocol layer is represented by an object, and these objects are

42 hierarchically structured to form a packet. This list is traversable

43 in both directions: from parent to child and vice versa.

44

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

46 the wire (see method get_packet).

47"""

48

49 class ImpactPacketException(Exception):

50 def __init__(self, value):

51 self.value = value

52 def __str__(self):

53 return repr(self.value)

54

55 class PacketBuffer(object):

56 """Implement the basic operations utilized to operate on a

57 packet's raw buffer. All the packet classes derive from this one.

58

59 The byte, word, long and ip_address getters and setters accept

60 negative indexes, having these the a similar effect as in a

61 regular Python sequence slice.

62 """

63

64 def __init__(self, length = None):

65 "If 'length' is specified the buffer is created with an initial size"

66 if length:

67 self.__bytes = array.array('B', b'\0' * length)

68 else:

69 self.__bytes = array.array('B')

70

71 def set_bytes_from_string(self, data):

72 "Sets the value of the packet buffer from the string 'data'"

73 self.__bytes = array.array('B', data)

74

75 def get_buffer_as_string(self):

76 "Returns the packet buffer as a string object"

77 return array_tobytes(self.__bytes)

78

79 def get_bytes(self):

80 "Returns the packet buffer as an array"

81 return self.__bytes

82

83 def set_bytes(self, bytes):

84 "Set the packet buffer from an array"

85 # Make a copy to be safe

86 self.__bytes = array.array('B', bytes.tolist())

87

88 def set_byte(self, index, value):

89 "Set byte at 'index' to 'value'"

90 index = self.__validate_index(index, 1)

91 self.__bytes[index] = value

92

93 def get_byte(self, index):

94 "Return byte at 'index'"

95 index = self.__validate_index(index, 1)

96 return self.__bytes[index]

97

98 def set_word(self, index, value, order = '!'):

99 "Set 2-byte word at 'index' to 'value'. See struct module's documentation to understand the meaning of 'order'."

100 index = self.__validate_index(index, 2)

101 ary = array.array("B", struct.pack(order + 'H', value))

102 if -2 == index: 102 ↛ 103line 102 didn't jump to line 103, because the condition on line 102 was never true

103 self.__bytes[index:] = ary

104 else:

105 self.__bytes[index: index+2] = ary

106

107 def get_word(self, index, order = '!'):

108 "Return 2-byte word at 'index'. See struct module's documentation to understand the meaning of 'order'."

109 index = self.__validate_index(index, 2)

110 if -2 == index: 110 ↛ 111line 110 didn't jump to line 111, because the condition on line 110 was never true

111 bytes = self.__bytes[index:]

112 else:

113 bytes = self.__bytes[index: index+2]

114 (value,) = struct.unpack(order + 'H', array_tobytes(bytes))

115 return value

116

117 def set_long(self, index, value, order = '!'):

118 "Set 4-byte 'value' at 'index'. See struct module's documentation to understand the meaning of 'order'."

119 index = self.__validate_index(index, 4)

120 ary = array.array("B", struct.pack(order + 'L', value))

121 if -4 == index:

122 self.__bytes[index:] = ary

123 else:

124 self.__bytes[index: index+4] = ary

125

126 def get_long(self, index, order = '!'):

127 "Return 4-byte value at 'index'. See struct module's documentation to understand the meaning of 'order'."

128 index = self.__validate_index(index, 4)

129 if -4 == index:

130 bytes = self.__bytes[index:]

131 else:

132 bytes = self.__bytes[index: index+4]

133 (value,) = struct.unpack(order + 'L', array_tobytes(bytes))

134 return value

135

136 def set_long_long(self, index, value, order = '!'):

137 "Set 8-byte 'value' at 'index'. See struct module's documentation to understand the meaning of 'order'."

138 index = self.__validate_index(index, 8)

139 ary = array.array("B", struct.pack(order + 'Q', value))

140 if -8 == index: 140 ↛ 141line 140 didn't jump to line 141, because the condition on line 140 was never true

141 self.__bytes[index:] = ary

142 else:

143 self.__bytes[index: index+8] = ary

144

145 def get_long_long(self, index, order = '!'):

146 "Return 8-byte value at 'index'. See struct module's documentation to understand the meaning of 'order'."

147 index = self.__validate_index(index, 8)

148 if -8 == index: 148 ↛ 149line 148 didn't jump to line 149, because the condition on line 148 was never true

149 bytes = self.__bytes[index:]

150 else:

151 bytes = self.__bytes[index: index+8]

152 (value,) = struct.unpack(order + 'Q', array_tobytes(bytes))

153 return value

154

155

156 def get_ip_address(self, index):

157 "Return 4-byte value at 'index' as an IP string"

158 index = self.__validate_index(index, 4)

159 if -4 == index: 159 ↛ 160line 159 didn't jump to line 160, because the condition on line 159 was never true

160 bytes = self.__bytes[index:]

161 else:

162 bytes = self.__bytes[index: index+4]

163 return socket.inet_ntoa(array_tobytes(bytes))

164

165 def set_ip_address(self, index, ip_string):

166 "Set 4-byte value at 'index' from 'ip_string'"

167 index = self.__validate_index(index, 4)

168 raw = socket.inet_aton(ip_string)

169 (b1,b2,b3,b4) = struct.unpack("BBBB", raw)

170 self.set_byte(index, b1)

171 self.set_byte(index + 1, b2)

172 self.set_byte(index + 2, b3)

173 self.set_byte(index + 3, b4)

174

175 def set_checksum_from_data(self, index, data):

176 "Set 16-bit checksum at 'index' by calculating checksum of 'data'"

177 self.set_word(index, self.compute_checksum(data))

178

179 def compute_checksum(self, anArray):

180 "Return the one's complement of the one's complement sum of all the 16-bit words in 'anArray'"

181 nleft = len(anArray)

182 sum = 0

183 pos = 0

184 while nleft > 1:

185 sum = anArray[pos] * 256 + (anArray[pos + 1] + sum)

186 pos = pos + 2

187 nleft = nleft - 2

188 if nleft == 1:

189 sum = sum + anArray[pos] * 256

190 return self.normalize_checksum(sum)

191

192 def normalize_checksum(self, aValue):

193 sum = aValue

194 sum = (sum >> 16) + (sum & 0xFFFF)

195 sum += (sum >> 16)

196 sum = (~sum & 0xFFFF)

197 return sum

198

199 def __validate_index(self, index, size):

200 """This method performs two tasks: to allocate enough space to

201 fit the elements at positions index through index+size, and to

202 adjust negative indexes to their absolute equivalent.

203 """

204

205 orig_index = index

206

207 curlen = len(self.__bytes)

208 if index < 0:

209 index = curlen + index

210

211 diff = index + size - curlen

212 if diff > 0:

213 array_frombytes(self.__bytes, b'\0' * diff)

214 if orig_index < 0: 214 ↛ 215line 214 didn't jump to line 215, because the condition on line 214 was never true

215 orig_index -= diff

216

217 return orig_index

218

219 class ProtocolLayer():

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

221

222 __child = None

223 __parent = None

224

225 def contains(self, aHeader):

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

227 self.__child = aHeader

228 aHeader.set_parent(self)

229

230 def set_parent(self, my_parent):

231 "Set the header 'my_parent' as the parent of this protocol layer"

232 self.__parent = my_parent

233

234 def child(self):

235 "Return the child of this protocol layer"

236 return self.__child

237

238 def parent(self):

239 "Return the parent of this protocol layer"

240 return self.__parent

241

242 def unlink_child(self):

243 "Break the hierarchy parent/child child/parent"

244 if self.__child:

245 self.__child.set_parent(None)

246 self.__child = None

247

248 class ProtocolPacket(ProtocolLayer):

249 __HEADER_SIZE = 0

250 __BODY_SIZE = 0

251 __TAIL_SIZE = 0

252

253 __header = None

254 __body = None

255 __tail = None

256

257 def __init__(self, header_size, tail_size):

258 self.__HEADER_SIZE = header_size

259 self.__TAIL_SIZE = tail_size

260 self.__header=PacketBuffer(self.__HEADER_SIZE)

261 self.__body=PacketBuffer()

262 self.__tail=PacketBuffer(self.__TAIL_SIZE)

263

264 def __update_body_from_child(self):

265 # Update child raw packet in my body

266 if self.child():

267 body=self.child().get_packet()

268 self.__BODY_SIZE=len(body)

269 self.__body.set_bytes_from_string(body)

270

271 def __get_header(self):

272 return self.__header

273

274 header = property(__get_header)

275

276 def __get_body(self):

277 self.__update_body_from_child()

278 return self.__body

279

280 body = property(__get_body)

281

282 def __get_tail(self):

283 return self.__tail

284

285 tail = property(__get_tail)

286

287 def get_header_size(self):

288 "Return frame header size"

289 return self.__HEADER_SIZE

290

291 def get_tail_size(self):

292 "Return frame tail size"

293 return self.__TAIL_SIZE

294

295 def get_body_size(self):

296 "Return frame body size"

297 self.__update_body_from_child()

298 return self.__BODY_SIZE

299

300 def get_size(self):

301 "Return frame total size"

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

303

304 def load_header(self, aBuffer):

305 self.__HEADER_SIZE=len(aBuffer)

306 self.__header.set_bytes_from_string(aBuffer)

307

308 def load_body(self, aBuffer):

309 "Load the packet body from string. "\

310 "WARNING: Using this function will break the hierarchy of preceding protocol layer"

311 self.unlink_child()

312 self.__BODY_SIZE=len(aBuffer)

313 self.__body.set_bytes_from_string(aBuffer)

314

315 def load_tail(self, aBuffer):

316 self.__TAIL_SIZE=len(aBuffer)

317 self.__tail.set_bytes_from_string(aBuffer)

318

319 def __extract_header(self, aBuffer):

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

321

322 def __extract_body(self, aBuffer):

323 if self.__TAIL_SIZE<=0:

324 end=None

325 else:

326 end=-self.__TAIL_SIZE

327 self.__BODY_SIZE=len(aBuffer[self.__HEADER_SIZE: end])

328 self.__body.set_bytes_from_string(aBuffer[self.__HEADER_SIZE: end])

329

330 def __extract_tail(self, aBuffer):

331 if self.__TAIL_SIZE<=0:

332 # leave the array empty

333 return

334 else:

335 start=-self.__TAIL_SIZE

336 self.__tail.set_bytes_from_string(aBuffer[start:])

337

338 def load_packet(self, aBuffer):

339 "Load the whole packet from a string" \

340 "WARNING: Using this function will break the hierarchy of preceding protocol layer"

341 self.unlink_child()

342

343 self.__extract_header(aBuffer)

344 self.__extract_body(aBuffer)

345 self.__extract_tail(aBuffer)

346

347 def get_header_as_string(self):

348 return self.__header.get_buffer_as_string()

349

350 def get_body_as_string(self):

351 self.__update_body_from_child()

352 return self.__body.get_buffer_as_string()

353 body_string = property(get_body_as_string)

354

355 def get_tail_as_string(self):

356 return self.__tail.get_buffer_as_string()

357 tail_string = property(get_tail_as_string)

358

359 def get_packet(self):

360 self.__update_body_from_child()

361

362 ret = b''

363

364 header = self.get_header_as_string()

365 if header:

366 ret += header

367

368 body = self.get_body_as_string()

369 if body:

370 ret += body

371

372 tail = self.get_tail_as_string()

373 if tail:

374 ret += tail

375

376 return ret

377

378 class Header(PacketBuffer,ProtocolLayer):

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

380

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

382

383 ethertype = None

384 protocol = None

385 def __init__(self, length = None):

386 PacketBuffer.__init__(self, length)

387 self.auto_checksum = 1

388

389 def get_data_as_string(self):

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

391

392 if self.child():

393 return self.child().get_packet()

394 else:

395 return None

396

397 def get_packet(self):

398 """Returns the raw representation of this packet and its

399 children as a string. The output from this method is a packet

400 ready to be transmitted over the wire.

401 """

402 self.calculate_checksum()

403

404 data = self.get_data_as_string()

405 if data:

406 return self.get_buffer_as_string() + data

407 else:

408 return self.get_buffer_as_string()

409

410 def get_size(self):

411 "Return the size of this header and all of it's children"

412 tmp_value = self.get_header_size()

413 if self.child():

414 tmp_value = tmp_value + self.child().get_size()

415 return tmp_value

416

417 def calculate_checksum(self):

418 "Calculate and set the checksum for this header"

419 pass

420

421 def get_pseudo_header(self):

422 "Pseudo headers can be used to limit over what content will the checksums be calculated."

423 # default implementation returns empty array

424 return array.array('B')

425

426 def load_header(self, aBuffer):

427 "Properly set the state of this instance to reflect that of the raw packet passed as argument."

428 self.set_bytes_from_string(aBuffer)

429 hdr_len = self.get_header_size()

430 if(len(aBuffer) < hdr_len): #we must do something like this 430 ↛ 431line 430 didn't jump to line 431, because the condition on line 430 was never true

431 diff = hdr_len - len(aBuffer)

432 for i in range(0, diff):

433 aBuffer += '\x00'

434 self.set_bytes_from_string(aBuffer[:hdr_len])

435

436 def get_header_size(self):

437 "Return the size of this header, that is, not counting neither the size of the children nor of the parents."

438 raise RuntimeError("Method %s.get_header_size must be overridden." % self.__class__)

439

440 def list_as_hex(self, aList):

441 if len(aList):

442 ltmp = []

443 line = []

444 count = 0

445 for byte in aList:

446 if not (count % 2):

447 if (count % 16):

448 ltmp.append(' ')

449 else:

450 ltmp.append(' '*4)

451 ltmp.append(''.join(line))

452 ltmp.append('\n')

453 line = []

454 if chr(byte) in Header.packet_printable:

455 line.append(chr(byte))

456 else:

457 line.append('.')

458 ltmp.append('%.2x' % byte)

459 count += 1

460 if (count%16):

461 left = 16 - (count%16)

462 ltmp.append(' ' * (4+(left // 2) + (left*2)))

463 ltmp.append(''.join(line))

464 ltmp.append('\n')

465 return ltmp

466 else:

467 return []

468

469 def __str__(self):

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

471

472 if self.child():

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

474

475 if len(ltmp)>0:

476 return ''.join(ltmp)

477 else:

478 return ''

479

480

481

482 class Data(Header):

483 """This packet type can hold raw data. It's normally employed to

484 hold a packet's innermost layer's contents in those cases for

485 which the protocol details are unknown, and there's a copy of a

486 valid packet available.

487

488 For instance, if all that's known about a certain protocol is that

489 a UDP packet with its contents set to "HELLO" initiate a new

490 session, creating such packet is as simple as in the following code

491 fragment:

492 packet = UDP()

493 packet.contains('HELLO')

494 """

495

496 def __init__(self, aBuffer = None):

497 Header.__init__(self)

498 if aBuffer:

499 self.set_data(aBuffer)

500

501 def set_data(self, data):

502 self.set_bytes_from_string(data)

503

504 def get_size(self):

505 return len(self.get_bytes())

506

507

508 class EthernetTag(PacketBuffer):

509 """Represents a VLAN header specified in IEEE 802.1Q and 802.1ad.

510 Provides methods for convenient manipulation with header fields."""

511

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

513 PacketBuffer.__init__(self, 4)

514 self.set_long(0, value)

515

516 def get_tpid(self):

517 """Returns Tag Protocol Identifier"""

518 return self.get_word(0)

519

520 def set_tpid(self, value):

521 """Sets Tag Protocol Identifier"""

522 return self.set_word(0, value)

523

524 def get_pcp(self):

525 """Returns Priority Code Point"""

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

527

528 def set_pcp(self, value):

529 """Sets Priority Code Point"""

530 orig_value = self.get_byte(2)

531 self.set_byte(2, (orig_value & 0x1F) | ((value & 0x07) << 5))

532

533 def get_dei(self):

534 """Returns Drop Eligible Indicator"""

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

536

537 def set_dei(self, value):

538 """Sets Drop Eligible Indicator"""

539 orig_value = self.get_byte(2)

540 self.set_byte(2, orig_value | 0x10 if value else orig_value & 0xEF)

541

542 def get_vid(self):

543 """Returns VLAN Identifier"""

544 return self.get_word(2) & 0x0FFF

545

546 def set_vid(self, value):

547 """Sets VLAN Identifier"""

548 orig_value = self.get_word(2)

549 self.set_word(2, (orig_value & 0xF000) | (value & 0x0FFF))

550

551 def __str__(self):

552 priorities = (

553 'Best Effort',

554 'Background',

555 'Excellent Effort',

556 'Critical Applications',

557 'Video, < 100 ms latency and jitter',

558 'Voice, < 10 ms latency and jitter',

559 'Internetwork Control',

560 'Network Control')

561

562 pcp = self.get_pcp()

563 return '\n'.join((

564 '802.1Q header: 0x{0:08X}'.format(self.get_long(0)),

565 'Priority Code Point: {0} ({1})'.format(pcp, priorities[pcp]),

566 'Drop Eligible Indicator: {0}'.format(self.get_dei()),

567 'VLAN Identifier: {0}'.format(self.get_vid())))

568

569

570 class Ethernet(Header):

571 def __init__(self, aBuffer = None):

572 Header.__init__(self, 14)

573 self.tag_cnt = 0

574 if(aBuffer): 574 ↛ exitline 574 didn't return from function '__init__', because the condition on line 574 was never false

575 self.load_header(aBuffer)

576

577 def set_ether_type(self, aValue):

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

579 self.set_word(12 + 4*self.tag_cnt, aValue)

580

581 def get_ether_type(self):

582 "Return ethernet data type field"

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

584

585 def get_tag(self, index):

586 """Returns an EthernetTag initialized from index-th VLAN tag.

587 The tags are numbered from 0 to self.tag_cnt-1 as they appear in the frame.

588 It is possible to use negative indexes as well."""

589 index = self.__validate_tag_index(index)

590 return EthernetTag(self.get_long(12+4*index))

591

592 def set_tag(self, index, tag):

593 """Sets the index-th VLAN tag to contents of an EthernetTag object.

594 The tags are numbered from 0 to self.tag_cnt-1 as they appear in the frame.

595 It is possible to use negative indexes as well."""

596 index = self.__validate_tag_index(index)

597 pos = 12 + 4*index

598 for i,val in enumerate(tag.get_bytes()):

599 self.set_byte(pos+i, val)

600

601 def push_tag(self, tag, index=0):

602 """Inserts contents of an EthernetTag object before the index-th VLAN tag.

603 Index defaults to 0 (the top of the stack)."""

604 if index < 0: 604 ↛ 605line 604 didn't jump to line 605, because the condition on line 604 was never true

605 index += self.tag_cnt

606 pos = 12 + 4*max(0, min(index, self.tag_cnt))

607 data = self.get_bytes()

608 data[pos: pos] = tag.get_bytes()

609 self.set_bytes(data)

610 self.tag_cnt += 1

611

612 def pop_tag(self, index=0):

613 """Removes the index-th VLAN tag and returns it as an EthernetTag object.

614 Index defaults to 0 (the top of the stack)."""

615 index = self.__validate_tag_index(index)

616 pos = 12 + 4*index

617 tag = self.get_long(pos)

618 data = self.get_bytes()

619 del data[pos: pos+4]

620 self.set_bytes(data)

621 self.tag_cnt -= 1

622 return EthernetTag(tag)

623

624 def load_header(self, aBuffer):

625 self.tag_cnt = 0

626 while aBuffer[12+4*self.tag_cnt:14+4*self.tag_cnt] in (b'\x81\x00', b'\x88\xa8', b'\x91\x00'):

627 self.tag_cnt += 1

628

629 hdr_len = self.get_header_size()

630 diff = hdr_len - len(aBuffer)

631 if diff > 0: 631 ↛ 632line 631 didn't jump to line 632, because the condition on line 631 was never true

632 aBuffer += b'\x00'*diff

633 self.set_bytes_from_string(aBuffer[:hdr_len])

634

635 def get_header_size(self):

636 "Return size of Ethernet header"

637 return 14 + 4*self.tag_cnt

638

639 def get_packet(self):

640

641 if self.child(): 641 ↛ 642line 641 didn't jump to line 642, because the condition on line 641 was never true

642 try:

643 self.set_ether_type(self.child().ethertype)

644 except:

645 " an Ethernet packet may have a Data() "

646 pass

647 return Header.get_packet(self)

648

649 def get_ether_dhost(self):

650 "Return 48 bit destination ethernet address as a 6 byte array"

651 return self.get_bytes()[0:6]

652

653 def set_ether_dhost(self, aValue):

654 "Set destination ethernet address from 6 byte array 'aValue'"

655 for i in range(0, 6):

656 self.set_byte(i, aValue[i])

657

658 def get_ether_shost(self):

659 "Return 48 bit source ethernet address as a 6 byte array"

660 return self.get_bytes()[6:12]

661

662 def set_ether_shost(self, aValue):

663 "Set source ethernet address from 6 byte array 'aValue'"

664 for i in range(0, 6):

665 self.set_byte(i + 6, aValue[i])

666

667 @staticmethod

668 def as_eth_addr(anArray):

669 tmp_list = [x > 15 and '%x'%x or '0%x'%x for x in anArray]

670 return '' + reduce(lambda x, y: x+':'+y, tmp_list)

671

672 def __str__(self):

673 tmp_str = 'Ether: ' + self.as_eth_addr(self.get_ether_shost()) + ' -> '

674 tmp_str += self.as_eth_addr(self.get_ether_dhost())

675 if self.child():

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

677 return tmp_str

678

679 def __validate_tag_index(self, index):

680 """Adjusts negative indices to their absolute equivalents.

681 Raises IndexError when out of range <0, self.tag_cnt-1>."""

682 if index < 0:

683 index += self.tag_cnt

684 if index < 0 or index >= self.tag_cnt:

685 raise IndexError("Tag index out of range")

686 return index

687

688# Linux "cooked" capture encapsulation.

689# Used, for instance, for packets returned by the "any" interface.

690 class LinuxSLL(Header):

691 type_descriptions = [

692 "sent to us by somebody else",

693 "broadcast by somebody else",

694 "multicast by somebody else",

695 "sent to somebody else to somebody else",

696 "sent by us",

697 ]

698

699 def __init__(self, aBuffer = None):

700 Header.__init__(self, 16)

701 if (aBuffer):

702 self.load_header(aBuffer)

703

704 def set_type(self, type):

705 "Sets the packet type field to type"

706 self.set_word(0, type)

707

708 def get_type(self):

709 "Returns the packet type field"

710 return self.get_word(0)

711

712 def set_arphdr(self, value):

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

714 self.set_word(2, type)

715

716 def get_arphdr(self):

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

718 return self.get_word(2)

719

720 def set_addr_len(self, len):

721 "Sets the length of the sender's address field to len"

722 self.set_word(4, len)

723

724 def get_addr_len(self):

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

726 return self.get_word(4)

727

728 def set_addr(self, addr):

729 "Sets the sender's address field to addr. Addr must be at most 8-byte long."

730 if (len(addr) < 8):

731 addr += b'\0' * (8 - len(addr))

732 self.get_bytes()[6:14] = addr

733

734 def get_addr(self):

735 "Returns the sender's address field"

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

737

738 def set_ether_type(self, aValue):

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

740 self.set_word(14, aValue)

741

742 def get_ether_type(self):

743 "Return ethernet data type field"

744 return self.get_word(14)

745

746 def get_header_size(self):

747 "Return size of packet header"

748 return 16

749

750 def get_packet(self):

751 if self.child():

752 self.set_ether_type(self.child().ethertype)

753 return Header.get_packet(self)

754

755 def get_type_desc(self):

756 type = self.get_type()

757 if type < len(LinuxSLL.type_descriptions):

758 return LinuxSLL.type_descriptions[type]

759 else:

760 return "Unknown"

761

762 def __str__(self):

763 ss = []

764 alen = self.get_addr_len()

765 addr = hexlify(self.get_addr()[0: alen])

766 ss.append("Linux SLL: addr=%s type=`%s'" % (addr, self.get_type_desc()))

767 if self.child():

768 ss.append(str(self.child()))

769

770 return '\n'.join(ss)

771

772

773 class IP(Header):

774 ethertype = 0x800

775 def __init__(self, aBuffer = None):

776 Header.__init__(self, 20)

777 self.set_ip_v(4)

778 self.set_ip_hl(5)

779 self.set_ip_ttl(255)

780 self.__option_list = []

781 if(aBuffer):

782 # When decoding, checksum shouldn't be modified

783 self.auto_checksum = 0

784 self.load_header(aBuffer)

785

786 if sys.platform.count('bsd'): 786 ↛ 787line 786 didn't jump to line 787, because the condition on line 786 was never true

787 self.is_BSD = True

788 else:

789 self.is_BSD = False

790

791

792 def get_packet(self):

793 # set protocol

794 if self.get_ip_p() == 0 and self.child(): 794 ↛ 795line 794 didn't jump to line 795, because the condition on line 794 was never true

795 self.set_ip_p(self.child().protocol)

796

797 # set total length

798 if self.get_ip_len() == 0:

799 self.set_ip_len(self.get_size())

800

801 child_data = self.get_data_as_string()

802

803 if self.auto_checksum:

804 self.reset_ip_sum()

805

806 my_bytes = self.get_bytes()

807

808 for op in self.__option_list: 808 ↛ 809line 808 didn't jump to line 809, because the loop on line 808 never started

809 my_bytes.extend(op.get_bytes())

810

811 # Pad to a multiple of 4 bytes

812 num_pad = (4 - (len(my_bytes) % 4)) % 4

813 if num_pad: 813 ↛ 814line 813 didn't jump to line 814, because the condition on line 813 was never true

814 array_frombytes(my_bytes, b"\0" * num_pad)

815

816 # only change ip_hl value if options are present

817 if len(self.__option_list): 817 ↛ 818line 817 didn't jump to line 818, because the condition on line 817 was never true

818 self.set_ip_hl(len(my_bytes) // 4)

819

820

821 # set the checksum if the user hasn't modified it

822 if self.auto_checksum:

823 self.set_ip_sum(self.compute_checksum(my_bytes))

824

825 if child_data is None: 825 ↛ 826line 825 didn't jump to line 826, because the condition on line 825 was never true

826 return array_tobytes(my_bytes)

827 else:

828 return array_tobytes(my_bytes) + child_data

829

830

831

832 # def calculate_checksum(self, buffer = None):

833 # tmp_value = self.get_ip_sum()

834 # if self.auto_checksum and (not tmp_value):

835 # if buffer:

836 # tmp_bytes = buffer

837 # else:

838 # tmp_bytes = self.bytes[0:self.get_header_size()]

839 #

840 # self.set_ip_sum(self.compute_checksum(tmp_bytes))

841

842

843 def get_pseudo_header(self):

844 pseudo_buf = array.array("B")

845 pseudo_buf.extend(self.get_bytes()[12:20])

846 pseudo_buf.fromlist([0])

847 pseudo_buf.extend(self.get_bytes()[9:10])

848 tmp_size = self.child().get_size()

849

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

851

852 array_frombytes(pseudo_buf, size_str)

853 return pseudo_buf

854

855 def add_option(self, option):

856 self.__option_list.append(option)

857 sum = 0

858 for op in self.__option_list:

859 sum += op.get_len()

860 if sum > 40:

861 raise ImpactPacketException("Options overflowed in IP packet with length: %d" % sum)

862

863

864 def get_ip_v(self):

865 n = self.get_byte(0)

866 return (n >> 4)

867

868 def set_ip_v(self, value):

869 n = self.get_byte(0)

870 version = value & 0xF

871 n = n & 0xF

872 n = n | (version << 4)

873 self.set_byte(0, n)

874

875 def get_ip_hl(self):

876 n = self.get_byte(0)

877 return (n & 0xF)

878

879 def set_ip_hl(self, value):

880 n = self.get_byte(0)

881 len = value & 0xF

882 n = n & 0xF0

883 n = (n | len)

884 self.set_byte(0, n)

885

886 def get_ip_tos(self):

887 return self.get_byte(1)

888

889 def set_ip_tos(self,value):

890 self.set_byte(1, value)

891

892 def get_ip_len(self):

893 if self.is_BSD: 893 ↛ 894line 893 didn't jump to line 894, because the condition on line 893 was never true

894 return self.get_word(2, order = '=')

895 else:

896 return self.get_word(2)

897

898 def set_ip_len(self, value):

899 if self.is_BSD: 899 ↛ 900line 899 didn't jump to line 900, because the condition on line 899 was never true

900 self.set_word(2, value, order = '=')

901 else:

902 self.set_word(2, value)

903

904 def get_ip_id(self):

905 return self.get_word(4)

906 def set_ip_id(self, value):

907 return self.set_word(4, value)

908

909 def get_ip_off(self):

910 if self.is_BSD: 910 ↛ 911line 910 didn't jump to line 911, because the condition on line 910 was never true

911 return self.get_word(6, order = '=')

912 else:

913 return self.get_word(6)

914

915 def set_ip_off(self, aValue):

916 if self.is_BSD: 916 ↛ 917line 916 didn't jump to line 917, because the condition on line 916 was never true

917 self.set_word(6, aValue, order = '=')

918 else:

919 self.set_word(6, aValue)

920

921 def get_ip_offmask(self):

922 return self.get_ip_off() & 0x1FFF

923

924 def set_ip_offmask(self, aValue):

925 tmp_value = self.get_ip_off() & 0xD000

926 tmp_value |= aValue

927 self.set_ip_off(tmp_value)

928

929 def get_ip_rf(self):

930 return self.get_ip_off() & 0x8000

931

932 def set_ip_rf(self, aValue):

933 tmp_value = self.get_ip_off()

934 if aValue: 934 ↛ 935line 934 didn't jump to line 935, because the condition on line 934 was never true

935 tmp_value |= 0x8000

936 else:

937 my_not = 0xFFFF ^ 0x8000

938 tmp_value &= my_not

939 self.set_ip_off(tmp_value)

940

941 def get_ip_df(self):

942 return self.get_ip_off() & 0x4000

943

944 def set_ip_df(self, aValue):

945 tmp_value = self.get_ip_off()

946 if aValue: 946 ↛ 947line 946 didn't jump to line 947, because the condition on line 946 was never true

947 tmp_value |= 0x4000

948 else:

949 my_not = 0xFFFF ^ 0x4000

950 tmp_value &= my_not

951 self.set_ip_off(tmp_value)

952

953 def get_ip_mf(self):

954 return self.get_ip_off() & 0x2000

955

956 def set_ip_mf(self, aValue):

957 tmp_value = self.get_ip_off()

958 if aValue: 958 ↛ 959line 958 didn't jump to line 959, because the condition on line 958 was never true

959 tmp_value |= 0x2000

960 else:

961 my_not = 0xFFFF ^ 0x2000

962 tmp_value &= my_not

963 self.set_ip_off(tmp_value)

964

965

966 def fragment_by_list(self, aList):

967 if self.child():

968 proto = self.child().protocol

969 else:

970 proto = 0

971

972 child_data = self.get_data_as_string()

973 if not child_data:

974 return [self]

975

976 ip_header_bytes = self.get_bytes()

977 current_offset = 0

978 fragment_list = []

979

980 for frag_size in aList:

981 ip = IP()

982 ip.set_bytes(ip_header_bytes) # copy of original header

983 ip.set_ip_p(proto)

984

985

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

987 frag_size += 8 - (frag_size % 8)

988

989

990 ip.set_ip_offmask(current_offset // 8)

991 current_offset += frag_size

992

993 data = Data(child_data[:frag_size])

994 child_data = child_data[frag_size:]

995

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

997 ip.contains(data)

998

999

1000 if child_data:

1001

1002 ip.set_ip_mf(1)

1003

1004 fragment_list.append(ip)

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

1006

1007 ip.set_ip_mf(0)

1008

1009 fragment_list.append(ip)

1010 return fragment_list

1011

1012 if child_data: # any remaining data?

1013 # create a fragment containing all of the remaining child_data

1014 ip = IP()

1015 ip.set_bytes(ip_header_bytes)

1016 ip.set_ip_offmask(current_offset)

1017 ip.set_ip_len(20 + len(child_data))

1018 data = Data(child_data)

1019 ip.contains(data)

1020 fragment_list.append(ip)

1021

1022 return fragment_list

1023

1024

1025 def fragment_by_size(self, aSize):

1026 data_len = len(self.get_data_as_string())

1027 num_frags = data_len // aSize

1028

1029 if data_len % aSize:

1030 num_frags += 1

1031

1032 size_list = []

1033 for i in range(0, num_frags):

1034 size_list.append(aSize)

1035 return self.fragment_by_list(size_list)

1036

1037

1038 def get_ip_ttl(self):

1039 return self.get_byte(8)

1040 def set_ip_ttl(self, value):

1041 self.set_byte(8, value)

1042

1043 def get_ip_p(self):

1044 return self.get_byte(9)

1045

1046 def set_ip_p(self, value):

1047 self.set_byte(9, value)

1048

1049 def get_ip_sum(self):

1050 return self.get_word(10)

1051 def set_ip_sum(self, value):

1052 self.auto_checksum = 0

1053 self.set_word(10, value)

1054

1055 def reset_ip_sum(self):

1056 self.set_ip_sum(0x0000)

1057 self.auto_checksum = 1

1058

1059 def get_ip_src(self):

1060 return self.get_ip_address(12)

1061 def set_ip_src(self, value):

1062 self.set_ip_address(12, value)

1063

1064 def get_ip_dst(self):

1065 return self.get_ip_address(16)

1066

1067 def set_ip_dst(self, value):

1068 self.set_ip_address(16, value)

1069

1070 def get_header_size(self):

1071 op_len = 0

1072 for op in self.__option_list: 1072 ↛ 1073line 1072 didn't jump to line 1073, because the loop on line 1072 never started

1073 op_len += op.get_len()

1074

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

1076

1077 return 20 + op_len + num_pad

1078

1079 def load_header(self, aBuffer):

1080 self.set_bytes_from_string(aBuffer[:20])

1081 opt_left = (self.get_ip_hl() - 5) * 4

1082 opt_bytes = array.array('B', aBuffer[20:(20 + opt_left)])

1083 if len(opt_bytes) != opt_left: 1083 ↛ 1084line 1083 didn't jump to line 1084, because the condition on line 1083 was never true

1084 raise ImpactPacketException("Cannot load options from truncated packet")

1085

1086

1087 while opt_left: 1087 ↛ 1088line 1087 didn't jump to line 1088, because the condition on line 1087 was never true

1088 op_type = opt_bytes[0]

1089 if op_type == IPOption.IPOPT_EOL or op_type == IPOption.IPOPT_NOP:

1090 new_option = IPOption(op_type)

1091 op_len = 1

1092 else:

1093 op_len = opt_bytes[1]

1094 if op_len > len(opt_bytes):

1095 raise ImpactPacketException("IP Option length is too high")

1096

1097 new_option = IPOption(op_type, op_len)

1098 new_option.set_bytes(opt_bytes[:op_len])

1099

1100 opt_bytes = opt_bytes[op_len:]

1101 opt_left -= op_len

1102 self.add_option(new_option)

1103 if op_type == IPOption.IPOPT_EOL:

1104 break

1105

1106

1107 def __str__(self):

1108 flags = ' '

1109 if self.get_ip_df():

1110 flags += 'DF '

1111 if self.get_ip_mf():

1112 flags += 'MF '

1113 if self.get_ip_rf():

1114 flags += 'RF '

1115 tmp_str = 'IP%s%s -> %s ' % (flags, self.get_ip_src(),self.get_ip_dst())

1116 for op in self.__option_list:

1117 tmp_str += '\n' + str(op)

1118 if self.child():

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

1120 return tmp_str

1121

1122

1123 class IPOption(PacketBuffer):

1124 IPOPT_EOL = 0

1125 IPOPT_NOP = 1

1126 IPOPT_RR = 7

1127 IPOPT_TS = 68

1128 IPOPT_LSRR = 131

1129 IPOPT_SSRR = 137

1130

1131 def __init__(self, opcode = 0, size = None):

1132 if size and (size < 3 or size > 40):

1133 raise ImpactPacketException("IP Options must have a size between 3 and 40 bytes")

1134

1135 if(opcode == IPOption.IPOPT_EOL):

1136 PacketBuffer.__init__(self, 1)

1137 self.set_code(IPOption.IPOPT_EOL)

1138 elif(opcode == IPOption.IPOPT_NOP):

1139 PacketBuffer.__init__(self, 1)

1140 self.set_code(IPOption.IPOPT_NOP)

1141 elif(opcode == IPOption.IPOPT_RR):

1142 if not size:

1143 size = 39

1144 PacketBuffer.__init__(self, size)

1145 self.set_code(IPOption.IPOPT_RR)

1146 self.set_len(size)

1147 self.set_ptr(4)

1148

1149 elif(opcode == IPOption.IPOPT_LSRR):

1150 if not size:

1151 size = 39

1152 PacketBuffer.__init__(self, size)

1153 self.set_code(IPOption.IPOPT_LSRR)

1154 self.set_len(size)

1155 self.set_ptr(4)

1156

1157 elif(opcode == IPOption.IPOPT_SSRR):

1158 if not size:

1159 size = 39

1160 PacketBuffer.__init__(self, size)

1161 self.set_code(IPOption.IPOPT_SSRR)

1162 self.set_len(size)

1163 self.set_ptr(4)

1164

1165 elif(opcode == IPOption.IPOPT_TS):

1166 if not size:

1167 size = 40

1168 PacketBuffer.__init__(self, size)

1169 self.set_code(IPOption.IPOPT_TS)

1170 self.set_len(size)

1171 self.set_ptr(5)

1172 self.set_flags(0)

1173 else:

1174 if not size:

1175 raise ImpactPacketException("Size required for this type")

1176 PacketBuffer.__init__(self,size)

1177 self.set_code(opcode)

1178 self.set_len(size)

1179

1180

1181 def append_ip(self, ip):

1182 op = self.get_code()

1183 if not (op == IPOption.IPOPT_RR or op == IPOption.IPOPT_LSRR or op == IPOption.IPOPT_SSRR or op == IPOption.IPOPT_TS):

1184 raise ImpactPacketException("append_ip() not support for option type %d" % self.opt_type)

1185

1186 p = self.get_ptr()

1187 if not p:

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

1189

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

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

1192

1193 self.set_ip_address(p - 1, ip)

1194 p += 4

1195 self.set_ptr(p)

1196

1197

1198 def set_code(self, value):

1199 self.set_byte(0, value)

1200

1201 def get_code(self):

1202 return self.get_byte(0)

1203

1204

1205 def set_flags(self, flags):

1206 if not (self.get_code() == IPOption.IPOPT_TS):

1207 raise ImpactPacketException("Operation only supported on Timestamp option")

1208 self.set_byte(3, flags)

1209

1210 def get_flags(self, flags):

1211 if not (self.get_code() == IPOption.IPOPT_TS):

1212 raise ImpactPacketException("Operation only supported on Timestamp option")

1213 return self.get_byte(3)

1214

1215

1216 def set_len(self, len):

1217 self.set_byte(1, len)

1218

1219

1220 def set_ptr(self, ptr):

1221 self.set_byte(2, ptr)

1222

1223 def get_ptr(self):

1224 return self.get_byte(2)

1225

1226 def get_len(self):

1227 return len(self.get_bytes())

1228

1229

1230 def __str__(self):

1231 map = {IPOption.IPOPT_EOL : "End of List ",

1232 IPOption.IPOPT_NOP : "No Operation ",

1233 IPOption.IPOPT_RR : "Record Route ",

1234 IPOption.IPOPT_TS : "Timestamp ",

1235 IPOption.IPOPT_LSRR : "Loose Source Route ",

1236 IPOption.IPOPT_SSRR : "Strict Source Route "}

1237

1238 tmp_str = "\tIP Option: "

1239 op = self.get_code()

1240 if op in map:

1241 tmp_str += map[op]

1242 else:

1243 tmp_str += "Code: %d " % op

1244

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

1246 tmp_str += self.print_addresses()

1247

1248

1249 return tmp_str

1250

1251

1252 def print_addresses(self):

1253 p = 3

1254 tmp_str = "["

1255 if self.get_len() >= 7: # at least one complete IP address

1256 while 1:

1257 if p + 1 == self.get_ptr():

1258 tmp_str += "#"

1259 tmp_str += self.get_ip_address(p)

1260 p += 4

1261 if p >= self.get_len():

1262 break

1263 else:

1264 tmp_str += ", "

1265 tmp_str += "] "

1266 if self.get_ptr() % 4: # ptr field should be a multiple of 4

1267 tmp_str += "nonsense ptr field: %d " % self.get_ptr()

1268 return tmp_str

1269

1270

1271 class UDP(Header):

1272 protocol = 17

1273 def __init__(self, aBuffer = None):

1274 Header.__init__(self, 8)

1275 if(aBuffer): 1275 ↛ 1276line 1275 didn't jump to line 1276, because the condition on line 1275 was never true

1276 self.load_header(aBuffer)

1277

1278 def get_uh_sport(self):

1279 return self.get_word(0)

1280 def set_uh_sport(self, value):

1281 self.set_word(0, value)

1282

1283 def get_uh_dport(self):

1284 return self.get_word(2)

1285 def set_uh_dport(self, value):

1286 self.set_word(2, value)

1287

1288 def get_uh_ulen(self):

1289 return self.get_word(4)

1290

1291 def set_uh_ulen(self, value):

1292 self.set_word(4, value)

1293

1294 def get_uh_sum(self):

1295 return self.get_word(6)

1296

1297 def set_uh_sum(self, value):

1298 self.set_word(6, value)

1299 self.auto_checksum = 0

1300

1301 def calculate_checksum(self):

1302 if self.auto_checksum and (not self.get_uh_sum()):

1303 # if there isn't a parent to grab a pseudo-header from we'll assume the user knows what they're doing

1304 # and won't meddle with the checksum or throw an exception

1305 if not self.parent():

1306 return

1307

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

1309

1310 buffer += self.get_bytes()

1311 data = self.get_data_as_string()

1312 if(data):

1313 array_frombytes(buffer, data)

1314 self.set_uh_sum(self.compute_checksum(buffer))

1315

1316 def get_header_size(self):

1317 return 8

1318

1319 def __str__(self):

1320 tmp_str = 'UDP %d -> %d' % (self.get_uh_sport(), self.get_uh_dport())

1321 if self.child():

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

1323 return tmp_str

1324

1325 def get_packet(self):

1326 # set total length

1327 if(self.get_uh_ulen() == 0):

1328 self.set_uh_ulen(self.get_size())

1329 return Header.get_packet(self)

1330

1331 class TCP(Header):

1332 protocol = 6

1333 TCP_FLAGS_MASK = 0x00FF # lowest 16 bits are the flags

1334 def __init__(self, aBuffer = None):

1335 Header.__init__(self, 20)

1336 self.set_th_off(5)

1337 self.__option_list = []

1338 if aBuffer: 1338 ↛ exitline 1338 didn't return from function '__init__', because the condition on line 1338 was never false

1339 self.load_header(aBuffer)

1340

1341 def add_option(self, option):

1342 self.__option_list.append(option)

1343

1344 sum = 0

1345 for op in self.__option_list:

1346 sum += op.get_size()

1347

1348 if sum > 40: 1348 ↛ 1349line 1348 didn't jump to line 1349, because the condition on line 1348 was never true

1349 raise ImpactPacketException("Cannot add TCP option, would overflow option space")

1350

1351 def get_options(self):

1352 return self.__option_list

1353

1354 def swapSourceAndDestination(self):

1355 oldSource = self.get_th_sport()

1356 self.set_th_sport(self.get_th_dport())

1357 self.set_th_dport(oldSource)

1358

1359 #

1360 # Header field accessors

1361 #

1362

1363 def set_th_sport(self, aValue):

1364 self.set_word(0, aValue)

1365

1366 def get_th_sport(self):

1367 return self.get_word(0)

1368

1369 def get_th_dport(self):

1370 return self.get_word(2)

1371

1372 def set_th_dport(self, aValue):

1373 self.set_word(2, aValue)

1374

1375 def get_th_seq(self):

1376 return self.get_long(4)

1377

1378 def set_th_seq(self, aValue):

1379 self.set_long(4, aValue)

1380

1381 def get_th_ack(self):

1382 return self.get_long(8)

1383

1384 def set_th_ack(self, aValue):

1385 self.set_long(8, aValue)

1386

1387 def get_th_flags(self):

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

1389

1390 def set_th_flags(self, aValue):

1391 masked = self.get_word(12) & (~self.TCP_FLAGS_MASK)

1392 nb = masked | (aValue & self.TCP_FLAGS_MASK)

1393 return self.set_word(12, nb, ">")

1394

1395 def get_th_win(self):

1396 return self.get_word(14)

1397

1398 def set_th_win(self, aValue):

1399 self.set_word(14, aValue)

1400

1401 def set_th_sum(self, aValue):

1402 self.set_word(16, aValue)

1403 self.auto_checksum = 0

1404

1405 def get_th_sum(self):

1406 return self.get_word(16)

1407

1408 def get_th_urp(self):

1409 return self.get_word(18)

1410

1411 def set_th_urp(self, aValue):

1412 return self.set_word(18, aValue)

1413

1414 # Flag accessors

1415

1416 def get_th_reserved(self):

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

1418 return tmp_value

1419

1420

1421 def get_th_off(self):

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

1423 return tmp_value

1424

1425 def set_th_off(self, aValue):

1426 mask = 0xF0

1427 masked = self.get_byte(12) & (~mask)

1428 nb = masked | ( (aValue << 4) & mask)

1429 return self.set_byte(12, nb)

1430

1431 def get_CWR(self):

1432 return self.get_flag(128)

1433 def set_CWR(self):

1434 return self.set_flags(128)

1435 def reset_CWR(self):

1436 return self.reset_flags(128)

1437

1438 def get_ECE(self):

1439 return self.get_flag(64)

1440 def set_ECE(self):

1441 return self.set_flags(64)

1442 def reset_ECE(self):

1443 return self.reset_flags(64)

1444

1445 def get_URG(self):

1446 return self.get_flag(32)

1447 def set_URG(self):

1448 return self.set_flags(32)

1449 def reset_URG(self):

1450 return self.reset_flags(32)

1451

1452 def get_ACK(self):

1453 return self.get_flag(16)

1454 def set_ACK(self):

1455 return self.set_flags(16)

1456 def reset_ACK(self):

1457 return self.reset_flags(16)

1458

1459 def get_PSH(self):

1460 return self.get_flag(8)

1461 def set_PSH(self):

1462 return self.set_flags(8)

1463 def reset_PSH(self):

1464 return self.reset_flags(8)

1465

1466 def get_RST(self):

1467 return self.get_flag(4)

1468 def set_RST(self):

1469 return self.set_flags(4)

1470 def reset_RST(self):

1471 return self.reset_flags(4)

1472

1473 def get_SYN(self):

1474 return self.get_flag(2)

1475 def set_SYN(self):

1476 return self.set_flags(2)

1477 def reset_SYN(self):

1478 return self.reset_flags(2)

1479

1480 def get_FIN(self):

1481 return self.get_flag(1)

1482 def set_FIN(self):

1483 return self.set_flags(1)

1484 def reset_FIN(self):

1485 return self.reset_flags(1)

1486

1487 # Overridden Methods

1488

1489 def get_header_size(self):

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

1491

1492 def calculate_checksum(self):

1493 if not self.auto_checksum or not self.parent(): 1493 ↛ 1496line 1493 didn't jump to line 1496, because the condition on line 1493 was never false

1494 return

1495

1496 self.set_th_sum(0)

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

1498 buffer += self.get_bytes()

1499 buffer += self.get_padded_options()

1500

1501 data = self.get_data_as_string()

1502 if(data):

1503 array_frombytes(buffer, data)

1504

1505 res = self.compute_checksum(buffer)

1506

1507 self.set_th_sum(self.compute_checksum(buffer))

1508

1509 def get_packet(self):

1510 "Returns entire packet including child data as a string. This is the function used to extract the final packet"

1511

1512 # only change th_off value if options are present

1513 if len(self.__option_list): 1513 ↛ 1516line 1513 didn't jump to line 1516, because the condition on line 1513 was never false

1514 self.set_th_off(self.get_header_size() // 4)

1515

1516 self.calculate_checksum()

1517

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

1519 data = self.get_data_as_string()

1520

1521 if data: 1521 ↛ 1522line 1521 didn't jump to line 1522, because the condition on line 1521 was never true

1522 return array_tobytes(bytes) + data

1523 else:

1524 return array_tobytes(bytes)

1525

1526 def load_header(self, aBuffer):

1527 self.set_bytes_from_string(aBuffer[:20])

1528 opt_left = (self.get_th_off() - 5) * 4

1529 opt_bytes = array.array('B', aBuffer[20:(20 + opt_left)])

1530 if len(opt_bytes) != opt_left: 1530 ↛ 1531line 1530 didn't jump to line 1531, because the condition on line 1530 was never true

1531 raise ImpactPacketException("Cannot load options from truncated packet")

1532

1533 while opt_left:

1534 op_kind = opt_bytes[0]

1535 if op_kind == TCPOption.TCPOPT_EOL or op_kind == TCPOption.TCPOPT_NOP:

1536 new_option = TCPOption(op_kind)

1537 op_len = 1

1538 else:

1539 op_len = opt_bytes[1]

1540 if op_len > len(opt_bytes): 1540 ↛ 1541line 1540 didn't jump to line 1541, because the condition on line 1540 was never true

1541 raise ImpactPacketException("TCP Option length is too high")

1542 if op_len < 2: 1542 ↛ 1543line 1542 didn't jump to line 1543, because the condition on line 1542 was never true

1543 raise ImpactPacketException("TCP Option length is too low")

1544

1545 new_option = TCPOption(op_kind)

1546 new_option.set_bytes(opt_bytes[:op_len])

1547

1548 opt_bytes = opt_bytes[op_len:]

1549 opt_left -= op_len

1550 self.add_option(new_option)

1551 if op_kind == TCPOption.TCPOPT_EOL: 1551 ↛ 1552line 1551 didn't jump to line 1552, because the condition on line 1551 was never true

1552 break

1553

1554 #

1555 # Private

1556 #

1557

1558 def get_flag(self, bit):

1559 if self.get_th_flags() & bit:

1560 return 1

1561 else:

1562 return 0

1563

1564 def reset_flags(self, aValue):

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

1566 return self.set_th_flags(tmp_value)

1567

1568 def set_flags(self, aValue):

1569 tmp_value = self.get_th_flags() | aValue

1570 return self.set_th_flags(tmp_value)

1571

1572 def get_padded_options(self):

1573 "Return an array containing all options padded to a 4 byte boundary"

1574 op_buf = array.array('B')

1575 for op in self.__option_list:

1576 op_buf += op.get_bytes()

1577 num_pad = (4 - (len(op_buf) % 4)) % 4

1578 if num_pad: 1578 ↛ 1579line 1578 didn't jump to line 1579, because the condition on line 1578 was never true

1579 array_frombytes(op_buf, "\0" * num_pad)

1580 return op_buf

1581

1582 def __str__(self):

1583 tmp_str = 'TCP '

1584 if self.get_ECE():

1585 tmp_str += 'ece '

1586 if self.get_CWR():

1587 tmp_str += 'cwr '

1588 if self.get_ACK():

1589 tmp_str += 'ack '

1590 if self.get_FIN():

1591 tmp_str += 'fin '

1592 if self.get_PSH():

1593 tmp_str += 'push '

1594 if self.get_RST():

1595 tmp_str += 'rst '

1596 if self.get_SYN():

1597 tmp_str += 'syn '

1598 if self.get_URG():

1599 tmp_str += 'urg '

1600 tmp_str += '%d -> %d' % (self.get_th_sport(), self.get_th_dport())

1601 for op in self.__option_list:

1602 tmp_str += '\n' + str(op)

1603

1604 if self.child():

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

1606 return tmp_str

1607

1608

1609 class TCPOption(PacketBuffer):

1610 TCPOPT_EOL = 0

1611 TCPOPT_NOP = 1

1612 TCPOPT_MAXSEG = 2

1613 TCPOPT_WINDOW = 3

1614 TCPOPT_SACK_PERMITTED = 4

1615 TCPOPT_SACK = 5

1616 TCPOPT_TIMESTAMP = 8

1617 TCPOPT_SIGNATURE = 19

1618

1619

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

1621

1622 if kind == TCPOption.TCPOPT_EOL: 1622 ↛ 1623line 1622 didn't jump to line 1623, because the condition on line 1622 was never true

1623 PacketBuffer.__init__(self, 1)

1624 self.set_kind(TCPOption.TCPOPT_EOL)

1625 elif kind == TCPOption.TCPOPT_NOP:

1626 PacketBuffer.__init__(self, 1)

1627 self.set_kind(TCPOption.TCPOPT_NOP)

1628 elif kind == TCPOption.TCPOPT_MAXSEG:

1629 PacketBuffer.__init__(self, 4)

1630 self.set_kind(TCPOption.TCPOPT_MAXSEG)

1631 self.set_len(4)

1632 if data: 1632 ↛ 1633line 1632 didn't jump to line 1633, because the condition on line 1632 was never true

1633 self.set_mss(data)

1634 else:

1635 self.set_mss(512)

1636 elif kind == TCPOption.TCPOPT_WINDOW:

1637 PacketBuffer.__init__(self, 3)

1638 self.set_kind(TCPOption.TCPOPT_WINDOW)

1639 self.set_len(3)

1640 if data: 1640 ↛ 1641line 1640 didn't jump to line 1641, because the condition on line 1640 was never true

1641 self.set_shift_cnt(data)

1642 else:

1643 self.set_shift_cnt(0)

1644 elif kind == TCPOption.TCPOPT_TIMESTAMP:

1645 PacketBuffer.__init__(self, 10)

1646 self.set_kind(TCPOption.TCPOPT_TIMESTAMP)

1647 self.set_len(10)

1648 if data: 1648 ↛ 1649line 1648 didn't jump to line 1649, because the condition on line 1648 was never true

1649 self.set_ts(data)

1650 else:

1651 self.set_ts(0)

1652 elif kind == TCPOption.TCPOPT_SACK_PERMITTED: 1652 ↛ 1657line 1652 didn't jump to line 1657, because the condition on line 1652 was never false

1653 PacketBuffer.__init__(self, 2)

1654 self.set_kind(TCPOption.TCPOPT_SACK_PERMITTED)

1655 self.set_len(2)

1656

1657 elif kind == TCPOption.TCPOPT_SACK:

1658 PacketBuffer.__init__(self, 2)

1659 self.set_kind(TCPOption.TCPOPT_SACK)

1660

1661 def set_left_edge(self, aValue):

1662 self.set_long (2, aValue)

1663

1664 def set_right_edge(self, aValue):

1665 self.set_long (6, aValue)

1666

1667 def set_kind(self, kind):

1668 self.set_byte(0, kind)

1669

1670

1671 def get_kind(self):

1672 return self.get_byte(0)

1673

1674

1675 def set_len(self, len):

1676 if self.get_size() < 2: 1676 ↛ 1677line 1676 didn't jump to line 1677, because the condition on line 1676 was never true

1677 raise ImpactPacketException("Cannot set length field on an option having a size smaller than 2 bytes")

1678 self.set_byte(1, len)

1679

1680 def get_len(self):

1681 if self.get_size() < 2:

1682 raise ImpactPacketException("Cannot retrieve length field from an option having a size smaller than 2 bytes")

1683 return self.get_byte(1)

1684

1685 def get_size(self):

1686 return len(self.get_bytes())

1687

1688

1689 def set_mss(self, len):

1690 if self.get_kind() != TCPOption.TCPOPT_MAXSEG: 1690 ↛ 1691line 1690 didn't jump to line 1691, because the condition on line 1690 was never true

1691 raise ImpactPacketException("Can only set MSS on TCPOPT_MAXSEG option")

1692 self.set_word(2, len)

1693

1694 def get_mss(self):

1695 if self.get_kind() != TCPOption.TCPOPT_MAXSEG:

1696 raise ImpactPacketException("Can only retrieve MSS from TCPOPT_MAXSEG option")

1697 return self.get_word(2)

1698

1699 def set_shift_cnt(self, cnt):

1700 if self.get_kind() != TCPOption.TCPOPT_WINDOW: 1700 ↛ 1701line 1700 didn't jump to line 1701, because the condition on line 1700 was never true

1701 raise ImpactPacketException("Can only set Shift Count on TCPOPT_WINDOW option")

1702 self.set_byte(2, cnt)

1703

1704 def get_shift_cnt(self):

1705 if self.get_kind() != TCPOption.TCPOPT_WINDOW:

1706 raise ImpactPacketException("Can only retrieve Shift Count from TCPOPT_WINDOW option")

1707 return self.get_byte(2)

1708

1709 def get_ts(self):

1710 if self.get_kind() != TCPOption.TCPOPT_TIMESTAMP:

1711 raise ImpactPacketException("Can only retrieve timestamp from TCPOPT_TIMESTAMP option")

1712 return self.get_long(2)

1713

1714 def set_ts(self, ts):

1715 if self.get_kind() != TCPOption.TCPOPT_TIMESTAMP: 1715 ↛ 1716line 1715 didn't jump to line 1716, because the condition on line 1715 was never true

1716 raise ImpactPacketException("Can only set timestamp on TCPOPT_TIMESTAMP option")

1717 self.set_long(2, ts)

1718

1719 def get_ts_echo(self):

1720 if self.get_kind() != TCPOption.TCPOPT_TIMESTAMP:

1721 raise ImpactPacketException("Can only retrieve timestamp from TCPOPT_TIMESTAMP option")

1722 return self.get_long(6)

1723

1724 def set_ts_echo(self, ts):

1725 if self.get_kind() != TCPOption.TCPOPT_TIMESTAMP:

1726 raise ImpactPacketException("Can only set timestamp on TCPOPT_TIMESTAMP option")

1727 self.set_long(6, ts)

1728

1729 def __str__(self):

1730 map = { TCPOption.TCPOPT_EOL : "End of List ",

1731 TCPOption.TCPOPT_NOP : "No Operation ",

1732 TCPOption.TCPOPT_MAXSEG : "Maximum Segment Size ",

1733 TCPOption.TCPOPT_WINDOW : "Window Scale ",

1734 TCPOption.TCPOPT_TIMESTAMP : "Timestamp " }

1735

1736 tmp_str = "\tTCP Option: "

1737 op = self.get_kind()

1738 if op in map:

1739 tmp_str += map[op]

1740 else:

1741 tmp_str += " kind: %d " % op

1742 if op == TCPOption.TCPOPT_MAXSEG:

1743 tmp_str += " MSS : %d " % self.get_mss()

1744 elif op == TCPOption.TCPOPT_WINDOW:

1745 tmp_str += " Shift Count: %d " % self.get_shift_cnt()

1746 elif op == TCPOption.TCPOPT_TIMESTAMP:

1747 pass # TODO

1748 return tmp_str

1749

1750 class ICMP(Header):

1751 protocol = 1

1752 ICMP_ECHOREPLY = 0

1753 ICMP_UNREACH = 3

1754 ICMP_UNREACH_NET = 0

1755 ICMP_UNREACH_HOST = 1

1756 ICMP_UNREACH_PROTOCOL = 2

1757 ICMP_UNREACH_PORT = 3

1758 ICMP_UNREACH_NEEDFRAG = 4

1759 ICMP_UNREACH_SRCFAIL = 5

1760 ICMP_UNREACH_NET_UNKNOWN = 6

1761 ICMP_UNREACH_HOST_UNKNOWN = 7

1762 ICMP_UNREACH_ISOLATED = 8

1763 ICMP_UNREACH_NET_PROHIB = 9

1764 ICMP_UNREACH_HOST_PROHIB = 10

1765 ICMP_UNREACH_TOSNET = 11

1766 ICMP_UNREACH_TOSHOST = 12

1767 ICMP_UNREACH_FILTERPROHIB = 13

1768 ICMP_UNREACH_HOST_PRECEDENCE = 14

1769 ICMP_UNREACH_PRECEDENCE_CUTOFF = 15

1770 ICMP_SOURCEQUENCH = 4

1771 ICMP_REDIRECT = 5

1772 ICMP_REDIRECT_NET = 0

1773 ICMP_REDIRECT_HOST = 1

1774 ICMP_REDIRECT_TOSNET = 2

1775 ICMP_REDIRECT_TOSHOST = 3

1776 ICMP_ALTHOSTADDR = 6

1777 ICMP_ECHO = 8

1778 ICMP_ROUTERADVERT = 9

1779 ICMP_ROUTERSOLICIT = 10

1780 ICMP_TIMXCEED = 11

1781 ICMP_TIMXCEED_INTRANS = 0

1782 ICMP_TIMXCEED_REASS = 1

1783 ICMP_PARAMPROB = 12

1784 ICMP_PARAMPROB_ERRATPTR = 0

1785 ICMP_PARAMPROB_OPTABSENT = 1

1786 ICMP_PARAMPROB_LENGTH = 2

1787 ICMP_TSTAMP = 13

1788 ICMP_TSTAMPREPLY = 14

1789 ICMP_IREQ = 15

1790 ICMP_IREQREPLY = 16

1791 ICMP_MASKREQ = 17

1792 ICMP_MASKREPLY = 18

1793

1794 def __init__(self, aBuffer = None):

1795 Header.__init__(self, 8)

1796 if aBuffer:

1797 self.load_header(aBuffer)

1798

1799 def get_header_size(self):

1800 anamolies = { ICMP.ICMP_TSTAMP : 20, ICMP.ICMP_TSTAMPREPLY : 20, ICMP.ICMP_MASKREQ : 12, ICMP.ICMP_MASKREPLY : 12 }

1801 if self.get_icmp_type() in anamolies: 1801 ↛ 1802line 1801 didn't jump to line 1802, because the condition on line 1801 was never true

1802 return anamolies[self.get_icmp_type()]

1803 else:

1804 return 8

1805

1806 def get_icmp_type(self):

1807 return self.get_byte(0)

1808

1809 def set_icmp_type(self, aValue):

1810 self.set_byte(0, aValue)

1811

1812 def get_icmp_code(self):

1813 return self.get_byte(1)

1814

1815 def set_icmp_code(self, aValue):

1816 self.set_byte(1, aValue)

1817

1818 def get_icmp_cksum(self):

1819 return self.get_word(2)

1820

1821 def set_icmp_cksum(self, aValue):

1822 self.set_word(2, aValue)

1823 self.auto_checksum = 0

1824

1825 def get_icmp_gwaddr(self):

1826 return self.get_ip_address(4)

1827

1828 def set_icmp_gwaddr(self, ip):

1829 self.set_ip_address(4, ip)

1830

1831 def get_icmp_id(self):

1832 return self.get_word(4)

1833

1834 def set_icmp_id(self, aValue):

1835 self.set_word(4, aValue)

1836

1837 def get_icmp_seq(self):

1838 return self.get_word(6)

1839

1840 def set_icmp_seq(self, aValue):

1841 self.set_word(6, aValue)

1842

1843 def get_icmp_void(self):

1844 return self.get_long(4)

1845

1846 def set_icmp_void(self, aValue):

1847 self.set_long(4, aValue)

1848

1849

1850 def get_icmp_nextmtu(self):

1851 return self.get_word(6)

1852

1853 def set_icmp_nextmtu(self, aValue):

1854 self.set_word(6, aValue)

1855

1856 def get_icmp_num_addrs(self):

1857 return self.get_byte(4)

1858

1859 def set_icmp_num_addrs(self, aValue):

1860 self.set_byte(4, aValue)

1861

1862 def get_icmp_wpa(self):

1863 return self.get_byte(5)

1864

1865 def set_icmp_wpa(self, aValue):

1866 self.set_byte(5, aValue)

1867

1868 def get_icmp_lifetime(self):

1869 return self.get_word(6)

1870

1871 def set_icmp_lifetime(self, aValue):

1872 self.set_word(6, aValue)

1873

1874 def get_icmp_otime(self):

1875 return self.get_long(8)

1876

1877 def set_icmp_otime(self, aValue):

1878 self.set_long(8, aValue)

1879

1880 def get_icmp_rtime(self):

1881 return self.get_long(12)

1882

1883 def set_icmp_rtime(self, aValue):

1884 self.set_long(12, aValue)

1885

1886 def get_icmp_ttime(self):

1887 return self.get_long(16)

1888

1889 def set_icmp_ttime(self, aValue):

1890 self.set_long(16, aValue)

1891

1892 def get_icmp_mask(self):

1893 return self.get_ip_address(8)

1894

1895 def set_icmp_mask(self, mask):

1896 self.set_ip_address(8, mask)

1897

1898

1899 def calculate_checksum(self):

1900 if self.auto_checksum and (not self.get_icmp_cksum()):

1901 buffer = self.get_buffer_as_string()

1902 data = self.get_data_as_string()

1903 if data: 1903 ↛ 1906line 1903 didn't jump to line 1906, because the condition on line 1903 was never false

1904 buffer += data

1905

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

1907 self.set_icmp_cksum(self.compute_checksum(tmp_array))

1908

1909 def get_type_name(self, aType):

1910 tmp_type = {0:'ECHOREPLY', 3:'UNREACH', 4:'SOURCEQUENCH',5:'REDIRECT', 6:'ALTHOSTADDR', 8:'ECHO', 9:'ROUTERADVERT', 10:'ROUTERSOLICIT', 11:'TIMXCEED', 12:'PARAMPROB', 13:'TSTAMP', 14:'TSTAMPREPLY', 15:'IREQ', 16:'IREQREPLY', 17:'MASKREQ', 18:'MASKREPLY', 30:'TRACEROUTE', 31:'DATACONVERR', 32:'MOBILE REDIRECT', 33:'IPV6 WHEREAREYOU', 34:'IPV6 IAMHERE', 35:'MOBILE REGREQUEST', 36:'MOBILE REGREPLY', 39:'SKIP', 40:'PHOTURIS'}

1911 answer = tmp_type.get(aType, 'UNKNOWN')

1912 return answer

1913

1914 def get_code_name(self, aType, aCode):

1915 tmp_code = {3:['UNREACH NET', 'UNREACH HOST', 'UNREACH PROTOCOL', 'UNREACH PORT', 'UNREACH NEEDFRAG', 'UNREACH SRCFAIL', 'UNREACH NET UNKNOWN', 'UNREACH HOST UNKNOWN', 'UNREACH ISOLATED', 'UNREACH NET PROHIB', 'UNREACH HOST PROHIB', 'UNREACH TOSNET', 'UNREACH TOSHOST', 'UNREACH FILTER PROHIB', 'UNREACH HOST PRECEDENCE', 'UNREACH PRECEDENCE CUTOFF', 'UNKNOWN ICMP UNREACH']}

1916 tmp_code[5] = ['REDIRECT NET', 'REDIRECT HOST', 'REDIRECT TOSNET', 'REDIRECT TOSHOST']

1917 tmp_code[9] = ['ROUTERADVERT NORMAL', None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,'ROUTERADVERT NOROUTE COMMON']

1918 tmp_code[11] = ['TIMXCEED INTRANS ', 'TIMXCEED REASS']

1919 tmp_code[12] = ['PARAMPROB ERRATPTR ', 'PARAMPROB OPTABSENT', 'PARAMPROB LENGTH']

1920 tmp_code[40] = [None, 'PHOTURIS UNKNOWN INDEX', 'PHOTURIS AUTH FAILED', 'PHOTURIS DECRYPT FAILED']

1921 if aType in tmp_code:

1922 tmp_list = tmp_code[aType]

1923 if ((aCode + 1) > len(tmp_list)) or (not tmp_list[aCode]):

1924 return 'UNKNOWN'

1925 else:

1926 return tmp_list[aCode]

1927 else:

1928 return 'UNKNOWN'

1929

1930 def __str__(self):

1931 tmp_type = self.get_icmp_type()

1932 tmp_code = self.get_icmp_code()

1933 tmp_str = 'ICMP type: ' + self.get_type_name(tmp_type)

1934 tmp_str+= ' code: ' + self.get_code_name(tmp_type, tmp_code)

1935 if self.child():

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

1937 return tmp_str

1938

1939 def isDestinationUnreachable(self):

1940 return self.get_icmp_type() == 3

1941

1942 def isError(self):

1943 return not self.isQuery()

1944

1945 def isHostUnreachable(self):

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

1947

1948 def isNetUnreachable(self):

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

1950

1951 def isPortUnreachable(self):

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

1953

1954 def isProtocolUnreachable(self):

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

1956

1957 def isQuery(self):

1958 tmp_dict = {8:'', 9:'', 10:'', 13:'', 14:'', 15:'', 16:'', 17:'', 18:''}

1959 return self.get_icmp_type() in tmp_dict

1960

1961 class IGMP(Header):

1962 protocol = 2

1963 def __init__(self, aBuffer = None):

1964 Header.__init__(self, 8)

1965 if aBuffer:

1966 self.load_header(aBuffer)

1967

1968 def get_igmp_type(self):

1969 return self.get_byte(0)

1970

1971 def set_igmp_type(self, aValue):

1972 self.set_byte(0, aValue)

1973

1974 def get_igmp_code(self):

1975 return self.get_byte(1)

1976

1977 def set_igmp_code(self, aValue):

1978 self.set_byte(1, aValue)

1979

1980 def get_igmp_cksum(self):

1981 return self.get_word(2)

1982

1983 def set_igmp_cksum(self, aValue):

1984 self.set_word(2, aValue)

1985

1986 def get_igmp_group(self):

1987 return self.get_long(4)

1988

1989 def set_igmp_group(self, aValue):

1990 self.set_long(4, aValue)

1991

1992 def get_header_size(self):

1993 return 8

1994

1995 def get_type_name(self, aType):

1996 tmp_dict = {0x11:'HOST MEMBERSHIP QUERY ', 0x12:'v1 HOST MEMBERSHIP REPORT ', 0x13:'IGMP DVMRP ', 0x14:' PIM ', 0x16:'v2 HOST MEMBERSHIP REPORT ', 0x17:'HOST LEAVE MESSAGE ', 0x1e:'MTRACE REPLY ', 0X1f:'MTRACE QUERY '}

1997 answer = tmp_dict.get(aType, 'UNKNOWN TYPE OR VERSION ')

1998 return answer

1999

2000 def calculate_checksum(self):

2001 if self.auto_checksum and (not self.get_igmp_cksum()):

2002 self.set_igmp_cksum(self.compute_checksum(self.get_bytes()))

2003

2004 def __str__(self):

2005 tmp_str = 'IGMP: ' + self.get_type_name(self.get_igmp_type())

2006 tmp_str += 'Group: ' + socket.inet_ntoa(struct.pack('!L',self.get_igmp_group()))

2007 if self.child():

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

2009 return tmp_str

2010

2011

2012

2013 class ARP(Header):

2014 ethertype = 0x806

2015 def __init__(self, aBuffer = None):

2016 Header.__init__(self, 7)

2017 if aBuffer: 2017 ↛ exitline 2017 didn't return from function '__init__', because the condition on line 2017 was never false

2018 self.load_header(aBuffer)

2019

2020 def get_ar_hrd(self):

2021 return self.get_word(0)

2022

2023 def set_ar_hrd(self, aValue):

2024 self.set_word(0, aValue)

2025

2026 def get_ar_pro(self):

2027 return self.get_word(2)

2028

2029 def set_ar_pro(self, aValue):

2030 self.set_word(2, aValue)

2031

2032 def get_ar_hln(self):

2033 return self.get_byte(4)

2034

2035 def set_ar_hln(self, aValue):

2036 self.set_byte(4, aValue)

2037

2038 def get_ar_pln(self):

2039 return self.get_byte(5)

2040

2041 def set_ar_pln(self, aValue):

2042 self.set_byte(5, aValue)

2043

2044 def get_ar_op(self):

2045 return self.get_word(6)

2046

2047 def set_ar_op(self, aValue):

2048 self.set_word(6, aValue)

2049

2050 def get_ar_sha(self):

2051 tmp_size = self.get_ar_hln()

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

2053

2054 def set_ar_sha(self, aValue):

2055 for i in range(0, self.get_ar_hln()):

2056 self.set_byte(i + 8, aValue[i])

2057

2058 def get_ar_spa(self):

2059 tmp_size = self.get_ar_pln()

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

2061

2062 def set_ar_spa(self, aValue):

2063 for i in range(0, self.get_ar_pln()):

2064 self.set_byte(i + 8 + self.get_ar_hln(), aValue[i])

2065

2066 def get_ar_tha(self):

2067 tmp_size = self.get_ar_hln()

2068 tmp_from = 8 + self.get_ar_hln() + self.get_ar_pln()

2069 return self.get_bytes().tolist()[tmp_from: tmp_from + tmp_size]

2070

2071 def set_ar_tha(self, aValue):

2072 tmp_from = 8 + self.get_ar_hln() + self.get_ar_pln()

2073 for i in range(0, self.get_ar_hln()):

2074 self.set_byte(i + tmp_from, aValue[i])

2075

2076 def get_ar_tpa(self):

2077 tmp_size = self.get_ar_pln()

2078 tmp_from = 8 + ( 2 * self.get_ar_hln()) + self.get_ar_pln()

2079 return self.get_bytes().tolist()[tmp_from: tmp_from + tmp_size]

2080

2081 def set_ar_tpa(self, aValue):

2082 tmp_from = 8 + (2 * self.get_ar_hln()) + self.get_ar_pln()

2083 for i in range(0, self.get_ar_pln()):

2084 self.set_byte(i + tmp_from, aValue[i])

2085

2086 def get_header_size(self):

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

2088

2089 def get_op_name(self, ar_op):

2090 tmp_dict = {1:'REQUEST', 2:'REPLY', 3:'REVREQUEST', 4:'REVREPLY', 8:'INVREQUEST', 9:'INVREPLY'}

2091 answer = tmp_dict.get(ar_op, 'UNKNOWN')

2092 return answer

2093

2094 def get_hrd_name(self, ar_hrd):

2095 tmp_dict = { 1:'ARPHRD ETHER', 6:'ARPHRD IEEE802', 15:'ARPHRD FRELAY'}

2096 answer = tmp_dict.get(ar_hrd, 'UNKNOWN')

2097 return answer

2098

2099

2100 def as_hrd(self, anArray):

2101 if not anArray:

2102 return ''

2103 tmp_str = '%x' % anArray[0]

2104 for i in range(1, len(anArray)):

2105 tmp_str += ':%x' % anArray[i]

2106 return tmp_str

2107

2108 def as_pro(self, anArray):

2109 if not anArray:

2110 return ''

2111 tmp_str = '%d' % anArray[0]

2112 for i in range(1, len(anArray)):

2113 tmp_str += '.%d' % anArray[i]

2114 return tmp_str

2115

2116 def __str__(self):

2117 tmp_op = self.get_ar_op()

2118 tmp_str = 'ARP format: ' + self.get_hrd_name(self.get_ar_hrd()) + ' '

2119 tmp_str += 'opcode: ' + self.get_op_name(tmp_op)

2120 tmp_str += '\n' + self.as_hrd(self.get_ar_sha()) + ' -> '

2121 tmp_str += self.as_hrd(self.get_ar_tha())

2122 tmp_str += '\n' + self.as_pro(self.get_ar_spa()) + ' -> '

2123 tmp_str += self.as_pro(self.get_ar_tpa())

2124 if self.child():

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

2126 return tmp_str

2127

2128 def example(): #To execute an example, remove this line

2129 a = Ethernet()

2130 b = ARP()

2131 c = Data('Hola loco!!!')

2132 b.set_ar_hln(6)

2133 b.set_ar_pln(4)

2134 #a.set_ip_dst('192.168.22.6')

2135 #a.set_ip_src('1.1.1.2')

2136 a.contains(b)

2137 b.contains(c)

2138 b.set_ar_op(2)

2139 b.set_ar_hrd(1)

2140 b.set_ar_spa((192, 168, 22, 6))

2141 b.set_ar_tpa((192, 168, 66, 171))

2142 a.set_ether_shost((0x0, 0xe0, 0x7d, 0x8a, 0xef, 0x3d))

2143 a.set_ether_dhost((0x0, 0xc0, 0xdf, 0x6, 0x5, 0xe))

2144 print("beto %s" % a)