Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/scapy/layers/ntp.py: 94%

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

324 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 

6""" 

7NTP (Network Time Protocol). 

8References : RFC 5905, RC 1305, ntpd source code 

9""" 

10 

11import struct 

12import time 

13import datetime 

14 

15from scapy.packet import Packet, bind_layers 

16from scapy.fields import ( 

17 BitEnumField, 

18 BitField, 

19 ByteEnumField, 

20 ByteField, 

21 ConditionalField, 

22 FieldLenField, 

23 FieldListField, 

24 FixedPointField, 

25 FlagsField, 

26 IP6Field, 

27 IPField, 

28 IntField, 

29 LEIntField, 

30 LEShortField, 

31 MayEnd, 

32 MultipleTypeField, 

33 PacketField, 

34 PacketListField, 

35 PadField, 

36 ShortField, 

37 SignedByteField, 

38 StrField, 

39 StrFixedLenEnumField, 

40 StrFixedLenField, 

41 StrLenField, 

42 XByteField, 

43 XStrFixedLenField, 

44) 

45from scapy.layers.inet import UDP 

46from scapy.utils import lhex 

47from scapy.config import conf 

48 

49 

50############################################################################# 

51# Constants 

52############################################################################# 

53 

54_NTP_AUTH_MD5_MIN_SIZE = 68 

55_NTP_EXT_MIN_SIZE = 16 

56_NTP_HDR_WITH_EXT_MIN_SIZE = _NTP_AUTH_MD5_MIN_SIZE + _NTP_EXT_MIN_SIZE 

57_NTP_AUTH_MD5_TAIL_SIZE = 20 

58_NTP_AUTH_MD5_DGST_SIZE = 16 

59_NTP_PRIVATE_PACKET_MIN_SIZE = 8 

60 

61# ntpd "Private" messages are the shortest 

62_NTP_PACKET_MIN_SIZE = _NTP_PRIVATE_PACKET_MIN_SIZE 

63 

64_NTP_PRIVATE_REQ_PKT_TAIL_LEN = 28 

65 

66# seconds between 01-01-1900 and 01-01-1970 

67_NTP_BASETIME = 2208988800 

68 

69# include/ntp.h 

70_NTP_SHIFT = 8 

71_NTP_HASH_SIZE = 128 

72 

73 

74############################################################################# 

75# Fields and utilities 

76############################################################################# 

77 

78class XLEShortField(LEShortField): 

79 """ 

80 XShortField which value is encoded in little endian. 

81 """ 

82 

83 def i2repr(self, pkt, x): 

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

85 

86 

87class TimeStampField(FixedPointField): 

88 """ 

89 This field handles the timestamp fields in the NTP header. 

90 """ 

91 

92 def __init__(self, name, default): 

93 FixedPointField.__init__(self, name, default, 64, 32) 

94 

95 def i2repr(self, pkt, val): 

96 if val is None: 

97 return "--" 

98 val = self.i2h(pkt, val) 

99 if val < _NTP_BASETIME: 

100 return str(val) 

101 return time.strftime( 

102 "%a, %d %b %Y %H:%M:%S +0000", 

103 time.gmtime(int(val - _NTP_BASETIME)) 

104 ) 

105 

106 def any2i(self, pkt, val): 

107 if isinstance(val, str): 

108 val = int(time.mktime(time.strptime(val))) + _NTP_BASETIME 

109 elif isinstance(val, datetime.datetime): 

110 val = int(val.strftime("%s")) + _NTP_BASETIME 

111 return FixedPointField.any2i(self, pkt, val) 

112 

113 def i2m(self, pkt, val): 

114 if val is None: 

115 val = FixedPointField.any2i(self, pkt, time.time() + _NTP_BASETIME) 

116 return FixedPointField.i2m(self, pkt, val) 

117 

118 

119############################################################################# 

120# NTP 

121############################################################################# 

122 

123# RFC 5905 / Section 7.3 

124_leap_indicator = { 

125 0: "no warning", 

126 1: "last minute of the day has 61 seconds", 

127 2: "last minute of the day has 59 seconds", 

128 3: "unknown (clock unsynchronized)" 

129} 

130 

131 

132# RFC 5905 / Section 7.3 

133_ntp_modes = { 

134 0: "reserved", 

135 1: "symmetric active", 

136 2: "symmetric passive", 

137 3: "client", 

138 4: "server", 

139 5: "broadcast", 

140 6: "NTP control message", 

141 7: "reserved for private use" 

142} 

143 

144 

145# RFC 5905 / Section 7.3 

146_reference_identifiers = { 

147 b"GOES": "Geosynchronous Orbit Environment Satellite", 

148 b"GPS ": "Global Position System", 

149 b"GAL ": "Galileo Positioning System", 

150 b"PPS ": "Generic pulse-per-second", 

151 b"IRIG": "Inter-Range Instrumentation Group", 

152 b"WWVB": "LF Radio WWVB Ft. Collins, CO 60 kHz", 

153 b"DCF ": "LF Radio DCF77 Mainflingen, DE 77.5 kHz", 

154 b"HBG ": "LF Radio HBG Prangins, HB 75 kHz", 

155 b"MSF ": "LF Radio MSF Anthorn, UK 60 kHz", 

156 b"JJY ": "LF Radio JJY Fukushima, JP 40 kHz, Saga, JP 60 kHz", 

157 b"LORC": "MF Radio LORAN C station, 100 kHz", 

158 b"TDF ": "MF Radio Allouis, FR 162 kHz", 

159 b"CHU ": "HF Radio CHU Ottawa, Ontario", 

160 b"WWV ": "HF Radio WWV Ft. Collins, CO", 

161 b"WWVH": "HF Radio WWVH Kauai, HI", 

162 b"NIST": "NIST telephone modem", 

163 b"ACTS": "NIST telephone modem", 

164 b"USNO": "USNO telephone modem", 

165 b"PTB ": "European telephone modem", 

166} 

167 

168 

169# RFC 5905 / Section 7.4 

170_kiss_codes = { 

171 "ACST": "The association belongs to a unicast server.", 

172 "AUTH": "Server authentication failed.", 

173 "AUTO": "Autokey sequence failed.", 

174 "BCST": "The association belongs to a broadcast server.", 

175 "CRYP": "Cryptographic authentication or identification failed.", 

176 "DENY": "Access denied by remote server.", 

177 "DROP": "Lost peer in symmetric mode.", 

178 "RSTR": "Access denied due to local policy.", 

179 "INIT": "The association has not yet synchronized for the first time.", 

180 "MCST": "The association belongs to a dynamically discovered server.", 

181 "NKEY": "No key found.", 

182 "RATE": "Rate exceeded.", 

183 "RMOT": "Alteration of association from a remote host running ntpdc." 

184} 

185 

186 

187# Used by _ntp_dispatcher to instantiate the appropriate class 

188def _ntp_dispatcher(payload): 

189 """ 

190 Returns the right class for a given NTP packet. 

191 """ 

192 # By default, calling NTP() will build a NTP packet as defined in RFC 5905 

193 # (see the code of NTPHeader). Use NTPHeader for extension fields and MAC. 

194 if payload is None: 

195 return NTPHeader 

196 else: 

197 length = len(payload) 

198 if length >= _NTP_PACKET_MIN_SIZE: 

199 first_byte = payload[0] 

200 # Extract NTP mode 

201 mode = first_byte & 7 

202 return {6: NTPControl, 7: NTPPrivate}.get(mode, NTPHeader) 

203 return conf.raw_layer 

204 

205 

206class NTP(Packet): 

207 """ 

208 Base class that allows easier instantiation of a NTP packet from binary 

209 data. 

210 """ 

211 

212 @classmethod 

213 def dispatch_hook(cls, _pkt=None, *args, **kargs): 

214 """ 

215 Returns the right class for the given data. 

216 """ 

217 

218 return _ntp_dispatcher(_pkt) 

219 

220 def pre_dissect(self, s): 

221 """ 

222 Check that the payload is long enough to build a NTP packet. 

223 """ 

224 length = len(s) 

225 if length < _NTP_PACKET_MIN_SIZE: 

