summaryrefslogtreecommitdiffhomepage
path: root/dhcpv6/option_ntp_server.go
diff options
context:
space:
mode:
Diffstat (limited to 'dhcpv6/option_ntp_server.go')
-rw-r--r--dhcpv6/option_ntp_server.go155
1 files changed, 155 insertions, 0 deletions
diff --git a/dhcpv6/option_ntp_server.go b/dhcpv6/option_ntp_server.go
new file mode 100644
index 0000000..a7aafb7
--- /dev/null
+++ b/dhcpv6/option_ntp_server.go
@@ -0,0 +1,155 @@
+package dhcpv6
+
+import (
+ "fmt"
+ "net"
+
+ "github.com/insomniacslk/dhcp/rfc1035label"
+ "github.com/u-root/uio/uio"
+)
+
+// NTPSuboptionSrvAddr is NTP_SUBOPTION_SRV_ADDR according to RFC 5908.
+type NTPSuboptionSrvAddr net.IP
+
+// Code returns the suboption code.
+func (n *NTPSuboptionSrvAddr) Code() OptionCode {
+ return NTPSuboptionSrvAddrCode
+}
+
+// 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()
+}
+
+func (n *NTPSuboptionSrvAddr) String() string {
+ return fmt.Sprintf("Server Address: %s", net.IP(*n).String())
+}
+
+// NTPSuboptionMCAddr is NTP_SUBOPTION_MC_ADDR according to RFC 5908.
+type NTPSuboptionMCAddr net.IP
+
+// Code returns the suboption code.
+func (n *NTPSuboptionMCAddr) Code() OptionCode {
+ return NTPSuboptionMCAddrCode
+}
+
+// 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()
+}
+
+func (n *NTPSuboptionMCAddr) String() string {
+ return fmt.Sprintf("Multicast Address: %s", net.IP(*n).String())
+}
+
+// NTPSuboptionSrvFQDN is NTP_SUBOPTION_SRV_FQDN according to RFC 5908.
+type NTPSuboptionSrvFQDN rfc1035label.Labels
+
+// Code returns the suboption code.
+func (n *NTPSuboptionSrvFQDN) Code() OptionCode {
+ return NTPSuboptionSrvFQDNCode
+}
+
+// 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()
+}
+
+func (n *NTPSuboptionSrvFQDN) String() string {
+ l := rfc1035label.Labels(*n)
+ return fmt.Sprintf("Server FQDN: %s", l.String())
+}
+
+// NTPSuboptionSrvAddr is the value of NTP_SUBOPTION_SRV_ADDR according to RFC 5908.
+const (
+ NTPSuboptionSrvAddrCode = OptionCode(1)
+ NTPSuboptionMCAddrCode = OptionCode(2)
+ NTPSuboptionSrvFQDNCode = OptionCode(3)
+)
+
+// 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)
+ }
+ 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 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
+ 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
+ }
+ return &OptNTPServer{
+ Suboptions: so,
+ }, nil
+}
+
+// OptNTPServer is an option NTP server as defined by RFC 5908.
+type OptNTPServer struct {
+ Suboptions Options
+}
+
+// Code returns the option code
+func (op *OptNTPServer) Code() OptionCode {
+ return OptionNTPServer
+}
+
+// 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()
+}
+
+func (op *OptNTPServer) String() string {
+ return fmt.Sprintf("NTP: %v", op.Suboptions)
+}