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

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

369 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 FieldListField, 

23 FixedPointField, 

24 FlagsField, 

25 IP6Field, 

26 IPField, 

27 IntField, 

28 LEIntField, 

29 LEShortField, 

30 MayEnd, 

31 PacketField, 

32 PacketLenField, 

33 PacketListField, 

34 PadField, 

35 ShortField, 

36 SignedByteField, 

37 StrField, 

38 StrFixedLenEnumField, 

39 StrFixedLenField, 

40 XByteField, 

41 XStrFixedLenField, 

42) 

43from scapy.layers.inet import UDP 

44from scapy.utils import lhex 

45from scapy.compat import orb 

46from scapy.config import conf 

47 

48 

49############################################################################# 

50# Constants 

51############################################################################# 

52 

53_NTP_AUTH_MD5_MIN_SIZE = 68 

54_NTP_EXT_MIN_SIZE = 16 

55_NTP_HDR_WITH_EXT_MIN_SIZE = _NTP_AUTH_MD5_MIN_SIZE + _NTP_EXT_MIN_SIZE 

56_NTP_AUTH_MD5_TAIL_SIZE = 20 

57_NTP_AUTH_MD5_DGST_SIZE = 16 

58_NTP_PRIVATE_PACKET_MIN_SIZE = 8 

59 

60# ntpd "Private" messages are the shortest 

61_NTP_PACKET_MIN_SIZE = _NTP_PRIVATE_PACKET_MIN_SIZE 

62 

63_NTP_PRIVATE_REQ_PKT_TAIL_LEN = 28 

64 

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

66_NTP_BASETIME = 2208988800 

67 

68# include/ntp.h 

69_NTP_SHIFT = 8 

70_NTP_HASH_SIZE = 128 

71 

72 

73############################################################################# 

74# Fields and utilities 

75############################################################################# 

76 

77class XLEShortField(LEShortField): 

78 """ 

79 XShortField which value is encoded in little endian. 

80 """ 

81 

82 def i2repr(self, pkt, x): 

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

84 

85 

86class TimeStampField(FixedPointField): 

87 """ 

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

89 """ 

90 

91 def __init__(self, name, default): 

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

93 

94 def i2repr(self, pkt, val): 

95 if val is None: 

96 return "--" 

97 val = self.i2h(pkt, val) 

98 if val < _NTP_BASETIME: 

99 return str(val) 

100 return time.strftime( 

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

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

103 ) 

104 

105 def any2i(self, pkt, val): 

106 if isinstance(val, str): 

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

108 elif isinstance(val, datetime.datetime): 

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

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

111 

112 def i2m(self, pkt, val): 

113 if val is None: 

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

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

116 

117 

118############################################################################# 

119# NTP 

120############################################################################# 

121 

122# RFC 5905 / Section 7.3 

123_leap_indicator = { 

124 0: "no warning", 

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

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

127 3: "unknown (clock unsynchronized)" 

128} 

129 

130 

131# RFC 5905 / Section 7.3 

132_ntp_modes = { 

133 0: "reserved", 

134 1: "symmetric active", 

135 2: "symmetric passive", 

136 3: "client", 

137 4: "server", 

138 5: "broadcast", 

139 6: "NTP control message", 

140 7: "reserved for private use" 

141} 

142 

143 

144# RFC 5905 / Section 7.3 

145_reference_identifiers = { 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

161 b"NIST": "NIST telephone modem", 

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

163 b"USNO": "USNO telephone modem", 

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

165} 

166 

167 

168# RFC 5905 / Section 7.4 

169_kiss_codes = { 

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

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

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

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

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

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

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

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

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

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

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

181 "RATE": "Rate exceeded.", 

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

183} 

184 

185 

186# Used by _ntp_dispatcher to instantiate the appropriate class 

187def _ntp_dispatcher(payload): 

188 """ 

189 Returns the right class for a given NTP packet. 

190 """ 

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

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

193 if payload is None: 

194 return NTPHeader 

195 else: 

196 length = len(payload) 

197 if length >= _NTP_PACKET_MIN_SIZE: 

198 first_byte = orb(payload[0]) 

199 # Extract NTP mode 

200 mode = first_byte & 7 

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

202 return conf.raw_layer 

203 

204 

205class NTP(Packet): 

206 """ 

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

208 data. 

209 """ 

210 

211 @classmethod 

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

213 """ 

214 Returns the right class for the given data. 

215 """ 

216 

217 return _ntp_dispatcher(_pkt) 

218 

219 def pre_dissect(self, s): 

220 """ 

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

222 """ 

223 length = len(s) 

224 if length < _NTP_PACKET_MIN_SIZE: 

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

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

227 raise _NTPInvalidDataException(err) 

228 return s 

229 

230 def mysummary(self): 

231 return self.sprintf( 

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

233 ) 

234 

235 

236class _NTPAuthenticatorPaddingField(StrField): 

237 """ 

238 StrField handling the padding that may be found before the 

239 "authenticator" field. 

240 """ 

241 

242 def getfield(self, pkt, s): 

243 ret = None 

244 remain = s 

245 length = len(s) 

246 

247 if length > _NTP_AUTH_MD5_TAIL_SIZE: 

248 start = length - _NTP_AUTH_MD5_TAIL_SIZE 

249 ret = s[:start] 

250 remain = s[start:] 

251 return remain, ret 

252 

253 

254class NTPAuthenticator(Packet): 

255 """ 

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

257 defined in RFC 5905. 

258 """ 

259 

260 name = "Authenticator" 

261 fields_desc = [ 

262 _NTPAuthenticatorPaddingField("padding", ""), 

263 IntField("key_id", 0), 

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

265 ] 

266 

267 def extract_padding(self, s): 

268 return b"", s 

269 

270 

271class NTPExtension(Packet): 

272 """ 

273 Packet handling a NTPv4 extension. 

274 """ 

275 

276 ######################################################################### 

277 # 

278 # RFC 7822 

279 ######################################################################### 

280 # 

281 # 7.5. NTP Extension Field Format 

282 # 

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

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

285 # 

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

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

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

289 # 

290 # 0 1 2 3 

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

292 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

293 # | Field Type | Length | 

294 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

295 # . . 

296 # . Value . 

297 # . . 

298 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

299 # | Padding (as needed) | 

300 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

301 # 

302 # Figure 14: Extension Field Format 

303 # 

304 # 

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

306 # boundary. 

307 ######################################################################### 

308 # 

309 

310 name = "extension" 