226 err = " ({}".format(length) + " is < _NTP_PACKET_MIN_SIZE " 

227 err += "({})).".format(_NTP_PACKET_MIN_SIZE) 

228 raise _NTPInvalidDataException(err) 

229 return s 

230 

231 def mysummary(self): 

232 return self.sprintf( 

233 "NTP v%ir,{0}.version%, %{0}.mode%".format(self.__class__.__name__) 

234 ) 

235 

236 

237class _NTPAuthenticatorPaddingField(StrField): 

238 """ 

239 StrField handling the padding that may be found before the 

240 "authenticator" field. 

241 """ 

242 

243 def getfield(self, pkt, s): 

244 ret = None 

245 remain = s 

246 length = len(s) 

247 

248 if length > _NTP_AUTH_MD5_TAIL_SIZE: 

249 start = length - _NTP_AUTH_MD5_TAIL_SIZE 

250 ret = s[:start] 

251 remain = s[start:] 

252 return remain, ret 

253 

254 

255class NTPAuthenticator(Packet): 

256 """ 

257 Packet handling the "authenticator" part of a NTP packet, as 

258 defined in RFC 5905. 

259 """ 

260 

261 name = "Authenticator" 

262 fields_desc = [ 

263 _NTPAuthenticatorPaddingField("padding", ""), 

264 IntField("key_id", 0), 

265 XStrFixedLenField("dgst", "", length_from=lambda x: 16) 

266 ] 

267 

268 def extract_padding(self, s): 

269 return b"", s 

270 

271 

272class NTPExtension(Packet): 

273 """ 

274 Packet handling a NTPv4 extension. 

275 """ 

276 

277 ######################################################################### 

278 # 

279 # RFC 7822 

280 ######################################################################### 

281 # 

282 # 7.5. NTP Extension Field Format 

283 # 

284 # In NTPv3, one or more extension fields can be inserted after the 

285 # header and before the MAC, if a MAC is present. 

286 # 

287 # Other than defining the field format, this document makes no use 

288 # of the field contents. An extension field contains a request or 

289 # response message in the format shown in Figure 14. 

290 # 

291 # 0 1 2 3 

292 # 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 

293 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

294 # | Field Type | Length | 

295 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

296 # . . 

297 # . Value . 

298 # . . 

299 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

300 # | Padding (as needed) | 

301 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

302 # 

303 # Figure 14: Extension Field Format 

304 # 

305 # 

306 # All extension fields are zero-padded to a word (four octets) 

307 # boundary. 

308 ######################################################################### 

309 # 

310 

311 name = "extension" 

312 fields_desc = [ 

313 ShortField("type", 0), 

314 ShortField("len", 0), 

315 PadField(PacketField("value", "", Packet), align=4, padwith=b"\x00") 

316 ] 

317 

318 

319class NTPExtPacketListField(PacketListField): 

320 

321 """ 

322 PacketListField handling NTPv4 extensions (NTPExtension list). 

323 """ 

324 

325 def m2i(self, pkt, m): 

326 ret = None 

327 if len(m) >= 16: 

328 ret = NTPExtension(m) 

329 else: 

330 ret = conf.raw_layer(m) 

331 return ret 

332 

333 def getfield(self, pkt, s): 

334 lst = [] 

335 remain = s 

336 length = len(s) 

337 if length > _NTP_AUTH_MD5_TAIL_SIZE: 

338 end = length - _NTP_AUTH_MD5_TAIL_SIZE 

339 extensions = s[:end] 

340 remain = s[end:] 

341 

342 extensions_len = len(extensions) 

343 while extensions_len >= 16: 

344 ext_len = struct.unpack("!H", extensions[2:4])[0] 

345 ext_len = min(ext_len, extensions_len) 

346 if ext_len < 1: 

347 ext_len = extensions_len 

348 current = extensions[:ext_len] 

349 extensions = extensions[ext_len:] 

350 current_packet = self.m2i(pkt, current) 

351 lst.append(current_packet) 

352 extensions_len = len(extensions) 

353 

354 if extensions_len > 0: 

355 lst.append(self.m2i(pkt, extensions)) 

356 

357 return remain, lst 

358 

359 

360class NTPExtensions(Packet): 

361 """ 

362 Packet handling the NTPv4 extensions and the "MAC part" of the packet. 

363 """ 

364 

365 ######################################################################### 

366 # 

367 # RFC 5905 / RFC 7822 

368 ######################################################################### 

369 # 

370 # 7.5. NTP Extension Field Format 

371 # 

372 # In NTPv4, one or more extension fields can be inserted after the 

373 # header and before the MAC, if a MAC is present. 

374 ######################################################################### 

375 # 

376 

377 name = "NTPv4 extensions" 

378 fields_desc = [ 

379 NTPExtPacketListField("extensions", [], Packet), 

380 PacketField("mac", NTPAuthenticator(), NTPAuthenticator) 

381 ] 

382 

383 

384class NTPHeader(NTP): 

385 

386 """ 

387 Packet handling the RFC 5905 NTP packet. 

388 """ 

389 

390 ######################################################################### 

391 # 

392 # RFC 5905 

393 ######################################################################### 

394 # 

395 # 0 1 2 3 

396 # 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 

397 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

398 # |LI | VN |Mode | Stratum | Poll | Precision | 

399 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

400 # | Root Delay | 

401 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

402 # | Root Dispersion | 

403 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

404 # | Reference ID | 

405 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

406 # | | 

407 # + Reference Timestamp (64) + 

408 # | | 

409 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

410 # | | 

411 # + Origin Timestamp (64) + 

412 # | | 

413 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

414 # | | 

415 # + Receive Timestamp (64) + 

416 # | | 

417 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

418 # | | 

419 # + Transmit Timestamp (64) + 

420 # | | 

421 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

422 # | | 

423 # . . 

424 # . Extension Field 1 (variable) . 

425 # . . 

426 # | | 

427 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

428 # | | 

429 # . . 

430 # . Extension Field 2 (variable) . 

431 # . . 

432 # | | 

433 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

434 # | Key Identifier | 

435 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

436 # | | 

437 # | dgst (128) | 

438 # | | 

439 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

440 # 

441 # Figure 8: Packet Header Format 

442 ######################################################################### 

443 # 

444 

445 name = "NTPHeader" 

446 match_subclass = True 

447 fields_desc = [ 

448 BitEnumField("leap", 0, 2, _leap_indicator), 

449 BitField("version", 4, 3), 

450 BitEnumField("mode", 3, 3, _ntp_modes), 

451 BitField("stratum", 2, 8), 

452 SignedByteField("poll", 0xa), 

453 SignedByteField("precision", 0), 

454 FixedPointField("delay", 0, size=32, frac_bits=16), 

455 FixedPointField("dispersion", 0, size=32, frac_bits=16), 

456 ConditionalField(IPField("id", "127.0.0.1"), lambda p: p.stratum > 1), 

457 ConditionalField( 

458 StrFixedLenEnumField( 

459 "ref_id", 

460 "", 

461 length=4, 

462 enum=_reference_identifiers 

463 ), 

464 lambda p: p.stratum < 2 

465 ), 

466 TimeStampField("ref", 0), 

467 TimeStampField("orig", None), 

468 TimeStampField("recv", 0), 

469 TimeStampField("sent", None), 

470 ] 

471 

472 def guess_payload_class(self, payload): 

473 """ 

474 Handles NTPv4 extensions and MAC part (when authentication is used.) 

475 """ 

476 plen = len(payload) 

477 

478 if plen - 4 in [16, 20, 32, 64]: # length of MD5, SHA1, SHA256, SHA512 

479 return NTPAuthenticator 

480 elif plen > _NTP_AUTH_MD5_TAIL_SIZE: 

481 return NTPExtensions 

482 

483 return Packet.guess_payload_class(self, payload) 

484 

485 

486class _NTPInvalidDataException(Exception): 

487 """ 

488 Raised when it is not possible to instantiate a NTP packet with the 

489 given data. 

490 """ 

491 

492 def __init__(self, details): 

