zeek/src/analyzer/protocol/ntp/ntp-protocol.pac

108 lines
3.7 KiB
JavaScript

# This is the common part in the header format.
# See RFC 5905 for details
type NTP_PDU(is_orig: bool) = record {
# The first byte of the NTP header contains the leap indicator,
# the version and the mode
first_byte : uint8;
# Modes 1-5 are standard NTP time sync
standard_modes : case (mode>=1 && mode<=5) of {
true -> std : NTP_std_msg;
false -> emp : empty;
};
modes_6_7 : case (mode) of {
# mode 6 is for control messages (format is different from modes 6-7)
6 -> control : NTP_control_msg;
# mode 7 is reserved or private (and implementation dependent). For example used for some commands such as MONLIST
7 -> mode7 : NTP_mode7_msg;
default -> unknown : bytestring &restofdata;
};
} &let {
leap: uint8 = (first_byte & 0xc0)>>6; # First 2 bits of 8-bits value
version: uint8 = (first_byte & 0x38)>>3; # Bits 3-5 of 8-bits value
mode: uint8 = (first_byte & 0x07); # Bits 6-8 of 8-bits value
} &byteorder=bigendian &exportsourcedata;
# This is the most common type of message, corresponding to modes 1-5
# This kind of msg are used for normal operation of syncronization
# See RFC 5905 for details
type NTP_std_msg = record {
stratum : uint8;
poll : int8;
precision : int8;
root_delay : NTP_Short_Time;
root_dispersion: NTP_Short_Time;
reference_id : bytestring &length=4;
reference_ts : NTP_Time;
origin_ts : NTP_Time;
receive_ts : NTP_Time;
transmit_ts : NTP_Time;
#extensions : Extension_Field[] &until($input.length() == 20); #TODO: this need to be properly parsed
mac_fields : case (mac_len) of {
20 -> mac : NTP_MAC;
24 -> mac_ext : NTP_MAC_ext;
false -> nil : empty;
} &requires(mac_len);
} &let {
length = sourcedata.length();
mac_len: uint32 = (length - offsetof(mac_fields));
} &byteorder=bigendian &exportsourcedata;
# This format is for mode==6, control msg
# See RFC 1119 for details
type NTP_control_msg = record {
second_byte : uint8;
sequence : uint16;
status : uint16; #TODO: this can be further parsed internally
association_id : uint16;
offs : uint16;
c : uint16;
data : bytestring &length=c;
mac_fields : case (has_control_mac) of {
true -> mac : NTP_CONTROL_MAC;
false -> nil : empty;
} &requires(has_control_mac);
} &let {
R: bool = (second_byte & 0x80) > 0; # First bit of 8-bits value
E: bool = (second_byte & 0x40) > 0; # Second bit of 8-bits value
M: bool = (second_byte & 0x20) > 0; # Third bit of 8-bits value
OpCode: uint8 = (second_byte & 0x1F); # Last 5 bits of 8-bits value
length = sourcedata.length();
has_control_mac: bool = (length - offsetof(mac_fields)) == 12;
} &byteorder=bigendian &exportsourcedata;
# As in RFC 5905
type NTP_MAC = record {
key_id: uint32;
digest: bytestring &length=16;
} &length=20;
# As in RFC 5906, same as NTP_MAC but with a 160 bit digest
type NTP_MAC_ext = record {
key_id: uint32;
digest: bytestring &length=20;
} &length=24;
# As in RFC 1119
type NTP_CONTROL_MAC = record {
key_id: uint32;
crypto_checksum: bytestring &length=8;
} &length=12;
type Extension_Field = record {
field_type: uint16;
ext_len : uint16;
data : bytestring &length=ext_len-4;
};
type NTP_Short_Time = record {
seconds: int16;
fractions: int16;
};
type NTP_Time = record {
seconds: uint32;
fractions: uint32;
};