311 fields_desc = [ 

312 ShortField("type", 0), 

313 ShortField("len", 0), 

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

315 ] 

316 

317 

318class NTPExtPacketListField(PacketListField): 

319 

320 """ 

321 PacketListField handling NTPv4 extensions (NTPExtension list). 

322 """ 

323 

324 def m2i(self, pkt, m): 

325 ret = None 

326 if len(m) >= 16: 

327 ret = NTPExtension(m) 

328 else: 

329 ret = conf.raw_layer(m) 

330 return ret 

331 

332 def getfield(self, pkt, s): 

333 lst = [] 

334 remain = s 

335 length = len(s) 

336 if length > _NTP_AUTH_MD5_TAIL_SIZE: 

337 end = length - _NTP_AUTH_MD5_TAIL_SIZE 

338 extensions = s[:end] 

339 remain = s[end:] 

340 

341 extensions_len = len(extensions) 

342 while extensions_len >= 16: 

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

344 ext_len = min(ext_len, extensions_len) 

345 if ext_len < 1: 

346 ext_len = extensions_len 

347 current = extensions[:ext_len] 

348 extensions = extensions[ext_len:] 

349 current_packet = self.m2i(pkt, current) 

350 lst.append(current_packet) 

351 extensions_len = len(extensions) 

352 

353 if extensions_len > 0: 

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

355 

356 return remain, lst 

357 

358 

359class NTPExtensions(Packet): 

360 """ 

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

362 """ 

363 

364 ######################################################################### 

365 # 

366 # RFC 5905 / RFC 7822 

367 ######################################################################### 

368 # 

369 # 7.5. NTP Extension Field Format 

370 # 

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

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

373 ######################################################################### 

374 # 

375 

376 name = "NTPv4 extensions" 

377 fields_desc = [ 

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

379 PacketField("mac", NTPAuthenticator(), NTPAuthenticator) 

380 ] 

381 

382 

383class NTPHeader(NTP): 

384 

385 """ 

386 Packet handling the RFC 5905 NTP packet. 

387 """ 

388 

389 ######################################################################### 

390 # 

391 # RFC 5905 

392 ######################################################################### 

393 # 

394 # 0 1 2 3 

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

396 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

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

398 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

399 # | Root Delay | 

400 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

401 # | Root Dispersion | 

402 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

403 # | Reference ID | 

404 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

405 # | | 

406 # + Reference Timestamp (64) + 

407 # | | 

408 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

409 # | | 

410 # + Origin Timestamp (64) + 

411 # | | 

412 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

413 # | | 

414 # + Receive Timestamp (64) + 

415 # | | 

416 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

417 # | | 

418 # + Transmit Timestamp (64) + 

419 # | | 

420 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

421 # | | 

422 # . . 

423 # . Extension Field 1 (variable) . 

424 # . . 

425 # | | 

426 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

427 # | | 

428 # . . 

429 # . Extension Field 2 (variable) . 

430 # . . 

431 # | | 

432 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

433 # | Key Identifier | 

434 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

435 # | | 

436 # | dgst (128) | 

437 # | | 

438 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

439 # 

440 # Figure 8: Packet Header Format 

441 ######################################################################### 

442 # 

443 

444 name = "NTPHeader" 

445 match_subclass = True 

446 fields_desc = [ 

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

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

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

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

451 SignedByteField("poll", 0xa), 

452 SignedByteField("precision", 0), 

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

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

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

456 ConditionalField( 

457 StrFixedLenEnumField( 

458 "ref_id", 

459 "", 

460 length=4, 

461 enum=_reference_identifiers 

462 ), 

463 lambda p: p.stratum < 2 

464 ), 

465 TimeStampField("ref", 0), 

466 TimeStampField("orig", None), 

467 TimeStampField("recv", 0), 

468 TimeStampField("sent", None), 

469 ] 

470 

471 def guess_payload_class(self, payload): 

472 """ 

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

474 """ 

475 plen = len(payload) 

476 

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

478 return NTPAuthenticator 

479 elif plen > _NTP_AUTH_MD5_TAIL_SIZE: 

480 return NTPExtensions 

481 

482 return Packet.guess_payload_class(self, payload) 

483 

484 

485class _NTPInvalidDataException(Exception): 

486 """ 

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

488 given data. 

489 """ 

490 

491 def __init__(self, details): 

492 Exception.__init__( 

493 self, 

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

495 ) 

496 

497 

498############################################################################## 

499# Private (mode 7) 

500############################################################################## 

501 

502# Operation codes 

503_op_codes = { 

504 0: "CTL_OP_UNSPEC", 

505 1: "CTL_OP_READSTAT", 

506 2: "CTL_OP_READVAR", 

507 3: "CTL_OP_WRITEVAR", 

508 4: "CTL_OP_READCLOCK", 

509 5: "CTL_OP_WRITECLOCK", 

510 6: "CTL_OP_SETTRAP", 

511 7: "CTL_OP_ASYNCMSG", 

512 8: "CTL_OP_CONFIGURE", 

513 9: "CTL_OP_SAVECONFIG", 

514 10: "CTL_OP_READ_MRU", 

515 11: "CTL_OP_READ_ORDLIST_A", 

516 12: "CTL_OP_REQ_NONCE", 

517 31: "CTL_OP_UNSETTRAP" 

518} 

519 

520 

521# System status words 

522_system_statuses = { 

523 0: "no warning", 

524 1: "last minute was 61 seconds", 

525 2: "last minute was 59 seconds", 

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

527} 

528 

529 

530_clock_sources = { 

531 0: "unspecified or unknown", 

532 1: " Calibrated atomic clock", 

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

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

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

536 5: "local net", 

537 6: "UDP/NTP", 

538 7: "UDP/TIME", 

539 8: "eyeball-and-wristwatch", 

540 9: "telephone modem" 

541} 

542 

543 

544_system_event_codes = { 

545 0: "unspecified", 

546 1: "system restart", 

547 2: "system or hardware fault", 

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

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

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

551 6: "system invalid time or date", 

552 7: "system clock exception", 

553} 

554 

555 

556# Peer status words 

557_peer_statuses = { 

558 0: "configured", 

559 1: "authentication enabled", 

560 2: "authentication okay", 

561 3: "reachability okay", 

562 4: "reserved" 

563} 

564 

565 

566_peer_selection = { 

567 0: "rejected", 

568 1: "passed sanity checks", 

569 2: "passed correctness checks", 

570 3: "passed candidate checks", 

571 4: "passed outlyer checks", 

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

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

574 7: "reserved" 

575} 

576 

577 