493 Exception.__init__( 

494 self, 

495 "Data does not seem to be a valid NTP message" + details 

496 ) 

497 

498 

499############################################################################## 

500# Private (mode 7) 

501############################################################################## 

502 

503# Operation codes 

504_op_codes = { 

505 0: "CTL_OP_UNSPEC", 

506 1: "CTL_OP_READSTAT", 

507 2: "CTL_OP_READVAR", 

508 3: "CTL_OP_WRITEVAR", 

509 4: "CTL_OP_READCLOCK", 

510 5: "CTL_OP_WRITECLOCK", 

511 6: "CTL_OP_SETTRAP", 

512 7: "CTL_OP_ASYNCMSG", 

513 8: "CTL_OP_CONFIGURE", 

514 9: "CTL_OP_SAVECONFIG", 

515 10: "CTL_OP_READ_MRU", 

516 11: "CTL_OP_READ_ORDLIST_A", 

517 12: "CTL_OP_REQ_NONCE", 

518 31: "CTL_OP_UNSETTRAP" 

519} 

520 

521 

522# System status words 

523_system_statuses = { 

524 0: "no warning", 

525 1: "last minute was 61 seconds", 

526 2: "last minute was 59 seconds", 

527 3: "alarm condition (clock not synchronized)" 

528} 

529 

530 

531_clock_sources = { 

532 0: "unspecified or unknown", 

533 1: " Calibrated atomic clock", 

534 2: "VLF (band 4) or LF (band 5) radio", 

535 3: "HF (band 7) radio", 

536 4: "UHF (band 9) satellite", 

537 5: "local net", 

538 6: "UDP/NTP", 

539 7: "UDP/TIME", 

540 8: "eyeball-and-wristwatch", 

541 9: "telephone modem" 

542} 

543 

544 

545_system_event_codes = { 

546 0: "unspecified", 

547 1: "system restart", 

548 2: "system or hardware fault", 

549 3: "system new status word (leap bits or synchronization change)", 

550 4: "system new synchronization source or stratum (sys.peer or sys.stratum change)", # noqa: E501 

551 5: "system clock reset (offset correction exceeds CLOCK.MAX)", 

552 6: "system invalid time or date", 

553 7: "system clock exception", 

554} 

555 

556 

557# Peer status words 

558_peer_statuses = { 

559 0: "configured", 

560 1: "authentication enabled", 

561 2: "authentication okay", 

562 3: "reachability okay", 

563 4: "reserved" 

564} 

565 

566 

567_peer_selection = { 

568 0: "rejected", 

569 1: "passed sanity checks", 

570 2: "passed correctness checks", 

571 3: "passed candidate checks", 

572 4: "passed outlyer checks", 

573 5: "current synchronization source; max distance exceeded", 

574 6: "current synchronization source; max distance okay", 

575 7: "reserved" 

576} 

577 

578 

579_peer_event_codes = { 

580 0: "unspecified", 

581 1: "peer IP error", 

582 2: "peer authentication failure", 

583 3: "peer unreachable", 

584 4: "peer reachable", 

585 5: "peer clock exception", 

586} 

587 

588 

589# Clock status words 

590_clock_statuses = { 

591 0: "clock operating within nominals", 

592 1: "reply timeout", 

593 2: "bad reply format", 

594 3: "hardware or software fault", 

595 4: "propagation failure", 

596 5: "bad date format or value", 

597 6: "bad time format or value" 

598} 

599 

600 

601# Error status words 

602_error_statuses = { 

603 0: "unspecified", 

604 1: "authentication failure", 

605 2: "invalid message length or format", 

606 3: "invalid opcode", 

607 4: "unknown association identifier", 

608 5: "unknown variable name", 

609 6: "invalid variable value", 

610 7: "administratively prohibited" 

611} 

612 

613 

614class NTPSystemStatusPacket(Packet): 

615 

616 """ 

617 Packet handling the system status fields. 

618 """ 

619 

620 name = "system status" 

621 fields_desc = [ 

622 BitEnumField("leap_indicator", 0, 2, _system_statuses), 

623 BitEnumField("clock_source", 0, 6, _clock_sources), 

624 BitField("system_event_counter", 0, 4), 

625 BitEnumField("system_event_code", 0, 4, _system_event_codes), 

626 ] 

627 

628 def extract_padding(self, s): 

629 return b"", s 

630 

631 

632class NTPPeerStatusPacket(Packet): 

633 """ 

634 Packet handling the peer status fields. 

635 """ 

636 

637 name = "peer status" 

638 fields_desc = [ 

639 BitField("configured", 0, 1), 

640 BitField("auth_enabled", 0, 1), 

641 BitField("authentic", 0, 1), 

642 BitField("reachability", 0, 1), 

643 BitField("reserved", 0, 1), 

644 BitEnumField("peer_sel", 0, 3, _peer_selection), 

645 BitField("peer_event_counter", 0, 4), 

646 BitEnumField("peer_event_code", 0, 4, _peer_event_codes), 

647 ] 

648 

649 def extract_padding(self, s): 

650 return b"", s 

651 

652 

653class NTPClockStatusPacket(Packet): 

654 """ 

655 Packet handling the clock status fields. 

656 """ 

657 

658 name = "clock status" 

659 fields_desc = [ 

660 BitEnumField("clock_status", 0, 8, _clock_statuses), 

661 BitField("code", 0, 8) 

662 ] 

663 

664 def extract_padding(self, s): 

665 return b"", s 

666 

667 

668class NTPErrorStatusPacket(Packet): 

669 """ 

670 Packet handling the error status fields. 

671 """ 

672 

673 name = "error status" 

674 fields_desc = [ 

675 BitEnumField("error_code", 0, 8, _error_statuses), 

676 BitField("reserved", 0, 8) 

677 ] 

678 

679 def extract_padding(self, s): 

680 return b"", s 

681 

682 

683class NTPPeerStatusDataPacket(Packet): 

684 """ 

685 Packet handling the data field when op_code is CTL_OP_READSTAT 

686 and the association_id field is null. 

687 """ 

688 

689 name = "data / peer status" 

690 fields_desc = [ 

691 ShortField("association_id", 0), 

692 PacketField("peer_status", NTPPeerStatusPacket(), NTPPeerStatusPacket), 

693 ] 

694 

695 def extract_padding(self, s): 

696 return b"", s 

697 

698 

699class NTPControlStatusField(PacketField): 

700 """ 

701 The various types of the "status" field. 

702 """ 

703 # RFC 9327 sect 3 

704 def m2i(self, pkt, m): 

705 association_id = struct.unpack("!H", m[2:4])[0] 

706 

707 if pkt.err == 1: 

708 return NTPErrorStatusPacket(m) 

709 elif pkt.op_code in [4, 5]: # Read/write clock 

710 return NTPClockStatusPacket(m) 

711 else: 

712 if association_id != 0: 

713 return NTPPeerStatusPacket(m) 

714 else: 

715 return NTPSystemStatusPacket(m) 

716 

717 

718class NTPControl(NTP): 

719 """ 

720 Packet handling NTP mode 6 / "Control" messages. 

721 """ 

722 deprecated_fields = { 

723 "status_word": ("status", "2.6.2"), 

724 } 

725 # RFC 9327 sect 2 

726 name = "NTP Control message" 

727 match_subclass = True 

728 fields_desc = [ 

729 BitEnumField("leap", 0, 2, _leap_indicator), 

730 BitField("version", 2, 3), 

731 BitEnumField("mode", 6, 3, _ntp_modes), 

732 BitField("response", 0, 1), 

733 BitField("err", 0, 1), 

734 BitField("more", 0, 1), 

735 BitEnumField("op_code", 0, 5, _op_codes), 

736 ShortField("sequence", 0), 

737 MultipleTypeField( 

738 [ 

739 ( 

740 ShortField("status", 0), 

741 lambda pkt: pkt.response == 0 or pkt.op_code in [6, 7] 

742 ) 

743 ], 

744 NTPControlStatusField("status", NTPSystemStatusPacket(), None), 

745 ), 

746 ShortField("association_id", 0), 

747 ShortField("offset", 0), 

748 FieldLenField("count", None, length_of="data"), 

749 MayEnd( 

750 PadField( 

751 MultipleTypeField( 

752 # RFC 1305 

753 [ 

754 ( 

755 PacketListField( 

756 "data", 

757 "", 

758 NTPPeerStatusDataPacket, 

759 length_from=lambda p: p.count, 

760 ), 

761 lambda pkt: ( 

762 pkt.response and 

763 pkt.op_code == 1 and 

764 pkt.association_id == 0 

765 ) 

766 ), 

767 ], 

768 StrLenField("data", "", length_from=lambda pkt: pkt.count), 

769 ), 

770 align=4 

771 ) 

772 ), 

773 PacketField("authenticator", "", NTPAuthenticator), 

774 ] 

