Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/scapy/fields.py: 69%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1908 statements  

1# SPDX-License-Identifier: GPL-2.0-only 

2# This file is part of Scapy 

3# See https://scapy.net/ for more information 

4# Copyright (C) Philippe Biondi <phil@secdev.org> 

5# Copyright (C) Michael Farrell <micolous+git@gmail.com> 

6 

7 

8""" 

9Fields: basic data structures that make up parts of packets. 

10""" 

11 

12import calendar 

13import collections 

14import copy 

15import datetime 

16import inspect 

17import math 

18import socket 

19import struct 

20import time 

21import warnings 

22 

23from types import MethodType 

24from uuid import UUID 

25from enum import Enum 

26 

27from scapy.config import conf 

28from scapy.dadict import DADict 

29from scapy.volatile import RandBin, RandByte, RandEnumKeys, RandInt, \ 

30 RandIP, RandIP6, RandLong, RandMAC, RandNum, RandShort, RandSInt, \ 

31 RandSByte, RandTermString, RandUUID, VolatileValue, RandSShort, \ 

32 RandSLong, RandFloat 

33from scapy.data import EPOCH 

34from scapy.error import log_runtime, Scapy_Exception 

35from scapy.compat import bytes_hex, plain_str, raw, bytes_encode 

36from scapy.pton_ntop import inet_ntop, inet_pton 

37from scapy.utils import inet_aton, inet_ntoa, lhex, mac2str, str2mac, EDecimal 

38from scapy.utils6 import in6_6to4ExtractAddr, in6_isaddr6to4, \ 

39 in6_isaddrTeredo, in6_ptop, Net6, teredoAddrExtractInfo 

40from scapy.base_classes import ( 

41 _ScopedIP, 

42 BasePacket, 

43 Field_metaclass, 

44 Net, 

45 ScopedIP, 

46) 

47 

48# Typing imports 

49from typing import ( 

50 Any, 

51 AnyStr, 

52 Callable, 

53 Dict, 

54 List, 

55 Generic, 

56 Optional, 

57 Set, 

58 Tuple, 

59 Type, 

60 TypeVar, 

61 Union, 

62 # func 

63 cast, 

64 TYPE_CHECKING, 

65) 

66 

67if TYPE_CHECKING: 

68 # Do not import on runtime ! (import loop) 

69 from scapy.packet import Packet 

70 

71 

72class RawVal: 

73 r""" 

74 A raw value that will not be processed by the field and inserted 

75 as-is in the packet string. 

76 

77 Example:: 

78 

79 >>> a = IP(len=RawVal("####")) 

80 >>> bytes(a) 

81 b'F\x00####\x00\x01\x00\x005\xb5\x00\x00\x7f\x00\x00\x01\x7f\x00\x00\x01\x00\x00' 

82 

83 """ 

84 

85 def __init__(self, val=b""): 

86 # type: (bytes) -> None 

87 self.val = bytes_encode(val) 

88 

89 def __str__(self): 

90 # type: () -> str 

91 return str(self.val) 

92 

93 def __bytes__(self): 

94 # type: () -> bytes 

95 return self.val 

96 

97 def __len__(self): 

98 # type: () -> int 

99 return len(self.val) 

100 

101 def __repr__(self): 

102 # type: () -> str 

103 return "<RawVal [%r]>" % self.val 

104 

105 

106class ObservableDict(Dict[int, str]): 

107 """ 

108 Helper class to specify a protocol extendable for runtime modifications 

109 """ 

110 

111 def __init__(self, *args, **kw): 

112 # type: (*Dict[int, str], **Any) -> None 

113 self.observers = [] # type: List[_EnumField[Any]] 

114 super(ObservableDict, self).__init__(*args, **kw) 

115 

116 def observe(self, observer): 

117 # type: (_EnumField[Any]) -> None 

118 self.observers.append(observer) 

119 

120 def __setitem__(self, key, value): 

121 # type: (int, str) -> None 

122 for o in self.observers: 

123 o.notify_set(self, key, value) 

124 super(ObservableDict, self).__setitem__(key, value) 

125 

126 def __delitem__(self, key): 

127 # type: (int) -> None 

128 for o in self.observers: 

129 o.notify_del(self, key) 

130 super(ObservableDict, self).__delitem__(key) 

131 

132 def update(self, anotherDict): # type: ignore 

133 for k in anotherDict: 

134 self[k] = anotherDict[k] 

135 

136 

137############ 

138# Fields # 

139############ 

140 

141I = TypeVar('I') # Internal storage # noqa: E741 

142M = TypeVar('M') # Machine storage 

143 

144 

145class Field(Generic[I, M], metaclass=Field_metaclass): 

146 """ 

147 For more information on how this works, please refer to the 

148 'Adding new protocols' chapter in the online documentation: 

149 

150 https://scapy.readthedocs.io/en/stable/build_dissect.html 

151 """ 

152 __slots__ = [ 

153 "name", 

154 "fmt", 

155 "default", 

156 "sz", 

157 "owners", 

158 "struct" 

159 ] 

160 islist = 0 

161 ismutable = False 

162 holds_packets = 0 

163 isconditional = False 

164 ismayend = False 

165 

166 def __init__(self, name, default, fmt="H"): 

167 # type: (str, Any, str) -> None 

168 if not isinstance(name, str): 

169 raise ValueError("name should be a string") 

170 self.name = name 

171 if fmt[0] in "@=<>!": 

172 self.fmt = fmt 

173 else: 

174 self.fmt = "!" + fmt 

175 self.struct = struct.Struct(self.fmt) 

176 self.default = self.any2i(None, default) 

177 self.sz = struct.calcsize(self.fmt) # type: int 

178 self.owners = [] # type: List[Type[Packet]] 

179 

180 def register_owner(self, cls): 

181 # type: (Type[Packet]) -> None 

182 self.owners.append(cls) 

183 

184 def i2len(self, 

185 pkt, # type: Packet 

186 x, # type: Any 

187 ): 

188 # type: (...) -> int 

189 """Convert internal value to a length usable by a FieldLenField""" 

190 if isinstance(x, RawVal): 

191 return len(x) 

192 return self.sz 

193 

194 def i2count(self, pkt, x): 

195 # type: (Optional[Packet], I) -> int 

196 """Convert internal value to a number of elements usable by a FieldLenField. 

197 Always 1 except for list fields""" 

198 return 1 

199 

200 def h2i(self, pkt, x): 

201 # type: (Optional[Packet], Any) -> I 

202 """Convert human value to internal value""" 

203 return x # type: ignore 

204 

205 def i2h(self, pkt, x): 

206 # type: (Optional[Packet], I) -> Any 

207 """Convert internal value to human value""" 

208 return x 

209 

210 def m2i(self, pkt, x): 

211 # type: (Optional[Packet], M) -> I 

212 """Convert machine value to internal value""" 

213 return x # type: ignore 

214 

215 def i2m(self, pkt, x): 

216 # type: (Optional[Packet], Optional[I]) -> M 

217 """Convert internal value to machine value""" 

218 if x is None: 

219 return 0 # type: ignore 

220 elif isinstance(x, str): 

221 return bytes_encode(x) # type: ignore 

222 return x # type: ignore 

223 

224 def any2i(self, pkt, x): 

225 # type: (Optional[Packet], Any) -> Optional[I] 

226 """Try to understand the most input values possible and make an internal value from them""" # noqa: E501 

227 return self.h2i(pkt, x) 

228 

229 def i2repr(self, pkt, x): 

230 # type: (Optional[Packet], I) -> str 

231 """Convert internal value to a nice representation""" 

232 return repr(self.i2h(pkt, x)) 

233 

234 def addfield(self, pkt, s, val): 

235 # type: (Packet, bytes, Optional[I]) -> bytes 

236 """Add an internal value to a string 

237 

238 Copy the network representation of field `val` (belonging to layer 

239 `pkt`) to the raw string packet `s`, and return the new string packet. 

240 """ 

241 try: 

242 return s + self.struct.pack(self.i2m(pkt, val)) 

243 except struct.error as ex: 

244 raise ValueError( 

245 "Incorrect type of value for field %s:\n" % self.name + 

246 "struct.error('%s')\n" % ex + 

247 "To inject bytes into the field regardless of the type, " + 

248 "use RawVal. See help(RawVal)" 

249 ) 

250 

251 def getfield(self, pkt, s): 

252 # type: (Packet, bytes) -> Tuple[bytes, I] 

253 """Extract an internal value from a string 

254 

255 Extract from the raw packet `s` the field value belonging to layer 

256 `pkt`. 

257 

258 Returns a two-element list, 

259 first the raw packet string after having removed the extracted field, 

260 second the extracted field itself in internal representation. 

261 """ 

262 # Use unpack_from for plain bytes (avoids temporary slice allocation). 

263 # Fall back to unpack+slice for subclasses that override __getitem__. 

264 if type(s) is bytes: 

265 return s[self.sz:], self.m2i(pkt, self.struct.unpack_from(s)[0]) 

266 return s[self.sz:], self.m2i(pkt, self.struct.unpack(s[:self.sz])[0]) 

267 

268 def do_copy(self, x): 

269 # type: (I) -> I 

270 if isinstance(x, list): 

271 x = x[:] # type: ignore 

272 for i in range(len(x)): 

273 if isinstance(x[i], BasePacket): 

274 x[i] = x[i].copy() 

275 return x # type: ignore 

276 if hasattr(x, "copy"): 

277 return x.copy() # type: ignore 

278 return x 

279 

280 def __repr__(self): 

281 # type: () -> str 

282 return "<%s (%s).%s>" % ( 

283 self.__class__.__name__, 

284 ",".join(x.__name__ for x in self.owners), 

285 self.name 

286 ) 

287 

288 def copy(self): 

289 # type: () -> Field[I, M] 

290 return copy.copy(self) 

291 

292 def randval(self): 

293 # type: () -> VolatileValue[Any] 

294 """Return a volatile object whose value is both random and suitable for this field""" # noqa: E501 

295 fmtt = self.fmt[-1] 

296 if fmtt in "BbHhIiQq": 

297 return {"B": RandByte, "b": RandSByte, 

298 "H": RandShort, "h": RandSShort, 

299 "I": RandInt, "i": RandSInt, 

300 "Q": RandLong, "q": RandSLong}[fmtt]() 

301 elif fmtt == "s": 

302 if self.fmt[0] in "0123456789": 

303 value = int(self.fmt[:-1]) 

304 else: 

305 value = int(self.fmt[1:-1]) 

306 return RandBin(value) 

307 else: 

308 raise ValueError( 

309 "no random class for [%s] (fmt=%s)." % ( 

310 self.name, self.fmt 

311 ) 

312 ) 

313 

314 

315class _FieldContainer(object): 

316 """ 

317 A field that acts as a container for another field 

318 """ 

319 __slots__ = ["fld"] 

320 isconditional = False 

321 ismayend = False 

322 

323 def __getattr__(self, attr): 

324 # type: (str) -> Any 

325 return getattr(self.fld, attr) 

326 

327 

328AnyField = Union[Field[Any, Any], _FieldContainer] 

329 

330 

331class Emph(_FieldContainer): 

332 """Empathize sub-layer for display""" 

333 __slots__ = ["fld"] 

334 

335 def __init__(self, fld): 

336 # type: (Any) -> None 

337 self.fld = fld 

338 

339 def __eq__(self, other): 

340 # type: (Any) -> bool 

341 return bool(self.fld == other) 

342 

343 def __hash__(self): 

344 # type: () -> int 

345 return hash(self.fld) 

346 

347 

348class MayEnd(_FieldContainer): 

349 """ 

350 Allow packet dissection to end after the dissection of this field 

351 if no bytes are left. 

352 

353 A good example would be a length field that can be 0 or a set value, 

354 and where it would be too annoying to use multiple ConditionalFields 

355 

356 Important note: any field below this one MUST default 

357 to an empty value, else the behavior will be unexpected. 

358 """ 

359 __slots__ = ["fld"] 

360 ismayend = True 

361 

362 def __init__(self, fld): 

363 # type: (Any) -> None 

364 self.fld = fld 

365 

366 def __eq__(self, other): 

367 # type: (Any) -> bool 

368 return bool(self.fld == other) 

369 

370 def __hash__(self): 

371 # type: () -> int 

372 return hash(self.fld) 

373 

374 

375class ActionField(_FieldContainer): 

376 __slots__ = ["fld", "_action_method", "_privdata"] 

377 

378 def __init__(self, fld, action_method, **kargs): 

379 # type: (Field[Any, Any], str, **Any) -> None 

380 self.fld = fld 

381 self._action_method = action_method 

382 self._privdata = kargs 

383 

384 def any2i(self, pkt, val): 

385 # type: (Optional[Packet], int) -> Any 

386 getattr(pkt, self._action_method)(val, self.fld, **self._privdata) 

387 return getattr(self.fld, "any2i")(pkt, val) 

388 

389 

390class ConditionalField(_FieldContainer): 

391 __slots__ = ["fld", "cond"] 

392 isconditional = True 

393 

394 def __init__(self, 

395 fld, # type: AnyField 

396 cond # type: Callable[[Packet], bool] 

397 ): 

398 # type: (...) -> None 

399 self.fld = fld 

400 self.cond = cond 

401 

402 def _evalcond(self, pkt): 

403 # type: (Packet) -> bool 

404 return bool(self.cond(pkt)) 

405 

406 def any2i(self, pkt, x): 

407 # type: (Optional[Packet], Any) -> Any 

408 # BACKWARD COMPATIBILITY 

409 # Note: we shouldn't need this function. (it's not correct) 

410 # However, having i2h implemented (#2364), it changes the default 

411 # behavior and broke all packets that wrongly use two ConditionalField 

412 # with the same name. Those packets are the problem: they are wrongly 

413 # built (they should either be reusing the same conditional field, or 

414 # using a MultipleTypeField). 

415 # But I don't want to dive into fixing all of them just yet, 

416 # so for now, let's keep this this way, even though it's not correct. 

417 if type(self.fld) is Field: 

418 return x 

419 return self.fld.any2i(pkt, x) 

420 

421 def i2h(self, pkt, val): 

422 # type: (Optional[Packet], Any) -> Any 

423 if pkt and not self._evalcond(pkt): 

424 return None 

425 return self.fld.i2h(pkt, val) 

426 

427 def getfield(self, pkt, s): 

428 # type: (Packet, bytes) -> Tuple[bytes, Any] 

429 if self._evalcond(pkt): 

430 return self.fld.getfield(pkt, s) 

431 else: 

432 return s, None 

433 

434 def addfield(self, pkt, s, val): 

435 # type: (Packet, bytes, Any) -> bytes 

436 if self._evalcond(pkt): 

437 return self.fld.addfield(pkt, s, val) 

438 else: 

439 return s 

440 

441 def __getattr__(self, attr): 

442 # type: (str) -> Any 

443 return getattr(self.fld, attr) 

444 

445 

446class MultipleTypeField(_FieldContainer): 

447 """ 

448 MultipleTypeField are used for fields that can be implemented by 

449 various Field subclasses, depending on conditions on the packet. 

450 

451 It is initialized with `flds` and `dflt`. 

452 

453 :param dflt: is the default field type, to be used when none of the 

454 conditions matched the current packet. 

455 :param flds: is a list of tuples (`fld`, `cond`) or (`fld`, `cond`, `hint`) 

456 where `fld` if a field type, and `cond` a "condition" to 

457 determine if `fld` is the field type that should be used. 

458 

459 ``cond`` is either: 

460 

461 - a callable `cond_pkt` that accepts one argument (the packet) and 

462 returns True if `fld` should be used, False otherwise. 

463 - a tuple (`cond_pkt`, `cond_pkt_val`), where `cond_pkt` is the same 

464 as in the previous case and `cond_pkt_val` is a callable that 

465 accepts two arguments (the packet, and the value to be set) and 

466 returns True if `fld` should be used, False otherwise. 

467 

468 See scapy.layers.l2.ARP (type "help(ARP)" in Scapy) for an example of 

469 use. 

470 """ 

471 

472 __slots__ = ["flds", "dflt", "hints", "name", "default"] 

473 

474 def __init__( 

475 self, 

476 flds: List[Union[ 

477 Tuple[Field[Any, Any], Any, str], 

478 Tuple[Field[Any, Any], Any] 

479 ]], 

480 dflt: Field[Any, Any] 

481 ) -> None: 

482 self.hints = { 

483 x[0]: x[2] 

484 for x in flds 

485 if len(x) == 3 

486 } 

487 self.flds = [ 

488 (x[0], x[1]) for x in flds 

489 ] 

490 self.dflt = dflt 

491 self.default = None # So that we can detect changes in defaults 

492 self.name = self.dflt.name 

493 if any(x[0].name != self.name for x in self.flds): 

494 warnings.warn( 

495 ("All fields should have the same name in a " 

496 "MultipleTypeField (%s). Use hints.") % self.name, 

497 SyntaxWarning 

498 ) 

499 

500 def _iterate_fields_cond(self, pkt, val, use_val): 

501 # type: (Optional[Packet], Any, bool) -> Field[Any, Any] 

502 """Internal function used by _find_fld_pkt & _find_fld_pkt_val""" 

503 # Iterate through the fields 

504 for fld, cond in self.flds: 

505 if isinstance(cond, tuple): 

506 if use_val: 

507 if val is None: 

508 val = self.dflt.default 

509 if cond[1](pkt, val): 

510 return fld 

511 continue 

512 else: 

513 cond = cond[0] 

514 if cond(pkt): 

515 return fld 

516 return self.dflt 

517 

518 def _find_fld_pkt(self, pkt): 

519 # type: (Optional[Packet]) -> Field[Any, Any] 

520 """Given a Packet instance `pkt`, returns the Field subclass to be 

521used. If you know the value to be set (e.g., in .addfield()), use 

522._find_fld_pkt_val() instead. 

523 

524 """ 

525 return self._iterate_fields_cond(pkt, None, False) 

526 

527 def _find_fld_pkt_val(self, 

528 pkt, # type: Optional[Packet] 

529 val, # type: Any 

530 ): 

531 # type: (...) -> Tuple[Field[Any, Any], Any] 

532 """Given a Packet instance `pkt` and the value `val` to be set, 

533returns the Field subclass to be used, and the updated `val` if necessary. 

534 

535 """ 

536 fld = self._iterate_fields_cond(pkt, val, True) 

537 if val is None: 

538 val = fld.default 

539 return fld, val 

540 

541 def _find_fld(self): 

542 # type: () -> Field[Any, Any] 

543 """Returns the Field subclass to be used, depending on the Packet 

544instance, or the default subclass. 

545 

546DEV: since the Packet instance is not provided, we have to use a hack 

547to guess it. It should only be used if you cannot provide the current 

548Packet instance (for example, because of the current Scapy API). 

549 

550If you have the current Packet instance, use ._find_fld_pkt_val() (if 

551the value to set is also known) of ._find_fld_pkt() instead. 

552 

553 """ 