578_peer_event_codes = { 

579 0: "unspecified", 

580 1: "peer IP error", 

581 2: "peer authentication failure", 

582 3: "peer unreachable", 

583 4: "peer reachable", 

584 5: "peer clock exception", 

585} 

586 

587 

588# Clock status words 

589_clock_statuses = { 

590 0: "clock operating within nominals", 

591 1: "reply timeout", 

592 2: "bad reply format", 

593 3: "hardware or software fault", 

594 4: "propagation failure", 

595 5: "bad date format or value", 

596 6: "bad time format or value" 

597} 

598 

599 

600# Error status words 

601_error_statuses = { 

602 0: "unspecified", 

603 1: "authentication failure", 

604 2: "invalid message length or format", 

605 3: "invalid opcode", 

606 4: "unknown association identifier", 

607 5: "unknown variable name", 

608 6: "invalid variable value", 

609 7: "administratively prohibited" 

610} 

611 

612 

613class NTPStatusPacket(Packet): 

614 """ 

615 Packet handling a non specific status word. 

616 """ 

617 

618 name = "status" 

619 fields_desc = [ShortField("status", 0)] 

620 

621 def extract_padding(self, s): 

622 return b"", s 

623 

624 

625class NTPSystemStatusPacket(Packet): 

626 

627 """ 

628 Packet handling the system status fields. 

629 """ 

630 

631 name = "system status" 

632 fields_desc = [ 

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

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

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

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

637 ] 

638 

639 def extract_padding(self, s): 

640 return b"", s 

641 

642 

643class NTPPeerStatusPacket(Packet): 

644 """ 

645 Packet handling the peer status fields. 

646 """ 

647 

648 name = "peer status" 

649 fields_desc = [ 

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

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

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

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

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

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

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

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

658 ] 

659 

660 def extract_padding(self, s): 

661 return b"", s 

662 

663 

664class NTPClockStatusPacket(Packet): 

665 """ 

666 Packet handling the clock status fields. 

667 """ 

668 

669 name = "clock status" 

670 fields_desc = [ 

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

672 BitField("code", 0, 8) 

673 ] 

674 

675 def extract_padding(self, s): 

676 return b"", s 

677 

678 

679class NTPErrorStatusPacket(Packet): 

680 """ 

681 Packet handling the error status fields. 

682 """ 

683 

684 name = "error status" 

685 fields_desc = [ 

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

687 BitField("reserved", 0, 8) 

688 ] 

689 

690 def extract_padding(self, s): 

691 return b"", s 

692 

693 

694class NTPControlStatusField(PacketField): 

695 """ 

696 This field provides better readability for the "status" field. 

697 """ 

698 

699 ######################################################################### 

700 # 

701 # RFC 1305 

702 ######################################################################### 

703 # 

704 # Appendix B.3. Commands // ntpd source code: ntp_control.h 

705 ######################################################################### 

706 # 

707 

708 def m2i(self, pkt, m): 

709 ret = None 

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

711 

712 if pkt.err == 1: 

713 ret = NTPErrorStatusPacket(m) 

714 

715 # op_code == CTL_OP_READSTAT 

716 elif pkt.op_code == 1: 

717 if association_id != 0: 

718 ret = NTPPeerStatusPacket(m) 

719 else: 

720 ret = NTPSystemStatusPacket(m) 

721 

722 # op_code == CTL_OP_READVAR 

723 elif pkt.op_code == 2: 

724 if association_id != 0: 

725 ret = NTPPeerStatusPacket(m) 

726 else: 

727 ret = NTPSystemStatusPacket(m) 

728 

729 # op_code == CTL_OP_WRITEVAR 

730 elif pkt.op_code == 3: 

731 ret = NTPStatusPacket(m) 

732 

733 # op_code == CTL_OP_READCLOCK or op_code == CTL_OP_WRITECLOCK 

734 elif pkt.op_code == 4 or pkt.op_code == 5: 

735 ret = NTPClockStatusPacket(m) 

736 

737 else: 

738 ret = NTPStatusPacket(m) 

739 

740 return ret 

741 

742 

743class NTPPeerStatusDataPacket(Packet): 

744 """ 

745 Packet handling the data field when op_code is CTL_OP_READSTAT 

746 and the association_id field is null. 

747 """ 

748 

749 name = "data / peer status" 

750 fields_desc = [ 

751 ShortField("association_id", 0), 

752 PacketField("peer_status", NTPPeerStatusPacket(), NTPPeerStatusPacket), 

753 ] 

754 

755 

756class NTPControlDataPacketLenField(PacketLenField): 

757 

758 """ 

759 PacketField handling the "data" field of NTP control messages. 

760 """ 

761 

762 def m2i(self, pkt, m): 

763 ret = None 

764 if not m: 

765 return ret 

766 

767 # op_code == CTL_OP_READSTAT 

768 if pkt.op_code == 1: 

769 if pkt.association_id == 0: 

770 # Data contains association ID and peer status 

771 ret = NTPPeerStatusDataPacket(m) 

772 else: 

773 ret = conf.raw_layer(m) 

774 else: 

775 ret = conf.raw_layer(m) 

776 

777 return ret 

778 

779 def getfield(self, pkt, s): 

780 length = self.length_from(pkt) 

781 i = None 

782 if length > 0: 

783 # RFC 1305 

784 # The maximum number of data octets is 468. 

785 # 

786 # include/ntp_control.h 

787 # u_char data[480 + MAX_MAC_LEN]; /* data + auth */ 

788 # 

789 # Set the minimum length to 480 - 468 

790 length = max(12, length) 

791 if length % 4: 

792 length += (4 - length % 4) 

793 try: 

794 i = self.m2i(pkt, s[:length]) 

795 except Exception: 

796 if conf.debug_dissector: 

797 raise 

798 i = conf.raw_layer(load=s[:length]) 

799 return s[length:], i 

800 

801 

802class NTPControl(NTP): 

803 """ 

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

805 """ 

806 

807 ######################################################################### 

808 # 

809 # RFC 1305 

810 ######################################################################### 

811 # 

812 # Appendix B.3. Commands // ntpd source code: ntp_control.h 

813 ######################################################################### 

814 # 

815 

816 name = "Control message" 

817 match_subclass = True 