775 

776 

777############################################################################## 

778# Private (mode 7) 

779############################################################################## 

780 

781_information_error_codes = { 

782 0: "INFO_OKAY", 

783 1: "INFO_ERR_IMPL", 

784 2: "INFO_ERR_REQ", 

785 3: "INFO_ERR_FMT", 

786 4: "INFO_ERR_NODATA", 

787 7: "INFO_ERR_AUTH" 

788} 

789 

790 

791_implementations = { 

792 0: "IMPL_UNIV", 

793 2: "IMPL_XNTPD_OLD", 

794 3: "XNTPD" 

795} 

796 

797 

798_request_codes = { 

799 0: "REQ_PEER_LIST", 

800 1: "REQ_PEER_LIST_SUM", 

801 2: "REQ_PEER_INFO", 

802 3: "REQ_PEER_STATS", 

803 4: "REQ_SYS_INFO", 

804 5: "REQ_SYS_STATS", 

805 6: "REQ_IO_STATS", 

806 7: "REQ_MEM_STATS", 

807 8: "REQ_LOOP_INFO", 

808 9: "REQ_TIMER_STATS", 

809 10: "REQ_CONFIG", 

810 11: "REQ_UNCONFIG", 

811 12: "REQ_SET_SYS_FLAG", 

812 13: "REQ_CLR_SYS_FLAG", 

813 14: "REQ_MONITOR", 

814 15: "REQ_NOMONITOR", 

815 16: "REQ_GET_RESTRICT", 

816 17: "REQ_RESADDFLAGS", 

817 18: "REQ_RESSUBFLAGS", 

818 19: "REQ_UNRESTRICT", 

819 20: "REQ_MON_GETLIST", 

820 21: "REQ_RESET_STATS", 

821 22: "REQ_RESET_PEER", 

822 23: "REQ_REREAD_KEYS", 

823 24: "REQ_DO_DIRTY_HACK", 

824 25: "REQ_DONT_DIRTY_HACK", 

825 26: "REQ_TRUSTKEY", 

826 27: "REQ_UNTRUSTKEY", 

827 28: "REQ_AUTHINFO", 

828 29: "REQ_TRAPS", 

829 30: "REQ_ADD_TRAP", 

830 31: "REQ_CLR_TRAP", 

831 32: "REQ_REQUEST_KEY", 

832 33: "REQ_CONTROL_KEY", 

833 34: "REQ_GET_CTLSTATS", 

834 35: "REQ_GET_LEAPINFO", 

835 36: "REQ_GET_CLOCKINFO", 

836 37: "REQ_SET_CLKFUDGE", 

837 38: "REQ_GET_KERNEL", 

838 39: "REQ_GET_CLKBUGINFO", 

839 41: "REQ_SET_PRECISION", 

840 42: "REQ_MON_GETLIST_1", 

841 43: "REQ_HOSTNAME_ASSOCID", 

842 44: "REQ_IF_STATS", 

843 45: "REQ_IF_RELOAD" 

844} 

845 

846 

847# Flags in the peer information returns 

848_peer_flags = [ 

849 "INFO_FLAG_CONFIG", 

850 "INFO_FLAG_SYSPEER", 

851 "INFO_FLAG_BURST", 

852 "INFO_FLAG_REFCLOCK", 

853 "INFO_FLAG_PREFER", 

854 "INFO_FLAG_AUTHENABLE", 

855 "INFO_FLAG_SEL_CANDIDATE", 

856 "INFO_FLAG_SHORTLIST", 

857 "INFO_FLAG_IBURST" 

858] 

859 

860 

861# Flags in the system information returns 

862_sys_info_flags = [ 

863 "INFO_FLAG_BCLIENT", 

864 "INFO_FLAG_AUTHENTICATE", 

865 "INFO_FLAG_NTP", 

866 "INFO_FLAG_KERNEL", 

867 "INFO_FLAG_CAL", 

868 "INFO_FLAG_PPS_SYNC", 

869 "INFO_FLAG_MONITOR", 

870 "INFO_FLAG_FILEGEN", 

871] 

872 

873 

874class NTPInfoPeerList(Packet): 

875 

876 """ 

877 Used to return raw lists of peers. 

878 """ 

879 name = "info_peer_list" 

880 fields_desc = [ 

881 IPField("addr", "0.0.0.0"), 

882 ShortField("port", 0), 

883 ByteEnumField("hmode", 0, _ntp_modes), 

884 FlagsField("flags", 0, 8, _peer_flags), 

885 IntField("v6_flag", 0), 

886 IntField("unused1", 0), 

887 IP6Field("addr6", "::") 

888 ] 

889 

890 

891class NTPInfoPeerSummary(Packet): 

892 """ 

893 Sort of the info that ntpdc returns by default. 

894 """ 

895 name = "info_peer_summary" 

896 fields_desc = [ 

897 IPField("dstaddr", "0.0.0.0"), 

898 IPField("srcaddr", "0.0.0.0"), 

899 ShortField("srcport", 0), 

900 ByteField("stratum", 0), 

901 ByteField("hpoll", 0), 

902 ByteField("ppoll", 0), 

903 ByteField("reach", 0), 

904 FlagsField("flags", 0, 8, _peer_flags), 

905 ByteField("hmode", _ntp_modes), 

906 FixedPointField("delay", 0, size=32, frac_bits=16), 

907 TimeStampField("offset", 0), 

908 FixedPointField("dispersion", 0, size=32, frac_bits=16), 

909 IntField("v6_flag", 0), 

910 IntField("unused1", 0), 

911 IP6Field("dstaddr6", "::"), 

912 IP6Field("srcaddr6", "::") 

913 ] 

914 

915 

916class NTPInfoPeer(Packet): 

917 """ 

918 Peer information structure. 

919 """ 

920 

921 name = "info_peer" 

922 fields_desc = [ 

923 IPField("dstaddr", "0.0.0.0"), 

924 IPField("srcaddr", "0.0.0.0"), 

925 ShortField("srcport", 0), 

926 FlagsField("flags", 0, 8, _peer_flags), 

927 ByteField("leap", 0), 

928 ByteEnumField("hmode", 0, _ntp_modes), 

929 ByteField("pmode", 0), 

930 ByteField("stratum", 0), 

931 ByteField("ppoll", 0), 

932 ByteField("hpoll", 0), 

933 SignedByteField("precision", 0), 

934 ByteField("version", 0), 

935 ByteField("unused8", 0), 

936 ByteField("reach", 0), 

937 ByteField("unreach", 0), 

938 XByteField("flash", 0), 

939 ByteField("ttl", 0), 

940 XLEShortField("flash2", 0), 

941 ShortField("associd", 0), 

942 LEIntField("keyid", 0), 

943 IntField("pkeyid", 0), 

944 IPField("refid", 0), 

945 IntField("timer", 0), 

946 FixedPointField("rootdelay", 0, size=32, frac_bits=16), 

947 FixedPointField("rootdispersion", 0, size=32, frac_bits=16), 

948 TimeStampField("reftime", 0), 

949 TimeStampField("org", 0), 

950 TimeStampField("rec", 0), 

951 TimeStampField("xmt", 0), 

952 FieldListField( 

953 "filtdelay", 

954 [0.0 for i in range(0, _NTP_SHIFT)], 

955 FixedPointField("", 0, size=32, frac_bits=16), 

956 count_from=lambda p: _NTP_SHIFT 

957 ), 

958 FieldListField( 

959 "filtoffset", 

960 [0.0 for i in range(0, _NTP_SHIFT)], 

961 TimeStampField("", 0), 

962 count_from=lambda p: _NTP_SHIFT 

963 ), 

964 FieldListField( 

965 "order", 

966 [0 for i in range(0, _NTP_SHIFT)], 

967 ByteField("", 0), 

968 count_from=lambda p: _NTP_SHIFT 

969 ), 

970 FixedPointField("delay", 0, size=32, frac_bits=16), 

971 FixedPointField("dispersion", 0, size=32, frac_bits=16), 

972 TimeStampField("offset", 0), 

973 FixedPointField("selectdisp", 0, size=32, frac_bits=16), 

974 IntField("unused1", 0), 

975 IntField("unused2", 0), 

976 IntField("unused3", 0), 

977 IntField("unused4", 0), 

978 IntField("unused5", 0), 

979 IntField("unused6", 0), 

980 IntField("unused7", 0), 

981 FixedPointField("estbdelay", 0, size=32, frac_bits=16), 

982 IntField("v6_flag", 0), 

983 IntField("unused9", 0), 

984 IP6Field("dstaddr6", "::"), 

985 IP6Field("srcaddr6", "::"), 

986 ] 

