19
19
ByteEnumField ,
20
20
ByteField ,
21
21
ConditionalField ,
22
+ FieldLenField ,
22
23
FieldListField ,
23
24
FixedPointField ,
24
25
FlagsField ,
28
29
LEIntField ,
29
30
LEShortField ,
30
31
MayEnd ,
32
+ MultipleTypeField ,
31
33
PacketField ,
32
- PacketLenField ,
33
34
PacketListField ,
34
35
PadField ,
35
36
ShortField ,
36
37
SignedByteField ,
37
38
StrField ,
38
39
StrFixedLenEnumField ,
39
40
StrFixedLenField ,
41
+ StrLenField ,
40
42
XByteField ,
41
43
XStrFixedLenField ,
42
44
)
@@ -610,18 +612,6 @@ def __init__(self, details):
610
612
}
611
613
612
614
613
- class 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
-
625
615
class NTPSystemStatusPacket (Packet ):
626
616
627
617
"""
@@ -691,55 +681,6 @@ def extract_padding(self, s):
691
681
return b"" , s
692
682
693
683
694
- class 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
-
743
684
class NTPPeerStatusDataPacket (Packet ):
744
685
"""
745
686
Packet handling the data field when op_code is CTL_OP_READSTAT
@@ -752,97 +693,87 @@ class NTPPeerStatusDataPacket(Packet):
752
693
PacketField ("peer_status" , NTPPeerStatusPacket (), NTPPeerStatusPacket ),
753
694
]
754
695
696
+ def extract_padding (self , s ):
697
+ return b"" , s
755
698
756
- class NTPControlDataPacketLenField (PacketLenField ):
757
699
700
+ class NTPControlStatusField (PacketField ):
758
701
"""
759
- PacketField handling the "data " field of NTP control messages .
702
+ The various types of the "status " field.
760
703
"""
761
-
704
+ # RFC 9327 sect 3
762
705
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
706
+ association_id = struct .unpack ("!H" , m [2 :4 ])[0 ]
778
707
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
708
+ if pkt .err == 1 :
709
+ return NTPErrorStatusPacket (m )
710
+ elif pkt .op_code in [4 , 5 ]: # Read/write clock
711
+ return NTPClockStatusPacket (m )
712
+ else :
713
+ if association_id != 0 :
714
+ return NTPPeerStatusPacket (m )
715
+ else :
716
+ return NTPSystemStatusPacket (m )
800
717
801
718
802
719
class NTPControl (NTP ):
803
720
"""
804
721
Packet handling NTP mode 6 / "Control" messages.
805
722
"""
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"
723
+ deprecated_fields = {
724
+ "status_word" : ("status" , "2.6.2" ),
725
+ }
726
+ # RFC 9327 sect 2
727
+ name = "NTP Control message"
817
728
match_subclass = True
818
729
fields_desc = [
819
- BitField ( "zeros " , 0 , 2 ),
730
+ BitEnumField ( "leap " , 0 , 2 , _leap_indicator ),
820
731
BitField ("version" , 2 , 3 ),
821
732
BitEnumField ("mode" , 6 , 3 , _ntp_modes ),
822
733
BitField ("response" , 0 , 1 ),
823
734
BitField ("err" , 0 , 1 ),
824
735
BitField ("more" , 0 , 1 ),
825
736
BitEnumField ("op_code" , 0 , 5 , _op_codes ),
826
737
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 ),
738
+ MultipleTypeField (
739
+ [
740
+ (
741
+ ShortField ("status" , 0 ),
742
+ lambda pkt : pkt .response == 0 or pkt .op_code in [6 , 7 ]
743
+ )
744
+ ],
745
+ NTPControlStatusField ("status" , NTPSystemStatusPacket (), None ),
746
+ ),
830
747
ShortField ("association_id" , 0 ),
831
748
ShortField ("offset" , 0 ),
832
- ShortField ("count" , None ),
833
- MayEnd (NTPControlDataPacketLenField (
834
- "data" , "" , Packet , length_from = lambda p : p .count )),
749
+ FieldLenField ("count" , None , length_of = "data" ),
750
+ MayEnd (
751
+ PadField (
752
+ MultipleTypeField (
753
+ # RFC 1305
754
+ [
755
+ (
756
+ PacketListField (
757
+ "data" ,
758
+ "" ,
759
+ NTPPeerStatusDataPacket ,
760
+ length_from = lambda p : p .count ,
761
+ ),
762
+ lambda pkt : (
763
+ pkt .response and
764
+ pkt .op_code == 1 and
765
+ pkt .association_id == 0
766
+ )
767
+ ),
768
+ ],
769
+ StrLenField ("data" , "" , length_from = lambda pkt : pkt .count ),
770
+ ),
771
+ align = 4
772
+ )
773
+ ),
835
774
PacketField ("authenticator" , "" , NTPAuthenticator ),
836
775
]
837
776
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
777
847
778
##############################################################################
848
779
# Private (mode 7)
0 commit comments