818 fields_desc = [ 

819 BitField("zeros", 0, 2), 

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

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

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

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

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

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

826 ShortField("sequence", 0), 

827 ConditionalField(NTPControlStatusField( 

828 "status_word", "", Packet), lambda p: p.response == 1), 

829 ConditionalField(ShortField("status", 0), lambda p: p.response == 0), 

830 ShortField("association_id", 0), 

831 ShortField("offset", 0), 

832 ShortField("count", None), 

833 MayEnd(NTPControlDataPacketLenField( 

834 "data", "", Packet, length_from=lambda p: p.count)), 

835 PacketField("authenticator", "", NTPAuthenticator), 

836 ] 

837 

838 def post_build(self, p, pay): 

839 if self.count is None: 

840 length = 0 

841 if self.data: 

842 length = len(self.data) 

843 p = p[:11] + struct.pack("!H", length) + p[13:] 

844 return p + pay 

845 

846 

847############################################################################## 

848# Private (mode 7) 

849############################################################################## 

850 

851_information_error_codes = { 

852 0: "INFO_OKAY", 

853 1: "INFO_ERR_IMPL", 

854 2: "INFO_ERR_REQ", 

855 3: "INFO_ERR_FMT", 

856 4: "INFO_ERR_NODATA", 

857 7: "INFO_ERR_AUTH" 

858} 

859 

860 

861_implementations = { 

862 0: "IMPL_UNIV", 

863 2: "IMPL_XNTPD_OLD", 

864 3: "XNTPD" 

865} 

866 

867 

868_request_codes = { 

869 0: "REQ_PEER_LIST", 

870 1: "REQ_PEER_LIST_SUM", 

871 2: "REQ_PEER_INFO", 

872 3: "REQ_PEER_STATS", 

873 4: "REQ_SYS_INFO", 

874 5: "REQ_SYS_STATS", 

875 6: "REQ_IO_STATS", 

876 7: "REQ_MEM_STATS", 

877 8: "REQ_LOOP_INFO", 

878 9: "REQ_TIMER_STATS", 

879 10: "REQ_CONFIG", 

880 11: "REQ_UNCONFIG", 

881 12: "REQ_SET_SYS_FLAG", 

882 13: "REQ_CLR_SYS_FLAG", 

883 14: "REQ_MONITOR", 

884 15: "REQ_NOMONITOR", 

885 16: "REQ_GET_RESTRICT", 

886 17: "REQ_RESADDFLAGS", 

887 18: "REQ_RESSUBFLAGS", 

888 19: "REQ_UNRESTRICT", 

889 20: "REQ_MON_GETLIST", 

890 21: "REQ_RESET_STATS", 

891 22: "REQ_RESET_PEER", 

892 23: "REQ_REREAD_KEYS", 

893 24: "REQ_DO_DIRTY_HACK", 

894 25: "REQ_DONT_DIRTY_HACK", 

895 26: "REQ_TRUSTKEY", 

896 27: "REQ_UNTRUSTKEY", 

897 28: "REQ_AUTHINFO", 

898 29: "REQ_TRAPS", 

899 30: "REQ_ADD_TRAP", 

900 31: "REQ_CLR_TRAP", 

901 32: "REQ_REQUEST_KEY", 

902 33: "REQ_CONTROL_KEY", 

903 34: "REQ_GET_CTLSTATS", 

904 35: "REQ_GET_LEAPINFO", 

905 36: "REQ_GET_CLOCKINFO", 

906 37: "REQ_SET_CLKFUDGE", 

907 38: "REQ_GET_KERNEL", 

908 39: "REQ_GET_CLKBUGINFO", 

909 41: "REQ_SET_PRECISION", 

910 42: "REQ_MON_GETLIST_1", 

911 43: "REQ_HOSTNAME_ASSOCID", 

912 44: "REQ_IF_STATS", 

913 45: "REQ_IF_RELOAD" 

914} 

915 

916 

917# Flags in the peer information returns 

918_peer_flags = [ 

919 "INFO_FLAG_CONFIG", 

920 "INFO_FLAG_SYSPEER", 

921 "INFO_FLAG_BURST", 

922 "INFO_FLAG_REFCLOCK", 

923 "INFO_FLAG_PREFER", 

924 "INFO_FLAG_AUTHENABLE", 

925 "INFO_FLAG_SEL_CANDIDATE", 

926 "INFO_FLAG_SHORTLIST", 

927 "INFO_FLAG_IBURST" 

928] 

929 

930 

931# Flags in the system information returns 

932_sys_info_flags = [ 

933 "INFO_FLAG_BCLIENT", 

934 "INFO_FLAG_AUTHENTICATE", 

935 "INFO_FLAG_NTP", 

936 "INFO_FLAG_KERNEL", 

937 "INFO_FLAG_CAL", 

938 "INFO_FLAG_PPS_SYNC", 

939 "INFO_FLAG_MONITOR", 

940 "INFO_FLAG_FILEGEN", 

941] 

942 

943 

944class NTPInfoPeerList(Packet): 

945 

946 """ 

947 Used to return raw lists of peers. 

948 """ 

949 name = "info_peer_list" 

950 fields_desc = [ 

951 IPField("addr", "0.0.0.0"), 

952 ShortField("port", 0), 

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

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

955 IntField("v6_flag", 0), 

956 IntField("unused1", 0), 

957 IP6Field("addr6", "::") 

958 ] 

959 

960 

961class NTPInfoPeerSummary(Packet): 

962 """ 

963 Sort of the info that ntpdc returns by default. 

964 """ 

965 name = "info_peer_summary" 

966 fields_desc = [ 

967 IPField("dstaddr", "0.0.0.0"), 

968 IPField("srcaddr", "0.0.0.0"), 

969 ShortField("srcport", 0), 

970 ByteField("stratum", 0), 

971 ByteField("hpoll", 0), 

972 ByteField("ppoll", 0), 

973 ByteField("reach", 0), 

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

975 ByteField("hmode", _ntp_modes), 

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

977 TimeStampField("offset", 0), 

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

979 IntField("v6_flag", 0), 

980 IntField("unused1", 0), 

981 IP6Field("dstaddr6", "::"), 

982 IP6Field("srcaddr6", "::") 

983 ] 

984 

985 

986class NTPInfoPeer(Packet): 

987 """ 

988 Peer information structure. 

989 """ 

990 

991 name = "info_peer" 