987 

988 

989class NTPInfoPeerStats(Packet): 

990 """ 

991 Peer statistics structure. 

992 """ 

993 

994 name = "info_peer_stats" 

995 fields_desc = [ 

996 IPField("dstaddr", "0.0.0.0"), 

997 IPField("srcaddr", "0.0.0.0"), 

998 ShortField("srcport", 0), 

999 FlagsField("flags", 0, 16, _peer_flags), 

1000 IntField("timereset", 0), 

1001 IntField("timereceived", 0), 

1002 IntField("timetosend", 0), 

1003 IntField("timereachable", 0), 

1004 IntField("sent", 0), 

1005 IntField("unused1", 0), 

1006 IntField("processed", 0), 

1007 IntField("unused2", 0), 

1008 IntField("badauth", 0), 

1009 IntField("bogusorg", 0), 

1010 IntField("oldpkt", 0), 

1011 IntField("unused3", 0), 

1012 IntField("unused4", 0), 

1013 IntField("seldisp", 0), 

1014 IntField("selbroken", 0), 

1015 IntField("unused5", 0), 

1016 ByteField("candidate", 0), 

1017 ByteField("unused6", 0), 

1018 ByteField("unused7", 0), 

1019 ByteField("unused8", 0), 

1020 IntField("v6_flag", 0), 

1021 IntField("unused9", 0), 

1022 IP6Field("dstaddr6", "::"), 

1023 IP6Field("srcaddr6", "::"), 

1024 ] 

1025 

1026 

1027class NTPInfoLoop(Packet): 

1028 """ 

1029 Loop filter variables. 

1030 """ 

1031 

1032 name = "info_loop" 

1033 fields_desc = [ 

1034 TimeStampField("last_offset", 0), 

1035 TimeStampField("drift_comp", 0), 

1036 IntField("compliance", 0), 

1037 IntField("watchdog_timer", 0) 

1038 ] 

1039 

1040 

1041class NTPInfoSys(Packet): 

1042 """ 

1043 System info. Mostly the sys.* variables, plus a few unique to 

1044 the implementation. 

1045 """ 

1046 

1047 name = "info_sys" 

1048 fields_desc = [ 

1049 IPField("peer", "0.0.0.0"), 

1050 ByteField("peer_mode", 0), 

1051 ByteField("leap", 0), 

1052 ByteField("stratum", 0), 

1053 SignedByteField("precision", 0), 

1054 FixedPointField("rootdelay", 0, size=32, frac_bits=16), 

1055 FixedPointField("rootdispersion", 0, size=32, frac_bits=16), 

1056 IPField("refid", 0), 

1057 TimeStampField("reftime", 0), 

1058 IntField("poll", 0), 

1059 FlagsField("flags", 0, 8, _sys_info_flags), 

1060 ByteField("unused1", 0), 

1061 ByteField("unused2", 0), 

1062 ByteField("unused3", 0), 

1063 FixedPointField("bdelay", 0, size=32, frac_bits=16), 

1064 FixedPointField("frequency", 0, size=32, frac_bits=16), 

1065 TimeStampField("authdelay", 0), 

1066 FixedPointField("stability", 0, size=32, frac_bits=16), 

1067 IntField("v6_flag", 0), 

1068 IntField("unused4", 0), 

1069 IP6Field("peer6", "::") 

1070 ] 

1071 

1072 

1073class NTPInfoSysStats(Packet): 

1074 """ 

1075 System stats. These are collected in the protocol module. 

1076 """ 

1077 

1078 name = "info_sys_stats" 

1079 fields_desc = [ 

1080 IntField("timeup", 0), 

1081 IntField("timereset", 0), 

1082 IntField("denied", 0), 

1083 IntField("oldversionpkt", 0), 

1084 IntField("newversionpkt", 0), 

1085 IntField("unknownversion", 0), 

1086 IntField("badlength", 0), 

1087 IntField("processed", 0), 

1088 IntField("badauth", 0), 

1089 IntField("received", 0), 

1090 IntField("limitrejected", 0) 

1091 ] 

1092 

1093 

1094class NTPInfoMemStats(Packet): 

1095 """ 

1096 Peer memory statistics. 

1097 """ 

1098 

1099 name = "info_mem_stats" 

1100 fields_desc = [ 

1101 IntField("timereset", 0), 

1102 ShortField("totalpeermem", 0), 

1103 ShortField("freepeermem", 0), 

1104 IntField("findpeer_calls", 0), 

1105 IntField("allocations", 0), 

1106 IntField("demobilizations", 0), 

1107 FieldListField( 

1108 "hashcount", 

1109 [0.0 for i in range(0, _NTP_HASH_SIZE)], 

1110 ByteField("", 0), 

1111 count_from=lambda p: _NTP_HASH_SIZE, 

1112 max_count=_NTP_HASH_SIZE 

1113 ) 

1114 ] 

1115 

1116 

1117class NTPInfoIOStats(Packet): 

1118 """ 

1119 I/O statistics. 

1120 """ 

1121 

1122 name = "info_io_stats" 

1123 fields_desc = [ 

1124 IntField("timereset", 0), 

1125 ShortField("totalrecvbufs", 0), 

1126 ShortField("freerecvbufs", 0), 

1127 ShortField("fullrecvbufs", 0), 

1128 ShortField("lowwater", 0), 

1129 IntField("dropped", 0), 

1130 IntField("ignored", 0), 

1131 IntField("received", 0), 

1132 IntField("sent", 0), 

1133 IntField("notsent", 0), 

1134 IntField("interrupts", 0), 

1135 IntField("int_received", 0) 

1136 ] 

1137 

1138 

1139class NTPInfoTimerStats(Packet): 

1140 """ 

1141 Timer stats. 

1142 """ 

1143 

1144 name = "info_timer_stats" 

1145 fields_desc = [ 

1146 IntField("timereset", 0), 

1147 IntField("alarms", 0), 

1148 IntField("overflows", 0), 

1149 IntField("xmtcalls", 0), 

1150 ] 

1151 

1152 

1153_conf_peer_flags = [ 

1154 "CONF_FLAG_AUTHENABLE", 

1155 "CONF_FLAG_PREFER", 

1156 "CONF_FLAG_BURST", 

1157 "CONF_FLAG_IBURST", 

1158 "CONF_FLAG_NOSELECT", 

1159 "CONF_FLAG_SKEY" 

1160] 

1161 

1162 

1163class NTPConfPeer(Packet): 

1164 """ 

1165 Structure for passing peer configuration information. 

1166 """ 

1167 

1168 name = "conf_peer" 