554 # Hack to preserve current Scapy API 

555 # See https://stackoverflow.com/a/7272464/3223422 

556 frame = inspect.currentframe().f_back.f_back # type: ignore 

557 while frame is not None: 

558 try: 

559 pkt = frame.f_locals['self'] 

560 except KeyError: 

561 pass 

562 else: 

563 if isinstance(pkt, tuple(self.dflt.owners)): 

564 if not pkt.default_fields: 

565 # Packet not initialized 

566 return self.dflt 

567 return self._find_fld_pkt(pkt) 

568 frame = frame.f_back 

569 return self.dflt 

570 

571 def getfield(self, 

572 pkt, # type: Packet 

573 s, # type: bytes 

574 ): 

575 # type: (...) -> Tuple[bytes, Any] 

576 return self._find_fld_pkt(pkt).getfield(pkt, s) 

577 

578 def addfield(self, pkt, s, val): 

579 # type: (Packet, bytes, Any) -> bytes 

580 fld, val = self._find_fld_pkt_val(pkt, val) 

581 return fld.addfield(pkt, s, val) 

582 

583 def any2i(self, pkt, val): 

584 # type: (Optional[Packet], Any) -> Any 

585 fld, val = self._find_fld_pkt_val(pkt, val) 

586 return fld.any2i(pkt, val) 

587 

588 def h2i(self, pkt, val): 

589 # type: (Optional[Packet], Any) -> Any 

590 fld, val = self._find_fld_pkt_val(pkt, val) 

591 return fld.h2i(pkt, val) 

592 

593 def i2h(self, 

594 pkt, # type: Packet 

595 val, # type: Any 

596 ): 

597 # type: (...) -> Any 

598 fld, val = self._find_fld_pkt_val(pkt, val) 

599 return fld.i2h(pkt, val) 

600 

601 def i2m(self, pkt, val): 

602 # type: (Optional[Packet], Optional[Any]) -> Any 

603 fld, val = self._find_fld_pkt_val(pkt, val) 

604 return fld.i2m(pkt, val) 

605 

606 def i2len(self, pkt, val): 

607 # type: (Packet, Any) -> int 

608 fld, val = self._find_fld_pkt_val(pkt, val) 

609 return fld.i2len(pkt, val) 

610 

611 def i2repr(self, pkt, val): 

612 # type: (Optional[Packet], Any) -> str 

613 fld, val = self._find_fld_pkt_val(pkt, val) 

614 hint = "" 

615 if fld in self.hints: 

616 hint = " (%s)" % self.hints[fld] 

617 return fld.i2repr(pkt, val) + hint 

618 

619 def register_owner(self, cls): 

620 # type: (Type[Packet]) -> None 

621 for fld, _ in self.flds: 

622 fld.owners.append(cls) 

623 self.dflt.owners.append(cls) 

624 

625 def get_fields_list(self): 

626 # type: () -> List[Any] 

627 return [self] 

628 

629 @property 

630 def fld(self): 

631 # type: () -> Field[Any, Any] 

632 return self._find_fld() 

633 

634 

635class PadField(_FieldContainer): 

636 """Add bytes after the proxified field so that it ends at the specified 

637 alignment from its beginning""" 

638 __slots__ = ["fld", "_align", "_padwith"] 

639 

640 def __init__(self, fld, align, padwith=None): 

641 # type: (AnyField, int, Optional[bytes]) -> None 

642 self.fld = fld 

643 self._align = align 

644 self._padwith = padwith or b"\x00" 

645 

646 def padlen(self, flen, pkt): 

647 # type: (int, Packet) -> int 

648 return -flen % self._align 

649 

650 def getfield(self, 

651 pkt, # type: Packet 

652 s, # type: bytes 

653 ): 

654 # type: (...) -> Tuple[bytes, Any] 

655 remain, val = self.fld.getfield(pkt, s) 

656 padlen = self.padlen(len(s) - len(remain), pkt) 

657 return remain[padlen:], val 

658 

659 def addfield(self, 

660 pkt, # type: Packet 

661 s, # type: bytes 

662 val, # type: Any 

663 ): 

664 # type: (...) -> bytes 

665 sval = self.fld.addfield(pkt, b"", val) 

666 return s + sval + ( 

667 self.padlen(len(sval), pkt) * self._padwith 

668 ) 

669 

670 

671class ReversePadField(PadField): 

672 """Add bytes BEFORE the proxified field so that it starts at the specified 

673 alignment from its beginning""" 

674 

675 def original_length(self, pkt): 

676 # type: (Packet) -> int 

677 return len(pkt.original) 

678 

679 def getfield(self, 

680 pkt, # type: Packet 

681 s, # type: bytes 

682 ): 

683 # type: (...) -> Tuple[bytes, Any] 

684 # We need to get the length that has already been dissected 

685 padlen = self.padlen(self.original_length(pkt) - len(s), pkt) 

686 return self.fld.getfield(pkt, s[padlen:]) 

687 

688 def addfield(self, 

689 pkt, # type: Packet 

690 s, # type: bytes 

691 val, # type: Any 

692 ): 

693 # type: (...) -> bytes 

694 sval = self.fld.addfield(pkt, b"", val) 

695 return s + struct.pack("%is" % ( 

696 self.padlen(len(s), pkt) 

697 ), self._padwith) + sval 

698 

699 

700class TrailerBytes(bytes): 

701 """ 

702 Reverses slice operations to take from the back of the packet, 

703 not the front 

704 """ 

705 

706 def __getitem__(self, item): # type: ignore 

707 # type: (Union[int, slice]) -> Union[int, bytes] 

708 if isinstance(item, int): 

709 if item < 0: 

710 item = 1 + item 

711 else: 

712 item = len(self) - 1 - item 

713 elif isinstance(item, slice): 

714 start, stop, step = item.start, item.stop, item.step 

715 new_start = -stop if stop else None 

716 new_stop = -start if start else None 

717 item = slice(new_start, new_stop, step) 

718 return super(self.__class__, self).__getitem__(item) 

719 

720 

721class TrailerField(_FieldContainer): 

722 """Special Field that gets its value from the end of the *packet* 

723 (Note: not layer, but packet). 

724 

725 Mostly used for FCS 

726 """ 

727 __slots__ = ["fld"] 

728 

729 def __init__(self, fld): 

730 # type: (Field[Any, Any]) -> None 

731 self.fld = fld 

732 

733 # Note: this is ugly. Very ugly. 

734 # Do not copy this crap elsewhere, so that if one day we get 

735 # brave enough to refactor it, it'll be easier. 

736 

737 def getfield(self, pkt, s): 

738 # type: (Packet, bytes) -> Tuple[bytes, int] 

739 previous_post_dissect = pkt.post_dissect 

740 

741 def _post_dissect(self, s): 

742 # type: (Packet, bytes) -> bytes 

743 # Reset packet to allow post_build 

744 self.raw_packet_cache = None 

745 self.post_dissect = previous_post_dissect # type: ignore 

746 return previous_post_dissect(s) 

747 pkt.post_dissect = MethodType(_post_dissect, pkt) # type: ignore 

748 s = TrailerBytes(s) 

749 s, val = self.fld.getfield(pkt, s) 

750 return bytes(s), val 

751 

752 def addfield(self, pkt, s, val): 

753 # type: (Packet, bytes, Optional[int]) -> bytes 

754 previous_post_build = pkt.post_build 

755 value = self.fld.addfield(pkt, b"", val) 

756 

757 def _post_build(self, p, pay): 

758 # type: (Packet, bytes, bytes) -> bytes 

759 pay += value 

760 self.post_build = previous_post_build # type: ignore 

761 return previous_post_build(p, pay) 

762 pkt.post_build = MethodType(_post_build, pkt) # type: ignore 

763 return s 

764 

765 

766class FCSField(TrailerField): 

767 """ 

768 A FCS field that gets appended at the end of the *packet* (not layer). 

769 """ 

770 

771 def __init__(self, *args, **kwargs): 

772 # type: (*Any, **Any) -> None 

773 super(FCSField, self).__init__(Field(*args, **kwargs)) 

774 

775 def i2repr(self, pkt, x): 

776 # type: (Optional[Packet], int) -> str 

777 return lhex(self.i2h(pkt, x)) 

778 

779 

780class DestField(Field[str, bytes]): 

781 __slots__ = ["defaultdst"] 

782 # Each subclass must have its own bindings attribute 

783 bindings = {} # type: Dict[Type[Packet], Tuple[str, Any]] 

784 

785 def __init__(self, name, default): 

786 # type: (str, str) -> None 

787 self.defaultdst = default 

788 

789 def dst_from_pkt(self, pkt): 

790 # type: (Packet) -> str 

791 for addr, condition in self.bindings.get(pkt.payload.__class__, []): 

792 try: 

793 if all(pkt.payload.getfieldval(field) == value 

794 for field, value in condition.items()): 

795 if callable(addr): 

796 return addr(pkt) # type: ignore 

797 else: 

798 return addr # type: ignore 

799 except AttributeError: 

800 pass 

801 return self.defaultdst 

802 

803 @classmethod 

804 def bind_addr(cls, layer, addr, **condition): 

805 # type: (Type[Packet], str, **Any) -> None 

806 cls.bindings.setdefault(layer, []).append( # type: ignore 

807 (addr, condition) 

808 ) 

809 

810 

811class MACField(Field[Optional[str], bytes]): 

812 def __init__(self, name, default): 

813 # type: (str, Optional[Any]) -> None 

814 Field.__init__(self, name, default, "6s") 

815 

816 def i2m(self, pkt, x): 

817 # type: (Optional[Packet], Optional[str]) -> bytes 

818 if not x: 

819 return b"\0\0\0\0\0\0" 

820 try: 

821 y = mac2str(x) 

822 except (struct.error, OverflowError, ValueError): 

823 y = bytes_encode(x) 

824 return y 

825 

826 def m2i(self, pkt, x): 

827 # type: (Optional[Packet], bytes) -> str 

828 return str2mac(x) 

829 

830 def any2i(self, pkt, x): 

831 # type: (Optional[Packet], Any) -> str 

832 if isinstance(x, bytes) and len(x) == 6: 

833 return self.m2i(pkt, x) 

834 return cast(str, x) 

835 

836 def i2repr(self, pkt, x): 

837 # type: (Optional[Packet], Optional[str]) -> str 

838 x = self.i2h(pkt, x) 

839 if x is None: 

840 return repr(x) 

841 if self in conf.resolve: 

842 x = conf.manufdb._resolve_MAC(x) 

843 return x 

844 

845 def randval(self): 

846 # type: () -> RandMAC 

847 return RandMAC() 

848 

849 

850class LEMACField(MACField): 

851 def i2m(self, pkt, x): 

852 # type: (Optional[Packet], Optional[str]) -> bytes 

853 return MACField.i2m(self, pkt, x)[::-1] 

854 

855 def m2i(self, pkt, x): 

856 # type: (Optional[Packet], bytes) -> str 

857 return MACField.m2i(self, pkt, x[::-1]) 

858 

859 

860class IPField(Field[Union[str, Net], bytes]): 

861 def __init__(self, name, default): 

862 # type: (str, Optional[str]) -> None 

863 Field.__init__(self, name, default, "4s") 

864 

865 def h2i(self, pkt, x): 

866 # type: (Optional[Packet], Union[AnyStr, List[AnyStr]]) -> Any 

867 if isinstance(x, bytes): 

868 x = plain_str(x) # type: ignore 

869 if isinstance(x, _ScopedIP): 

870 return x 

871 elif isinstance(x, str): 

872 x = ScopedIP(x) 

873 try: 

874 inet_aton(x) 

875 except socket.error: 

876 return Net(x) 

877 elif isinstance(x, tuple): 

878 if len(x) != 2: 

879 raise ValueError("Invalid IP format") 

880 return Net(*x) 

881 elif isinstance(x, list): 

882 return [self.h2i(pkt, n) for n in x] 

883 return x 

884 

885 def i2h(self, pkt, x): 

886 # type: (Optional[Packet], Optional[Union[str, Net]]) -> str 

887 return cast(str, x) 

888 

889 def resolve(self, x): 

890 # type: (str) -> str 

891 if self in conf.resolve: 

892 try: 

893 ret = socket.gethostbyaddr(x)[0] 

894 except Exception: 

895 pass 

896 else: 

897 if ret: 

898 return ret 

899 return x 

900 

901 def i2m(self, pkt, x): 

902 # type: (Optional[Packet], Optional[Union[str, Net]]) -> bytes 

903 if x is None: 

904 return b'\x00\x00\x00\x00' 

905 return inet_aton(plain_str(x)) 

906 

907 def m2i(self, pkt, x): 

908 # type: (Optional[Packet], bytes) -> str 

909 return inet_ntoa(x) 

910 

911 def any2i(self, pkt, x): 

912 # type: (Optional[Packet], Any) -> Any 

913 return self.h2i(pkt, x) 

914 

915 def i2repr(self, pkt, x): 

916 # type: (Optional[Packet], Union[str, Net]) -> str 

917 if isinstance(x, _ScopedIP) and x.scope: 

918 return repr(x) 

919 r = self.resolve(self.i2h(pkt, x)) 

920 return r if isinstance(r, str) else repr(r) 

921 

922 def randval(self): 

923 # type: () -> RandIP 

924 return RandIP() 

925 

926 

927class SourceIPField(IPField): 

928 def __init__(self, name): 

929 # type: (str) -> None 

930 IPField.__init__(self, name, None) 

931 

932 def __findaddr(self, pkt): 

933 # type: (Packet) -> Optional[str] 

934 if conf.route is None: 

935 # unused import, only to initialize conf.route 

936 import scapy.route # noqa: F401 

937 return pkt.route()[1] or conf.route.route()[1] 

938 

939 def i2m(self, pkt, x): 

940 # type: (Optional[Packet], Optional[Union[str, Net]]) -> bytes 

941 if x is None and pkt is not None: 

942 x = self.__findaddr(pkt) 

943 return super(SourceIPField, self).i2m(pkt, x) 

944 

945 def i2h(self, pkt, x): 

946 # type: (Optional[Packet], Optional[Union[str, Net]]) -> str 

947 if x is None and pkt is not None: 

948 x = self.__findaddr(pkt) 

949 return super(SourceIPField, self).i2h(pkt, x) 

950 

951 

952class IP6Field(Field[Optional[Union[str, Net6]], bytes]): 

953 def __init__(self, name, default): 

954 # type: (str, Optional[str]) -> None 

955 Field.__init__(self, name, default, "16s") 

956 

957 def h2i(self, pkt, x): 

958 # type: (Optional[Packet], Any) -> str 

959 if isinstance(x, bytes): 

960 x = plain_str(x) 

961 if isinstance(x, _ScopedIP): 

962 return x 

963 elif isinstance(x, str): 

964 x = ScopedIP(x) 

965 try: 

966 x = ScopedIP(in6_ptop(x), scope=x.scope) 

967 except socket.error: 

968 return Net6(x) # type: ignore 

969 elif isinstance(x, tuple): 

970 if len(x) != 2: 

971 raise ValueError("Invalid IPv6 format") 

972 return Net6(*x) # type: ignore 

973 elif isinstance(x, list): 

974 x = [self.h2i(pkt, n) for n in x] 

975 return x # type: ignore 

976 

977 def i2h(self, pkt, x): 

978 # type: (Optional[Packet], Optional[Union[str, Net6]]) -> str 

979 return cast(str, x) 

980 

981 def i2m(self, pkt, x): 

982 # type: (Optional[Packet], Optional[Union[str, Net6]]) -> bytes 

983 if x is None: 

984 x = "::" 

985 return inet_pton(socket.AF_INET6, plain_str(x)) 

986 

987 def m2i(self, pkt, x): 

988 # type: (Optional[Packet], bytes) -> str 

989 return inet_ntop(socket.AF_INET6, x) 

990 

991 def any2i(self, pkt, x): 

992 # type: (Optional[Packet], Optional[str]) -> str 

993 return self.h2i(pkt, x) 

994 

995 def i2repr(self, pkt, x): 

996 # type: (Optional[Packet], Optional[Union[str, Net6]]) -> str 

997 if x is None: 

998 return self.i2h(pkt, x) 

999 elif not isinstance(x, Net6) and not isinstance(x, list): 

1000 if in6_isaddrTeredo(x): # print Teredo info 

1001 server, _, maddr, mport = teredoAddrExtractInfo(x) 

1002 return "%s [Teredo srv: %s cli: %s:%s]" % (self.i2h(pkt, x), server, maddr, mport) # noqa: E501 

1003 elif in6_isaddr6to4(x): # print encapsulated address 

1004 vaddr = in6_6to4ExtractAddr(x) 

1005 return "%s [6to4 GW: %s]" % (self.i2h(pkt, x), vaddr) 

1006 elif isinstance(x, _ScopedIP) and x.scope: 

1007 return repr(x) 

1008 r = self.i2h(pkt, x) # No specific information to return 

1009 return r if isinstance(r, str) else repr(r) 

1010 

1011 def randval(self): 

1012 # type: () -> RandIP6 

1013 return RandIP6() 

1014 

1015 

1016class SourceIP6Field(IP6Field): 

1017 def __init__(self, name): 

1018 # type: (str) -> None 

1019 IP6Field.__init__(self, name, None) 

1020 

1021 def __findaddr(self, pkt): 

1022 # type: (Packet) -> Optional[str] 

1023 if conf.route6 is None: 

1024 # unused import, only to initialize conf.route 

1025 import scapy.route6 # noqa: F401 

1026 return pkt.route()[1] 

1027 

1028 def i2m(self, pkt, x): 

1029 # type: (Optional[Packet], Optional[Union[str, Net6]]) -> bytes 

1030 if x is None and pkt is not None: 

1031 x = self.__findaddr(pkt) 

1032 return super(SourceIP6Field, self).i2m(pkt, x) 

1033 

1034 def i2h(self, pkt, x): 

1035 # type: (Optional[Packet], Optional[Union[str, Net6]]) -> str 

1036 if x is None and pkt is not None: 

1037 x = self.__findaddr(pkt) 

1038 return super(SourceIP6Field, self).i2h(pkt, x) 

1039 

1040 

1041class DestIP6Field(IP6Field, DestField): 

1042 bindings = {} # type: Dict[Type[Packet], Tuple[str, Any]] 

1043 

1044 def __init__(self, name, default): 

1045 # type: (str, str) -> None 

1046 IP6Field.__init__(self, name, None) 

1047 DestField.__init__(self, name, default) 

1048 

1049 def i2m(self, pkt, x): 

1050 # type: (Optional[Packet], Optional[Union[str, Net6]]) -> bytes 

1051 if x is None and pkt is not None: 

1052 x = self.dst_from_pkt(pkt) 

1053 return IP6Field.i2m(self, pkt, x) 

1054 

1055 def i2h(self, pkt, x): 

1056 # type: (Optional[Packet], Optional[Union[str, Net6]]) -> str 