992 fields_desc = [ 

993 IPField("dstaddr", "0.0.0.0"), 

994 IPField("srcaddr", "0.0.0.0"), 

995 ShortField("srcport", 0), 

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

997 ByteField("leap", 0), 

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

999 ByteField("pmode", 0), 

1000 ByteField("stratum", 0), 

1001 ByteField("ppoll", 0), 

1002 ByteField("hpoll", 0), 

1003 SignedByteField("precision", 0), 

1004 ByteField("version", 0), 

1005 ByteField("unused8", 0), 

1006 ByteField("reach", 0), 

1007 ByteField("unreach", 0), 

1008 XByteField("flash", 0), 

1009 ByteField("ttl", 0), 

1010 XLEShortField("flash2", 0), 

1011 ShortField("associd", 0), 

1012 LEIntField("keyid", 0), 

1013 IntField("pkeyid", 0), 

1014 IPField("refid", 0), 

1015 IntField("timer", 0), 

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

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

1018 TimeStampField("reftime", 0), 

1019 TimeStampField("org", 0), 

1020 TimeStampField("rec", 0), 

1021 TimeStampField("xmt", 0), 

1022 FieldListField( 

1023 "filtdelay", 

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

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

1026 count_from=lambda p: _NTP_SHIFT 

1027 ), 

1028 FieldListField( 

1029 "filtoffset", 

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

1031 TimeStampField("", 0), 

1032 count_from=lambda p: _NTP_SHIFT 

1033 ), 

1034 FieldListField( 

1035 "order", 

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

1037 ByteField("", 0), 

1038 count_from=lambda p: _NTP_SHIFT 

1039 ), 

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

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

1042 TimeStampField("offset", 0), 

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

1044 IntField("unused1", 0), 

1045 IntField("unused2", 0), 

1046 IntField("unused3", 0), 

1047 IntField("unused4", 0), 

1048 IntField("unused5", 0), 

1049 IntField("unused6", 0), 

1050 IntField("unused7", 0), 

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

1052 IntField("v6_flag", 0), 

1053 IntField("unused9", 0), 

1054 IP6Field("dstaddr6", "::"), 

1055 IP6Field("srcaddr6", "::"), 

1056 ] 

1057 

1058 

1059class NTPInfoPeerStats(Packet): 

1060 """ 

1061 Peer statistics structure. 

1062 """ 

1063 

1064 name = "info_peer_stats" 

1065 fields_desc = [ 

1066 IPField("dstaddr", "0.0.0.0"), 

1067 IPField("srcaddr", "0.0.0.0"), 

1068 ShortField("srcport", 0), 

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

1070 IntField("timereset", 0), 

1071 IntField("timereceived", 0), 

1072 IntField("timetosend", 0), 

1073 IntField("timereachable", 0), 

1074 IntField("sent", 0), 

1075 IntField("unused1", 0), 

1076 IntField("processed", 0), 

1077 IntField("unused2", 0), 

1078 IntField("badauth", 0), 

1079 IntField("bogusorg", 0), 

1080 IntField("oldpkt", 0), 

1081 IntField("unused3", 0), 

1082 IntField("unused4", 0), 

1083 IntField("seldisp", 0), 

1084 IntField("selbroken", 0), 

1085 IntField("unused5", 0), 

1086 ByteField("candidate", 0), 

1087 ByteField("unused6", 0), 

1088 ByteField("unused7", 0), 

1089 ByteField("unused8", 0), 

1090 IntField("v6_flag", 0), 

1091 IntField("unused9", 0), 

1092 IP6Field("dstaddr6", "::"), 

1093 IP6Field("srcaddr6", "::"), 

1094 ] 

1095 

1096 

1097class NTPInfoLoop(Packet): 

1098 """ 

1099 Loop filter variables. 

1100 """ 

1101 

1102 name = "info_loop" 

1103 fields_desc = [ 

1104 TimeStampField("last_offset", 0), 

1105 TimeStampField("drift_comp", 0), 

1106 IntField("compliance", 0), 

1107 IntField("watchdog_timer", 0) 

1108 ] 

1109 

1110 

1111class NTPInfoSys(Packet): 

1112 """ 

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

1114 the implementation. 

1115 """ 

1116 

1117 name = "info_sys" 

1118 fields_desc = [ 

1119 IPField("peer", "0.0.0.0"), 

1120 ByteField("peer_mode", 0), 

1121 ByteField("leap", 0), 

1122 ByteField("stratum", 0), 

1123 SignedByteField("precision", 0), 

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

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

1126 IPField("refid", 0), 

1127 TimeStampField("reftime", 0), 

1128 IntField("poll", 0), 

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

1130 ByteField("unused1", 0), 

1131 ByteField("unused2", 0), 

1132 ByteField("unused3", 0), 

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

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

1135 TimeStampField("authdelay", 0), 

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

1137 IntField("v6_flag", 0), 

1138 IntField("unused4", 0), 

1139 IP6Field("peer6", "::") 

1140 ] 

1141 

1142 

1143class NTPInfoSysStats(Packet): 

1144 """ 

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

1146 """ 

1147 

1148 name = "info_sys_stats" 

1149 fields_desc = [ 

1150 IntField("timeup", 0), 

1151 IntField("timereset", 0), 

1152 IntField("denied", 0), 

1153 IntField("oldversionpkt", 0), 

1154 IntField("newversionpkt", 0), 

1155 IntField("unknownversion", 0), 

1156 IntField("badlength", 0), 

1157 IntField("processed", 0), 

1158 IntField("badauth", 0), 

1159 IntField("received", 0), 

1160 IntField("limitrejected", 0) 

1161 ] 

1162 

1163 

1164class NTPInfoMemStats(Packet): 

1165 """ 

1166 Peer memory statistics. 

1167 """ 

1168 

1169 name = "info_mem_stats" 

1170 fields_desc = [ 

1171 IntField("timereset", 0), 

1172 ShortField("totalpeermem", 0), 

1173 ShortField("freepeermem", 0), 

1174 IntField("findpeer_calls", 0), 

1175 IntField("allocations", 0), 

1176 IntField("demobilizations", 0), 

1177 FieldListField( 

1178 "hashcount", 

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

1180 ByteField("", 0), 

1181 count_from=lambda p: _NTP_HASH_SIZE, 

1182 max_count=_NTP_HASH_SIZE 

1183 ) 

1184 ] 

1185 

1186 

1187class NTPInfoIOStats(Packet): 

1188 """ 

1189 I/O statistics. 

1190 """ 

1191 

1192 name = "info_io_stats" 

1193 fields_desc = [ 

1194 IntField("timereset", 0), 

1195 ShortField("totalrecvbufs", 0), 

1196 ShortField("freerecvbufs", 0), 

1197 ShortField("fullrecvbufs", 0), 

1198 ShortField("lowwater", 0), 

1199 IntField("dropped", 0), 

1200 IntField("ignored", 0), 

1201 IntField("received", 0), 

1202 IntField("sent", 0), 

1203 IntField("notsent", 0), 

1204 IntField("interrupts", 0), 

1205 IntField("int_received", 0) 

1206 ] 