1169 fields_desc = [ 

1170 IPField("peeraddr", "0.0.0.0"), 

1171 ByteField("hmode", 0), 

1172 ByteField("version", 0), 

1173 ByteField("minpoll", 0), 

1174 ByteField("maxpoll", 0), 

1175 FlagsField("flags", 0, 8, _conf_peer_flags), 

1176 ByteField("ttl", 0), 

1177 ShortField("unused1", 0), 

1178 IntField("keyid", 0), 

1179 StrFixedLenField("keystr", "", length=128), 

1180 IntField("v6_flag", 0), 

1181 IntField("unused2", 0), 

1182 IP6Field("peeraddr6", "::") 

1183 ] 

1184 

1185 

1186class NTPConfUnpeer(Packet): 

1187 """ 

1188 Structure for passing peer deletion information. 

1189 """ 

1190 

1191 name = "conf_unpeer" 

1192 fields_desc = [ 

1193 IPField("peeraddr", "0.0.0.0"), 

1194 IntField("v6_flag", 0), 

1195 IP6Field("peeraddr6", "::") 

1196 ] 

1197 

1198 

1199_restrict_flags = [ 

1200 "RES_IGNORE", 

1201 "RES_DONTSERVE", 

1202 "RES_DONTTRUST", 

1203 "RES_VERSION", 

1204 "RES_NOPEER", 

1205 "RES_LIMITED", 

1206 "RES_NOQUERY", 

1207 "RES_NOMODIFY", 

1208 "RES_NOTRAP", 

1209 "RES_LPTRAP", 

1210 "RES_KOD", 

1211 "RES_MSSNTP", 

1212 "RES_FLAKE", 

1213 "RES_NOMRULIST", 

1214] 

1215 

1216 

1217class NTPConfRestrict(Packet): 

1218 """ 

1219 Structure used for specifying restrict entries. 

1220 """ 

1221 

1222 name = "conf_restrict" 

1223 fields_desc = [ 

1224 IPField("addr", "0.0.0.0"), 

1225 IPField("mask", "0.0.0.0"), 

1226 FlagsField("flags", 0, 16, _restrict_flags), 

1227 ShortField("m_flags", 0), 

1228 IntField("v6_flag", 0), 

1229 IP6Field("addr6", "::"), 

1230 IP6Field("mask6", "::") 

1231 ] 

1232 

1233 

1234class NTPInfoKernel(Packet): 

1235 """ 

1236 Structure used for returning kernel pll/PPS information 

1237 """ 

1238 

1239 name = "info_kernel" 

1240 fields_desc = [ 

1241 IntField("offset", 0), 

1242 IntField("freq", 0), 

1243 IntField("maxerror", 0), 

1244 IntField("esterror", 0), 

1245 ShortField("status", 0), 

1246 ShortField("shift", 0), 

1247 IntField("constant", 0), 

1248 IntField("precision", 0), 

1249 IntField("tolerance", 0), 

1250 IntField("ppsfreq", 0), 

1251 IntField("jitter", 0), 

1252 IntField("stabil", 0), 

1253 IntField("jitcnt", 0), 

1254 IntField("calcnt", 0), 

1255 IntField("errcnt", 0), 

1256 IntField("stbcnt", 0), 

1257 ] 

1258 

1259 

1260class NTPInfoIfStatsIPv4(Packet): 

1261 """ 

1262 Interface statistics. 

1263 """ 

1264 

1265 name = "info_if_stats" 

1266 fields_desc = [ 

1267 PadField(IPField("unaddr", "0.0.0.0"), 16, padwith=b"\x00"), 

1268 PadField(IPField("unbcast", "0.0.0.0"), 16, padwith=b"\x00"), 

1269 PadField(IPField("unmask", "0.0.0.0"), 16, padwith=b"\x00"), 

1270 IntField("v6_flag", 0), 

1271 StrFixedLenField("ifname", "", length=32), 

1272 IntField("flags", 0), 

1273 IntField("last_ttl", 0), 

1274 IntField("num_mcast", 0), 

1275 IntField("received", 0), 

1276 IntField("sent", 0), 

1277 IntField("notsent", 0), 

1278 IntField("uptime", 0), 

1279 IntField("scopeid", 0), 

1280 IntField("ifindex", 0), 

1281 IntField("ifnum", 0), 

1282 IntField("peercnt", 0), 

1283 ShortField("family", 0), 

1284 ByteField("ignore_packets", 0), 

1285 ByteField("action", 0), 

1286 IntField("_filler0", 0) 

1287 ] 

1288 

1289 

1290class NTPInfoIfStatsIPv6(Packet): 

1291 """ 

1292 Interface statistics. 

1293 """ 

1294 

1295 name = "info_if_stats" 

1296 fields_desc = [ 

1297 IP6Field("unaddr", "::"), 

1298 IP6Field("unbcast", "::"), 

1299 IP6Field("unmask", "::"), 

1300 IntField("v6_flag", 0), 

1301 StrFixedLenField("ifname", "", length=32), 

1302 IntField("flags", 0), 

1303 IntField("last_ttl", 0), 

1304 IntField("num_mcast", 0), 

1305 IntField("received", 0), 

1306 IntField("sent", 0), 

1307 IntField("notsent", 0), 

1308 IntField("uptime", 0), 

1309 IntField("scopeid", 0), 

1310 IntField("ifindex", 0), 

1311 IntField("ifnum", 0), 

1312 IntField("peercnt", 0), 

1313 ShortField("family", 0), 

1314 ByteField("ignore_packets", 0), 

1315 ByteField("action", 0), 

1316 IntField("_filler0", 0) 

1317 ] 

1318 

1319 

1320class NTPInfoMonitor1(Packet): 

1321 """ 

1322 Structure used for returning monitor data. 

1323 """ 

1324 

1325 name = "InfoMonitor1" 

1326 fields_desc = [ 

1327 IntField("lasttime", 0), 

1328 IntField("firsttime", 0), 

1329 IntField("lastdrop", 0), 

1330 IntField("count", 0), 

1331 IPField("addr", "0.0.0.0"), 

1332 IPField("daddr", "0.0.0.0"), 

1333 IntField("flags", 0), 

1334 ShortField("port", 0), 

1335 ByteField("mode", 0), 

1336 ByteField("version", 0), 

1337 IntField("v6_flag", 0), 

1338 IntField("unused1", 0), 

1339 IP6Field("addr6", "::"), 

1340 IP6Field("daddr6", "::") 

1341 ] 

1342 

1343 

1344class NTPInfoAuth(Packet): 

1345 """ 

1346 Structure used to return information concerning the authentication module. 

1347 """ 

1348 

1349 name = "info_auth" 

1350 fields_desc = [ 

1351 IntField("timereset", 0), 

1352 IntField("numkeys", 0), 

1353 IntField("numfreekeys", 0), 

1354 IntField("keylookups", 0), 

1355 IntField("keynotfound", 0), 

1356 IntField("encryptions", 0), 

1357 IntField("decryptions", 0), 

1358 IntField("expired", 0), 

1359 IntField("keyuncached", 0), 

1360 ] 

1361 

1362 

1363class NTPConfTrap(Packet): 

1364 """ 

1365 Structure used to pass add/clear trap information to the client 

1366 """ 

1367 

1368 name = "conf_trap" 

1369 fields_desc = [ 

1370 IPField("local_address", "0.0.0.0"), 

1371 IPField("trap_address", "0.0.0.0"), 

1372 ShortField("trap_port", 0), 

1373 ShortField("unused", 0), 

1374 IntField("v6_flag", 0), 

1375 IP6Field("local_address6", "::"), 

1376 IP6Field("trap_address6", "::"), 

1377 ] 

1378 

1379 

1380class NTPInfoControl(Packet): 

1381 """ 

1382 Structure used to return statistics from the control module. 

1383 """ 

1384 

1385 name = "info_control" 

1386 fields_desc = [ 

1387 IntField("ctltimereset", 0), 

1388 IntField("numctlreq", 0), 

1389 IntField("numctlbadpkts", 0), 

1390 IntField("numctlresponses", 0), 

1391 IntField("numctlfrags", 0), 

1392 IntField("numctlerrors", 0), 

1393 IntField("numctltooshort", 0), 

1394 IntField("numctlinputresp", 0), 

1395 IntField("numctlinputfrag", 0), 

1396 IntField("numctlinputerr", 0), 

1397 IntField("numctlbadoffset", 0), 

1398 IntField("numctlbadversion", 0), 

1399 IntField("numctldatatooshort", 0), 

1400 IntField("numctlbadop", 0), 

1401 IntField("numasyncmsgs", 0), 

1402 ] 