1057 if x is None and pkt is not None: 

1058 x = self.dst_from_pkt(pkt) 

1059 return super(DestIP6Field, self).i2h(pkt, x) 

1060 

1061 

1062class ByteField(Field[int, int]): 

1063 def __init__(self, name, default): 

1064 # type: (str, Optional[int]) -> None 

1065 Field.__init__(self, name, default, "B") 

1066 

1067 

1068class XByteField(ByteField): 

1069 def i2repr(self, pkt, x): 

1070 # type: (Optional[Packet], int) -> str 

1071 return lhex(self.i2h(pkt, x)) 

1072 

1073 

1074# XXX Unused field: at least add some tests 

1075class OByteField(ByteField): 

1076 def i2repr(self, pkt, x): 

1077 # type: (Optional[Packet], int) -> str 

1078 return "%03o" % self.i2h(pkt, x) 

1079 

1080 

1081class ThreeBytesField(Field[int, int]): 

1082 def __init__(self, name, default): 

1083 # type: (str, int) -> None 

1084 Field.__init__(self, name, default, "!I") 

1085 self.sz = 3 # emits/consumes 3 bytes; keep i2len consistent for FieldLenField 

1086 

1087 def addfield(self, pkt, s, val): 

1088 # type: (Packet, bytes, Optional[int]) -> bytes 

1089 return s + struct.pack(self.fmt, self.i2m(pkt, val))[1:4] 

1090 

1091 def getfield(self, pkt, s): 

1092 # type: (Packet, bytes) -> Tuple[bytes, int] 

1093 return s[3:], self.m2i(pkt, struct.unpack(self.fmt, b"\x00" + s[:3])[0]) # noqa: E501 

1094 

1095 

1096class X3BytesField(ThreeBytesField, XByteField): 

1097 def i2repr(self, pkt, x): 

1098 # type: (Optional[Packet], int) -> str 

1099 return XByteField.i2repr(self, pkt, x) 

1100 

1101 

1102class LEThreeBytesField(ByteField): 

1103 def __init__(self, name, default): 

1104 # type: (str, Optional[int]) -> None 

1105 Field.__init__(self, name, default, "<I") 

1106 self.sz = 3 # emits/consumes 3 bytes; keep i2len consistent for FieldLenField 

1107 

1108 def addfield(self, pkt, s, val): 

1109 # type: (Packet, bytes, Optional[int]) -> bytes 

1110 return s + struct.pack(self.fmt, self.i2m(pkt, val))[:3] 

1111 

1112 def getfield(self, pkt, s): 

1113 # type: (Optional[Packet], bytes) -> Tuple[bytes, int] 

1114 return s[3:], self.m2i(pkt, struct.unpack(self.fmt, s[:3] + b"\x00")[0]) # noqa: E501 

1115 

1116 

1117class XLE3BytesField(LEThreeBytesField, XByteField): 

1118 def i2repr(self, pkt, x): 

1119 # type: (Optional[Packet], int) -> str 

1120 return XByteField.i2repr(self, pkt, x) 

1121 

1122 

1123def LEX3BytesField(*args, **kwargs): 

1124 # type: (*Any, **Any) -> Any 

1125 warnings.warn( 

1126 "LEX3BytesField is deprecated. Use XLE3BytesField", 

1127 DeprecationWarning 

1128 ) 

1129 return XLE3BytesField(*args, **kwargs) 

1130 

1131 

1132class NBytesField(Field[int, List[int]]): 

1133 def __init__(self, name, default, sz): 

1134 # type: (str, Optional[int], int) -> None 

1135 Field.__init__(self, name, default, "<" + "B" * sz) 

1136 

1137 def i2m(self, pkt, x): 

1138 # type: (Optional[Packet], Optional[int]) -> List[int] 

1139 if x is None: 

1140 return [0] * self.sz 

1141 x2m = list() 

1142 for _ in range(self.sz): 

1143 x2m.append(x % 256) 

1144 x //= 256 

1145 return x2m[::-1] 

1146 

1147 def m2i(self, pkt, x): 

1148 # type: (Optional[Packet], Union[List[int], int]) -> int 

1149 if isinstance(x, int): 

1150 return x 

1151 # x can be a tuple when coming from struct.unpack (from getfield) 

1152 if isinstance(x, (list, tuple)): 

1153 return sum(d * (256 ** i) for i, d in enumerate(reversed(x))) 

1154 return 0 

1155 

1156 def i2repr(self, pkt, x): 

1157 # type: (Optional[Packet], int) -> str 

1158 if isinstance(x, int): 

1159 return '%i' % x 

1160 return super(NBytesField, self).i2repr(pkt, x) 

1161 

1162 def addfield(self, pkt, s, val): 

1163 # type: (Optional[Packet], bytes, Optional[int]) -> bytes 

1164 return s + self.struct.pack(*self.i2m(pkt, val)) 

1165 

1166 def getfield(self, pkt, s): 

1167 # type: (Optional[Packet], bytes) -> Tuple[bytes, int] 

1168 return (s[self.sz:], 

1169 self.m2i(pkt, self.struct.unpack(s[:self.sz]))) # type: ignore 

1170 

1171 def randval(self): 

1172 # type: () -> RandNum 

1173 return RandNum(0, 2 ** (self.sz * 8) - 1) 

1174 

1175 

1176class XNBytesField(NBytesField): 

1177 def i2repr(self, pkt, x): 

1178 # type: (Optional[Packet], int) -> str 

1179 if isinstance(x, int): 

1180 return '0x%x' % x 

1181 # x can be a tuple when coming from struct.unpack (from getfield) 

1182 if isinstance(x, (list, tuple)): 

1183 return "0x" + "".join("%02x" % b for b in x) 

1184 return super(XNBytesField, self).i2repr(pkt, x) 

1185 

1186 

1187class SignedByteField(Field[int, int]): 

1188 def __init__(self, name, default): 

1189 # type: (str, Optional[int]) -> None 

1190 Field.__init__(self, name, default, "b") 

1191 

1192 

1193class FieldValueRangeException(Scapy_Exception): 

1194 pass 

1195 

1196 

1197class MaximumItemsCount(Scapy_Exception): 

1198 pass 

1199 

1200 

1201class FieldAttributeException(Scapy_Exception): 

1202 pass 

1203 

1204 

1205class YesNoByteField(ByteField): 

1206 """ 

1207 A byte based flag field that shows representation of its number 

1208 based on a given association 

1209 

1210 In its default configuration the following representation is generated: 

1211 x == 0 : 'no' 

1212 x != 0 : 'yes' 

1213 

1214 In more sophisticated use-cases (e.g. yes/no/invalid) one can use the 

1215 config attribute to configure. 

1216 Key-value, key-range and key-value-set associations that will be used to 

1217 generate the values representation. 

1218 

1219 - A range is given by a tuple (<first-val>, <last-value>) including the 

1220 last value. 

1221 - A single-value tuple is treated as scalar. 

1222 - A list defines a set of (probably non consecutive) values that should be 

1223 associated to a given key. 

1224 

1225 All values not associated with a key will be shown as number of type 

1226 unsigned byte. 

1227 

1228 **For instance**:: 

1229 

1230 config = { 

1231 'no' : 0, 

1232 'foo' : (1,22), 

1233 'yes' : 23, 

1234 'bar' : [24,25, 42, 48, 87, 253] 

1235 } 

1236 

1237 Generates the following representations:: 

1238 

1239 x == 0 : 'no' 

1240 x == 15: 'foo' 

1241 x == 23: 'yes' 

1242 x == 42: 'bar' 

1243 x == 43: 43 

1244 

1245 Another example, using the config attribute one could also revert 

1246 the stock-yes-no-behavior:: 

1247 

1248 config = { 

1249 'yes' : 0, 

1250 'no' : (1,255) 

1251 } 

1252 

1253 Will generate the following value representation:: 

1254 

1255 x == 0 : 'yes' 

1256 x != 0 : 'no' 

1257 

1258 """ 

1259 __slots__ = ['eval_fn'] 

1260 

1261 def _build_config_representation(self, config): 

1262 # type: (Dict[str, Any]) -> None 

1263 assoc_table = dict() 

1264 for key in config: 

1265 value_spec = config[key] 

1266 

1267 value_spec_type = type(value_spec) 

1268 

1269 if value_spec_type is int: 

1270 if value_spec < 0 or value_spec > 255: 

1271 raise FieldValueRangeException('given field value {} invalid - ' # noqa: E501 

1272 'must be in range [0..255]'.format(value_spec)) # noqa: E501 

1273 assoc_table[value_spec] = key 

1274 

1275 elif value_spec_type is list: 

1276 for value in value_spec: 

1277 if value < 0 or value > 255: 

1278 raise FieldValueRangeException('given field value {} invalid - ' # noqa: E501 

1279 'must be in range [0..255]'.format(value)) # noqa: E501 

1280 assoc_table[value] = key 

1281 

1282 elif value_spec_type is tuple: 

1283 value_spec_len = len(value_spec) 

1284 if value_spec_len != 2: 

1285 raise FieldAttributeException('invalid length {} of given config item tuple {} - must be ' # noqa: E501 

1286 '(<start-range>, <end-range>).'.format(value_spec_len, value_spec)) # noqa: E501 

1287 

1288 value_range_start = value_spec[0] 

1289 if value_range_start < 0 or value_range_start > 255: 

1290 raise FieldValueRangeException('given field value {} invalid - ' # noqa: E501 

1291 'must be in range [0..255]'.format(value_range_start)) # noqa: E501 

1292 

1293 value_range_end = value_spec[1] 

1294 if value_range_end < 0 or value_range_end > 255: 

1295 raise FieldValueRangeException('given field value {} invalid - ' # noqa: E501 

1296 'must be in range [0..255]'.format(value_range_end)) # noqa: E501 

1297 

1298 for value in range(value_range_start, value_range_end + 1): 

1299 

1300 assoc_table[value] = key 

1301 

1302 self.eval_fn = lambda x: assoc_table[x] if x in assoc_table else x 

1303 

1304 def __init__(self, name, default, config=None): 

1305 # type: (str, int, Optional[Dict[str, Any]]) -> None 

1306 

1307 if not config: 

1308 # this represents the common use case and therefore it is kept small # noqa: E501 

1309 self.eval_fn = lambda x: 'no' if x == 0 else 'yes' 

1310 else: 

1311 self._build_config_representation(config) 

1312 ByteField.__init__(self, name, default) 

1313 

1314 def i2repr(self, pkt, x): 

1315 # type: (Optional[Packet], int) -> str 

1316 return self.eval_fn(x) # type: ignore 

1317 

1318 

1319class ShortField(Field[int, int]): 

1320 def __init__(self, name, default): 

1321 # type: (str, Optional[int]) -> None 

1322 Field.__init__(self, name, default, "H") 

1323 

1324 

1325class SignedShortField(Field[int, int]): 

1326 def __init__(self, name, default): 

1327 # type: (str, Optional[int]) -> None 

1328 Field.__init__(self, name, default, "h") 

1329 

1330 

1331class LEShortField(Field[int, int]): 

1332 def __init__(self, name, default): 

1333 # type: (str, Optional[int]) -> None 

1334 Field.__init__(self, name, default, "<H") 

1335 

1336 

1337class LESignedShortField(Field[int, int]): 

1338 def __init__(self, name, default): 

1339 # type: (str, Optional[int]) -> None 

1340 Field.__init__(self, name, default, "<h") 

1341 

1342 

1343class XShortField(ShortField): 

1344 def i2repr(self, pkt, x): 

1345 # type: (Optional[Packet], int) -> str 

1346 return lhex(self.i2h(pkt, x)) 

1347 

1348 

1349class IntField(Field[int, int]): 

1350 def __init__(self, name, default): 

1351 # type: (str, Optional[int]) -> None 

1352 Field.__init__(self, name, default, "I") 

1353 

1354 

1355class SignedIntField(Field[int, int]): 

1356 def __init__(self, name, default): 

1357 # type: (str, int) -> None 

1358 Field.__init__(self, name, default, "i") 

1359 

1360 

1361class LEIntField(Field[int, int]): 

1362 def __init__(self, name, default): 

1363 # type: (str, Optional[int]) -> None 

1364 Field.__init__(self, name, default, "<I") 

1365 

1366 

1367class LESignedIntField(Field[int, int]): 

1368 def __init__(self, name, default): 

1369 # type: (str, int) -> None 

1370 Field.__init__(self, name, default, "<i") 

1371 

1372 

1373class XIntField(IntField): 

1374 def i2repr(self, pkt, x): 

1375 # type: (Optional[Packet], int) -> str 

1376 return lhex(self.i2h(pkt, x)) 

1377 

1378 

1379class XLEIntField(LEIntField, XIntField): 

1380 def i2repr(self, pkt, x): 

1381 # type: (Optional[Packet], int) -> str 

1382 return XIntField.i2repr(self, pkt, x) 

1383 

1384 

1385class XLEShortField(LEShortField, XShortField): 

1386 def i2repr(self, pkt, x): 

1387 # type: (Optional[Packet], int) -> str 

1388 return XShortField.i2repr(self, pkt, x) 

1389 

1390 

1391class LongField(Field[int, int]): 

1392 def __init__(self, name, default): 

1393 # type: (str, int) -> None 

1394 Field.__init__(self, name, default, "Q") 

1395 

1396 

1397class SignedLongField(Field[int, int]): 

1398 def __init__(self, name, default): 

1399 # type: (str, Optional[int]) -> None 

1400 Field.__init__(self, name, default, "q") 

1401 

1402 

1403class LELongField(LongField): 

1404 def __init__(self, name, default): 

1405 # type: (str, Optional[int]) -> None 

1406 Field.__init__(self, name, default, "<Q") 

1407 

1408 

1409class LESignedLongField(Field[int, int]): 

1410 def __init__(self, name, default): 

1411 # type: (str, Optional[Any]) -> None 

1412 Field.__init__(self, name, default, "<q") 

1413 

1414 

1415class XLongField(LongField): 

1416 def i2repr(self, pkt, x): 

1417 # type: (Optional[Packet], int) -> str 

1418 return lhex(self.i2h(pkt, x)) 

1419 

1420 

1421class XLELongField(LELongField, XLongField): 

1422 def i2repr(self, pkt, x): 

1423 # type: (Optional[Packet], int) -> str 

1424 return XLongField.i2repr(self, pkt, x) 

1425 

1426 

1427class IEEEFloatField(Field[int, int]): 

1428 def __init__(self, name, default): 

1429 # type: (str, Optional[int]) -> None 

1430 Field.__init__(self, name, default, "f") 

1431 

1432 

1433class IEEEDoubleField(Field[int, int]): 

1434 def __init__(self, name, default): 

1435 # type: (str, Optional[int]) -> None 

1436 Field.__init__(self, name, default, "d") 

1437 

1438 

1439class _StrField(Field[I, bytes]): 

1440 __slots__ = ["remain"] 

1441 

1442 def __init__(self, name, default, fmt="H", remain=0): 

1443 # type: (str, Optional[I], str, int) -> None 

1444 Field.__init__(self, name, default, fmt) 

1445 self.remain = remain 

1446 

1447 def i2len(self, pkt, x): 

1448 # type: (Optional[Packet], Any) -> int 

1449 if x is None: 

1450 return 0 

1451 return len(x) 

1452 

1453 def any2i(self, pkt, x): 

1454 # type: (Optional[Packet], Any) -> I 

1455 if isinstance(x, str): 

1456 x = bytes_encode(x) 

1457 return super(_StrField, self).any2i(pkt, x) # type: ignore 

1458 

1459 def i2repr(self, pkt, x): 

1460 # type: (Optional[Packet], I) -> str 

1461 if x and isinstance(x, bytes): 

1462 return repr(x) 

1463 return super(_StrField, self).i2repr(pkt, x) 

1464 

1465 def i2m(self, pkt, x): 

1466 # type: (Optional[Packet], Optional[I]) -> bytes 

1467 if x is None: 

1468 return b"" 

1469 if not isinstance(x, bytes): 

1470 return bytes_encode(x) 

1471 return x 

1472 

1473 def addfield(self, pkt, s, val): 

1474 # type: (Packet, bytes, Optional[I]) -> bytes 

1475 return s + self.i2m(pkt, val) 

1476 

1477 def getfield(self, pkt, s): 

1478 # type: (Packet, bytes) -> Tuple[bytes, I] 

1479 if self.remain == 0: 

1480 return b"", self.m2i(pkt, s) 

1481 else: 

1482 return s[-self.remain:], self.m2i(pkt, s[:-self.remain]) 

1483 

1484 def randval(self): 

1485 # type: () -> RandBin 

1486 return RandBin(RandNum(0, 1200)) 

1487 

1488 

1489class StrField(_StrField[bytes]): 

1490 pass 

1491 

1492 

1493class StrFieldUtf16(StrField): 

1494 def any2i(self, pkt, x): 

1495 # type: (Optional[Packet], Optional[str]) -> bytes 

1496 if isinstance(x, str): 

1497 return self.h2i(pkt, x) 

1498 return super(StrFieldUtf16, self).any2i(pkt, x) 

1499 

1500 def i2repr(self, pkt, x): 

1501 # type: (Optional[Packet], bytes) -> str 

1502 return plain_str(self.i2h(pkt, x)) 

1503 

1504 def h2i(self, pkt, x): 

1505 # type: (Optional[Packet], Optional[str]) -> bytes 

1506 return plain_str(x).encode('utf-16-le', errors="replace") 

1507 

1508 def i2h(self, pkt, x): 

1509 # type: (Optional[Packet], bytes) -> str 

1510 return bytes_encode(x).decode('utf-16-le', errors="replace") 

1511 

1512 

1513class _StrEnumField: 

1514 def __init__(self, **kwargs): 

1515 # type: (**Any) -> None 

1516 self.enum = kwargs.pop("enum", {}) 

1517 

1518 def i2repr(self, pkt, v): 

1519 # type: (Optional[Packet], bytes) -> str 

1520 r = v.rstrip(b"\0") 

1521 rr = repr(r) 

1522 if self.enum: 

1523 if v in self.enum: 

1524 rr = "%s (%s)" % (rr, self.enum[v]) 

1525 elif r in self.enum: 

1526 rr = "%s (%s)" % (rr, self.enum[r]) 

1527 return rr 

1528 

1529 

1530class StrEnumField(_StrEnumField, StrField): 

1531 __slots__ = ["enum"] 

1532 

1533 def __init__( 

1534 self, 

1535 name, # type: str 

1536 default, # type: bytes 

1537 enum=None, # type: Optional[Dict[str, str]] 

1538 **kwargs # type: Any 

1539 ): 

1540 # type: (...) -> None 

1541 StrField.__init__(self, name, default, **kwargs) # type: ignore 

1542 self.enum = enum 

1543 

1544 

1545K = TypeVar('K', List[BasePacket], BasePacket, Optional[BasePacket]) 

1546 

1547 

1548class _PacketField(_StrField[K]): 