1207 

1208 

1209class NTPInfoTimerStats(Packet): 

1210 """ 

1211 Timer stats. 

1212 """ 

1213 

1214 name = "info_timer_stats" 

1215 fields_desc = [ 

1216 IntField("timereset", 0), 

1217 IntField("alarms", 0), 

1218 IntField("overflows", 0), 

1219 IntField("xmtcalls", 0), 

1220 ] 

1221 

1222 

1223_conf_peer_flags = [ 

1224 "CONF_FLAG_AUTHENABLE", 

1225 "CONF_FLAG_PREFER", 

1226 "CONF_FLAG_BURST", 

1227 "CONF_FLAG_IBURST", 

1228 "CONF_FLAG_NOSELECT", 

1229 "CONF_FLAG_SKEY" 

1230] 

1231 

1232 

1233class NTPConfPeer(Packet): 

1234 """ 

1235 Structure for passing peer configuration information. 

1236 """ 

1237 

1238 name = "conf_peer" 

1239 fields_desc = [ 

1240 IPField("peeraddr", "0.0.0.0"), 

1241 ByteField("hmode", 0), 

1242 ByteField("version", 0), 

1243 ByteField("minpoll", 0), 

1244 ByteField("maxpoll", 0), 

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

1246 ByteField("ttl", 0), 

1247 ShortField("unused1", 0), 

1248 IntField("keyid", 0), 

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

1250 IntField("v6_flag", 0), 

1251 IntField("unused2", 0), 

1252 IP6Field("peeraddr6", "::") 

1253 ] 

1254 

1255 

1256class NTPConfUnpeer(Packet): 

1257 """ 

1258 Structure for passing peer deletion information. 

1259 """ 

1260 

1261 name = "conf_unpeer" 

1262 fields_desc = [ 

1263 IPField("peeraddr", "0.0.0.0"), 

1264 IntField("v6_flag", 0), 

1265 IP6Field("peeraddr6", "::") 

1266 ] 

1267 

1268 

1269_restrict_flags = [ 

1270 "RES_IGNORE", 

1271 "RES_DONTSERVE", 

1272 "RES_DONTTRUST", 

1273 "RES_VERSION", 

1274 "RES_NOPEER", 

1275 "RES_LIMITED", 

1276 "RES_NOQUERY", 

1277 "RES_NOMODIFY", 

1278 "RES_NOTRAP", 

1279 "RES_LPTRAP", 

1280 "RES_KOD", 

1281 "RES_MSSNTP", 

1282 "RES_FLAKE", 

1283 "RES_NOMRULIST", 

1284] 

1285 

1286 

1287class NTPConfRestrict(Packet): 

1288 """ 

1289 Structure used for specifying restrict entries. 

1290 """ 

1291 

1292 name = "conf_restrict" 

1293 fields_desc = [ 

1294 IPField("addr", "0.0.0.0"), 

1295 IPField("mask", "0.0.0.0"), 

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

1297 ShortField("m_flags", 0), 

1298 IntField("v6_flag", 0), 

1299 IP6Field("addr6", "::"), 

1300 IP6Field("mask6", "::") 

1301 ] 

1302 

1303 

1304class NTPInfoKernel(Packet): 

1305 """ 

1306 Structure used for returning kernel pll/PPS information 

1307 """ 

1308 

1309 name = "info_kernel" 

1310 fields_desc = [ 

1311 IntField("offset", 0), 

1312 IntField("freq", 0), 

1313 IntField("maxerror", 0), 

1314 IntField("esterror", 0), 

1315 ShortField("status", 0), 

1316 ShortField("shift", 0), 

1317 IntField("constant", 0), 

1318 IntField("precision", 0), 

1319 IntField("tolerance", 0), 

1320 IntField("ppsfreq", 0), 

1321 IntField("jitter", 0), 

1322 IntField("stabil", 0), 

1323 IntField("jitcnt", 0), 

1324 IntField("calcnt", 0), 

1325 IntField("errcnt", 0), 

1326 IntField("stbcnt", 0), 

1327 ] 

1328 

1329 

1330class NTPInfoIfStatsIPv4(Packet): 

1331 """ 

1332 Interface statistics. 

1333 """ 

1334 

1335 name = "info_if_stats" 

1336 fields_desc = [ 

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

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

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

1340 IntField("v6_flag", 0), 

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

1342 IntField("flags", 0), 

1343 IntField("last_ttl", 0), 

1344 IntField("num_mcast", 0), 

1345 IntField("received", 0), 

1346 IntField("sent", 0), 

1347 IntField("notsent", 0), 

1348 IntField("uptime", 0), 

1349 IntField("scopeid", 0), 

1350 IntField("ifindex", 0), 

1351 IntField("ifnum", 0), 

1352 IntField("peercnt", 0), 

1353 ShortField("family", 0), 

1354 ByteField("ignore_packets", 0), 

1355 ByteField("action", 0), 

1356 IntField("_filler0", 0) 

1357 ] 

1358 

1359 

1360class NTPInfoIfStatsIPv6(Packet): 

1361 """ 

1362 Interface statistics. 

1363 """ 

1364 

1365 name = "info_if_stats" 

1366 fields_desc = [ 

1367 IP6Field("unaddr", "::"), 

1368 IP6Field("unbcast", "::"), 

1369 IP6Field("unmask", "::"), 

1370 IntField("v6_flag", 0), 

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

1372 IntField("flags", 0), 

1373 IntField("last_ttl", 0), 

1374 IntField("num_mcast", 0), 

1375 IntField("received", 0), 

1376 IntField("sent", 0), 

1377 IntField("notsent", 0), 

1378 IntField("uptime", 0), 

1379 IntField("scopeid", 0), 

1380 IntField("ifindex", 0), 

1381 IntField("ifnum", 0), 

1382 IntField("peercnt", 0), 

1383 ShortField("family", 0), 

1384 ByteField("ignore_packets", 0), 

1385 ByteField("action", 0), 

1386 IntField("_filler0", 0) 

1387 ] 

1388 

1389 

1390class NTPInfoMonitor1(Packet): 

1391 """ 

1392 Structure used for returning monitor data. 

1393 """ 

1394 

1395 name = "InfoMonitor1" 