1403 

1404 

1405# ntp_request.h 

1406_ntpd_private_errors = { 

1407 0: "no error", 

1408 1: "incompatible implementation number", 

1409 2: "unimplemented request code", 

1410 3: "format error (wrong data items, data size, packet size etc.)", 

1411 4: "no data available (e.g. request for details on unknown peer)", 

1412 5: "I don\"t know", 

1413 6: "I don\"t know", 

1414 7: "authentication failure (i.e. permission denied)", 

1415} 

1416 

1417 

1418# dict mapping request codes to the right response data class 

1419_private_data_objects = { 

1420 0: NTPInfoPeerList, # "REQ_PEER_LIST", 

1421 1: NTPInfoPeerSummary, # "REQ_PEER_LIST_SUM", 

1422 2: NTPInfoPeer, # "REQ_PEER_INFO", 

1423 3: NTPInfoPeerStats, # "REQ_PEER_STATS", 

1424 4: NTPInfoSys, # "REQ_SYS_INFO", 

1425 5: NTPInfoSysStats, # "REQ_SYS_STATS", 

1426 6: NTPInfoIOStats, # "REQ_IO_STATS", 

1427 7: NTPInfoMemStats, # "REQ_MEM_STATS", 

1428 8: NTPInfoLoop, # "REQ_LOOP_INFO", 

1429 9: NTPInfoTimerStats, # "REQ_TIMER_STATS", 

1430 10: NTPConfPeer, # "REQ_CONFIG", 

1431 11: NTPConfUnpeer, # "REQ_UNCONFIG", 

1432 28: NTPInfoAuth, # "REQ_AUTHINFO", 

1433 30: NTPConfTrap, # "REQ_ADD_TRAP", 

1434 34: NTPInfoControl, # "REQ_GET_CTLSTATS", 

1435 38: NTPInfoKernel, # "REQ_GET_KERNEL", 

1436 42: NTPInfoMonitor1, # "REQ_MON_GETLIST_1", 

1437} 

1438 

1439 

1440class NTPPrivateRespPacketListField(PacketListField): 

1441 """ 

1442 PacketListField handling the response data. 

1443 """ 

1444 

1445 def m2i(self, pkt, s): 

1446 ret = None 

1447 

1448 # info_if_stats 

1449 if pkt.request_code == 44 or pkt.request_code == 45: 

1450 is_v6 = struct.unpack("!I", s[48:52])[0] 

1451 ret = NTPInfoIfStatsIPv6(s) if is_v6 else NTPInfoIfStatsIPv4(s) 

1452 else: 

1453 ret = _private_data_objects.get(pkt.request_code, conf.raw_layer)(s) # noqa: E501 

1454 

1455 return ret 

1456 

1457 def getfield(self, pkt, s): 

1458 lst = [] 

1459 remain = s 

1460 length = pkt.data_item_size 

1461 if length > 0: 

1462 item_counter = 0 

1463 # Response payloads can be placed in several packets 

1464 while len(remain) >= pkt.data_item_size and item_counter < pkt.nb_items: # noqa: E501 

1465 current = remain[:length] 

1466 remain = remain[length:] 

1467 current_packet = self.m2i(pkt, current) 

1468 lst.append(current_packet) 

1469 item_counter += 1 

1470 

1471 return remain, lst 

1472 

1473 

1474class NTPPrivateReqPacket(Packet): 

1475 """ 

1476 Packet handling request data. 

1477 """ 

1478 

1479 name = "request data" 

1480 fields_desc = [StrField("req_data", "")] 

1481 

1482 

1483_request_codes = { 

1484 0: "REQ_PEER_LIST", 

1485 1: "REQ_PEER_LIST_SUM", 

1486 2: "REQ_PEER_INFO", 

1487 3: "REQ_PEER_STATS", 

1488 4: "REQ_SYS_INFO", 

1489 5: "REQ_SYS_STATS", 

1490 6: "REQ_IO_STATS", 

1491 7: "REQ_MEM_STATS", 

1492 8: "REQ_LOOP_INFO", 

1493 9: "REQ_TIMER_STATS", 

1494 10: "REQ_CONFIG", 

1495 11: "REQ_UNCONFIG", 

1496 12: "REQ_SET_SYS_FLAG", 

1497 13: "REQ_CLR_SYS_FLAG", 

1498 14: "REQ_MONITOR", 

1499 15: "REQ_NOMONITOR", 

1500 16: "REQ_GET_RESTRICT", 

1501 17: "REQ_RESADDFLAGS", 

1502 18: "REQ_RESSUBFLAGS", 

1503 19: "REQ_UNRESTRICT", 

1504 20: "REQ_MON_GETLIST", 

1505 21: "REQ_RESET_STATS", 

1506 22: "REQ_RESET_PEER", 

1507 23: "REQ_REREAD_KEYS", 

1508 24: "REQ_DO_DIRTY_HACK", 

1509 25: "REQ_DONT_DIRTY_HACK", 

1510 26: "REQ_TRUSTKEY", 

1511 27: "REQ_UNTRUSTKEY", 

1512 28: "REQ_AUTHINFO", 

1513 29: "REQ_TRAPS", 

1514 30: "REQ_ADD_TRAP", 

1515 31: "REQ_CLR_TRAP", 

1516 32: "REQ_REQUEST_KEY", 

1517 33: "REQ_CONTROL_KEY", 

1518 34: "REQ_GET_CTLSTATS", 

1519 35: "REQ_GET_LEAPINFO", 

1520 36: "REQ_GET_CLOCKINFO", 

1521 37: "REQ_SET_CLKFUDGE", 

1522 38: "REQ_GET_KERNEL", 

1523 39: "REQ_GET_CLKBUGINFO", 

1524 41: "REQ_SET_PRECISION", 

1525 42: "REQ_MON_GETLIST_1", 

1526 43: "REQ_HOSTNAME_ASSOCID", 

1527 44: "REQ_IF_STATS", 

1528 45: "REQ_IF_RELOAD" 

1529} 

1530 

1531 

1532class NTPPrivateReqPacketListField(PacketListField): 

1533 """ 

1534 Handles specific request packets. 

1535 """ 

1536 

1537 # See ntpdc/ntpdc.c and ntpdc/ntpdc_ops.c 

1538 

1539 def m2i(self, pkt, s): 

1540 ret = None 

1541 

1542 if pkt.request_code == 2 or pkt.request_code == 3: 

1543 # REQ_PEER_INFO (see ntpdc/ntpdc_ops.c: showpeer()) 

1544 # REQ_PEER_STATS (for request only) 

1545 ret = NTPInfoPeerList(s) 

1546 

1547 elif pkt.request_code == 10: 

1548 # REQ_CONFIG 

1549 ret = NTPConfPeer(s) 

1550 

1551 elif pkt.request_code == 11: 

1552 # REQ_CONFIG 

1553 ret = NTPConfUnpeer(s) 

1554 

1555 elif pkt.request_code == 17: 

1556 # REQ_RESADDFLAGS 

1557 ret = NTPConfRestrict(s) 

1558 

1559 elif pkt.request_code == 18: 

1560 # REQ_RESSUBFLAGS 

1561 ret = NTPConfRestrict(s) 

1562 

1563 elif pkt.request_code == 22: 

1564 # REQ_RESET_PEER 

1565 ret = NTPConfUnpeer(s) 

1566 

1567 elif pkt.request_code == 30 or pkt.request_code == 31: 

1568 # REQ_ADD_TRAP 

1569 ret = NTPConfTrap(s) 

1570 

1571 else: 

1572 ret = NTPPrivateReqPacket(s) 

1573 

1574 return ret 

1575 

1576 def getfield(self, pkt, s): 

1577 lst = [] 

1578 remain = s 