1549 __slots__ = ["cls"] 

1550 holds_packets = 1 

1551 

1552 def __init__(self, 

1553 name, # type: str 

1554 default, # type: Optional[K] 

1555 pkt_cls, # type: Union[Callable[[bytes], Packet], Type[Packet]] # noqa: E501 

1556 ): 

1557 # type: (...) -> None 

1558 super(_PacketField, self).__init__(name, default) 

1559 self.cls = pkt_cls 

1560 

1561 def i2m(self, 

1562 pkt, # type: Optional[Packet] 

1563 i, # type: Any 

1564 ): 

1565 # type: (...) -> bytes 

1566 if i is None: 

1567 return b"" 

1568 return raw(i) 

1569 

1570 def m2i(self, pkt, m): # type: ignore 

1571 # type: (Optional[Packet], bytes) -> Packet 

1572 try: 

1573 # we want to set parent wherever possible 

1574 return self.cls(m, _parent=pkt) # type: ignore 

1575 except TypeError: 

1576 return self.cls(m) 

1577 

1578 

1579class _PacketFieldSingle(_PacketField[K]): 

1580 def any2i(self, pkt, x): 

1581 # type: (Optional[Packet], Any) -> K 

1582 if x and pkt and hasattr(x, "add_parent"): 

1583 cast("Packet", x).add_parent(pkt) 

1584 return super(_PacketFieldSingle, self).any2i(pkt, x) 

1585 

1586 def getfield(self, 

1587 pkt, # type: Packet 

1588 s, # type: bytes 

1589 ): 

1590 # type: (...) -> Tuple[bytes, K] 

1591 i = self.m2i(pkt, s) 

1592 remain = b"" 

1593 # Dissection always appends Padding last, so checking the topmost 

1594 # layer avoids a full recursive haslayer()+getlayer() lookup. 

1595 r = i.lastlayer() 

1596 if isinstance(r, conf.padding_layer): 

1597 del r.underlayer.payload # type: ignore 

1598 remain = r.load 

1599 return remain, i # type: ignore 

1600 

1601 

1602class PacketField(_PacketFieldSingle[BasePacket]): 

1603 def randval(self): # type: ignore 

1604 # type: () -> Packet 

1605 from scapy.packet import fuzz 

1606 return fuzz(self.cls()) # type: ignore 

1607 

1608 

1609class PacketLenField(_PacketFieldSingle[Optional[BasePacket]]): 

1610 __slots__ = ["length_from"] 

1611 

1612 def __init__(self, 

1613 name, # type: str 

1614 default, # type: Packet 

1615 cls, # type: Union[Callable[[bytes], Packet], Type[Packet]] # noqa: E501 

1616 length_from=None # type: Optional[Callable[[Packet], int]] # noqa: E501 

1617 ): 

1618 # type: (...) -> None 

1619 super(PacketLenField, self).__init__(name, default, cls) 

1620 self.length_from = length_from or (lambda x: 0) 

1621 

1622 def getfield(self, 

1623 pkt, # type: Packet 

1624 s, # type: bytes 

1625 ): 

1626 # type: (...) -> Tuple[bytes, Optional[BasePacket]] 

1627 len_pkt = self.length_from(pkt) 

1628 i = None 

1629 if len_pkt: 

1630 try: 

1631 i = self.m2i(pkt, s[:len_pkt]) 

1632 except Exception: 

1633 if conf.debug_dissector: 

1634 raise 

1635 i = conf.raw_layer(load=s[:len_pkt]) 

1636 return s[len_pkt:], i 

1637 

1638 

1639class PacketListField(_PacketField[List[BasePacket]]): 

1640 """PacketListField represents a list containing a series of Packet instances 

1641 that might occur right in the middle of another Packet field. 

1642 This field type may also be used to indicate that a series of Packet 

1643 instances have a sibling semantic instead of a parent/child relationship 

1644 (i.e. a stack of layers). All elements in PacketListField have current 

1645 packet referenced in parent field. 

1646 """ 

1647 __slots__ = ["count_from", "length_from", "next_cls_cb", "max_count"] 

1648 islist = 1 

1649 

1650 def __init__( 

1651 self, 

1652 name, # type: str 

1653 default, # type: Optional[List[BasePacket]] 

1654 pkt_cls=None, # type: Optional[Union[Callable[[bytes], Packet], Type[Packet]]] # noqa: E501 

1655 count_from=None, # type: Optional[Callable[[Packet], int]] 

1656 length_from=None, # type: Optional[Callable[[Packet], int]] 

1657 next_cls_cb=None, # type: Optional[Callable[[Packet, List[BasePacket], Optional[Packet], bytes], Optional[Type[Packet]]]] # noqa: E501 

1658 max_count=None, # type: Optional[int] 

1659 ): 

1660 # type: (...) -> None 

1661 """ 

1662 The number of Packet instances that are dissected by this field can 

1663 be parametrized using one of three different mechanisms/parameters: 

1664 

1665 * count_from: a callback that returns the number of Packet 

1666 instances to dissect. The callback prototype is:: 

1667 

1668 count_from(pkt:Packet) -> int 

1669 

1670 * length_from: a callback that returns the number of bytes that 

1671 must be dissected by this field. The callback prototype is:: 

1672 

1673 length_from(pkt:Packet) -> int 

1674 

1675 * next_cls_cb: a callback that enables a Scapy developer to 

1676 dynamically discover if another Packet instance should be 

1677 dissected or not. See below for this callback prototype. 

1678 

1679 The bytes that are not consumed during the dissection of this field 

1680 are passed to the next field of the current packet. 

1681 

1682 For the serialization of such a field, the list of Packets that are 

1683 contained in a PacketListField can be heterogeneous and is 

1684 unrestricted. 

1685 

1686 The type of the Packet instances that are dissected with this field is 

1687 specified or discovered using one of the following mechanism: 

1688 

1689 * the pkt_cls parameter may contain a callable that returns an 

1690 instance of the dissected Packet. This may either be a 

1691 reference of a Packet subclass (e.g. DNSRROPT in layers/dns.py) 

1692 to generate an homogeneous PacketListField or a function 

1693 deciding the type of the Packet instance 

1694 (e.g. _CDPGuessAddrRecord in contrib/cdp.py) 

1695 

1696 * the pkt_cls parameter may contain a class object with a defined 

1697 ``dispatch_hook`` classmethod. That method must return a Packet 

1698 instance. The ``dispatch_hook`` callmethod must implement the 

1699 following prototype:: 

1700 

1701 dispatch_hook(cls, 

1702 _pkt:Optional[Packet], 

1703 *args, **kargs 

1704 ) -> Type[Packet] 

1705 

1706 The _pkt parameter may contain a reference to the packet 

1707 instance containing the PacketListField that is being 

1708 dissected. 

1709 

1710 * the ``next_cls_cb`` parameter may contain a callable whose 

1711 prototype is:: 

1712 

1713 cbk(pkt:Packet, 

1714 lst:List[Packet], 

1715 cur:Optional[Packet], 

1716 remain:bytes, 

1717 ) -> Optional[Type[Packet]] 

1718 

1719 The pkt argument contains a reference to the Packet instance 

1720 containing the PacketListField that is being dissected. 

1721 The lst argument is the list of all Packet instances that were 

1722 previously parsed during the current ``PacketListField`` 

1723 dissection, saved for the very last Packet instance. 

1724 The cur argument contains a reference to that very last parsed 

1725 ``Packet`` instance. The remain argument contains the bytes 

1726 that may still be consumed by the current PacketListField 

1727 dissection operation. 

1728 

1729 This callback returns either the type of the next Packet to 

1730 dissect or None to indicate that no more Packet are to be 

1731 dissected. 

1732 

1733 These four arguments allows a variety of dynamic discovery of 

1734 the number of Packet to dissect and of the type of each one of 

1735 these Packets, including: type determination based on current 

1736 Packet instances or its underlayers, continuation based on the 

1737 previously parsed Packet instances within that PacketListField, 

1738 continuation based on a look-ahead on the bytes to be 

1739 dissected... 

1740 

1741 The pkt_cls and next_cls_cb parameters are semantically exclusive, 

1742 although one could specify both. If both are specified, pkt_cls is 

1743 silently ignored. The same is true for count_from and next_cls_cb. 

1744 

1745 length_from and next_cls_cb are compatible and the dissection will 

1746 end, whichever of the two stop conditions comes first. 

1747 

1748 :param name: the name of the field 

1749 :param default: the default value of this field; generally an empty 

1750 Python list 

1751 :param pkt_cls: either a callable returning a Packet instance or a 

1752 class object defining a ``dispatch_hook`` class method 

1753 :param count_from: a callback returning the number of Packet 

1754 instances to dissect. 

1755 :param length_from: a callback returning the number of bytes to dissect 

1756 :param next_cls_cb: a callback returning either None or the type of 

1757 the next Packet to dissect. 

1758 :param max_count: an int containing the max amount of results. This is 

1759 a safety mechanism, exceeding this value will raise a Scapy_Exception. 

1760 """ 

1761 if default is None: 

1762 default = [] # Create a new list for each instance 

1763 super(PacketListField, self).__init__( 

1764 name, 

1765 default, 

1766 pkt_cls # type: ignore 

1767 ) 

1768 self.count_from = count_from 

1769 self.length_from = length_from 

1770 self.next_cls_cb = next_cls_cb 

1771 self.max_count = max_count 

1772 

1773 def any2i(self, pkt, x): 

1774 # type: (Optional[Packet], Any) -> List[BasePacket] 

1775 if not isinstance(x, list): 

1776 if x and pkt and hasattr(x, "add_parent"): 

1777 x.add_parent(pkt) 

1778 return [x] 

1779 elif pkt: 

1780 for i in x: 

1781 if not i or not hasattr(i, "add_parent"): 

1782 continue 

1783 i.add_parent(pkt) 

1784 return x 

1785 

1786 def i2count(self, 

1787 pkt, # type: Optional[Packet] 

1788 val, # type: List[BasePacket] 

1789 ): 

1790 # type: (...) -> int 

1791 if isinstance(val, list): 

1792 return len(val) 

1793 return 1 

1794 

1795 def i2len(self, 

1796 pkt, # type: Optional[Packet] 

1797 val, # type: List[Packet] 

1798 ): 

1799 # type: (...) -> int 

1800 return sum(len(self.i2m(pkt, p)) for p in val) 

1801 

1802 def getfield(self, pkt, s): 

1803 # type: (Packet, bytes) -> Tuple[bytes, List[BasePacket]] 

1804 c = len_pkt = cls = None 

1805 if self.length_from is not None: 

1806 len_pkt = self.length_from(pkt) 

1807 elif self.count_from is not None: 

1808 c = self.count_from(pkt) 

1809 if self.next_cls_cb is not None: 

1810 cls = self.next_cls_cb(pkt, [], None, s) 

1811 c = 1 

1812 if cls is None: 

1813 c = 0 

1814 

1815 lst = [] # type: List[BasePacket] 

1816 ret = b"" 

1817 remain = s 

1818 if len_pkt is not None: 

1819 remain, ret = s[:len_pkt], s[len_pkt:] 

1820 while remain: 

1821 if c is not None: 

1822 if c <= 0: 

1823 break 

1824 c -= 1 

1825 try: 

1826 if cls is not None: 

1827 try: 

1828 # we want to set parent wherever possible 

1829 p = cls(remain, _parent=pkt) 

1830 except TypeError: 

1831 p = cls(remain) 

1832 else: 

1833 p = self.m2i(pkt, remain) 

1834 except Exception: 

1835 if conf.debug_dissector: 

1836 raise 

1837 p = conf.raw_layer(load=remain) 

1838 remain = b"" 

1839 else: 

1840 pad = p.lastlayer() 

1841 if isinstance(pad, conf.padding_layer): 

1842 remain = pad.load 

1843 del pad.underlayer.payload # type: ignore 

1844 if self.next_cls_cb is not None: 

1845 cls = self.next_cls_cb(pkt, lst, p, remain) 

1846 if cls is not None: 

1847 c = 0 if c is None else c 

1848 c += 1 

1849 else: 

1850 remain = b"" 

1851 lst.append(p) 

1852 if len(lst) > (self.max_count or conf.max_list_count): 

1853 raise MaximumItemsCount( 

1854 "Maximum amount of items reached in PacketListField: %s " 

1855 "(defaults to conf.max_list_count)" 

1856 % (self.max_count or conf.max_list_count) 

1857 ) 

1858 

1859 if isinstance(remain, tuple): 

1860 remain, nb = remain 

1861 return (remain + ret, nb), lst 

1862 else: 

1863 return remain + ret, lst 

1864 

1865 def i2m(self, 

1866 pkt, # type: Optional[Packet] 

1867 i, # type: Any 

1868 ): 

1869 # type: (...) -> bytes 

1870 return bytes_encode(i) 

1871 

1872 def addfield(self, pkt, s, val): 

1873 # type: (Packet, bytes, Any) -> bytes 

1874 return s + b"".join(self.i2m(pkt, v) for v in val) 

1875 

1876 

1877class StrFixedLenField(StrField): 

1878 __slots__ = ["length_from"] 

1879 

1880 def __init__( 

1881 self, 

1882 name, # type: str 

1883 default, # type: Optional[bytes] 

1884 length=None, # type: Optional[int] 

1885 length_from=None, # type: Optional[Callable[[Packet], int]] 

1886 ): 

1887 # type: (...) -> None 

1888 super(StrFixedLenField, self).__init__(name, default) 

1889 self.length_from = length_from or (lambda x: 0) 

1890 if length is not None: 

1891 self.sz = length 

1892 self.length_from = lambda x, length=length: length # type: ignore 

1893 

1894 def i2repr(self, 

1895 pkt, # type: Optional[Packet] 

1896 v, # type: bytes 

1897 ): 

1898 # type: (...) -> str 

1899 if isinstance(v, bytes) and not conf.debug_strfixedlenfield: 

1900 v = v.rstrip(b"\0") 

1901 return super(StrFixedLenField, self).i2repr(pkt, v) 

1902 

1903 def getfield(self, pkt, s): 

1904 # type: (Packet, bytes) -> Tuple[bytes, bytes] 

1905 len_pkt = self.length_from(pkt) 

1906 if len_pkt == 0: 

1907 return s, b"" 

1908 return s[len_pkt:], self.m2i(pkt, s[:len_pkt]) 

1909 

1910 def addfield(self, pkt, s, val): 

1911 # type: (Packet, bytes, Optional[bytes]) -> bytes 

1912 len_pkt = self.length_from(pkt) 

1913 if len_pkt is None: 

1914 return s + self.i2m(pkt, val) 

1915 return s + struct.pack("%is" % len_pkt, self.i2m(pkt, val)) 

1916 

1917 def randval(self): 

1918 # type: () -> RandBin 

1919 try: 

1920 return RandBin(self.length_from(None)) # type: ignore 

1921 except Exception: 

1922 return RandBin(RandNum(0, 200)) 

1923 

1924 

1925class StrFixedLenFieldUtf16(StrFixedLenField, StrFieldUtf16): 

1926 pass 

1927 

1928 

1929class StrFixedLenEnumField(_StrEnumField, StrFixedLenField): 

1930 __slots__ = ["enum"] 

1931 

1932 def __init__( 

1933 self, 

1934 name, # type: str 

1935 default, # type: bytes 

1936 enum=None, # type: Optional[Dict[str, str]] 

1937 length=None, # type: Optional[int] 

1938 length_from=None # type: Optional[Callable[[Optional[Packet]], int]] # noqa: E501 

1939 ): 

1940 # type: (...) -> None 

1941 StrFixedLenField.__init__(self, name, default, length=length, length_from=length_from) # noqa: E501 

1942 self.enum = enum 

1943 

1944 

1945class NetBIOSNameField(StrFixedLenField): 

1946 def __init__(self, name, default, length=31): 

1947 # type: (str, bytes, int) -> None 

1948 StrFixedLenField.__init__(self, name, default, length) 

1949 

1950 def h2i(self, pkt, x): 

1951 # type: (Optional[Packet], bytes) -> bytes 

1952 if x and len(x) > 15: 

1953 x = x[:15] 

1954 return x 

1955 

1956 def i2m(self, pkt, y): 

1957 # type: (Optional[Packet], Optional[bytes]) -> bytes 

1958 if pkt: 

1959 len_pkt = self.length_from(pkt) // 2 

1960 else: 

1961 len_pkt = 0 

1962 x = bytes_encode(y or b"") # type: bytes 

1963 x += b" " * len_pkt 

1964 x = x[:len_pkt] 

1965 x = b"".join( 

1966 struct.pack( 

1967 "!BB", 

1968 0x41 + (b >> 4), 

1969 0x41 + (b & 0xf), 

1970 ) 

1971 for b in x 

1972 ) 

1973 return b" " + x 

1974 

1975 def m2i(self, pkt, x): 

1976 # type: (Optional[Packet], bytes) -> bytes 

1977 x = x[1:].strip(b"\x00") 

1978 return b"".join(map( 

1979 lambda x, y: struct.pack( 

1980 "!B", 

1981 (((x - 1) & 0xf) << 4) + ((y - 1) & 0xf) 

1982 ), 

1983 x[::2], x[1::2] 

1984 )).rstrip(b" ") 

1985 

1986 

1987class StrLenField(StrField): 

1988 """ 

1989 StrField with a length 

1990 

1991 :param length_from: a function that returns the size of the string 

1992 :param max_length: max size to use as randval 

1993 """ 

1994 __slots__ = ["length_from", "max_length"] 

1995 ON_WIRE_SIZE_UTF16 = True 

1996 

1997 def __init__( 

1998 self, 

1999 name, # type: str 

2000 default, # type: bytes 

2001 length_from=None, # type: Optional[Callable[[Packet], int]] 

2002 max_length=None, # type: Optional[Any] 

2003 ): 

2004 # type: (...) -> None 

2005 super(StrLenField, self).__init__(name, default) 

2006 self.length_from = length_from 

2007 self.max_length = max_length 

2008 

2009 def getfield(self, pkt, s): 

2010 # type: (Any, bytes) -> Tuple[bytes, bytes] 

2011 len_pkt = (self.length_from or (lambda x: 0))(pkt) 

2012 if not self.ON_WIRE_SIZE_UTF16: 

2013 len_pkt *= 2 

2014 if len_pkt == 0: 

2015 return s, b"" 

2016 return s[len_pkt:], self.m2i(pkt, s[:len_pkt]) 

2017 

2018 def randval(self): 

2019 # type: () -> RandBin 

2020 return RandBin(RandNum(0, self.max_length or 1200)) 

2021 

2022 

2023class _XStrField(Field[bytes, bytes]): 

2024 def i2repr(self, pkt, x): 

2025 # type: (Optional[Packet], bytes) -> str 

2026 if isinstance(x, bytes): 

2027 return bytes_hex(x).decode() 

2028 return super(_XStrField, self).i2repr(pkt, x) 

2029 

2030 