1396 fields_desc = [ 

1397 IntField("lasttime", 0), 

1398 IntField("firsttime", 0), 

1399 IntField("lastdrop", 0), 

1400 IntField("count", 0), 

1401 IPField("addr", "0.0.0.0"), 

1402 IPField("daddr", "0.0.0.0"), 

1403 IntField("flags", 0), 

1404 ShortField("port", 0), 

1405 ByteField("mode", 0), 

1406 ByteField("version", 0), 

1407 IntField("v6_flag", 0), 

1408 IntField("unused1", 0), 

1409 IP6Field("addr6", "::"), 

1410 IP6Field("daddr6", "::") 

1411 ] 

1412 

1413 

1414class NTPInfoAuth(Packet): 

1415 """ 

1416 Structure used to return information concerning the authentication module. 

1417 """ 

1418 

1419 name = "info_auth" 

1420 fields_desc = [ 

1421 IntField("timereset", 0), 

1422 IntField("numkeys", 0), 

1423 IntField("numfreekeys", 0), 

1424 IntField("keylookups", 0), 

1425 IntField("keynotfound", 0), 

1426 IntField("encryptions", 0), 

1427 IntField("decryptions", 0), 

1428 IntField("expired", 0), 

1429 IntField("keyuncached", 0), 

1430 ] 

1431 

1432 

1433class NTPConfTrap(Packet): 

1434 """ 

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

1436 """ 

1437 

1438 name = "conf_trap" 

1439 fields_desc = [ 

1440 IPField("local_address", "0.0.0.0"), 

1441 IPField("trap_address", "0.0.0.0"), 

1442 ShortField("trap_port", 0), 

1443 ShortField("unused", 0), 

1444 IntField("v6_flag", 0), 

1445 IP6Field("local_address6", "::"), 

1446 IP6Field("trap_address6", "::"), 

1447 ] 

1448 

1449 

1450class NTPInfoControl(Packet): 

1451 """ 

1452 Structure used to return statistics from the control module. 

1453 """ 

1454 

1455 name = "info_control" 

1456 fields_desc = [ 

1457 IntField("ctltimereset", 0), 

1458 IntField("numctlreq", 0), 

1459 IntField("numctlbadpkts", 0), 

1460 IntField("numctlresponses", 0), 

1461 IntField("numctlfrags", 0), 

1462 IntField("numctlerrors", 0), 

1463 IntField("numctltooshort", 0), 

1464 IntField("numctlinputresp", 0), 

1465 IntField("numctlinputfrag", 0), 

1466 IntField("numctlinputerr", 0), 

1467 IntField("numctlbadoffset", 0), 

1468 IntField("numctlbadversion", 0), 

1469 IntField("numctldatatooshort", 0), 

1470 IntField("numctlbadop", 0), 

1471 IntField("numasyncmsgs", 0), 

1472 ] 

1473 

1474 

1475# ntp_request.h 

1476_ntpd_private_errors = { 

1477 0: "no error", 

1478 1: "incompatible implementation number", 

1479 2: "unimplemented request code", 

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

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

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

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

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

1485} 

1486 

1487 

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

1489_private_data_objects = { 

1490 0: NTPInfoPeerList, # "REQ_PEER_LIST", 

1491 1: NTPInfoPeerSummary, # "REQ_PEER_LIST_SUM", 

1492 2: NTPInfoPeer, # "REQ_PEER_INFO", 

1493 3: NTPInfoPeerStats, # "REQ_PEER_STATS", 

1494 4: NTPInfoSys, # "REQ_SYS_INFO", 

1495 5: NTPInfoSysStats, # "REQ_SYS_STATS", 

1496 6: NTPInfoIOStats, # "REQ_IO_STATS", 

1497 7: NTPInfoMemStats, # "REQ_MEM_STATS", 

1498 8: NTPInfoLoop, # "REQ_LOOP_INFO", 

1499 9: NTPInfoTimerStats, # "REQ_TIMER_STATS", 

1500 10: NTPConfPeer, # "REQ_CONFIG", 

1501 11: NTPConfUnpeer, # "REQ_UNCONFIG", 

1502 28: NTPInfoAuth, # "REQ_AUTHINFO", 

1503 30: NTPConfTrap, # "REQ_ADD_TRAP", 

1504 34: NTPInfoControl, # "REQ_GET_CTLSTATS", 

1505 38: NTPInfoKernel, # "REQ_GET_KERNEL", 

1506 42: NTPInfoMonitor1, # "REQ_MON_GETLIST_1", 

1507} 

1508 

1509 

1510class NTPPrivateRespPacketListField(PacketListField): 

1511 """ 

1512 PacketListField handling the response data. 

1513 """ 

1514 

1515 def m2i(self, pkt, s): 

1516 ret = None 

1517 

1518 # info_if_stats 

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

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

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

1522 else: 

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

1524 

1525 return ret 

1526 

1527 def getfield(self, pkt, s): 

1528 lst = [] 

1529 remain = s 

1530 length = pkt.data_item_size 

1531 if length > 0: 

1532 item_counter = 0 

1533 # Response payloads can be placed in several packets 

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

1535 current = remain[:length] 

1536 remain = remain[length:] 

1537 current_packet = self.m2i(pkt, current) 

1538 lst.append(current_packet) 

1539 item_counter += 1 

1540 

1541 return remain, lst 

1542 

1543 

1544class NTPPrivateReqPacket(Packet): 

1545 """ 

1546 Packet handling request data. 

1547 """ 

1548 

1549 name = "request data" 

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

1551 

1552 

