diff options
author | Chris Koch <chrisko@google.com> | 2023-02-18 20:40:36 -0800 |
---|---|---|
committer | Chris K <c@chrisko.ch> | 2023-02-19 22:39:16 -0800 |
commit | 54181a38109b83fef570bb6ff42cede506070ee6 (patch) | |
tree | 7502a2a525327bcf951adde076e57a1dd3202d46 /dhcpv6/option_ntp_server.go | |
parent | 598984875576cb96c67c63ec59df9b402e3cd006 (diff) |
Improve NTP server option parsing
Signed-off-by: Chris Koch <chrisko@google.com>
Diffstat (limited to 'dhcpv6/option_ntp_server.go')
-rw-r--r-- | dhcpv6/option_ntp_server.go | 113 |
1 files changed, 46 insertions, 67 deletions
diff --git a/dhcpv6/option_ntp_server.go b/dhcpv6/option_ntp_server.go index a7aafb7..a5b0cfb 100644 --- a/dhcpv6/option_ntp_server.go +++ b/dhcpv6/option_ntp_server.go @@ -18,17 +18,20 @@ func (n *NTPSuboptionSrvAddr) Code() OptionCode { // ToBytes returns the byte serialization of the suboption. func (n *NTPSuboptionSrvAddr) ToBytes() []byte { - buf := uio.NewBigEndianBuffer(nil) - buf.Write16(uint16(NTPSuboptionSrvAddrCode)) - buf.Write16(uint16(net.IPv6len)) - buf.WriteBytes(net.IP(*n).To16()) - return buf.Data() + return net.IP(*n).To16() } func (n *NTPSuboptionSrvAddr) String() string { return fmt.Sprintf("Server Address: %s", net.IP(*n).String()) } +// FromBytes parses NTP server address from a byte slice p. +func (n *NTPSuboptionSrvAddr) FromBytes(p []byte) error { + buf := uio.NewBigEndianBuffer(p) + *n = NTPSuboptionSrvAddr(buf.CopyN(net.IPv6len)) + return buf.FinError() +} + // NTPSuboptionMCAddr is NTP_SUBOPTION_MC_ADDR according to RFC 5908. type NTPSuboptionMCAddr net.IP @@ -39,19 +42,24 @@ func (n *NTPSuboptionMCAddr) Code() OptionCode { // ToBytes returns the byte serialization of the suboption. func (n *NTPSuboptionMCAddr) ToBytes() []byte { - buf := uio.NewBigEndianBuffer(nil) - buf.Write16(uint16(NTPSuboptionMCAddrCode)) - buf.Write16(uint16(net.IPv6len)) - buf.WriteBytes(net.IP(*n).To16()) - return buf.Data() + return net.IP(*n).To16() } func (n *NTPSuboptionMCAddr) String() string { return fmt.Sprintf("Multicast Address: %s", net.IP(*n).String()) } +// FromBytes parses NTP multicast address from a byte slice p. +func (n *NTPSuboptionMCAddr) FromBytes(p []byte) error { + buf := uio.NewBigEndianBuffer(p) + *n = NTPSuboptionMCAddr(buf.CopyN(net.IPv6len)) + return buf.FinError() +} + // NTPSuboptionSrvFQDN is NTP_SUBOPTION_SRV_FQDN according to RFC 5908. -type NTPSuboptionSrvFQDN rfc1035label.Labels +type NTPSuboptionSrvFQDN struct { + rfc1035label.Labels +} // Code returns the suboption code. func (n *NTPSuboptionSrvFQDN) Code() OptionCode { @@ -60,17 +68,16 @@ func (n *NTPSuboptionSrvFQDN) Code() OptionCode { // ToBytes returns the byte serialization of the suboption. func (n *NTPSuboptionSrvFQDN) ToBytes() []byte { - buf := uio.NewBigEndianBuffer(nil) - buf.Write16(uint16(NTPSuboptionSrvFQDNCode)) - l := rfc1035label.Labels(*n) - buf.Write16(uint16(l.Length())) - buf.WriteBytes(l.ToBytes()) - return buf.Data() + return n.Labels.ToBytes() } func (n *NTPSuboptionSrvFQDN) String() string { - l := rfc1035label.Labels(*n) - return fmt.Sprintf("Server FQDN: %s", l.String()) + return fmt.Sprintf("Server FQDN: %s", n.Labels.String()) +} + +// FromBytes parses an NTP server FQDN from a byte slice p. +func (n *NTPSuboptionSrvFQDN) FromBytes(p []byte) error { + return n.Labels.FromBytes(p) } // NTPSuboptionSrvAddr is the value of NTP_SUBOPTION_SRV_ADDR according to RFC 5908. @@ -82,53 +89,25 @@ const ( // parseNTPSuboption implements the OptionParser interface. func parseNTPSuboption(code OptionCode, data []byte) (Option, error) { - //var o Options - buf := uio.NewBigEndianBuffer(data) - length := len(data) - data, err := buf.ReadN(length) - if err != nil { - return nil, fmt.Errorf("failed to read %d bytes for suboption: %w", length, err) - } + var o Option + var err error switch code { - case NTPSuboptionSrvAddrCode, NTPSuboptionMCAddrCode: - if length != net.IPv6len { - return nil, fmt.Errorf("invalid suboption length, want %d, got %d", net.IPv6len, length) - } - var so Option - switch code { - case NTPSuboptionSrvAddrCode: - sos := NTPSuboptionSrvAddr(data) - so = &sos - case NTPSuboptionMCAddrCode: - som := NTPSuboptionMCAddr(data) - so = &som - } - return so, nil + case NTPSuboptionSrvAddrCode: + var opt NTPSuboptionSrvAddr + err = opt.FromBytes(data) + o = &opt + case NTPSuboptionMCAddrCode: + var opt NTPSuboptionMCAddr + err = opt.FromBytes(data) + o = &opt case NTPSuboptionSrvFQDNCode: - l, err := rfc1035label.FromBytes(data) - if err != nil { - return nil, fmt.Errorf("failed to parse rfc1035 labels: %w", err) - } - // TODO according to rfc3315, this label must not be compressed. - // Need to add support for compression detection to the - // `rfc1035label` package in order to do that. - so := NTPSuboptionSrvFQDN(*l) - return &so, nil + var opt NTPSuboptionSrvFQDN + err = opt.FromBytes(data) + o = &opt default: - gopt := OptionGeneric{OptionCode: code, OptionData: data} - return &gopt, nil - } -} - -// ParseOptNTPServer parses a sequence of bytes into an OptNTPServer object. -func ParseOptNTPServer(data []byte) (*OptNTPServer, error) { - var so Options - if err := so.FromBytesWithParser(data, parseNTPSuboption); err != nil { - return nil, err + o = &OptionGeneric{OptionCode: code, OptionData: append([]byte(nil), data...)} } - return &OptNTPServer{ - Suboptions: so, - }, nil + return o, err } // OptNTPServer is an option NTP server as defined by RFC 5908. @@ -141,13 +120,13 @@ func (op *OptNTPServer) Code() OptionCode { return OptionNTPServer } +func (op *OptNTPServer) FromBytes(data []byte) error { + return op.Suboptions.FromBytesWithParser(data, parseNTPSuboption) +} + // ToBytes returns the option serialized to bytes. func (op *OptNTPServer) ToBytes() []byte { - buf := uio.NewBigEndianBuffer(nil) - for _, so := range op.Suboptions { - buf.WriteBytes(so.ToBytes()) - } - return buf.Data() + return op.Suboptions.ToBytes() } func (op *OptNTPServer) String() string { |