1579 length = pkt.data_item_size 

1580 if length > 0: 

1581 item_counter = 0 

1582 while len(remain) >= pkt.data_item_size * pkt.nb_items and item_counter < pkt.nb_items: # noqa: E501 

1583 current = remain[:length] 

1584 remain = remain[length:] 

1585 current_packet = self.m2i(pkt, current) 

1586 lst.append(current_packet) 

1587 item_counter += 1 

1588 

1589 # If "auth" bit is set, don't forget the padding bytes 

1590 if pkt.auth: 

1591 padding_end = len(remain) - _NTP_PRIVATE_REQ_PKT_TAIL_LEN 

1592 current_packet = conf.raw_layer(remain[:padding_end]) 

1593 lst.append(current_packet) 

1594 remain = remain[padding_end:] 

1595 

1596 return remain, lst 

1597 

1598 

1599class NTPPrivatePktTail(Packet): 

1600 """ 

1601 include/ntp_request.h 

1602 The req_pkt_tail structure is used by ntpd to adjust for different 

1603 packet sizes that may arrive. 

1604 """ 

1605 

1606 name = "req_pkt_tail" 

1607 fields_desc = [ 

1608 TimeStampField("tstamp", 0), 

1609 IntField("key_id", 0), 

1610 XStrFixedLenField( 

1611 "dgst", "", length_from=lambda x: _NTP_AUTH_MD5_DGST_SIZE) 

1612 ] 

1613 

1614 

1615class NTPPrivate(NTP): 

1616 """ 

1617 Packet handling the private (mode 7) messages. 

1618 """ 

1619 

1620 ######################################################################### 

1621 # ntpd source code: ntp_request.h 

1622 ######################################################################### 

1623 # 

1624 # A mode 7 packet is used exchanging data between an NTP server 

1625 # and a client for purposes other than time synchronization, e.g. 

1626 # monitoring, statistics gathering and configuration. A mode 7 

1627 # packet has the following format: 

1628 # 

1629 # 0 1 2 3 

1630 # 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 

1631 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

1632 # |R|M| VN | Mode|A| Sequence | Implementation| Req Code | 

1633 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

1634 # | Err | Number of data items | MBZ | Size of data item | 

1635 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

1636 # | | 

1637 # | Data (Minimum 0 octets, maximum 500 octets) | 

1638 # | | 

1639 # [...] | 

1640 # | | 

1641 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

1642 # | Encryption Keyid (when A bit set) | 

1643 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

1644 # | | 

1645 # | Message Authentication Code (when A bit set) | 

1646 # | | 

1647 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

1648 # 

1649 # where the fields are (note that the client sends requests, the server 

1650 # responses): 

1651 # 

1652 # Response Bit: This packet is a response (if clear, packet is a request). 

1653 # 

1654 # More Bit: Set for all packets but the last in a response which 

1655 # requires more than one packet. 

1656 # 

1657 # Version Number: 2 for current version 

1658 # 

1659 # Mode: Always 7 

1660 # 

1661 # Authenticated bit: If set, this packet is authenticated. 

1662 # 

1663 # Sequence number: For a multipacket response, contains the sequence 

1664 # number of this packet. 0 is the first in the sequence, 

1665 # 127 (or less) is the last. The More Bit must be set in 

1666 # all packets but the last. 

1667 # 

1668 # Implementation number: The number of the implementation this request code 

1669 # is defined by. An implementation number of zero is used 

1670 # for request codes/data formats which all implementations 

1671 # agree on. Implementation number 255 is reserved (for 

1672 # extensions, in case we run out). 

1673 # 

1674 # Request code: An implementation-specific code which specifies the 

1675 # operation to be (which has been) performed and/or the 

1676 # format and semantics of the data included in the packet. 

1677 # 

1678 # Err: Must be 0 for a request. For a response, holds an error 

1679 # code relating to the request. If nonzero, the operation 

1680 # requested wasn't performed. 

1681 # 

1682 # 0 - no error 

1683 # 1 - incompatible implementation number 

1684 # 2 - unimplemented request code 

1685 # 3 - format error (wrong data items, data size, packet size etc.) # noqa: E501 

1686 # 4 - no data available (e.g. request for details on unknown peer) # noqa: E501 

1687 # 5-6 I don"t know 

1688 # 7 - authentication failure (i.e. permission denied) 

1689 # 

1690 # Number of data items: number of data items in packet. 0 to 500 

1691 # 

1692 # MBZ: A reserved data field, must be zero in requests and responses. 

1693 # 

1694 # Size of data item: size of each data item in packet. 0 to 500 

1695 # 

1696 # Data: Variable sized area containing request/response data. For 

1697 # requests and responses the size in octets must be greater 

1698 # than or equal to the product of the number of data items 

1699 # and the size of a data item. For requests the data area 

1700 # must be exactly 40 octets in length. For responses the 

1701 # data area may be any length between 0 and 500 octets 

1702 # inclusive. 

1703 # 

1704 # Message Authentication Code: Same as NTP spec, in definition and function. # noqa: E501 

1705 # May optionally be included in requests which require 

1706 # authentication, is never included in responses. 

1707 # 

1708 # The version number, mode and keyid have the same function and are 

1709 # in the same location as a standard NTP packet. The request packet 

1710 # is the same size as a standard NTP packet to ease receive buffer 

1711 # management, and to allow the same encryption procedure to be used 

1712 # both on mode 7 and standard NTP packets. The mac is included when 

1713 # it is required that a request be authenticated, the keyid should be 

1714 # zero in requests in which the mac is not included. 

1715 # 

1716 # The data format depends on the implementation number/request code pair 

1717 # and whether the packet is a request or a response. The only requirement 

1718 # is that data items start in the octet immediately following the size 

1719 # word and that data items be concatenated without padding between (i.e. 

1720 # if the data area is larger than data_items*size, all padding is at 

1721 # the end). Padding is ignored, other than for encryption purposes. 

1722 # Implementations using encryption might want to include a time stamp 

1723 # or other data in the request packet padding. The key used for requests 

1724 # is implementation defined, but key 15 is suggested as a default. 

1725 ######################################################################### 

1726 # 

1727 

1728 name = "Private (mode 7)" 

1729 match_subclass = True 

1730 fields_desc = [ 

1731 BitField("response", 0, 1), 

1732 BitField("more", 0, 1), 

1733 BitField("version", 2, 3), 

1734 BitEnumField("mode", 7, 3, _ntp_modes), 

1735 BitField("auth", 0, 1), 

1736 BitField("seq", 0, 7), 

1737 ByteEnumField("implementation", 0, _implementations), 

1738 ByteEnumField("request_code", 0, _request_codes), 

1739 BitEnumField("err", 0, 4, _ntpd_private_errors), 

1740 BitField("nb_items", 0, 12), 

1741 BitField("mbz", 0, 4), 

1742 BitField("data_item_size", 0, 12), 

1743 ConditionalField( 

1744 NTPPrivateReqPacketListField( 

1745 "req_data", 

1746 [], 

1747 Packet, 

1748 length_from=lambda p: p.data_item_size, 

1749 count_from=lambda p: p.nb_items 

1750 ), 

1751 lambda p: p.response == 0 

1752 ), 

1753 # Responses 

1754 ConditionalField( 

1755 NTPPrivateRespPacketListField( 

1756 "data", 

1757 [], 

1758 Packet, 

1759 length_from=lambda p: p.data_item_size, 

1760 count_from=lambda p: p.nb_items 

1761 ), 

1762 lambda p: p.response == 1 

1763 ), 

1764 # Responses are not supposed to be authenticated 

1765 ConditionalField(PacketField("authenticator", "", NTPPrivatePktTail), 

1766 lambda p: p.response == 0 and p.auth == 1), 

1767 ] 

1768 

1769 

1770############################################################################## 

1771# Layer bindings 

1772############################################################################## 

1773 

1774bind_layers(UDP, NTP, {"sport": 123}) 

1775bind_layers(UDP, NTP, {"dport": 123}) 

1776bind_layers(UDP, NTP, {"sport": 123, "dport": 123})