1553_request_codes = { 

1554 0: "REQ_PEER_LIST", 

1555 1: "REQ_PEER_LIST_SUM", 

1556 2: "REQ_PEER_INFO", 

1557 3: "REQ_PEER_STATS", 

1558 4: "REQ_SYS_INFO", 

1559 5: "REQ_SYS_STATS", 

1560 6: "REQ_IO_STATS", 

1561 7: "REQ_MEM_STATS", 

1562 8: "REQ_LOOP_INFO", 

1563 9: "REQ_TIMER_STATS", 

1564 10: "REQ_CONFIG", 

1565 11: "REQ_UNCONFIG", 

1566 12: "REQ_SET_SYS_FLAG", 

1567 13: "REQ_CLR_SYS_FLAG", 

1568 14: "REQ_MONITOR", 

1569 15: "REQ_NOMONITOR", 

1570 16: "REQ_GET_RESTRICT", 

1571 17: "REQ_RESADDFLAGS", 

1572 18: "REQ_RESSUBFLAGS", 

1573 19: "REQ_UNRESTRICT", 

1574 20: "REQ_MON_GETLIST", 

1575 21: "REQ_RESET_STATS", 

1576 22: "REQ_RESET_PEER", 

1577 23: "REQ_REREAD_KEYS", 

1578 24: "REQ_DO_DIRTY_HACK", 

1579 25: "REQ_DONT_DIRTY_HACK", 

1580 26: "REQ_TRUSTKEY", 

1581 27: "REQ_UNTRUSTKEY", 

1582 28: "REQ_AUTHINFO", 

1583 29: "REQ_TRAPS", 

1584 30: "REQ_ADD_TRAP", 

1585 31: "REQ_CLR_TRAP", 

1586 32: "REQ_REQUEST_KEY", 

1587 33: "REQ_CONTROL_KEY", 

1588 34: "REQ_GET_CTLSTATS", 

1589 35: "REQ_GET_LEAPINFO", 

1590 36: "REQ_GET_CLOCKINFO", 

1591 37: "REQ_SET_CLKFUDGE", 

1592 38: "REQ_GET_KERNEL", 

1593 39: "REQ_GET_CLKBUGINFO", 

1594 41: "REQ_SET_PRECISION", 

1595 42: "REQ_MON_GETLIST_1", 

1596 43: "REQ_HOSTNAME_ASSOCID", 

1597 44: "REQ_IF_STATS", 

1598 45: "REQ_IF_RELOAD" 

1599} 

1600 

1601 

1602class NTPPrivateReqPacketListField(PacketListField): 

1603 """ 

1604 Handles specific request packets. 

1605 """ 

1606 

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

1608 

1609 def m2i(self, pkt, s): 

1610 ret = None 

1611 

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

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

1614 # REQ_PEER_STATS (for request only) 

1615 ret = NTPInfoPeerList(s) 

1616 

1617 elif pkt.request_code == 10: 

1618 # REQ_CONFIG 

1619 ret = NTPConfPeer(s) 

1620 

1621 elif pkt.request_code == 11: 

1622 # REQ_CONFIG 

1623 ret = NTPConfUnpeer(s) 

1624 

1625 elif pkt.request_code == 17: 

1626 # REQ_RESADDFLAGS 

1627 ret = NTPConfRestrict(s) 

1628 

1629 elif pkt.request_code == 18: 

1630 # REQ_RESSUBFLAGS 

1631 ret = NTPConfRestrict(s) 

1632 

1633 elif pkt.request_code == 22: 

1634 # REQ_RESET_PEER 

1635 ret = NTPConfUnpeer(s) 

1636 

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

1638 # REQ_ADD_TRAP 

1639 ret = NTPConfTrap(s) 

1640 

1641 else: 

1642 ret = NTPPrivateReqPacket(s) 

1643 

1644 return ret 

1645 

1646 def getfield(self, pkt, s): 

1647 lst = [] 

1648 remain = s 

1649 length = pkt.data_item_size 

1650 if length > 0: 

1651 item_counter = 0 

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

1653 current = remain[:length] 

1654 remain = remain[length:] 

1655 current_packet = self.m2i(pkt, current) 

1656 lst.append(current_packet) 

1657 item_counter += 1 

1658 

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

1660 if pkt.auth: 

1661 padding_end = len(remain) - _NTP_PRIVATE_REQ_PKT_TAIL_LEN 

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

1663 lst.append(current_packet) 

1664 remain = remain[padding_end:] 

1665 

1666 return remain, lst 

1667 

1668 

1669class NTPPrivatePktTail(Packet): 

1670 """ 

1671 include/ntp_request.h 

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

1673 packet sizes that may arrive. 

1674 """ 

1675 

1676 name = "req_pkt_tail" 

1677 fields_desc = [ 

1678 TimeStampField("tstamp", 0), 

1679 IntField("key_id", 0), 

1680 XStrFixedLenField( 

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

1682 ] 

1683 

1684 

1685class NTPPrivate(NTP): 

1686 """ 

1687 Packet handling the private (mode 7) messages. 

1688 """ 

1689 

1690 ######################################################################### 

1691 # ntpd source code: ntp_request.h 

1692 ######################################################################### 

1693 # 

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

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

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

1697 # packet has the following format: 

1698 # 

1699 # 0 1 2 3 

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

1701 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

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

1703 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

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

1705 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

1706 # | | 

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

1708 # | | 

1709 # [...] | 

1710 # | | 

1711 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

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

1713 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

1714 # | | 

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

1716 # | | 

1717 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

1718 # 

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

1720 # responses): 

1721 # 

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

1723 # 

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

1725 # requires more than one packet. 

1726 # 

1727 # Version Number: 2 for current version 

1728 # 

1729 # Mode: Always 7 

1730 # 

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

1732 # 

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

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

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

1736 # all packets but the last. 

1737 # 

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

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

1740 # for request codes/data formats which all implementations 

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

1742 # extensions, in case we run out). 

1743 # 

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

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

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

1747 # 

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

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

1750 # requested wasn't performed. 

1751 # 

1752 # 0 - no error 

1753 # 1 - incompatible implementation number 

1754 # 2 - unimplemented request code 

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

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

1757 # 5-6 I don"t know 

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

1759 # 

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

1761 # 

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

1763 # 

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

1765 # 

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

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

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

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

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

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

1772 # inclusive. 

1773 # 

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

1775 # May optionally be included in requests which require 

1776 # authentication, is never included in responses. 

1777 # 

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

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

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

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

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

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

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

1785 # 

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

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

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

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

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

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

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

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

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

1795 ######################################################################### 

1796 # 

1797 

1798 name = "Private (mode 7)" 

1799 match_subclass = True 

1800 fields_desc = [ 

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

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

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

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

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

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

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

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

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

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

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

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

1813 ConditionalField( 

1814 NTPPrivateReqPacketListField( 

1815 "req_data", 

1816 [], 

1817 Packet, 

1818 length_from=lambda p: p.data_item_size, 

1819 count_from=lambda p: p.nb_items 

1820 ), 

1821 lambda p: p.response == 0 

1822 ), 

1823 # Responses 

1824 ConditionalField( 

1825 NTPPrivateRespPacketListField( 

1826 "data", 

1827 [], 

1828 Packet, 

1829 length_from=lambda p: p.data_item_size, 

1830 count_from=lambda p: p.nb_items 

1831 ), 

1832 lambda p: p.response == 1 

1833 ), 

1834 # Responses are not supposed to be authenticated 

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

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

1837 ] 

1838 

1839 

1840############################################################################## 

1841# Layer bindings 

1842############################################################################## 

1843 

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

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

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