2031class XStrField(_XStrField, StrField): 

2032 """ 

2033 StrField which value is printed as hexadecimal. 

2034 """ 

2035 

2036 

2037class XStrLenField(_XStrField, StrLenField): 

2038 """ 

2039 StrLenField which value is printed as hexadecimal. 

2040 """ 

2041 

2042 

2043class XStrFixedLenField(_XStrField, StrFixedLenField): 

2044 """ 

2045 StrFixedLenField which value is printed as hexadecimal. 

2046 """ 

2047 

2048 

2049class XLEStrLenField(XStrLenField): 

2050 def i2m(self, pkt, x): 

2051 # type: (Optional[Packet], Optional[bytes]) -> bytes 

2052 if not x: 

2053 return b"" 

2054 return x[:: -1] 

2055 

2056 def m2i(self, pkt, x): 

2057 # type: (Optional[Packet], bytes) -> bytes 

2058 return x[:: -1] 

2059 

2060 

2061class StrLenFieldUtf16(StrLenField, StrFieldUtf16): 

2062 pass 

2063 

2064 

2065class StrLenEnumField(_StrEnumField, StrLenField): 

2066 __slots__ = ["enum"] 

2067 

2068 def __init__( 

2069 self, 

2070 name, # type: str 

2071 default, # type: bytes 

2072 enum=None, # type: Optional[Dict[str, str]] 

2073 **kwargs # type: Any 

2074 ): 

2075 # type: (...) -> None 

2076 StrLenField.__init__(self, name, default, **kwargs) 

2077 self.enum = enum 

2078 

2079 

2080class BoundStrLenField(StrLenField): 

2081 __slots__ = ["minlen", "maxlen"] 

2082 

2083 def __init__( 

2084 self, 

2085 name, # type: str 

2086 default, # type: bytes 

2087 minlen=0, # type: int 

2088 maxlen=255, # type: int 

2089 length_from=None # type: Optional[Callable[[Packet], int]] 

2090 ): 

2091 # type: (...) -> None 

2092 StrLenField.__init__(self, name, default, length_from=length_from) 

2093 self.minlen = minlen 

2094 self.maxlen = maxlen 

2095 

2096 def randval(self): 

2097 # type: () -> RandBin 

2098 return RandBin(RandNum(self.minlen, self.maxlen)) 

2099 

2100 

2101class FieldListField(Field[List[Any], List[Any]]): 

2102 __slots__ = ["field", "count_from", "length_from", "max_count"] 

2103 islist = 1 

2104 

2105 def __init__( 

2106 self, 

2107 name, # type: str 

2108 default, # type: Optional[List[AnyField]] 

2109 field, # type: AnyField 

2110 length_from=None, # type: Optional[Callable[[Packet], int]] 

2111 count_from=None, # type: Optional[Callable[[Packet], int]] 

2112 max_count=None, # type: Optional[int] 

2113 ): 

2114 # type: (...) -> None 

2115 if default is None: 

2116 default = [] # Create a new list for each instance 

2117 self.field = field 

2118 Field.__init__(self, name, default) 

2119 self.count_from = count_from 

2120 self.length_from = length_from 

2121 self.max_count = max_count 

2122 

2123 def i2count(self, pkt, val): 

2124 # type: (Optional[Packet], List[Any]) -> int 

2125 if isinstance(val, list): 

2126 return len(val) 

2127 return 1 

2128 

2129 def i2len(self, pkt, val): 

2130 # type: (Packet, List[Any]) -> int 

2131 return int(sum(self.field.i2len(pkt, v) for v in val)) 

2132 

2133 def any2i(self, pkt, x): 

2134 # type: (Optional[Packet], List[Any]) -> List[Any] 

2135 if not isinstance(x, list): 

2136 return [self.field.any2i(pkt, x)] 

2137 else: 

2138 return [self.field.any2i(pkt, e) for e in x] 

2139 

2140 def i2repr(self, 

2141 pkt, # type: Optional[Packet] 

2142 x, # type: List[Any] 

2143 ): 

2144 # type: (...) -> str 

2145 return "[%s]" % ", ".join(self.field.i2repr(pkt, v) for v in x) 

2146 

2147 def addfield(self, 

2148 pkt, # type: Packet 

2149 s, # type: bytes 

2150 val, # type: Optional[List[Any]] 

2151 ): 

2152 # type: (...) -> bytes 

2153 val = self.i2m(pkt, val) 

2154 for v in val: 

2155 s = self.field.addfield(pkt, s, v) 

2156 return s 

2157 

2158 def getfield(self, 

2159 pkt, # type: Packet 

2160 s, # type: bytes 

2161 ): 

2162 # type: (...) -> Any 

2163 c = len_pkt = None 

2164 if self.length_from is not None: 

2165 len_pkt = self.length_from(pkt) 

2166 elif self.count_from is not None: 

2167 c = self.count_from(pkt) 

2168 

2169 val = [] 

2170 ret = b"" 

2171 if len_pkt is not None: 

2172 s, ret = s[:len_pkt], s[len_pkt:] 

2173 

2174 while s: 

2175 if c is not None: 

2176 if c <= 0: 

2177 break 

2178 c -= 1 

2179 s, v = self.field.getfield(pkt, s) 

2180 val.append(v) 

2181 if len(val) > (self.max_count or conf.max_list_count): 

2182 raise MaximumItemsCount( 

2183 "Maximum amount of items reached in FieldListField: %s " 

2184 "(defaults to conf.max_list_count)" 

2185 % (self.max_count or conf.max_list_count) 

2186 ) 

2187 

2188 if isinstance(s, tuple): 

2189 s, bn = s 

2190 return (s + ret, bn), val 

2191 else: 

2192 return s + ret, val 

2193 

2194 

2195class FieldLenField(Field[int, int]): 

2196 __slots__ = ["length_of", "count_of", "adjust"] 

2197 

2198 def __init__( 

2199 self, 

2200 name, # type: str 

2201 default, # type: Optional[Any] 

2202 length_of=None, # type: Optional[str] 

2203 fmt="H", # type: str 

2204 count_of=None, # type: Optional[str] 

2205 adjust=lambda pkt, x: x, # type: Callable[[Packet, int], int] 

2206 ): 

2207 # type: (...) -> None 

2208 Field.__init__(self, name, default, fmt) 

2209 self.length_of = length_of 

2210 self.count_of = count_of 

2211 self.adjust = adjust 

2212 

2213 def i2m(self, pkt, x): 

2214 # type: (Optional[Packet], Optional[int]) -> int 

2215 if x is None and pkt is not None: 

2216 if self.length_of is not None: 

2217 fld, fval = pkt.getfield_and_val(self.length_of) 

2218 f = fld.i2len(pkt, fval) 

2219 elif self.count_of is not None: 

2220 fld, fval = pkt.getfield_and_val(self.count_of) 

2221 f = fld.i2count(pkt, fval) 

2222 else: 

2223 raise ValueError( 

2224 "Field should have either length_of or count_of" 

2225 ) 

2226 x = self.adjust(pkt, f) 

2227 elif x is None: 

2228 x = 0 

2229 return x 

2230 

2231 

2232class StrNullField(StrField): 

2233 DELIMITER = b"\x00" 

2234 

2235 def addfield(self, pkt, s, val): 

2236 # type: (Packet, bytes, Optional[bytes]) -> bytes 

2237 return s + self.i2m(pkt, val) + self.DELIMITER 

2238 

2239 def getfield(self, 

2240 pkt, # type: Packet 

2241 s, # type: bytes 

2242 ): 

2243 # type: (...) -> Tuple[bytes, bytes] 

2244 len_str = 0 

2245 while True: 

2246 len_str = s.find(self.DELIMITER, len_str) 

2247 if len_str < 0: 

2248 # DELIMITER not found: return empty 

2249 return b"", s 

2250 if len_str % len(self.DELIMITER): 

2251 len_str += 1 

2252 else: 

2253 break 

2254 return s[len_str + len(self.DELIMITER):], self.m2i(pkt, s[:len_str]) 

2255 

2256 def randval(self): 

2257 # type: () -> RandTermString 

2258 return RandTermString(RandNum(0, 1200), self.DELIMITER) 

2259 

2260 def i2len(self, pkt, x): 

2261 # type: (Optional[Packet], Any) -> int 

2262 return super(StrNullField, self).i2len(pkt, x) + 1 

2263 

2264 

2265class StrNullFieldUtf16(StrNullField, StrFieldUtf16): 

2266 DELIMITER = b"\x00\x00" 

2267 

2268 

2269class StrStopField(StrField): 

2270 __slots__ = ["stop", "additional"] 

2271 

2272 def __init__(self, name, default, stop, additional=0): 

2273 # type: (str, str, bytes, int) -> None 

2274 Field.__init__(self, name, default) 

2275 self.stop = stop 

2276 self.additional = additional 

2277 

2278 def getfield(self, pkt, s): 

2279 # type: (Optional[Packet], bytes) -> Tuple[bytes, bytes] 

2280 len_str = s.find(self.stop) 

2281 if len_str < 0: 

2282 return b"", s 

2283 len_str += len(self.stop) + self.additional 

2284 return s[len_str:], s[:len_str] 

2285 

2286 def randval(self): 

2287 # type: () -> RandTermString 

2288 return RandTermString(RandNum(0, 1200), self.stop) 

2289 

2290 

2291class LenField(Field[int, int]): 

2292 """ 

2293 If None, will be filled with the size of the payload 

2294 """ 

2295 __slots__ = ["adjust"] 

2296 

2297 def __init__(self, name, default, fmt="H", adjust=lambda x: x): 

2298 # type: (str, Optional[Any], str, Callable[[int], int]) -> None 

2299 Field.__init__(self, name, default, fmt) 

2300 self.adjust = adjust 

2301 

2302 def i2m(self, 

2303 pkt, # type: Optional[Packet] 

2304 x, # type: Optional[int] 

2305 ): 

2306 # type: (...) -> int 

2307 if x is None: 

2308 x = 0 

2309 if pkt is not None: 

2310 x = self.adjust(len(pkt.payload)) 

2311 return x 

2312 

2313 

2314class BCDFloatField(Field[float, int]): 

2315 def i2m(self, pkt, x): 

2316 # type: (Optional[Packet], Optional[float]) -> int 

2317 if x is None: 

2318 return 0 

2319 return int(256 * x) 

2320 

2321 def m2i(self, pkt, x): 

2322 # type: (Optional[Packet], int) -> float 

2323 return x / 256.0 

2324 

2325 

2326class _BitField(Field[I, int]): 

2327 """ 

2328 Field to handle bits. 

2329 

2330 :param name: name of the field 

2331 :param default: default value 

2332 :param size: size (in bits). If negative, Low endian 

2333 :param tot_size: size of the total group of bits (in bytes) the bitfield 

2334 is in. If negative, Low endian. 

2335 :param end_tot_size: same but for the BitField ending a group. 

2336 

2337 Example - normal usage:: 

2338 

2339 0 1 2 3 

2340 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 

2341 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

2342 | A | B | C | 

2343 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

2344 

2345 Fig. TestPacket 

2346 

2347 class TestPacket(Packet): 

2348 fields_desc = [ 

2349 BitField("a", 0, 14), 

2350 BitField("b", 0, 16), 

2351 BitField("c", 0, 2), 

2352 ] 

2353 

2354 Example - Low endian stored as 16 bits on the network:: 

2355 

2356 x x x x x x x x x x x x x x x x 

2357 a [b] [ c ] [ a ] 

2358 

2359 Will first get reversed during dissecion: 

2360 

2361 x x x x x x x x x x x x x x x x 

2362 [ a ] [b] [ c ] 

2363 

2364 class TestPacket(Packet): 

2365 fields_desc = [ 

2366 BitField("a", 0, 9, tot_size=-2), 

2367 BitField("b", 0, 2), 

2368 BitField("c", 0, 5, end_tot_size=-2) 

2369 ] 

2370 

2371 """ 

2372 __slots__ = ["rev", "size", "tot_size", "end_tot_size"] 

2373 

2374 def __init__(self, name, default, size, 

2375 tot_size=0, end_tot_size=0): 

2376 # type: (str, Optional[I], int, int, int) -> None 

2377 Field.__init__(self, name, default) 

2378 if callable(size): 

2379 size = size(self) 

2380 self.rev = size < 0 or tot_size < 0 or end_tot_size < 0 

2381 self.size = abs(size) 

2382 if not tot_size: 

2383 tot_size = self.size // 8 

2384 self.tot_size = abs(tot_size) 

2385 if not end_tot_size: 

2386 end_tot_size = self.size // 8 

2387 self.end_tot_size = abs(end_tot_size) 

2388 # Fields always have a round sz except BitField 

2389 # so to keep it simple, we'll ignore it here. 

2390 self.sz = self.size / 8. # type: ignore 

2391 

2392 # We need to # type: ignore a few things because of how special 

2393 # BitField is 

2394 def addfield(self, # type: ignore 

2395 pkt, # type: Packet 

2396 s, # type: Union[Tuple[bytes, int, int], bytes] 

2397 ival, # type: I 

2398 ): 

2399 # type: (...) -> Union[Tuple[bytes, int, int], bytes] 

2400 val = self.i2m(pkt, ival) 

2401 if isinstance(s, tuple): 

2402 s, bitsdone, v = s 

2403 else: 

2404 bitsdone = 0 

2405 v = 0 

2406 v <<= self.size 

2407 v |= val & ((1 << self.size) - 1) 

2408 bitsdone += self.size 

2409 while bitsdone >= 8: 

2410 bitsdone -= 8 

2411 s = s + struct.pack("!B", v >> bitsdone) 

2412 v &= (1 << bitsdone) - 1 

2413 if bitsdone: 

2414 return s, bitsdone, v 

2415 else: 

2416 # Apply LE if necessary 

2417 if self.rev and self.end_tot_size > 1: 

2418 s = s[:-self.end_tot_size] + s[-self.end_tot_size:][::-1] 

2419 return s 

2420 

2421 def getfield(self, # type: ignore 

2422 pkt, # type: Packet 

2423 s, # type: Union[Tuple[bytes, int], bytes] 

2424 ): 

2425 # type: (...) -> Union[Tuple[Tuple[bytes, int], I], Tuple[bytes, I]] # noqa: E501 

2426 if isinstance(s, tuple): 

2427 s, bn = s 

2428 else: 

2429 bn = 0 

2430 # Apply LE if necessary 

2431 if self.rev and self.tot_size > 1: 

2432 s = s[:self.tot_size][::-1] + s[self.tot_size:] 

2433 

2434 # we don't want to process all the string 

2435 nb_bytes = (self.size + bn - 1) // 8 + 1 

2436 w = s[:nb_bytes] 

2437 

2438 if len(w) < nb_bytes: 

2439 raise struct.error("unpack requires a buffer of %d bytes" % nb_bytes) 

2440 b = int.from_bytes(w, byteorder="big") 

2441 

2442 # get rid of high order bits 

2443 b &= (1 << (nb_bytes * 8 - bn)) - 1 

2444 

2445 # remove low order bits 

2446 b = b >> (nb_bytes * 8 - self.size - bn) 

2447 

2448 bn += self.size 

