1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 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)
}
|