2449 s = s[bn // 8:] 

2450 bn = bn % 8 

2451 b2 = self.m2i(pkt, b) 

2452 if bn: 

2453 return (s, bn), b2 

2454 else: 

2455 return s, b2 

2456 

2457 def randval(self): 

2458 # type: () -> RandNum 

2459 return RandNum(0, 2**self.size - 1) 

2460 

2461 def i2len(self, pkt, x): # type: ignore 

2462 # type: (Optional[Packet], Optional[float]) -> float 

2463 return float(self.size) / 8 

2464 

2465 

2466class BitField(_BitField[int]): 

2467 __doc__ = _BitField.__doc__ 

2468 

2469 

2470class BitLenField(BitField): 

2471 __slots__ = ["length_from"] 

2472 

2473 def __init__(self, 

2474 name, # type: str 

2475 default, # type: Optional[int] 

2476 length_from # type: Callable[[Packet], int] 

2477 ): 

2478 # type: (...) -> None 

2479 self.length_from = length_from 

2480 super(BitLenField, self).__init__(name, default, 0) 

2481 

2482 def getfield(self, # type: ignore 

2483 pkt, # type: Packet 

2484 s, # type: Union[Tuple[bytes, int], bytes] 

2485 ): 

2486 # type: (...) -> Union[Tuple[Tuple[bytes, int], int], Tuple[bytes, int]] # noqa: E501 

2487 self.size = self.length_from(pkt) 

2488 return super(BitLenField, self).getfield(pkt, s) 

2489 

2490 def addfield(self, # type: ignore 

2491 pkt, # type: Packet 

2492 s, # type: Union[Tuple[bytes, int, int], bytes] 

2493 val # type: int 

2494 ): 

2495 # type: (...) -> Union[Tuple[bytes, int, int], bytes] 

2496 self.size = self.length_from(pkt) 

2497 return super(BitLenField, self).addfield(pkt, s, val) 

2498 

2499 

2500class BitFieldLenField(BitField): 

2501 __slots__ = ["length_of", "count_of", "adjust", "tot_size", "end_tot_size"] 

2502 

2503 def __init__(self, 

2504 name, # type: str 

2505 default, # type: Optional[int] 

2506 size, # type: int 

2507 length_of=None, # type: Optional[Union[Callable[[Optional[Packet]], int], str]] # noqa: E501 

2508 count_of=None, # type: Optional[str] 

2509 adjust=lambda pkt, x: x, # type: Callable[[Optional[Packet], int], int] # noqa: E501 

2510 tot_size=0, # type: int 

2511 end_tot_size=0, # type: int 

2512 ): 

2513 # type: (...) -> None 

2514 super(BitFieldLenField, self).__init__(name, default, size, 

2515 tot_size, end_tot_size) 

2516 self.length_of = length_of 

2517 self.count_of = count_of 

2518 self.adjust = adjust 

2519 

2520 def i2m(self, pkt, x): 

2521 # type: (Optional[Packet], Optional[Any]) -> int 

2522 return FieldLenField.i2m(self, pkt, x) # type: ignore 

2523 

2524 

2525class XBitField(BitField): 

2526 def i2repr(self, pkt, x): 

2527 # type: (Optional[Packet], int) -> str 

2528 return lhex(self.i2h(pkt, x)) 

2529 

2530 

2531_EnumType = Union[Dict[I, str], Dict[str, I], List[str], DADict[I, str], Type[Enum], Tuple[Callable[[I], str], Callable[[str], I]]] # noqa: E501 

2532 

2533 

2534class _EnumField(Field[Union[List[I], I], I]): 

2535 def __init__(self, 

2536 name, # type: str 

2537 default, # type: Optional[I] 

2538 enum, # type: _EnumType[I] 

2539 fmt="H", # type: str 

2540 ): 

2541 # type: (...) -> None 

2542 """ Initializes enum fields. 

2543 

2544 @param name: name of this field 

2545 @param default: default value of this field 

2546 @param enum: either an enum, a dict or a tuple of two callables. 

2547 Dict keys are the internal values, while the dict 

2548 values are the user-friendly representations. If the 

2549 tuple is provided, the first callable receives the 

2550 internal value as parameter and returns the 

2551 user-friendly representation and the second callable 

2552 does the converse. The first callable may return None 

2553 to default to a literal string (repr()) representation. 

2554 @param fmt: struct.pack format used to parse and serialize the 

2555 internal value from and to machine representation. 

2556 """ 

2557 if isinstance(enum, ObservableDict): 

2558 cast(ObservableDict, enum).observe(self) 

2559 

2560 if isinstance(enum, tuple): 

2561 self.i2s_cb = enum[0] # type: Optional[Callable[[I], str]] 

2562 self.s2i_cb = enum[1] # type: Optional[Callable[[str], I]] 

2563 self.i2s = None # type: Optional[Dict[I, str]] 

2564 self.s2i = None # type: Optional[Dict[str, I]] 

2565 elif isinstance(enum, type) and issubclass(enum, Enum): 

2566 # Python's Enum 

2567 i2s = self.i2s = {} 

2568 s2i = self.s2i = {} 

2569 self.i2s_cb = None 

2570 self.s2i_cb = None 

2571 names = [x.name for x in enum] 

2572 for n in names: 

2573 value = enum[n].value 

2574 i2s[value] = n 

2575 s2i[n] = value 

2576 else: 

2577 i2s = self.i2s = {} 

2578 s2i = self.s2i = {} 

2579 self.i2s_cb = None 

2580 self.s2i_cb = None 

2581 keys = [] # type: List[I] 

2582 if isinstance(enum, list): 

2583 keys = list(range(len(enum))) # type: ignore 

2584 elif isinstance(enum, DADict): 

2585 keys = enum.keys() 

2586 else: 

2587 keys = list(enum) # type: ignore 

2588 if any(isinstance(x, str) for x in keys): 

2589 i2s, s2i = s2i, i2s # type: ignore 

2590 for k in keys: 

2591 value = cast(str, enum[k]) # type: ignore 

2592 i2s[k] = value 

2593 s2i[value] = k 

2594 Field.__init__(self, name, default, fmt) 

2595 

2596 def any2i_one(self, pkt, x): 

2597 # type: (Optional[Packet], Any) -> I 

2598 if isinstance(x, Enum): 

2599 return cast(I, x.value) 

2600 elif isinstance(x, str): 

2601 if self.s2i: 

2602 x = self.s2i[x] 

2603 elif self.s2i_cb: 

2604 x = self.s2i_cb(x) 

2605 return cast(I, x) 

2606 

2607 def _i2repr(self, pkt, x): 

2608 # type: (Optional[Packet], I) -> str 

2609 return repr(x) 

2610 

2611 def i2repr_one(self, pkt, x): 

2612 # type: (Optional[Packet], I) -> str 

2613 if self not in conf.noenum and not isinstance(x, VolatileValue): 

2614 if self.i2s: 

2615 try: 

2616 return self.i2s[x] 

2617 except KeyError: 

2618 pass 

2619 elif self.i2s_cb: 

2620 ret = self.i2s_cb(x) 

2621 if ret is not None: 

2622 return ret 

2623 return self._i2repr(pkt, x) 

2624 

2625 def any2i(self, pkt, x): 

2626 # type: (Optional[Packet], Any) -> Union[I, List[I]] 

2627 if isinstance(x, list): 

2628 return [self.any2i_one(pkt, z) for z in x] 

2629 else: 

2630 return self.any2i_one(pkt, x) 

2631 

2632 def i2repr(self, pkt, x): # type: ignore 

2633 # type: (Optional[Packet], Any) -> Union[List[str], str] 

2634 if isinstance(x, list): 

2635 return [self.i2repr_one(pkt, z) for z in x] 

2636 else: 

2637 return self.i2repr_one(pkt, x) 

2638 

2639 def notify_set(self, enum, key, value): 

2640 # type: (ObservableDict, I, str) -> None 

2641 ks = "0x%x" if isinstance(key, int) else "%s" 

2642 log_runtime.debug( 

2643 "At %s: Change to %s at " + ks, self, value, key 

2644 ) 

2645 if self.i2s is not None and self.s2i is not None: 

2646 self.i2s[key] = value 

2647 self.s2i[value] = key 

2648 

2649 def notify_del(self, enum, key): 

2650 # type: (ObservableDict, I) -> None 

2651 ks = "0x%x" if isinstance(key, int) else "%s" 

2652 log_runtime.debug("At %s: Delete value at " + ks, self, key) 

2653 if self.i2s is not None and self.s2i is not None: 

2654 value = self.i2s[key] 

2655 del self.i2s[key] 

2656 del self.s2i[value] 

2657 

2658 

2659class EnumField(_EnumField[I]): 

2660 __slots__ = ["i2s", "s2i", "s2i_cb", "i2s_cb"] 

2661 

2662 

2663class CharEnumField(EnumField[str]): 

2664 def __init__(self, 

2665 name, # type: str 

2666 default, # type: str 

2667 enum, # type: _EnumType[str] 

2668 fmt="1s", # type: str 

2669 ): 

2670 # type: (...) -> None 

2671 super(CharEnumField, self).__init__(name, default, enum, fmt) 

2672 if self.i2s is not None: 

2673 k = list(self.i2s) 

2674 if k and len(k[0]) != 1: 

2675 self.i2s, self.s2i = self.s2i, self.i2s 

2676 

2677 def any2i_one(self, pkt, x): 

2678 # type: (Optional[Packet], str) -> str 

2679 if len(x) != 1: 

2680 if self.s2i: 

2681 x = self.s2i[x] 

2682 elif self.s2i_cb: 

2683 x = self.s2i_cb(x) 

2684 return x 

2685 

2686 

2687class BitEnumField(_BitField[Union[List[int], int]], _EnumField[int]): 

2688 __slots__ = EnumField.__slots__ 

2689 

2690 def __init__(self, 

2691 name, # type: str 

2692 default, # type: Optional[int] 

2693 size, # type: int 

2694 enum, # type: _EnumType[int] 

2695 **kwargs # type: Any 

2696 ): 

2697 # type: (...) -> None 

2698 _EnumField.__init__(self, name, default, enum) 

2699 _BitField.__init__(self, name, default, size, **kwargs) 

2700 

2701 def any2i(self, pkt, x): 

2702 # type: (Optional[Packet], Any) -> Union[List[int], int] 

2703 return _EnumField.any2i(self, pkt, x) 

2704 

2705 def i2repr(self, 

2706 pkt, # type: Optional[Packet] 

2707 x, # type: Union[List[int], int] 

2708 ): 

2709 # type: (...) -> Any 

2710 return _EnumField.i2repr(self, pkt, x) 

2711 

2712 

2713class BitLenEnumField(BitLenField, _EnumField[int]): 

2714 __slots__ = EnumField.__slots__ 

2715 

2716 def __init__(self, 

2717 name, # type: str 

2718 default, # type: Optional[int] 

2719 length_from, # type: Callable[[Packet], int] 

2720 enum, # type: _EnumType[int] 

2721 **kwargs, # type: Any 

2722 ): 

2723 # type: (...) -> None 

2724 _EnumField.__init__(self, name, default, enum) 

2725 BitLenField.__init__(self, name, default, length_from, **kwargs) 

2726 

2727 def any2i(self, pkt, x): 

2728 # type: (Optional[Packet], Any) -> int 

2729 return _EnumField.any2i(self, pkt, x) # type: ignore 

2730 

2731 def i2repr(self, 

2732 pkt, # type: Optional[Packet] 

2733 x, # type: Union[List[int], int] 

2734 ): 

2735 # type: (...) -> Any 

2736 return _EnumField.i2repr(self, pkt, x) 

2737 

2738 

2739class ShortEnumField(EnumField[int]): 

2740 __slots__ = EnumField.__slots__ 

2741 

2742 def __init__(self, 

2743 name, # type: str 

2744 default, # type: Optional[int] 

2745 enum, # type: _EnumType[int] 

2746 ): 

2747 # type: (...) -> None 

2748 super(ShortEnumField, self).__init__(name, default, enum, "H") 

2749 

2750 

2751class LEShortEnumField(EnumField[int]): 

2752 def __init__(self, 

2753 name, # type: str 

2754 default, # type: Optional[int] 

2755 enum, # type: _EnumType[int] 

2756 ): 

2757 # type: (...) -> None 

2758 super(LEShortEnumField, self).__init__(name, default, enum, "<H") 

2759 

2760 

2761class LongEnumField(EnumField[int]): 

2762 def __init__(self, 

2763 name, # type: str 

2764 default, # type: Optional[int] 

2765 enum, # type: _EnumType[int] 

2766 ): 

2767 # type: (...) -> None 

2768 super(LongEnumField, self).__init__(name, default, enum, "Q") 

2769 

2770 

2771class LELongEnumField(EnumField[int]): 

2772 def __init__(self, 

2773 name, # type: str 

2774 default, # type: Optional[int] 

2775 enum, # type: _EnumType[int] 

2776 ): 

2777 # type: (...) -> None 

2778 super(LELongEnumField, self).__init__(name, default, enum, "<Q") 

2779 

2780 

2781class ByteEnumField(EnumField[int]): 

2782 def __init__(self, 

2783 name, # type: str 

2784 default, # type: Optional[int] 

2785 enum, # type: _EnumType[int] 

2786 ): 

2787 # type: (...) -> None 

2788 super(ByteEnumField, self).__init__(name, default, enum, "B") 

2789 

2790 

2791class XByteEnumField(ByteEnumField): 

2792 def i2repr_one(self, pkt, x): 

2793 # type: (Optional[Packet], int) -> str 

2794 if self not in conf.noenum and not isinstance(x, VolatileValue): 

2795 if self.i2s: 

2796 try: 

2797 return self.i2s[x] 

2798 except KeyError: 

2799 pass 

2800 elif self.i2s_cb: 

2801 ret = self.i2s_cb(x) 

2802 if ret is not None: 

2803 return ret 

2804 return lhex(x) 

2805 

2806 

2807class IntEnumField(EnumField[int]): 

2808 def __init__(self, 

2809 name, # type: str 

2810 default, # type: Optional[int] 

2811 enum, # type: _EnumType[int] 

2812 ): 

2813 # type: (...) -> None 

2814 super(IntEnumField, self).__init__(name, default, enum, "I") 

2815 

2816 

2817class SignedIntEnumField(EnumField[int]): 

2818 def __init__(self, 

2819 name, # type: str 

2820 default, # type: Optional[int] 

2821 enum, # type: _EnumType[int] 

2822 ): 

2823 # type: (...) -> None 

2824 super(SignedIntEnumField, self).__init__(name, default, enum, "i") 

2825 

2826 

2827class LEIntEnumField(EnumField[int]): 

2828 def __init__(self, 

2829 name, # type: str 

2830 default, # type: Optional[int] 

2831 enum, # type: _EnumType[int] 

2832 ): 

2833 # type: (...) -> None 

2834 super(LEIntEnumField, self).__init__(name, default, enum, "<I") 

2835 

2836 

2837class XLEIntEnumField(LEIntEnumField): 

2838 def _i2repr(self, pkt, x): 

2839 # type: (Optional[Packet], Any) -> str 

2840 return lhex(x) 

2841 

2842 

2843class XShortEnumField(ShortEnumField): 

2844 def _i2repr(self, pkt, x): 

2845 # type: (Optional[Packet], Any) -> str 

2846 return lhex(x) 

2847 

2848 

2849class LE3BytesEnumField(LEThreeBytesField, _EnumField[int]): 

2850 __slots__ = EnumField.__slots__ 

2851 

2852 def __init__(self, 

2853 name, # type: str 

2854 default, # type: Optional[int] 

2855 enum, # type: _EnumType[int] 

2856 ): 

2857 # type: (...) -> None 

2858 _EnumField.__init__(self, name, default, enum) 

2859 LEThreeBytesField.__init__(self, name, default) 

2860 

2861 def any2i(self, pkt, x): 

2862 # type: (Optional[Packet], Any) -> int 

2863 return _EnumField.any2i(self, pkt, x) # type: ignore 

2864 

2865 def i2repr(self, pkt, x): # type: ignore 

2866 # type: (Optional[Packet], Any) -> Union[List[str], str] 

2867 return _EnumField.i2repr(self, pkt, x) 

2868 

2869 

2870class XLE3BytesEnumField(LE3BytesEnumField): 

2871 def _i2repr(self, pkt, x): 

2872 # type: (Optional[Packet], Any) -> str 

2873 return lhex(x) 

2874 

2875 

2876class _MultiEnumField(_EnumField[I]): 

2877 def __init__(self, 

2878 name, # type: str 

2879 default, # type: int 

2880 enum, # type: Dict[I, Dict[I, str]] 

2881 depends_on, # type: Callable[[Optional[Packet]], I] 

2882 fmt="H" # type: str 

2883 ): 

2884 # type: (...) -> None 

2885 

2886 self.depends_on = depends_on 

2887 self.i2s_multi = enum 

2888 self.s2i_multi = {} # type: Dict[I, Dict[str, I]] 

2889 self.s2i_all = {} # type: Dict[str, I] 

2890 for m in enum: 

2891 s2i = {} # type: Dict[str, I] 

2892 self.s2i_multi[m] = s2i 

2893 for k, v in enum[m].items(): 

2894 s2i[v] = k 

2895 self.s2i_all[v] = k 

2896 Field.__init__(self, name, default, fmt) 

2897 

2898 def any2i_one(self, pkt, x): 

2899 # type: (Optional[Packet], Any) -> I 

2900 if isinstance(x, str): 

2901 v = self.depends_on(pkt) 

2902 if v in self.s2i_multi: 

2903 s2i = self.s2i_multi[v] 

2904 if x in s2i: 

2905 return s2i[x] 

2906 return self.s2i_all[x] 

2907 return cast(I, x) 

2908 

2909 def i2repr_one(self, pkt, x): 

2910 # type: (Optional[Packet], I) -> str 

2911 v = self.depends_on(pkt) 

2912 if isinstance(v, VolatileValue): 

2913 return repr(v) 

2914 if v in self.i2s_multi: 

2915 return str(self.i2s_multi[v].get(x, x)) 

2916 return str(x) 

2917 

2918 

2919class MultiEnumField(_MultiEnumField[int], EnumField[int]): 

2920 __slots__ = ["depends_on", "i2s_multi", "s2i_multi", "s2i_all"] 

2921 

2922 

2923class BitMultiEnumField(_BitField[Union[List[int], int]], 

2924 _MultiEnumField[int]): 

2925 __slots__ = EnumField.__slots__ + MultiEnumField.__slots__ 

2926 

2927 def __init__( 

2928 self, 

2929 name, # type: str 

2930 default, # type: int 

2931 size, # type: int 

2932 enum, # type: Dict[int, Dict[int, str]] 

2933 depends_on # type: Callable[[Optional[Packet]], int] 

2934 ): 

2935 # type: (...) -> None 

2936 _MultiEnumField.__init__(self, name, default, enum, depends_on) 

2937 self.rev = size < 0 

2938 self.size = abs(size) 

2939 self.sz = self.size / 8. # type: ignore 

2940 

2941 def any2i(self, pkt, x): 

2942 # type: (Optional[Packet], Any) -> Union[List[int], int] 

2943 return _MultiEnumField[int].any2i( 

2944 self, # type: ignore 

2945 pkt, 

2946 x 

2947 ) 

2948 

2949 def i2repr( # type: ignore 

2950 self, 

2951 pkt, # type: Optional[Packet] 

2952 x # type: Union[List[int], int] 

2953 ): 

2954 # type: (...) -> Union[str, List[str]] 

2955 return _MultiEnumField[int].i2repr( 

2956 self, # type: ignore 

2957 pkt, 

2958 x 

2959 ) 

2960 

2961 

2962class ByteEnumKeysField(ByteEnumField): 

2963 """ByteEnumField that picks valid values when fuzzed. """ 

2964 

2965 def randval(self): 

2966 # type: () -> RandEnumKeys 

2967 return RandEnumKeys(self.i2s or {}) 

2968 

2969 

2970class ShortEnumKeysField(ShortEnumField): 

2971 """ShortEnumField that picks valid values when fuzzed. """ 

2972 

2973 def randval(self): 

2974 # type: () -> RandEnumKeys 

2975 return RandEnumKeys(self.i2s or {}) 

2976 

2977 

2978class IntEnumKeysField(IntEnumField): 

2979 """IntEnumField that picks valid values when fuzzed. """ 

2980 

2981 def randval(self): 

2982 # type: () -> RandEnumKeys 

2983 return RandEnumKeys(self.i2s or {}) 

2984 

2985 

2986# Little endian fixed length field 

2987 

2988 

2989class LEFieldLenField(FieldLenField): 

2990 def __init__( 

2991 self, 

2992 name, # type: str 

2993 default, # type: Optional[Any] 

2994 length_of=None, # type: Optional[str] 

2995 fmt="<H", # type: str 

2996 count_of=None, # type: Optional[str] 

2997 adjust=lambda pkt, x: x, # type: Callable[[Packet, int], int] 

2998 ): 

2999 # type: (...) -> None 

3000 FieldLenField.__init__( 

3001 self, name, default, 

3002 length_of=length_of, 

3003 fmt=fmt, 

3004 count_of=count_of, 

3005 adjust=adjust 

3006 ) 

3007 

3008 

3009class FlagValueIter(object): 

3010 

3011 __slots__ = ["flagvalue", "cursor"] 

3012 

3013 def __init__(self, flagvalue): 

3014 # type: (FlagValue) -> None 

3015 self.flagvalue = flagvalue 

3016 self.cursor = 0 

3017 

3018 def __iter__(self): 

3019 # type: () -> FlagValueIter 

3020 return self 

3021 

3022 def __next__(self): 

3023 # type: () -> str 

3024 x = int(self.flagvalue) 

3025 x >>= self.cursor 

3026 while x: 

3027 self.cursor += 1 

3028 if x & 1: 

3029 return self.flagvalue.names[self.cursor - 1] 

3030 x >>= 1 

3031 raise StopIteration 

3032 

3033 next = __next__ 

3034 

3035 

3036class FlagValue(object): 

3037 __slots__ = ["value", "names", "multi"] 

3038 

3039 def _fixvalue(self, value): 

3040 # type: (Any) -> int 

3041 if not value: 

3042 return 0 

3043 if isinstance(value, str): 

3044 value = value.split('+') if self.multi else list(value) 

3045 if isinstance(value, list): 

3046 y = 0 

3047 for i in value: 

3048 y |= 1 << self.names.index(i) 

3049 value = y 

3050 return int(value) 

3051 

3052 def __init__(self, value, names): 

3053 # type: (Union[List[str], int, str], Union[List[str], str]) -> None 

3054 self.multi = isinstance(names, list) 

3055 self.names = names 

3056 self.value = self._fixvalue(value) 

3057 

3058 def __hash__(self): 

3059 # type: () -> int 

3060 return hash(self.value) 

3061 

3062 def __int__(self): 

3063 # type: () -> int 

3064 return self.value 

3065 

3066 def __eq__(self, other): 

3067 # type: (Any) -> bool 

3068 return self.value == self._fixvalue(other) 

3069 

3070 def __lt__(self, other): 

3071 # type: (Any) -> bool 

3072 return self.value < self._fixvalue(other) 

3073 

3074 def __le__(self, other): 

3075 # type: (Any) -> bool 

3076 return self.value <= self._fixvalue(other) 

3077 

3078 def __gt__(self, other): 

3079 # type: (Any) -> bool 

3080 return self.value > self._fixvalue(other) 

3081 

3082 def __ge__(self, other): 

3083 # type: (Any) -> bool 

3084 return self.value >= self._fixvalue(other) 

3085 

3086 def __ne__(self, other): 

3087 # type: (Any) -> bool 

3088 return self.value != self._fixvalue(other) 

3089 

3090 def __and__(self, other): 

3091 # type: (int) -> FlagValue 

3092 return self.__class__(self.value & self._fixvalue(other), self.names) 

3093 __rand__ = __and__ 

3094 

3095 def __or__(self, other): 

3096 # type: (int) -> FlagValue 

3097 return self.__class__(self.value | self._fixvalue(other), self.names) 

3098 __ror__ = __or__ 

3099 __add__ = __or__ # + is an alias for | 

3100 

3101 def __sub__(self, other): 

3102 # type: (int) -> FlagValue 

3103 return self.__class__( 

3104 self.value & (2 ** len(self.names) - 1 - self._fixvalue(other)), 

3105 self.names 

3106 ) 

3107 

3108 def __xor__(self, other): 

3109 # type: (int) -> FlagValue 

3110 return self.__class__(self.value ^ self._fixvalue(other), self.names) 

3111 

3112 def __lshift__(self, other): 

3113 # type: (int) -> int 

3114 return self.value << self._fixvalue(other) 

3115 

3116 def __rshift__(self, other): 

3117 # type: (int) -> int 

3118 return self.value >> self._fixvalue(other) 

3119 

3120 def __nonzero__(self): 

3121 # type: () -> bool 

3122 return bool(self.value) 

3123 __bool__ = __nonzero__ 

3124 

3125 def flagrepr(self): 

3126 # type: () -> str 

3127 warnings.warn( 

3128 "obj.flagrepr() is obsolete. Use str(obj) instead.", 

3129 DeprecationWarning 

3130 ) 

3131 return str(self) 

3132 

3133 def __str__(self): 

3134 # type: () -> str 

3135 i = 0 

3136 r = [] 

3137 x = int(self) 

3138 while x: 

3139 if x & 1: 

3140 try: 

3141 name = self.names[i] 

3142 except IndexError: 

3143 name = "?" 

3144 r.append(name) 

3145 i += 1 

3146 x >>= 1 

3147 return ("+" if self.multi else "").join(r) 

3148 

3149 def __iter__(self): 

3150 # type: () -> FlagValueIter 

3151 return FlagValueIter(self) 

3152 

3153 def __repr__(self): 

3154 # type: () -> str 

3155 return "<Flag %d (%s)>" % (self, self) 

3156 

3157 def __deepcopy__(self, memo): 

3158 # type: (Dict[Any, Any]) -> FlagValue 

3159 return self.__class__(int(self), self.names) 

3160 

3161 def __getattr__(self, attr): 

3162 # type: (str) -> Any 

3163 if attr in self.__slots__: 

3164 return super(FlagValue, self).__getattribute__(attr) 

3165 try: 

3166 if self.multi: 

3167 return bool((2 ** self.names.index(attr)) & int(self)) 

3168 return all(bool((2 ** self.names.index(flag)) & int(self)) 

3169 for flag in attr) 

3170 except ValueError: 

3171 if '_' in attr: 

3172 try: 

3173 return self.__getattr__(attr.replace('_', '-')) 

3174 except AttributeError: 

3175 pass 

3176 return super(FlagValue, self).__getattribute__(attr) 

3177 

3178 def __setattr__(self, attr, value): 

3179 # type: (str, Union[List[str], int, str]) -> None 

3180 if attr == "value" and not isinstance(value, int): 

3181 raise ValueError(value) 

3182 if attr in self.__slots__: 

3183 return super(FlagValue, self).__setattr__(attr, value) 

3184 if attr in self.names: 

3185 if value: 

3186 self.value |= (2 ** self.names.index(attr)) 

3187 else: 

3188 self.value &= ~(2 ** self.names.index(attr)) 

3189 else: 

3190 return super(FlagValue, self).__setattr__(attr, value) 

3191 

3192 def copy(self): 

3193 # type: () -> FlagValue 

3194 return self.__class__(self.value, self.names) 

3195 

3196 

3197class FlagsField(_BitField[Optional[Union[int, FlagValue]]]): 

3198 """ Handle Flag type field 

3199 

3200 Make sure all your flags have a label 

3201 

3202 Example (list): 

3203 >>> from scapy.packet import Packet 

3204 >>> class FlagsTest(Packet): 

3205 fields_desc = [FlagsField("flags", 0, 8, ["f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7"])] # noqa: E501 

3206 >>> FlagsTest(flags=9).show2() 

3207 ###[ FlagsTest ]### 

3208 flags = f0+f3 

3209 

3210 Example (str): 

3211 >>> from scapy.packet import Packet 

3212 >>> class TCPTest(Packet): 

3213 fields_desc = [ 

3214 BitField("reserved", 0, 7), 

3215 FlagsField("flags", 0x2, 9, "FSRPAUECN") 

3216 ] 

3217 >>> TCPTest(flags=3).show2() 

3218 ###[ FlagsTest ]### 

3219 reserved = 0 

3220 flags = FS 

3221 

3222 Example (dict): 

3223 >>> from scapy.packet import Packet 

3224 >>> class FlagsTest2(Packet): 

3225 fields_desc = [ 

3226 FlagsField("flags", 0x2, 16, { 

3227 0x0001: "A", 

3228 0x0008: "B", 

3229 }) 

3230 ] 

3231 

3232 :param name: field's name 

3233 :param default: default value for the field 

3234 :param size: number of bits in the field (in bits). if negative, LE 

3235 :param names: (list or str or dict) label for each flag 

3236 If it's a str or a list, the least Significant Bit tag's name 

3237 is written first. 

3238 """ 

3239 ismutable = True 

3240 __slots__ = ["names"] 

3241 

3242 def __init__(self, 

3243 name, # type: str 

3244 default, # type: Optional[Union[int, FlagValue]] 

3245 size, # type: int 

3246 names, # type: Union[List[str], str, Dict[int, str]] 

3247 **kwargs # type: Any 

3248 ): 

3249 # type: (...) -> None 

3250 # Convert the dict to a list 

3251 if isinstance(names, dict): 

3252 tmp = ["bit_%d" % i for i in range(abs(size))] 

3253 for i, v in names.items(): 

3254 tmp[int(math.floor(math.log(i, 2)))] = v 

3255 names = tmp 

3256 # Store the names as str or list 

3257 self.names = names 

3258 super(FlagsField, self).__init__(name, default, size, **kwargs) 

3259 

3260 def _fixup_val(self, x): 

3261 # type: (Any) -> Optional[FlagValue] 

3262 """Returns a FlagValue instance when needed. Internal method, to be 

3263used in *2i() and i2*() methods. 

3264 

3265 """ 

3266 if isinstance(x, (FlagValue, VolatileValue)): 

3267 return x # type: ignore 

3268 if x is None: 

3269 return None 

3270 return FlagValue(x, self.names) 

3271 

3272 def any2i(self, pkt, x): 

3273 # type: (Optional[Packet], Any) -> Optional[FlagValue] 

3274 return self._fixup_val(super(FlagsField, self).any2i(pkt, x)) 

3275 

3276 def m2i(self, pkt, x): 

3277 # type: (Optional[Packet], int) -> Optional[FlagValue] 

3278 return self._fixup_val(super(FlagsField, self).m2i(pkt, x)) 

3279 

3280 def i2h(self, pkt, x): 

3281 # type: (Optional[Packet], Any) -> Optional[FlagValue] 

3282 return self._fixup_val(super(FlagsField, self).i2h(pkt, x)) 

3283 

3284 def i2repr(self, 

3285 pkt, # type: Optional[Packet] 

3286 x, # type: Any 

3287 ): 

3288 # type: (...) -> str 

3289 if isinstance(x, (list, tuple)): 

3290 return repr(type(x)( 

3291 "None" if v is None else str(self._fixup_val(v)) for v in x 

3292 )) 

3293 return "None" if x is None else str(self._fixup_val(x)) 

3294 

3295 

3296MultiFlagsEntry = collections.namedtuple('MultiFlagsEntry', ['short', 'long']) 

3297 

3298 

3299class MultiFlagsField(_BitField[Set[str]]): 

3300 __slots__ = FlagsField.__slots__ + ["depends_on"] 

3301 

3302 def __init__(self, 

3303 name, # type: str 

3304 default, # type: Set[str] 

3305 size, # type: int 

3306 names, # type: Dict[int, Dict[int, MultiFlagsEntry]] 

3307 depends_on, # type: Callable[[Optional[Packet]], int] 

3308 ): 

3309 # type: (...) -> None 

3310 self.names = names 

3311 self.depends_on = depends_on 

3312 super(MultiFlagsField, self).__init__(name, default, size) 

3313 

3314 def any2i(self, pkt, x): 

3315 # type: (Optional[Packet], Any) -> Set[str] 

3316 if not isinstance(x, (set, int)): 

3317 raise ValueError('set expected') 

3318 

3319 if pkt is not None: 

3320 if isinstance(x, int): 

3321 return self.m2i(pkt, x) 

3322 else: 

3323 v = self.depends_on(pkt) 

3324 if v is not None: 

3325 assert v in self.names, 'invalid dependency' 

3326 these_names = self.names[v] 

3327 s = set() 

3328 for i in x: 

3329 for val in these_names.values(): 

3330 if val.short == i: 

3331 s.add(i) 

3332 break 

3333 else: 

3334 assert False, 'Unknown flag "{}" with this dependency'.format(i) # noqa: E501 

3335 continue 

3336 return s 

3337 if isinstance(x, int): 

3338 return set() 

3339 return x 

3340 

3341 def i2m(self, pkt, x): 

3342 # type: (Optional[Packet], Optional[Set[str]]) -> int 

3343 v = self.depends_on(pkt) 

3344 these_names = self.names.get(v, {}) 

3345 

3346 r = 0 

3347 if x is None: 

3348 return r 

3349 for flag_set in x: 

3350 for i, val in these_names.items(): 

3351 if val.short == flag_set: 

3352 r |= 1 << i 

3353 break 

3354 else: 

3355 r |= 1 << int(flag_set[len('bit '):]) 

3356 return r 

3357 

3358 def m2i(self, pkt, x): 

3359 # type: (Optional[Packet], int) -> Set[str] 

3360 v = self.depends_on(pkt) 

3361 these_names = self.names.get(v, {}) 

3362 

3363 r = set() 

3364 i = 0 

3365 while x: 

3366 if x & 1: 

3367 if i in these_names: 

3368 r.add(these_names[i].short) 

3369 else: 

3370 r.add('bit {}'.format(i)) 

3371 x >>= 1 

3372 i += 1 

3373 return r 

3374 

3375 def i2repr(self, pkt, x): 

3376 # type: (Optional[Packet], Set[str]) -> str 

3377 v = self.depends_on(pkt) 

3378 these_names = self.names.get(v, {}) 

3379 

3380 r = set() 

3381 for flag_set in x: 

3382 for i in these_names.values(): 

3383 if i.short == flag_set: 

3384 r.add("{} ({})".format(i.long, i.short)) 

3385 break 

3386 else: 

3387 r.add(flag_set) 

3388 return repr(r) 

3389 

3390 

3391class FixedPointField(BitField): 

3392 __slots__ = ['frac_bits'] 

3393 

3394 def __init__(self, name, default, size, frac_bits=16): 

3395 # type: (str, int, int, int) -> None 

3396 self.frac_bits = frac_bits 

3397 super(FixedPointField, self).__init__(name, default, size) 

3398 

3399 def any2i(self, pkt, val): 

3400 # type: (Optional[Packet], Optional[float]) -> Optional[int] 

3401 if val is None: 

3402 return val 

3403 ival = int(val) 

3404 fract = int((val - ival) * 2**self.frac_bits) 

3405 return (ival << self.frac_bits) | fract 

3406 

3407 def i2h(self, pkt, val): 

3408 # type: (Optional[Packet], Optional[int]) -> Optional[EDecimal] 

3409 # A bit of trickery to get precise floats 

3410 if val is None: 

3411 return val 

3412 int_part = val >> self.frac_bits 

3413 pw = 2.0**self.frac_bits 

3414 frac_part = EDecimal(val & (1 << self.frac_bits) - 1) 

3415 frac_part /= pw # type: ignore 

3416 return int_part + frac_part.normalize(int(math.log10(pw))) 

3417 

3418 def i2repr(self, pkt, val): 

3419 # type: (Optional[Packet], int) -> str 

3420 return str(self.i2h(pkt, val)) 

3421 

3422 

3423# Base class for IPv4 and IPv6 Prefixes inspired by IPField and IP6Field. 

3424# Machine values are encoded in a multiple of wordbytes bytes. 

3425class _IPPrefixFieldBase(Field[Tuple[str, int], Tuple[bytes, int]]): 

3426 __slots__ = ["wordbytes", "maxbytes", "aton", "ntoa", "length_from"] 

3427 

3428 def __init__( 

3429 self, 

3430 name, # type: str 

3431 default, # type: Tuple[str, int] 

3432 wordbytes, # type: int 

3433 maxbytes, # type: int 

3434 aton, # type: Callable[..., Any] 

3435 ntoa, # type: Callable[..., Any] 

3436 length_from=None # type: Optional[Callable[[Packet], int]] 

3437 ): 

3438 # type: (...) -> None 

3439 self.wordbytes = wordbytes 

3440 self.maxbytes = maxbytes 

3441 self.aton = aton 

3442 self.ntoa = ntoa 

3443 Field.__init__(self, name, default, "%is" % self.maxbytes) 

3444 if length_from is None: 

3445 length_from = lambda x: 0 

3446 self.length_from = length_from 

3447 

3448 def _numbytes(self, pfxlen): 

3449 # type: (int) -> int 

3450 wbits = self.wordbytes * 8 

3451 return ((pfxlen + (wbits - 1)) // wbits) * self.wordbytes 

3452 

3453 def h2i(self, pkt, x): 

3454 # type: (Optional[Packet], str) -> Tuple[str, int] 

3455 # "fc00:1::1/64" -> ("fc00:1::1", 64) 

3456 [pfx, pfxlen] = x.split('/') 

3457 self.aton(pfx) # check for validity 

3458 return (pfx, int(pfxlen)) 

3459 

3460 def i2h(self, pkt, x): 

3461 # type: (Optional[Packet], Tuple[str, int]) -> str 

3462 # ("fc00:1::1", 64) -> "fc00:1::1/64" 

3463 (pfx, pfxlen) = x 

3464 return "%s/%i" % (pfx, pfxlen) 

3465 

3466 def i2m(self, 

3467 pkt, # type: Optional[Packet] 

3468 x # type: Optional[Tuple[str, int]] 

3469 ): 

3470 # type: (...) -> Tuple[bytes, int] 

3471 # ("fc00:1::1", 64) -> (b"\xfc\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 64) # noqa: E501 

3472 if x is None: 

3473 pfx, pfxlen = "", 0 

3474 else: 

3475 (pfx, pfxlen) = x 

3476 s = self.aton(pfx) 

3477 return (s[:self._numbytes(pfxlen)], pfxlen) 

3478 

3479 def m2i(self, pkt, x): 

3480 # type: (Optional[Packet], Tuple[bytes, int]) -> Tuple[str, int] 

3481 # (b"\xfc\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 64) -> ("fc00:1::1", 64) # noqa: E501 

3482 (s, pfxlen) = x 

3483 

3484 if len(s) < self.maxbytes: 

3485 s = s + (b"\0" * (self.maxbytes - len(s))) 

3486 return (self.ntoa(s), pfxlen) 

3487 

3488 def any2i(self, pkt, x): 

3489 # type: (Optional[Packet], Optional[Any]) -> Tuple[str, int] 

3490 if x is None: 

3491 return (self.ntoa(b"\0" * self.maxbytes), 1) 

3492 

3493 return self.h2i(pkt, x) 

3494 

3495 def i2len(self, pkt, x): 

3496 # type: (Packet, Tuple[str, int]) -> int 

3497 (_, pfxlen) = x 

3498 return pfxlen 

3499 

3500 def addfield(self, pkt, s, val): 

3501 # type: (Packet, bytes, Optional[Tuple[str, int]]) -> bytes 

3502 (rawpfx, pfxlen) = self.i2m(pkt, val) 

3503 fmt = "!%is" % self._numbytes(pfxlen) 

3504 return s + struct.pack(fmt, rawpfx) 

3505 

3506 def getfield(self, pkt, s): 

3507 # type: (Packet, bytes) -> Tuple[bytes, Tuple[str, int]] 

3508 pfxlen = self.length_from(pkt) 

3509 numbytes = self._numbytes(pfxlen) 

3510 fmt = "!%is" % numbytes 

3511 return s[numbytes:], self.m2i(pkt, (struct.unpack(fmt, s[:numbytes])[0], pfxlen)) # noqa: E501 

3512 

3513 

3514class IPPrefixField(_IPPrefixFieldBase): 

3515 def __init__( 

3516 self, 

3517 name, # type: str 

3518 default, # type: Tuple[str, int] 

3519 wordbytes=1, # type: int 

3520 length_from=None # type: Optional[Callable[[Packet], int]] 

3521 ): 

3522 _IPPrefixFieldBase.__init__( 

3523 self, 

3524 name, 

3525 default, 

3526 wordbytes, 

3527 4, 

3528 inet_aton, 

3529 inet_ntoa, 

3530 length_from 

3531 ) 

3532 

3533 

3534class IP6PrefixField(_IPPrefixFieldBase): 

3535 def __init__( 

3536 self, 

3537 name, # type: str 

3538 default, # type: Tuple[str, int] 

3539 wordbytes=1, # type: int 

3540 length_from=None # type: Optional[Callable[[Packet], int]] 

3541 ): 

3542 # type: (...) -> None 

3543 _IPPrefixFieldBase.__init__( 

3544 self, 

3545 name, 

3546 default, 

3547 wordbytes, 

3548 16, 

3549 lambda a: inet_pton(socket.AF_INET6, a), 

3550 lambda n: inet_ntop(socket.AF_INET6, n), 

3551 length_from 

3552 ) 

3553 

3554 

3555class UTCTimeField(Field[float, int]): 

3556 __slots__ = ["epoch", "delta", "strf", 

3557 "use_msec", "use_micro", "use_nano", "custom_scaling"] 

3558 

3559 def __init__(self, 

3560 name, # type: str 

3561 default, # type: int 

3562 use_msec=False, # type: bool 

3563 use_micro=False, # type: bool 

3564 use_nano=False, # type: bool 

3565 epoch=None, # type: Optional[Tuple[int, int, int, int, int, int, int, int, int]] # noqa: E501 

3566 strf="%a, %d %b %Y %H:%M:%S %z", # type: str 

3567 custom_scaling=None, # type: Optional[int] 

3568 fmt="I" # type: str 

3569 ): 

3570 # type: (...) -> None 

3571 Field.__init__(self, name, default, fmt=fmt) 

3572 mk_epoch = EPOCH if epoch is None else calendar.timegm(epoch) 

3573 self.epoch = mk_epoch 

3574 self.delta = mk_epoch - EPOCH 

3575 self.strf = strf 

3576 self.use_msec = use_msec 

3577 self.use_micro = use_micro 

3578 self.use_nano = use_nano 

3579 self.custom_scaling = custom_scaling 

3580 

3581 def i2repr(self, pkt, x): 

3582 # type: (Optional[Packet], float) -> str 

3583 if x is None: 

3584 x = time.time() - self.delta 

3585 elif self.use_msec: 

3586 x = x / 1e3 

3587 elif self.use_micro: 

3588 x = x / 1e6 

3589 elif self.use_nano: 

3590 x = x / 1e9 

3591 elif self.custom_scaling: 

3592 x = x / self.custom_scaling 

3593 x += self.delta 

3594 # To make negative timestamps work on all plateforms (e.g. Windows), 

3595 # we need a trick. 

3596 t = ( 

3597 datetime.datetime(1970, 1, 1) + 

3598 datetime.timedelta(seconds=x) 

3599 ).strftime(self.strf) 

3600 return "%s (%d)" % (t, int(x)) 

3601 

3602 def i2m(self, pkt, x): 

3603 # type: (Optional[Packet], Optional[float]) -> int 

3604 if x is None: 

3605 x = time.time() - self.delta 

3606 if self.use_msec: 

3607 x = x * 1e3 

3608 elif self.use_micro: 

3609 x = x * 1e6 

3610 elif self.use_nano: 

3611 x = x * 1e9 

3612 elif self.custom_scaling: 

3613 x = x * self.custom_scaling 

3614 return int(x) 

3615 return int(x) 

3616 

3617 

3618class SecondsIntField(Field[float, int]): 

3619 __slots__ = ["use_msec", "use_micro", "use_nano"] 

3620 

3621 def __init__(self, name, default, 

3622 use_msec=False, 

3623 use_micro=False, 

3624 use_nano=False): 

3625 # type: (str, int, bool, bool, bool) -> None 

3626 Field.__init__(self, name, default, "I") 

3627 self.use_msec = use_msec 

3628 self.use_micro = use_micro 

3629 self.use_nano = use_nano 

3630 

3631 def i2repr(self, pkt, x): 

3632 # type: (Optional[Packet], Optional[float]) -> str 

3633 if x is None: 

3634 y = 0 # type: Union[int, float] 

3635 elif self.use_msec: 

3636 y = x / 1e3 

3637 elif self.use_micro: 

3638 y = x / 1e6 

3639 elif self.use_nano: 

3640 y = x / 1e9 

3641 else: 

3642 y = x 

3643 return "%s sec" % y 

3644 

3645 

3646class _ScalingField(object): 

3647 def __init__(self, 

3648 name, # type: str 

3649 default, # type: float 

3650 scaling=1, # type: Union[int, float] 

3651 unit="", # type: str 

3652 offset=0, # type: Union[int, float] 

3653 ndigits=3, # type: int 

3654 fmt="B", # type: str 

3655 ): 

3656 # type: (...) -> None 

3657 self.scaling = scaling 

3658 self.unit = unit 

3659 self.offset = offset 

3660 self.ndigits = ndigits 

3661 Field.__init__(self, name, default, fmt) # type: ignore 

3662 

3663 def i2m(self, 

3664 pkt, # type: Optional[Packet] 

3665 x # type: Optional[Union[int, float]] 

3666 ): 

3667 # type: (...) -> Union[int, float] 

3668 if x is None: 

3669 x = 0 

3670 x = (x - self.offset) / self.scaling 

3671 if isinstance(x, float) and self.fmt[-1] != "f": # type: ignore 

3672 x = int(round(x)) 

3673 return x 

3674 

3675 def m2i(self, pkt, x): 

3676 # type: (Optional[Packet], Union[int, float]) -> Union[int, float] 

3677 x = x * self.scaling + self.offset 

3678 if isinstance(x, float) and self.fmt[-1] != "f": # type: ignore 

3679 x = round(x, self.ndigits) 

3680 return x 

3681 

3682 def any2i(self, pkt, x): 

3683 # type: (Optional[Packet], Any) -> Union[int, float, None] 

3684 if isinstance(x, (str, bytes)): 

3685 x = struct.unpack(self.fmt, bytes_encode(x))[0] # type: ignore 

3686 x = self.m2i(pkt, x) 

3687 if not isinstance(x, (int, float)) and x is not None: 

3688 raise ValueError("Unknown type") 

3689 return x 

3690 

3691 def i2repr(self, pkt, x): 

3692 # type: (Optional[Packet], Union[int, float]) -> str 

3693 return "%s %s" % ( 

3694 self.i2h(pkt, x), # type: ignore 

3695 self.unit 

3696 ) 

3697 

3698 def randval(self): 

3699 # type: () -> RandFloat 

3700 value = Field.randval(self) # type: ignore 

3701 if value is not None: 

3702 min_val = round(value.min * self.scaling + self.offset, 

3703 self.ndigits) 

3704 max_val = round(value.max * self.scaling + self.offset, 

3705 self.ndigits) 

3706 

3707 return RandFloat(min(min_val, max_val), max(min_val, max_val)) 

3708 

3709 

3710class ScalingField(_ScalingField, 

3711 Field[Union[int, float], Union[int, float]]): 

3712 """ Handle physical values which are scaled and/or offset for communication 

3713 

3714 Example: 

3715 >>> from scapy.packet import Packet 

3716 >>> class ScalingFieldTest(Packet): 

3717 fields_desc = [ScalingField('data', 0, scaling=0.1, offset=-1, unit='mV')] # noqa: E501 

3718 >>> ScalingFieldTest(data=10).show2() 

3719 ###[ ScalingFieldTest ]### 

3720 data= 10.0 mV 

3721 >>> hexdump(ScalingFieldTest(data=10)) 

3722 0000 6E n 

3723 >>> hexdump(ScalingFieldTest(data=b"\x6D")) 

3724 0000 6D m 

3725 >>> ScalingFieldTest(data=b"\x6D").show2() 

3726 ###[ ScalingFieldTest ]### 

3727 data= 9.9 mV 

3728 

3729 bytes(ScalingFieldTest(...)) will produce 0x6E in this example. 

3730 0x6E is 110 (decimal). This is calculated through the scaling factor 

3731 and the offset. "data" was set to 10, which means, we want to transfer 

3732 the physical value 10 mV. To calculate the value, which has to be 

3733 sent on the bus, the offset has to subtracted and the scaling has to be 

3734 applied by division through the scaling factor. 

3735 bytes = (data - offset) / scaling 

3736 bytes = ( 10 - (-1) ) / 0.1 

3737 bytes = 110 = 0x6E 

3738 

3739 If you want to force a certain internal value, you can assign a byte- 

3740 string to the field (data=b"\x6D"). If a string of a bytes object is 

3741 given to the field, no internal value conversion will be applied 

3742 

3743 :param name: field's name 

3744 :param default: default value for the field 

3745 :param scaling: scaling factor for the internal value conversion 

3746 :param unit: string for the unit representation of the internal value 

3747 :param offset: value to offset the internal value during conversion 

3748 :param ndigits: number of fractional digits for the internal conversion 

3749 :param fmt: struct.pack format used to parse and serialize the internal value from and to machine representation # noqa: E501 

3750 """ 

3751 

3752 

3753class BitScalingField(_ScalingField, BitField): # type: ignore 

3754 """ 

3755 A ScalingField that is a BitField 

3756 """ 

3757 

3758 def __init__(self, name, default, size, *args, **kwargs): 

3759 # type: (str, int, int, *Any, **Any) -> None 

3760 _ScalingField.__init__(self, name, default, *args, **kwargs) 

3761 BitField.__init__(self, name, default, size) # type: ignore 

3762 

3763 

3764class OUIField(X3BytesField): 

3765 """ 

3766 A field designed to carry a OUI (3 bytes) 

3767 """ 

3768 

3769 def i2repr(self, pkt, val): 

3770 # type: (Optional[Packet], int) -> str 

3771 by_val = struct.pack("!I", val or 0)[1:] 

3772 oui = str2mac(by_val + b"\0" * 3)[:8] 

3773 if conf.manufdb: 

3774 fancy = conf.manufdb._get_manuf(oui) 

3775 if fancy != oui: 

3776 return "%s (%s)" % (fancy, oui) 

3777 return oui 

3778 

3779 

3780class UUIDField(Field[UUID, bytes]): 

3781 """Field for UUID storage, wrapping Python's uuid.UUID type. 

3782 

3783 The internal storage format of this field is ``uuid.UUID`` from the Python 

3784 standard library. 

3785 

3786 There are three formats (``uuid_fmt``) for this field type: 

3787 

3788 * ``FORMAT_BE`` (default): the UUID is six fields in big-endian byte order, 

3789 per RFC 4122. 

3790 

3791 This format is used by DHCPv6 (RFC 6355) and most network protocols. 

3792 

3793 * ``FORMAT_LE``: the UUID is six fields, with ``time_low``, ``time_mid`` 

3794 and ``time_high_version`` in little-endian byte order. This *doesn't* 

3795 change the arrangement of the fields from RFC 4122. 

3796 

3797 This format is used by Microsoft's COM/OLE libraries. 

3798 

3799 * ``FORMAT_REV``: the UUID is a single 128-bit integer in little-endian 

3800 byte order. This *changes the arrangement* of the fields. 

3801 

3802 This format is used by Bluetooth Low Energy. 

3803 

3804 Note: You should use the constants here. 

3805 

3806 The "human encoding" of this field supports a number of different input 

3807 formats, and wraps Python's ``uuid.UUID`` library appropriately: 

3808 

3809 * Given a bytearray, bytes or str of 16 bytes, this class decodes UUIDs in 

3810 wire format. 

3811 

3812 * Given a bytearray, bytes or str of other lengths, this delegates to 

3813 ``uuid.UUID`` the Python standard library. This supports a number of 

3814 different encoding options -- see the Python standard library 

3815 documentation for more details. 

3816 

3817 * Given an int or long, presumed to be a 128-bit integer to pass to 

3818 ``uuid.UUID``. 

3819 

3820 * Given a tuple: 

3821 

3822 * Tuples of 11 integers are treated as having the last 6 integers forming 

3823 the ``node`` field, and are merged before being passed as a tuple of 6 

3824 integers to ``uuid.UUID``. 

3825 

3826 * Otherwise, the tuple is passed as the ``fields`` parameter to 

3827 ``uuid.UUID`` directly without modification. 

3828 

3829 ``uuid.UUID`` expects a tuple of 6 integers. 

3830 

3831 Other types (such as ``uuid.UUID``) are passed through. 

3832 """ 

3833 

3834 __slots__ = ["uuid_fmt"] 

3835 

3836 FORMAT_BE = 0 

3837 FORMAT_LE = 1 

3838 FORMAT_REV = 2 

3839 

3840 # Change this when we get new formats 

3841 FORMATS = (FORMAT_BE, FORMAT_LE, FORMAT_REV) 

3842 

3843 def __init__(self, name, default, uuid_fmt=FORMAT_BE): 

3844 # type: (str, Optional[int], int) -> None 

3845 self.uuid_fmt = uuid_fmt 

3846 self._check_uuid_fmt() 

3847 Field.__init__(self, name, default, "16s") 

3848 

3849 def _check_uuid_fmt(self): 

3850 # type: () -> None 

3851 """Checks .uuid_fmt, and raises an exception if it is not valid.""" 

3852 if self.uuid_fmt not in UUIDField.FORMATS: 

3853 raise FieldValueRangeException( 

3854 "Unsupported uuid_fmt ({})".format(self.uuid_fmt)) 

3855 

3856 def i2m(self, pkt, x): 

3857 # type: (Optional[Packet], Optional[UUID]) -> bytes 

3858 self._check_uuid_fmt() 

3859 if x is None: 

3860 return b'\0' * 16 

3861 if self.uuid_fmt == UUIDField.FORMAT_BE: 

3862 return x.bytes 

3863 elif self.uuid_fmt == UUIDField.FORMAT_LE: 

3864 return x.bytes_le 

3865 elif self.uuid_fmt == UUIDField.FORMAT_REV: 

3866 return x.bytes[::-1] 

3867 else: 

3868 raise FieldAttributeException("Unknown fmt") 

3869 

3870 def m2i(self, 

3871 pkt, # type: Optional[Packet] 

3872 x, # type: bytes 

3873 ): 

3874 # type: (...) -> UUID 

3875 self._check_uuid_fmt() 

3876 if self.uuid_fmt == UUIDField.FORMAT_BE: 

3877 return UUID(bytes=x) 

3878 elif self.uuid_fmt == UUIDField.FORMAT_LE: 

3879 return UUID(bytes_le=x) 

3880 elif self.uuid_fmt == UUIDField.FORMAT_REV: 

3881 return UUID(bytes=x[::-1]) 

3882 else: 

3883 raise FieldAttributeException("Unknown fmt") 

3884 

3885 def any2i(self, 

3886 pkt, # type: Optional[Packet] 

3887 x # type: Any # noqa: E501 

3888 ): 

3889 # type: (...) -> Optional[UUID] 

3890 # Python's uuid doesn't handle bytearray, so convert to an immutable 

3891 # type first. 

3892 if isinstance(x, bytearray): 

3893 x = bytes_encode(x) 

3894 

3895 if isinstance(x, int): 

3896 u = UUID(int=x) 

3897 elif isinstance(x, tuple): 

3898 if len(x) == 11: 

3899 # For compatibility with dce_rpc: this packs into a tuple where 

3900 # elements 7..10 are the 48-bit node ID. 

3901 node = 0 

3902 for i in x[5:]: 

3903 node = (node << 8) | i 

3904 

3905 x = (x[0], x[1], x[2], x[3], x[4], node) 

3906 

3907 u = UUID(fields=x) 

3908 elif isinstance(x, (str, bytes)): 

3909 if len(x) == 16: 

3910 # Raw bytes 

3911 u = self.m2i(pkt, bytes_encode(x)) 

3912 else: 

3913 u = UUID(plain_str(x)) 

3914 elif isinstance(x, (UUID, RandUUID)): 

3915 u = cast(UUID, x) 

3916 else: 

3917 return None 

3918 return u 

3919 

3920 @staticmethod 

3921 def randval(): 

3922 # type: () -> RandUUID 

3923 return RandUUID() 

3924 

3925 

3926class UUIDEnumField(UUIDField, _EnumField[UUID]): 

3927 __slots__ = EnumField.__slots__ 

3928 

3929 def __init__(self, name, default, enum, uuid_fmt=0): 

3930 # type: (str, Optional[int], Any, int) -> None 

3931 _EnumField.__init__(self, name, default, enum, "16s") # type: ignore 

3932 UUIDField.__init__(self, name, default, uuid_fmt=uuid_fmt) 

3933 

3934 def any2i(self, pkt, x): 

3935 # type: (Optional[Packet], Any) -> UUID 

3936 return _EnumField.any2i(self, pkt, x) # type: ignore 

3937 

3938 def i2repr(self, 

3939 pkt, # type: Optional[Packet] 

3940 x, # type: UUID 

3941 ): 

3942 # type: (...) -> Any 

3943 return _EnumField.i2repr(self, pkt, x) 

3944 

3945 

3946class BitExtendedField(Field[Optional[int], int]): 

3947 """ 

3948 Low E Bit Extended Field 

3949 

3950 This type of field has a variable number of bytes. Each byte is defined 

3951 as follows: 

3952 - 7 bits of data 

3953 - 1 bit an an extension bit: 

3954 

3955 + 0 means it is last byte of the field ("stopping bit") 

3956 + 1 means there is another byte after this one ("forwarding bit") 

3957 

3958 To get the actual data, it is necessary to hop the binary data byte per 

3959 byte and to check the extension bit until 0 

3960 """ 

3961 

3962 __slots__ = ["extension_bit"] 

3963 

3964 def __init__(self, name, default, extension_bit): 

3965 # type: (str, Optional[Any], int) -> None 

3966 Field.__init__(self, name, default, "B") 

3967 assert extension_bit in [7, 0] 

3968 self.extension_bit = extension_bit 

3969 

3970 def addfield(self, pkt, s, val): 

3971 # type: (Optional[Packet], bytes, Optional[int]) -> bytes 

3972 val = self.i2m(pkt, val) 

3973 if not val: 

3974 return s + b"\0" 

3975 rv = b"" 

3976 mask = 1 << self.extension_bit 

3977 shift = (self.extension_bit + 1) % 8 

3978 while val: 

3979 bv = (val & 0x7F) << shift 

3980 val = val >> 7 

3981 if val: 

3982 bv |= mask 

3983 rv += struct.pack("!B", bv) 

3984 return s + rv 

3985 

3986 def getfield(self, pkt, s): 

3987 # type: (Optional[Any], bytes) -> Tuple[bytes, Optional[int]] 

3988 val = 0 

3989 smask = 1 << self.extension_bit 

3990 mask = 0xFF & ~ (1 << self.extension_bit) 

3991 shift = (self.extension_bit + 1) % 8 

3992 i = 0 

3993 while s: 

3994 val |= ((s[0] & mask) >> shift) << (7 * i) 

3995 if (s[0] & smask) == 0: # extension bit is 0 

3996 # end 

3997 s = s[1:] 

3998 break 

3999 s = s[1:] 

4000 i += 1 

4001 return s, self.m2i(pkt, val) 

4002 

4003 

4004class LSBExtendedField(BitExtendedField): 

4005 # This is a BitExtendedField with the extension bit on LSB 

4006 def __init__(self, name, default): 

4007 # type: (str, Optional[Any]) -> None 

4008 BitExtendedField.__init__(self, name, default, extension_bit=0) 

4009 

4010 

4011class MSBExtendedField(BitExtendedField): 

4012 # This is a BitExtendedField with the extension bit on MSB 

4013 def __init__(self, name, default): 

4014 # type: (str, Optional[Any]) -> None 

4015 BitExtendedField.__init__(self, name, default, extension_bit=7)