Update dependencies

This commit is contained in:
bluepython508
2024-11-01 17:33:34 +00:00
parent 033ac0b400
commit 5cdfab398d
3596 changed files with 1033483 additions and 259 deletions

10
vendor/github.com/insomniacslk/dhcp/CONTRIBUTORS.md generated vendored Normal file
View File

@@ -0,0 +1,10 @@
## Contributors
* Andrea Barberio (main author)
* Pablo Mazzini (tons of fixes and new options)
* Sean Karlage (BSDP package, and of tons of improvements to the DHCPv4 package)
* Owen Mooney (several option fixes and modifiers)
* Mikolaj Walczak (asynchronous DHCPv6 client)
* Chris Koch (tons of improvements in DHCPv4 and DHCPv6 internals and interface)
* Akshay Navale, Brandon Bennett and Chris Gorham (ZTPv6 and ZTPv4 packages)
* Anatole Denis (tons of fixes and new options)

29
vendor/github.com/insomniacslk/dhcp/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2018, Andrea Barberio
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,10 @@
package dhcpv4
import (
"github.com/insomniacslk/dhcp/interfaces"
)
// BindToInterface (deprecated) redirects to interfaces.BindToInterface
func BindToInterface(fd int, ifname string) error {
return interfaces.BindToInterface(fd, ifname)
}

View File

@@ -0,0 +1,6 @@
package dhcpv4
const (
ServerPort = 67
ClientPort = 68
)

831
vendor/github.com/insomniacslk/dhcp/dhcpv4/dhcpv4.go generated vendored Normal file
View File

@@ -0,0 +1,831 @@
// Package dhcpv4 provides encoding and decoding of DHCPv4 packets and options.
//
// Example Usage:
//
// p, err := dhcpv4.New(
// dhcpv4.WithClientIP(net.IP{192, 168, 0, 1}),
// dhcpv4.WithMessageType(dhcpv4.MessageTypeInform),
// )
// p.UpdateOption(dhcpv4.OptServerIdentifier(net.IP{192, 110, 110, 110}))
//
// // Retrieve the DHCP Message Type option.
// m := p.MessageType()
//
// bytesOnTheWire := p.ToBytes()
// longSummary := p.Summary()
package dhcpv4
import (
"bytes"
"context"
"errors"
"fmt"
"net"
"strings"
"time"
"github.com/insomniacslk/dhcp/iana"
"github.com/insomniacslk/dhcp/rfc1035label"
"github.com/u-root/uio/rand"
"github.com/u-root/uio/uio"
)
const (
// minPacketLen is the minimum DHCP header length.
minPacketLen = 236
// MaxHWAddrLen is the maximum hardware address length of the ClientHWAddr
// (client hardware address) according to RFC 2131, Section 2. This is the
// link-layer destination a server must send responses to.
MaxHWAddrLen = 16
// MaxMessageSize is the maximum size in bytes that a DHCPv4 packet can hold.
MaxMessageSize = 576
// Per RFC 951, the minimum length of a packet is 300 bytes.
bootpMinLen = 300
)
// RandomTimeout is the amount of time to wait until random number generation
// is canceled.
var RandomTimeout = 2 * time.Minute
// magicCookie is the magic 4-byte value at the beginning of the list of options
// in a DHCPv4 packet.
var magicCookie = [4]byte{99, 130, 83, 99}
// DHCPv4 represents a DHCPv4 packet header and options. See the New* functions
// to build DHCPv4 packets.
type DHCPv4 struct {
OpCode OpcodeType
HWType iana.HWType
HopCount uint8
TransactionID TransactionID
NumSeconds uint16
Flags uint16
ClientIPAddr net.IP
YourIPAddr net.IP
ServerIPAddr net.IP
GatewayIPAddr net.IP
ClientHWAddr net.HardwareAddr
ServerHostName string
BootFileName string
Options Options
}
// Modifier defines the signature for functions that can modify DHCPv4
// structures. This is used to simplify packet manipulation
type Modifier func(d *DHCPv4)
// IPv4AddrsForInterface obtains the currently-configured, non-loopback IPv4
// addresses for iface.
func IPv4AddrsForInterface(iface *net.Interface) ([]net.IP, error) {
if iface == nil {
return nil, errors.New("IPv4AddrsForInterface: iface cannot be nil")
}
addrs, err := iface.Addrs()
if err != nil {
return nil, err
}
return GetExternalIPv4Addrs(addrs)
}
// GetExternalIPv4Addrs obtains the currently-configured, non-loopback IPv4
// addresses from `addrs` coming from a particular interface (e.g.
// net.Interface.Addrs).
func GetExternalIPv4Addrs(addrs []net.Addr) ([]net.IP, error) {
var v4addrs []net.IP
for _, addr := range addrs {
var ip net.IP
switch v := addr.(type) {
case *net.IPAddr:
ip = v.IP
case *net.IPNet:
ip = v.IP
}
if ip == nil || ip.IsLoopback() {
continue
}
ip = ip.To4()
if ip == nil {
continue
}
v4addrs = append(v4addrs, ip)
}
return v4addrs, nil
}
// GenerateTransactionID generates a random 32-bits number suitable for use as
// TransactionID
func GenerateTransactionID() (TransactionID, error) {
var xid TransactionID
ctx, cancel := context.WithTimeout(context.Background(), RandomTimeout)
defer cancel()
n, err := rand.ReadContext(ctx, xid[:])
if err != nil {
return xid, fmt.Errorf("could not get random number: %v", err)
}
if n != 4 {
return xid, errors.New("invalid random sequence for transaction ID: smaller than 32 bits")
}
return xid, err
}
// New creates a new DHCPv4 structure and fill it up with default values. It
// won't be a valid DHCPv4 message so you will need to adjust its fields.
// See also NewDiscovery, NewRequest, NewAcknowledge, NewInform and NewRelease.
func New(modifiers ...Modifier) (*DHCPv4, error) {
xid, err := GenerateTransactionID()
if err != nil {
return nil, err
}
d := DHCPv4{
OpCode: OpcodeBootRequest,
HWType: iana.HWTypeEthernet,
ClientHWAddr: make(net.HardwareAddr, 6),
HopCount: 0,
TransactionID: xid,
NumSeconds: 0,
Flags: 0,
ClientIPAddr: net.IPv4zero,
YourIPAddr: net.IPv4zero,
ServerIPAddr: net.IPv4zero,
GatewayIPAddr: net.IPv4zero,
Options: make(Options),
}
for _, mod := range modifiers {
mod(&d)
}
return &d, nil
}
// NewDiscoveryForInterface builds a new DHCPv4 Discovery message, with a default
// Ethernet HW type and the hardware address obtained from the specified
// interface.
func NewDiscoveryForInterface(ifname string, modifiers ...Modifier) (*DHCPv4, error) {
iface, err := net.InterfaceByName(ifname)
if err != nil {
return nil, err
}
return NewDiscovery(iface.HardwareAddr, modifiers...)
}
// NewDiscovery builds a new DHCPv4 Discovery message, with a default Ethernet
// HW type and specified hardware address.
func NewDiscovery(hwaddr net.HardwareAddr, modifiers ...Modifier) (*DHCPv4, error) {
return New(PrependModifiers(modifiers,
WithHwAddr(hwaddr),
WithRequestedOptions(
OptionSubnetMask,
OptionRouter,
OptionDomainName,
OptionDomainNameServer,
),
WithMessageType(MessageTypeDiscover),
)...)
}
// NewInformForInterface builds a new DHCPv4 Informational message with default
// Ethernet HW type and the hardware address obtained from the specified
// interface.
func NewInformForInterface(ifname string, needsBroadcast bool) (*DHCPv4, error) {
// get hw addr
iface, err := net.InterfaceByName(ifname)
if err != nil {
return nil, err
}
// Set Client IP as iface's currently-configured IP.
localIPs, err := IPv4AddrsForInterface(iface)
if err != nil || len(localIPs) == 0 {
return nil, fmt.Errorf("could not get local IPs for iface %s", ifname)
}
pkt, err := NewInform(iface.HardwareAddr, localIPs[0])
if err != nil {
return nil, err
}
if needsBroadcast {
pkt.SetBroadcast()
} else {
pkt.SetUnicast()
}
return pkt, nil
}
// PrependModifiers prepends other to m.
func PrependModifiers(m []Modifier, other ...Modifier) []Modifier {
return append(other, m...)
}
// NewInform builds a new DHCPv4 Informational message with the specified
// hardware address.
func NewInform(hwaddr net.HardwareAddr, localIP net.IP, modifiers ...Modifier) (*DHCPv4, error) {
return New(PrependModifiers(modifiers,
WithHwAddr(hwaddr),
WithMessageType(MessageTypeInform),
WithClientIP(localIP),
)...)
}
// NewRequestFromOffer builds a DHCPv4 request from an offer.
// It assumes the SELECTING state by default, see Section 4.3.2 in RFC 2131 for more details.
func NewRequestFromOffer(offer *DHCPv4, modifiers ...Modifier) (*DHCPv4, error) {
return New(PrependModifiers(modifiers,
WithReply(offer),
WithMessageType(MessageTypeRequest),
WithClientIP(offer.ClientIPAddr),
WithOption(OptRequestedIPAddress(offer.YourIPAddr)),
// This is usually the server IP.
WithOptionCopied(offer, OptionServerIdentifier),
WithRequestedOptions(
OptionSubnetMask,
OptionRouter,
OptionDomainName,
OptionDomainNameServer,
),
)...)
}
// NewRenewFromAck builds a DHCPv4 RENEW-style request from the ACK of a lease. RENEW requests have
// minor changes to their options compared to SELECT requests as specified by RFC 2131, section 4.3.2.
func NewRenewFromAck(ack *DHCPv4, modifiers ...Modifier) (*DHCPv4, error) {
return New(PrependModifiers(modifiers,
WithReply(ack),
WithMessageType(MessageTypeRequest),
// The client IP must be filled in with the IP offered to the client
WithClientIP(ack.YourIPAddr),
// The renewal request must use unicast
WithBroadcast(false),
WithRequestedOptions(
OptionSubnetMask,
OptionRouter,
OptionDomainName,
OptionDomainNameServer,
),
)...)
}
// NewReplyFromRequest builds a DHCPv4 reply from a request.
func NewReplyFromRequest(request *DHCPv4, modifiers ...Modifier) (*DHCPv4, error) {
return New(PrependModifiers(modifiers,
WithReply(request),
WithGatewayIP(request.GatewayIPAddr),
WithOptionCopied(request, OptionRelayAgentInformation),
// RFC 6842 states the Client Identifier option must be copied
// from the request if a client specified it.
WithOptionCopied(request, OptionClientIdentifier),
)...)
}
// NewReleaseFromACK creates a DHCPv4 Release message from ACK.
// default Release message without any Modifer is created as following:
// - option Message Type is Release
// - ClientIP is set to ack.YourIPAddr
// - ClientHWAddr is set to ack.ClientHWAddr
// - Unicast
// - option Server Identifier is set to ack's ServerIdentifier
func NewReleaseFromACK(ack *DHCPv4, modifiers ...Modifier) (*DHCPv4, error) {
return New(PrependModifiers(modifiers,
WithMessageType(MessageTypeRelease),
WithClientIP(ack.YourIPAddr),
WithHwAddr(ack.ClientHWAddr),
WithBroadcast(false),
WithOptionCopied(ack, OptionServerIdentifier),
)...)
}
// FromBytes decodes a DHCPv4 packet from a sequence of bytes, and returns an
// error if the packet is not valid.
func FromBytes(q []byte) (*DHCPv4, error) {
var p DHCPv4
buf := uio.NewBigEndianBuffer(q)
p.OpCode = OpcodeType(buf.Read8())
p.HWType = iana.HWType(buf.Read8())
hwAddrLen := buf.Read8()
p.HopCount = buf.Read8()
buf.ReadBytes(p.TransactionID[:])
p.NumSeconds = buf.Read16()
p.Flags = buf.Read16()
p.ClientIPAddr = net.IP(buf.CopyN(net.IPv4len))
p.YourIPAddr = net.IP(buf.CopyN(net.IPv4len))
p.ServerIPAddr = net.IP(buf.CopyN(net.IPv4len))
p.GatewayIPAddr = net.IP(buf.CopyN(net.IPv4len))
if hwAddrLen > 16 {
hwAddrLen = 16
}
// Always read 16 bytes, but only use hwaddrlen of them.
p.ClientHWAddr = make(net.HardwareAddr, 16)
buf.ReadBytes(p.ClientHWAddr)
p.ClientHWAddr = p.ClientHWAddr[:hwAddrLen]
var sname [64]byte
buf.ReadBytes(sname[:])
length := strings.Index(string(sname[:]), "\x00")
if length == -1 {
length = 64
}
p.ServerHostName = string(sname[:length])
var file [128]byte
buf.ReadBytes(file[:])
length = strings.Index(string(file[:]), "\x00")
if length == -1 {
length = 128
}
p.BootFileName = string(file[:length])
var cookie [4]byte
buf.ReadBytes(cookie[:])
if err := buf.Error(); err != nil {
return nil, err
}
if cookie != magicCookie {
return nil, fmt.Errorf("malformed DHCP packet: got magic cookie %v, want %v", cookie[:], magicCookie[:])
}
p.Options = make(Options)
if err := p.Options.fromBytesCheckEnd(buf.Data(), true); err != nil {
return nil, err
}
return &p, nil
}
// FlagsToString returns a human-readable representation of the flags field.
func (d *DHCPv4) FlagsToString() string {
flags := ""
if d.IsBroadcast() {
flags += "Broadcast"
} else {
flags += "Unicast"
}
if d.Flags&0xfe != 0 {
flags += " (reserved bits not zeroed)"
}
return flags
}
// IsBroadcast indicates whether the packet is a broadcast packet.
func (d *DHCPv4) IsBroadcast() bool {
return d.Flags&0x8000 == 0x8000
}
// SetBroadcast sets the packet to be a broadcast packet.
func (d *DHCPv4) SetBroadcast() {
d.Flags |= 0x8000
}
// IsUnicast indicates whether the packet is a unicast packet.
func (d *DHCPv4) IsUnicast() bool {
return d.Flags&0x8000 == 0
}
// SetUnicast sets the packet to be a unicast packet.
func (d *DHCPv4) SetUnicast() {
d.Flags &= ^uint16(0x8000)
}
// GetOneOption returns the option that matches the given option code.
//
// According to RFC 3396, options that are specified more than once are
// concatenated, and hence this should always just return one option.
func (d *DHCPv4) GetOneOption(code OptionCode) []byte {
return d.Options.Get(code)
}
// DeleteOption deletes an existing option with the given option code.
func (d *DHCPv4) DeleteOption(code OptionCode) {
if d.Options != nil {
d.Options.Del(code)
}
}
// UpdateOption replaces an existing option with the same option code with the
// given one, adding it if not already present.
func (d *DHCPv4) UpdateOption(opt Option) {
if d.Options == nil {
d.Options = make(Options)
}
d.Options.Update(opt)
}
// String implements fmt.Stringer.
func (d *DHCPv4) String() string {
return fmt.Sprintf("DHCPv4(xid=%s hwaddr=%s msg_type=%s, your_ip=%s, server_ip=%s)",
d.TransactionID, d.ClientHWAddr, d.MessageType(), d.YourIPAddr, d.ServerIPAddr)
}
// SummaryWithVendor prints a summary of the packet, interpreting the
// vendor-specific info option using the given parser (can be nil).
func (d *DHCPv4) SummaryWithVendor(vendorDecoder OptionDecoder) string {
ret := fmt.Sprintf(
"DHCPv4 Message\n"+
" opcode: %s\n"+
" hwtype: %s\n"+
" hopcount: %v\n"+
" transaction ID: %s\n"+
" num seconds: %v\n"+
" flags: %v (0x%02x)\n"+
" client IP: %s\n"+
" your IP: %s\n"+
" server IP: %s\n"+
" gateway IP: %s\n"+
" client MAC: %s\n"+
" server hostname: %s\n"+
" bootfile name: %s\n",
d.OpCode,
d.HWType,
d.HopCount,
d.TransactionID,
d.NumSeconds,
d.FlagsToString(),
d.Flags,
d.ClientIPAddr,
d.YourIPAddr,
d.ServerIPAddr,
d.GatewayIPAddr,
d.ClientHWAddr,
d.ServerHostName,
d.BootFileName,
)
ret += " options:\n"
ret += d.Options.Summary(vendorDecoder)
return ret
}
// Summary prints detailed information about the packet.
func (d *DHCPv4) Summary() string {
return d.SummaryWithVendor(nil)
}
// IsOptionRequested returns true if that option is within the requested
// options of the DHCPv4 message.
func (d *DHCPv4) IsOptionRequested(requested OptionCode) bool {
rq := d.ParameterRequestList()
if rq == nil {
// RFC2131§3.5
// Not all clients require initialization of all parameters [...]
// Two techniques are used to reduce the number of parameters transmitted from
// the server to the client. [...] Second, in its initial DHCPDISCOVER or
// DHCPREQUEST message, a client may provide the server with a list of specific
// parameters the client is interested in.
// We interpret this to say that all available parameters should be sent if
// the parameter request list is not sent at all.
return true
}
for _, o := range rq {
if o == requested {
return true
}
}
return false
}
// In case somebody forgets to set an IP, just write 0s as default values.
func writeIP(b *uio.Lexer, ip net.IP) {
var zeros [net.IPv4len]byte
if ip == nil {
b.WriteBytes(zeros[:])
} else {
// Converting IP to 4 byte format
ip = ip.To4()
b.WriteBytes(ip[:net.IPv4len])
}
}
// ToBytes writes the packet to binary.
func (d *DHCPv4) ToBytes() []byte {
buf := uio.NewBigEndianBuffer(make([]byte, 0, minPacketLen))
buf.Write8(uint8(d.OpCode))
buf.Write8(uint8(d.HWType))
// HwAddrLen
hlen := uint8(len(d.ClientHWAddr))
buf.Write8(hlen)
buf.Write8(d.HopCount)
buf.WriteBytes(d.TransactionID[:])
buf.Write16(d.NumSeconds)
buf.Write16(d.Flags)
writeIP(buf, d.ClientIPAddr)
writeIP(buf, d.YourIPAddr)
writeIP(buf, d.ServerIPAddr)
writeIP(buf, d.GatewayIPAddr)
copy(buf.WriteN(16), d.ClientHWAddr)
var sname [64]byte
copy(sname[:63], []byte(d.ServerHostName))
buf.WriteBytes(sname[:])
var file [128]byte
copy(file[:127], []byte(d.BootFileName))
buf.WriteBytes(file[:])
// The magic cookie.
buf.WriteBytes(magicCookie[:])
// Write all options.
d.Options.Marshal(buf)
// Finish the options.
buf.Write8(OptionEnd.Code())
// DHCP is based on BOOTP, and BOOTP messages have a minimum length of
// 300 bytes per RFC 951. This not stated explicitly, but if you sum up
// all the bytes in the message layout, you'll get 300 bytes.
//
// Some DHCP servers and relay agents care about this BOOTP legacy B.S.
// and "conveniently" drop messages that are less than 300 bytes long.
if buf.Len() < bootpMinLen {
buf.WriteBytes(bytes.Repeat([]byte{OptionPad.Code()}, bootpMinLen-buf.Len()))
}
return buf.Data()
}
// GetBroadcastAddress returns the DHCPv4 Broadcast Address value in d.
//
// The broadcast address option is described in RFC 2132, Section 5.3.
func (d *DHCPv4) BroadcastAddress() net.IP {
return GetIP(OptionBroadcastAddress, d.Options)
}
// RequestedIPAddress returns the DHCPv4 Requested IP Address value in d.
//
// The requested IP address option is described by RFC 2132, Section 9.1.
func (d *DHCPv4) RequestedIPAddress() net.IP {
return GetIP(OptionRequestedIPAddress, d.Options)
}
// ServerIdentifier returns the DHCPv4 Server Identifier value in d.
//
// The server identifier option is described by RFC 2132, Section 9.7.
func (d *DHCPv4) ServerIdentifier() net.IP {
return GetIP(OptionServerIdentifier, d.Options)
}
// Router parses the DHCPv4 Router option if present.
//
// The Router option is described by RFC 2132, Section 3.5.
func (d *DHCPv4) Router() []net.IP {
return GetIPs(OptionRouter, d.Options)
}
// ClasslessStaticRoute parses the DHCPv4 Classless Static Route option if present.
//
// The Classless Static Route option is described by RFC 3442.
func (d *DHCPv4) ClasslessStaticRoute() []*Route {
v := d.Options.Get(OptionClasslessStaticRoute)
if v == nil {
return nil
}
var routes Routes
if err := routes.FromBytes(v); err != nil {
return nil
}
return routes
}
// NTPServers parses the DHCPv4 NTP Servers option if present.
//
// The NTP servers option is described by RFC 2132, Section 8.3.
func (d *DHCPv4) NTPServers() []net.IP {
return GetIPs(OptionNTPServers, d.Options)
}
// DNS parses the DHCPv4 Domain Name Server option if present.
//
// The DNS server option is described by RFC 2132, Section 3.8.
func (d *DHCPv4) DNS() []net.IP {
return GetIPs(OptionDomainNameServer, d.Options)
}
// DomainName parses the DHCPv4 Domain Name option if present.
//
// The Domain Name option is described by RFC 2132, Section 3.17.
func (d *DHCPv4) DomainName() string {
return GetString(OptionDomainName, d.Options)
}
// HostName parses the DHCPv4 Host Name option if present.
//
// The Host Name option is described by RFC 2132, Section 3.14.
func (d *DHCPv4) HostName() string {
name := GetString(OptionHostName, d.Options)
return strings.TrimRight(name, "\x00")
}
// RootPath parses the DHCPv4 Root Path option if present.
//
// The Root Path option is described by RFC 2132, Section 3.19.
func (d *DHCPv4) RootPath() string {
return GetString(OptionRootPath, d.Options)
}
// BootFileNameOption parses the DHCPv4 Bootfile Name option if present.
//
// The Bootfile Name option is described by RFC 2132, Section 9.5.
func (d *DHCPv4) BootFileNameOption() string {
name := GetString(OptionBootfileName, d.Options)
return strings.TrimRight(name, "\x00")
}
// TFTPServerName parses the DHCPv4 TFTP Server Name option if present.
//
// The TFTP Server Name option is described by RFC 2132, Section 9.4.
func (d *DHCPv4) TFTPServerName() string {
name := GetString(OptionTFTPServerName, d.Options)
return strings.TrimRight(name, "\x00")
}
// ClassIdentifier parses the DHCPv4 Class Identifier option if present.
//
// The Vendor Class Identifier option is described by RFC 2132, Section 9.13.
func (d *DHCPv4) ClassIdentifier() string {
return GetString(OptionClassIdentifier, d.Options)
}
// ClientArch returns the Client System Architecture Type option.
func (d *DHCPv4) ClientArch() []iana.Arch {
v := d.Options.Get(OptionClientSystemArchitectureType)
if v == nil {
return nil
}
var archs iana.Archs
if err := archs.FromBytes(v); err != nil {
return nil
}
return archs
}
// DomainSearch returns the domain search list if present.
//
// The domain search option is described by RFC 3397, Section 2.
func (d *DHCPv4) DomainSearch() *rfc1035label.Labels {
v := d.Options.Get(OptionDNSDomainSearchList)
if v == nil {
return nil
}
labels, err := rfc1035label.FromBytes(v)
if err != nil {
return nil
}
return labels
}
// IPAddressLeaseTime returns the IP address lease time or the given
// default duration if not present.
//
// The IP address lease time option is described by RFC 2132, Section 9.2.
func (d *DHCPv4) IPAddressLeaseTime(def time.Duration) time.Duration {
v := d.Options.Get(OptionIPAddressLeaseTime)
if v == nil {
return def
}
var dur Duration
if err := dur.FromBytes(v); err != nil {
return def
}
return time.Duration(dur)
}
// IPAddressRenewalTime returns the IP address renewal time or the given
// default duration if not present.
//
// The IP address renewal time option is described by RFC 2132, Section 9.11.
func (d *DHCPv4) IPAddressRenewalTime(def time.Duration) time.Duration {
v := d.Options.Get(OptionRenewTimeValue)
if v == nil {
return def
}
var dur Duration
if err := dur.FromBytes(v); err != nil {
return def
}
return time.Duration(dur)
}
// IPAddressRebindingTime returns the IP address rebinding time or the given
// default duration if not present.
//
// The IP address rebinding time option is described by RFC 2132, Section 9.12.
func (d *DHCPv4) IPAddressRebindingTime(def time.Duration) time.Duration {
v := d.Options.Get(OptionRebindingTimeValue)
if v == nil {
return def
}
var dur Duration
if err := dur.FromBytes(v); err != nil {
return def
}
return time.Duration(dur)
}
// MaxMessageSize returns the DHCP Maximum Message Size if present.
//
// The Maximum DHCP Message Size option is described by RFC 2132, Section 9.10.
func (d *DHCPv4) MaxMessageSize() (uint16, error) {
return GetUint16(OptionMaximumDHCPMessageSize, d.Options)
}
// MessageType returns the DHCPv4 Message Type option.
func (d *DHCPv4) MessageType() MessageType {
v := d.Options.Get(OptionDHCPMessageType)
if v == nil {
return MessageTypeNone
}
var m MessageType
if err := m.FromBytes(v); err != nil {
return MessageTypeNone
}
return m
}
// Message returns the DHCPv4 (Error) Message option.
//
// The message options is described in RFC 2132, Section 9.9.
func (d *DHCPv4) Message() string {
return GetString(OptionMessage, d.Options)
}
// ParameterRequestList returns the DHCPv4 Parameter Request List.
//
// The parameter request list option is described by RFC 2132, Section 9.8.
func (d *DHCPv4) ParameterRequestList() OptionCodeList {
v := d.Options.Get(OptionParameterRequestList)
if v == nil {
return nil
}
var codes OptionCodeList
if err := codes.FromBytes(v); err != nil {
return nil
}
return codes
}
// RelayAgentInfo returns options embedded by the relay agent.
//
// The relay agent info option is described by RFC 3046.
func (d *DHCPv4) RelayAgentInfo() *RelayOptions {
v := d.Options.Get(OptionRelayAgentInformation)
if v == nil {
return nil
}
var relayOptions RelayOptions
if err := relayOptions.FromBytes(v); err != nil {
return nil
}
return &relayOptions
}
// SubnetMask returns a subnet mask option contained if present.
//
// The subnet mask option is described by RFC 2132, Section 3.3.
func (d *DHCPv4) SubnetMask() net.IPMask {
v := d.Options.Get(OptionSubnetMask)
if v == nil {
return nil
}
var im IPMask
if err := im.FromBytes(v); err != nil {
return nil
}
return net.IPMask(im)
}
// UserClass returns the user class if present.
//
// The user class information option is defined by RFC 3004.
func (d *DHCPv4) UserClass() []string {
v := d.Options.Get(OptionUserClassInformation)
if v == nil {
return nil
}
var uc Strings
if err := uc.FromBytes(v); err != nil {
return []string{GetString(OptionUserClassInformation, d.Options)}
}
return uc
}
// VIVC returns the vendor-identifying vendor class option if present.
func (d *DHCPv4) VIVC() VIVCIdentifiers {
v := d.Options.Get(OptionVendorIdentifyingVendorClass)
if v == nil {
return nil
}
var ids VIVCIdentifiers
if err := ids.FromBytes(v); err != nil {
return nil
}
return ids
}

171
vendor/github.com/insomniacslk/dhcp/dhcpv4/modifiers.go generated vendored Normal file
View File

@@ -0,0 +1,171 @@
package dhcpv4
import (
"net"
"time"
"github.com/insomniacslk/dhcp/iana"
"github.com/insomniacslk/dhcp/rfc1035label"
)
// WithTransactionID sets the Transaction ID for the DHCPv4 packet
func WithTransactionID(xid TransactionID) Modifier {
return func(d *DHCPv4) {
d.TransactionID = xid
}
}
// WithClientIP sets the Client IP for a DHCPv4 packet.
func WithClientIP(ip net.IP) Modifier {
return func(d *DHCPv4) {
d.ClientIPAddr = ip
}
}
// WithYourIP sets the Your IP for a DHCPv4 packet.
func WithYourIP(ip net.IP) Modifier {
return func(d *DHCPv4) {
d.YourIPAddr = ip
}
}
// WithServerIP sets the Server IP for a DHCPv4 packet.
func WithServerIP(ip net.IP) Modifier {
return func(d *DHCPv4) {
d.ServerIPAddr = ip
}
}
// WithGatewayIP sets the Gateway IP for the DHCPv4 packet.
func WithGatewayIP(ip net.IP) Modifier {
return func(d *DHCPv4) {
d.GatewayIPAddr = ip
}
}
// WithOptionCopied copies the value of option opt from request.
func WithOptionCopied(request *DHCPv4, opt OptionCode) Modifier {
return func(d *DHCPv4) {
if val := request.Options.Get(opt); val != nil {
d.UpdateOption(OptGeneric(opt, val))
}
}
}
// WithReply fills in opcode, hwtype, xid, clienthwaddr, and flags from the given packet.
func WithReply(request *DHCPv4) Modifier {
return func(d *DHCPv4) {
if request.OpCode == OpcodeBootRequest {
d.OpCode = OpcodeBootReply
} else {
d.OpCode = OpcodeBootRequest
}
d.HWType = request.HWType
d.TransactionID = request.TransactionID
d.ClientHWAddr = request.ClientHWAddr
d.Flags = request.Flags
}
}
// WithHWType sets the Hardware Type for a DHCPv4 packet.
func WithHWType(hwt iana.HWType) Modifier {
return func(d *DHCPv4) {
d.HWType = hwt
}
}
// WithBroadcast sets the packet to be broadcast or unicast
func WithBroadcast(broadcast bool) Modifier {
return func(d *DHCPv4) {
if broadcast {
d.SetBroadcast()
} else {
d.SetUnicast()
}
}
}
// WithHwAddr sets the hardware address for a packet
func WithHwAddr(hwaddr net.HardwareAddr) Modifier {
return func(d *DHCPv4) {
d.ClientHWAddr = hwaddr
}
}
// WithOption appends a DHCPv4 option provided by the user
func WithOption(opt Option) Modifier {
return func(d *DHCPv4) {
d.UpdateOption(opt)
}
}
// WithoutOption removes the DHCPv4 option with the given code
func WithoutOption(code OptionCode) Modifier {
return func(d *DHCPv4) {
d.DeleteOption(code)
}
}
// WithUserClass adds a user class option to the packet.
// The rfc parameter allows you to specify if the userclass should be
// rfc compliant or not. More details in issue #113
func WithUserClass(uc string, rfc bool) Modifier {
// TODO let the user specify multiple user classes
return func(d *DHCPv4) {
if rfc {
d.UpdateOption(OptRFC3004UserClass([]string{uc}))
} else {
d.UpdateOption(OptUserClass(uc))
}
}
}
// WithNetboot adds bootfile URL and bootfile param options to a DHCPv4 packet.
func WithNetboot(d *DHCPv4) {
WithRequestedOptions(OptionTFTPServerName, OptionBootfileName)(d)
}
// WithMessageType adds the DHCPv4 message type m to a packet.
func WithMessageType(m MessageType) Modifier {
return WithOption(OptMessageType(m))
}
// WithRequestedOptions adds requested options to the packet.
func WithRequestedOptions(optionCodes ...OptionCode) Modifier {
return func(d *DHCPv4) {
cl := d.ParameterRequestList()
cl.Add(optionCodes...)
d.UpdateOption(OptParameterRequestList(cl...))
}
}
// WithRelay adds parameters required for DHCPv4 to be relayed by the relay
// server with given ip
func WithRelay(ip net.IP) Modifier {
return func(d *DHCPv4) {
d.SetUnicast()
d.GatewayIPAddr = ip
d.HopCount++
}
}
// WithNetmask adds or updates an OptSubnetMask
func WithNetmask(mask net.IPMask) Modifier {
return WithOption(OptSubnetMask(mask))
}
// WithLeaseTime adds or updates an OptIPAddressLeaseTime
func WithLeaseTime(leaseTime uint32) Modifier {
return WithOption(OptIPAddressLeaseTime(time.Duration(leaseTime) * time.Second))
}
// WithDomainSearchList adds or updates an OptionDomainSearch
func WithDomainSearchList(searchList ...string) Modifier {
return WithOption(OptDomainSearch(&rfc1035label.Labels{
Labels: searchList,
}))
}
func WithGeneric(code OptionCode, value []byte) Modifier {
return WithOption(OptGeneric(code, value))
}

View File

@@ -0,0 +1,27 @@
package dhcpv4
import (
"fmt"
)
// OptionGeneric is an option that only contains the option code and associated
// data. Every option that does not have a specific implementation will fall
// back to this option.
type OptionGeneric struct {
Data []byte
}
// ToBytes returns a serialized generic option as a slice of bytes.
func (o OptionGeneric) ToBytes() []byte {
return o.Data
}
// String returns a human-readable representation of a generic option.
func (o OptionGeneric) String() string {
return fmt.Sprintf("%v", o.Data)
}
// OptGeneric returns a generic option.
func OptGeneric(code OptionCode, value []byte) Option {
return Option{Code: code, Value: OptionGeneric{value}}
}

View File

@@ -0,0 +1,62 @@
package dhcpv4
import (
"net"
"github.com/u-root/uio/uio"
)
// IP implements DHCPv4 IP option marshaling and unmarshaling as described by
// RFC 2132, Sections 5.3, 9.1, 9.7, and others.
type IP net.IP
// FromBytes parses an IP from data in binary form.
func (i *IP) FromBytes(data []byte) error {
buf := uio.NewBigEndianBuffer(data)
*i = IP(buf.CopyN(net.IPv4len))
return buf.FinError()
}
// ToBytes returns a serialized stream of bytes for this option.
func (i IP) ToBytes() []byte {
return []byte(net.IP(i).To4())
}
// String returns a human-readable IP.
func (i IP) String() string {
return net.IP(i).String()
}
// GetIP returns code out of o parsed as an IP.
func GetIP(code OptionCode, o Options) net.IP {
v := o.Get(code)
if v == nil {
return nil
}
var ip IP
if err := ip.FromBytes(v); err != nil {
return nil
}
return net.IP(ip)
}
// OptBroadcastAddress returns a new DHCPv4 Broadcast Address option.
//
// The broadcast address option is described in RFC 2132, Section 5.3.
func OptBroadcastAddress(ip net.IP) Option {
return Option{Code: OptionBroadcastAddress, Value: IP(ip)}
}
// OptRequestedIPAddress returns a new DHCPv4 Requested IP Address option.
//
// The requested IP address option is described by RFC 2132, Section 9.1.
func OptRequestedIPAddress(ip net.IP) Option {
return Option{Code: OptionRequestedIPAddress, Value: IP(ip)}
}
// OptServerIdentifier returns a new DHCPv4 Server Identifier option.
//
// The server identifier option is described by RFC 2132, Section 9.7.
func OptServerIdentifier(ip net.IP) Option {
return Option{Code: OptionServerIdentifier, Value: IP(ip)}
}

View File

@@ -0,0 +1,41 @@
package dhcpv4
import (
"math"
"time"
"github.com/u-root/uio/uio"
)
// MaxLeaseTime is the maximum lease time that can be encoded.
var MaxLeaseTime = math.MaxUint32 * time.Second
// Duration implements the IP address lease time option described by RFC 2132,
// Section 9.2.
type Duration time.Duration
// FromBytes parses a duration from a byte stream according to RFC 2132, Section 9.2.
func (d *Duration) FromBytes(data []byte) error {
buf := uio.NewBigEndianBuffer(data)
*d = Duration(time.Duration(buf.Read32()) * time.Second)
return buf.FinError()
}
// ToBytes returns a serialized stream of bytes for this option.
func (d Duration) ToBytes() []byte {
buf := uio.NewBigEndianBuffer(nil)
buf.Write32(uint32(time.Duration(d) / time.Second))
return buf.Data()
}
// String returns a human-readable string for this option.
func (d Duration) String() string {
return time.Duration(d).String()
}
// OptIPAddressLeaseTime returns a new IP address lease time option.
//
// The IP address lease time option is described by RFC 2132, Section 9.2.
func OptIPAddressLeaseTime(d time.Duration) Option {
return Option{Code: OptionIPAddressLeaseTime, Value: Duration(d)}
}

View File

@@ -0,0 +1,103 @@
package dhcpv4
import (
"fmt"
"net"
"strings"
"github.com/u-root/uio/uio"
)
// IPs are IPv4 addresses from a DHCP packet as used and specified by options
// in RFC 2132, Sections 3.5 through 3.13, 8.2, 8.3, 8.5, 8.6, 8.9, and 8.10.
//
// IPs implements the OptionValue type.
type IPs []net.IP
// FromBytes parses an IPv4 address from a DHCP packet as used and specified by
// options in RFC 2132, Sections 3.5 through 3.13, 8.2, 8.3, 8.5, 8.6, 8.9, and
// 8.10.
func (i *IPs) FromBytes(data []byte) error {
buf := uio.NewBigEndianBuffer(data)
if buf.Len() == 0 {
return fmt.Errorf("IP DHCP options must always list at least one IP")
}
*i = make(IPs, 0, buf.Len()/net.IPv4len)
for buf.Has(net.IPv4len) {
*i = append(*i, net.IP(buf.CopyN(net.IPv4len)))
}
return buf.FinError()
}
// ToBytes marshals IPv4 addresses to a DHCP packet as specified by RFC 2132,
// Section 3.5 et al.
func (i IPs) ToBytes() []byte {
buf := uio.NewBigEndianBuffer(nil)
for _, ip := range i {
buf.WriteBytes(ip.To4())
}
return buf.Data()
}
// String returns a human-readable representation of a list of IPs.
func (i IPs) String() string {
s := make([]string, 0, len(i))
for _, ip := range i {
s = append(s, ip.String())
}
return strings.Join(s, ", ")
}
// GetIPs parses a list of IPs from code in o.
func GetIPs(code OptionCode, o Options) []net.IP {
v := o.Get(code)
if v == nil {
return nil
}
var ips IPs
if err := ips.FromBytes(v); err != nil {
return nil
}
return []net.IP(ips)
}
// OptRouter returns a new DHCPv4 Router option.
//
// The Router option is described by RFC 2132, Section 3.5.
func OptRouter(routers ...net.IP) Option {
return Option{
Code: OptionRouter,
Value: IPs(routers),
}
}
// WithRouter updates a packet with the DHCPv4 Router option.
func WithRouter(routers ...net.IP) Modifier {
return WithOption(OptRouter(routers...))
}
// OptNTPServers returns a new DHCPv4 NTP Server option.
//
// The NTP servers option is described by RFC 2132, Section 8.3.
func OptNTPServers(ntpServers ...net.IP) Option {
return Option{
Code: OptionNTPServers,
Value: IPs(ntpServers),
}
}
// OptDNS returns a new DHCPv4 Domain Name Server option.
//
// The DNS server option is described by RFC 2132, Section 3.8.
func OptDNS(servers ...net.IP) Option {
return Option{
Code: OptionDomainNameServer,
Value: IPs(servers),
}
}
// WithDNS modifies a packet with the DHCPv4 Domain Name Server option.
func WithDNS(servers ...net.IP) Modifier {
return WithOption(OptDNS(servers...))
}

View File

@@ -0,0 +1,50 @@
package dhcpv4
import (
"fmt"
"github.com/u-root/uio/uio"
)
// Uint16 implements encoding and decoding functions for a uint16 as used in
// RFC 2132, Section 9.10.
type Uint16 uint16
// ToBytes returns a serialized stream of bytes for this option.
func (o Uint16) ToBytes() []byte {
buf := uio.NewBigEndianBuffer(nil)
buf.Write16(uint16(o))
return buf.Data()
}
// String returns a human-readable string for this option.
func (o Uint16) String() string {
return fmt.Sprintf("%d", uint16(o))
}
// FromBytes decodes data into o as per RFC 2132, Section 9.10.
func (o *Uint16) FromBytes(data []byte) error {
buf := uio.NewBigEndianBuffer(data)
*o = Uint16(buf.Read16())
return buf.FinError()
}
// GetUint16 parses a uint16 from code in o.
func GetUint16(code OptionCode, o Options) (uint16, error) {
v := o.Get(code)
if v == nil {
return 0, fmt.Errorf("option not present")
}
var u Uint16
if err := u.FromBytes(v); err != nil {
return 0, err
}
return uint16(u), nil
}
// OptMaxMessageSize returns a new DHCP Maximum Message Size option.
//
// The Maximum DHCP Message Size option is described by RFC 2132, Section 9.10.
func OptMaxMessageSize(size uint16) Option {
return Option{Code: OptionMaximumDHCPMessageSize, Value: Uint16(size)}
}

View File

@@ -0,0 +1,6 @@
package dhcpv4
// OptMessageType returns a new DHCPv4 Message Type option.
func OptMessageType(m MessageType) Option {
return Option{Code: OptionDHCPMessageType, Value: m}
}

View File

@@ -0,0 +1,23 @@
package dhcpv4
import (
"github.com/insomniacslk/dhcp/iana"
"github.com/insomniacslk/dhcp/rfc1035label"
)
// OptDomainSearch returns a new domain search option.
//
// The domain search option is described by RFC 3397, Section 2.
func OptDomainSearch(labels *rfc1035label.Labels) Option {
return Option{Code: OptionDNSDomainSearchList, Value: labels}
}
// OptClientArch returns a new Client System Architecture Type option.
func OptClientArch(archs ...iana.Arch) Option {
return Option{Code: OptionClientSystemArchitectureType, Value: iana.Archs(archs)}
}
// OptClientIdentifier returns a new Client Identifier option.
func OptClientIdentifier(ident []byte) Option {
return OptGeneric(OptionClientIdentifier, ident)
}

View File

@@ -0,0 +1,72 @@
package dhcpv4
import (
"sort"
"strings"
"github.com/u-root/uio/uio"
)
// OptionCodeList is a list of DHCP option codes.
type OptionCodeList []OptionCode
// Has returns whether c is in the list.
func (ol OptionCodeList) Has(c OptionCode) bool {
for _, code := range ol {
if code == c {
return true
}
}
return false
}
// Add adds option codes in cs to ol.
func (ol *OptionCodeList) Add(cs ...OptionCode) {
for _, c := range cs {
if !ol.Has(c) {
*ol = append(*ol, c)
}
}
}
func (ol OptionCodeList) sort() {
sort.Slice(ol, func(i, j int) bool { return ol[i].Code() < ol[j].Code() })
}
// String returns a human-readable string for the option names.
func (ol OptionCodeList) String() string {
var names []string
ol.sort()
for _, code := range ol {
names = append(names, code.String())
}
return strings.Join(names, ", ")
}
// ToBytes returns a serialized stream of bytes for this option as defined by
// RFC 2132, Section 9.8.
func (ol OptionCodeList) ToBytes() []byte {
buf := uio.NewBigEndianBuffer(nil)
for _, req := range ol {
buf.Write8(req.Code())
}
return buf.Data()
}
// FromBytes parses a byte stream for this option as described by RFC 2132,
// Section 9.8.
func (ol *OptionCodeList) FromBytes(data []byte) error {
buf := uio.NewBigEndianBuffer(data)
*ol = make(OptionCodeList, 0, buf.Len())
for buf.Has(1) {
*ol = append(*ol, optionCode(buf.Read8()))
}
return buf.FinError()
}
// OptParameterRequestList returns a new DHCPv4 Parameter Request List.
//
// The parameter request list option is described by RFC 2132, Section 9.8.
func OptParameterRequestList(codes ...OptionCode) Option {
return Option{Code: OptionParameterRequestList, Value: OptionCodeList(codes)}
}

View File

@@ -0,0 +1,92 @@
package dhcpv4
import (
"fmt"
)
// RelayOptions is like Options, but stringifies using the Relay Agent Specific
// option space.
type RelayOptions struct {
Options
}
var relayHumanizer = OptionHumanizer{
ValueHumanizer: func(code OptionCode, data []byte) fmt.Stringer {
return raiSubOptionValue{data}
},
CodeHumanizer: func(c uint8) OptionCode {
return raiSubOptionCode(c)
},
}
// String prints the contained options using Relay Agent-specific option code parsing.
func (r RelayOptions) String() string {
return "\n" + r.Options.ToString(relayHumanizer)
}
// FromBytes parses relay agent options from data.
func (r *RelayOptions) FromBytes(data []byte) error {
r.Options = make(Options)
return r.Options.FromBytes(data)
}
// OptRelayAgentInfo returns a new DHCP Relay Agent Info option.
//
// The relay agent info option is described by RFC 3046.
func OptRelayAgentInfo(o ...Option) Option {
return Option{Code: OptionRelayAgentInformation, Value: RelayOptions{OptionsFromList(o...)}}
}
type raiSubOptionValue struct {
val []byte
}
func (rv raiSubOptionValue) String() string {
return fmt.Sprintf("%s (%v)", string(rv.val), rv.val)
}
type raiSubOptionCode uint8
func (o raiSubOptionCode) Code() uint8 {
return uint8(o)
}
func (o raiSubOptionCode) String() string {
if s, ok := raiSubOptionCodeToString[o]; ok {
return s
}
return fmt.Sprintf("unknown (%d)", o)
}
// Option 82 Relay Agention Information Sub Options
const (
AgentCircuitIDSubOption raiSubOptionCode = 1 // RFC 3046
AgentRemoteIDSubOption raiSubOptionCode = 2 // RFC 3046
DOCSISDeviceClassSubOption raiSubOptionCode = 4 // RFC 3256
LinkSelectionSubOption raiSubOptionCode = 5 // RFC 3527
SubscriberIDSubOption raiSubOptionCode = 6 // RFC 3993
RADIUSAttributesSubOption raiSubOptionCode = 7 // RFC 4014
AuthenticationSubOption raiSubOptionCode = 8 // RFC 4030
VendorSpecificInformationSubOption raiSubOptionCode = 9 // RFC 4243
RelayAgentFlagsSubOption raiSubOptionCode = 10 // RFC 5010
ServerIdentifierOverrideSubOption raiSubOptionCode = 11 // RFC 5107
RelaySourcePortSubOption raiSubOptionCode = 19 // RFC 8357
VirtualSubnetSelectionSubOption raiSubOptionCode = 151 // RFC 6607
VirtualSubnetSelectionControlSubOption raiSubOptionCode = 152 // RFC 6607
)
var raiSubOptionCodeToString = map[raiSubOptionCode]string{
AgentCircuitIDSubOption: "Agent Circuit ID Sub-option",
AgentRemoteIDSubOption: "Agent Remote ID Sub-option",
DOCSISDeviceClassSubOption: "DOCSIS Device Class Sub-option",
LinkSelectionSubOption: "Link Selection Sub-option",
SubscriberIDSubOption: "Subscriber ID Sub-option",
RADIUSAttributesSubOption: "RADIUS Attributes Sub-option",
AuthenticationSubOption: "Authentication Sub-option",
VendorSpecificInformationSubOption: "Vendor Specific Sub-option",
RelayAgentFlagsSubOption: "Relay Agent Flags Sub-option",
ServerIdentifierOverrideSubOption: "Server Identifier Override Sub-option",
RelaySourcePortSubOption: "Relay Source Port Sub-option",
VirtualSubnetSelectionSubOption: "Virtual Subnet Selection Sub-option",
VirtualSubnetSelectionControlSubOption: "Virtual Subnet Selection Control Sub-option",
}

View File

@@ -0,0 +1,104 @@
package dhcpv4
import (
"fmt"
"net"
"strings"
"github.com/u-root/uio/uio"
)
// Route is a classless static route as per RFC 3442.
type Route struct {
// Dest is the destination network.
Dest *net.IPNet
// Router is the router to use for the given destination network.
Router net.IP
}
// Marshal implements uio.Marshaler.
//
// Format described in RFC 3442:
//
// <size of mask in number of bits>
// <destination address, omitting octets that must be zero per mask>
// <route IP>
func (r Route) Marshal(buf *uio.Lexer) {
ones, _ := r.Dest.Mask.Size()
buf.Write8(uint8(ones))
// Only write the non-zero octets.
dstLen := (ones + 7) / 8
buf.WriteBytes(r.Dest.IP.To4()[:dstLen])
buf.WriteBytes(r.Router.To4())
}
// Unmarshal implements uio.Unmarshaler.
func (r *Route) Unmarshal(buf *uio.Lexer) error {
maskSize := buf.Read8()
if maskSize > 32 {
return fmt.Errorf("invalid mask length %d in route option", maskSize)
}
r.Dest = &net.IPNet{
IP: make([]byte, net.IPv4len),
Mask: net.CIDRMask(int(maskSize), 32),
}
dstLen := (maskSize + 7) / 8
buf.ReadBytes(r.Dest.IP[:dstLen])
r.Router = buf.CopyN(net.IPv4len)
return buf.Error()
}
// String prints the destination network and router IP.
func (r *Route) String() string {
return fmt.Sprintf("route to %s via %s", r.Dest, r.Router)
}
// Routes is a collection of network routes.
type Routes []*Route
// FromBytes parses routes from a set of bytes as described by RFC 3442.
func (r *Routes) FromBytes(p []byte) error {
buf := uio.NewBigEndianBuffer(p)
for buf.Has(1) {
var route Route
if err := route.Unmarshal(buf); err != nil {
return err
}
*r = append(*r, &route)
}
return buf.FinError()
}
// ToBytes marshals a set of routes as described by RFC 3442.
func (r Routes) ToBytes() []byte {
buf := uio.NewBigEndianBuffer(nil)
for _, route := range r {
route.Marshal(buf)
}
return buf.Data()
}
// String prints all routes.
func (r Routes) String() string {
s := make([]string, 0, len(r))
for _, route := range r {
s = append(s, route.String())
}
return strings.Join(s, "; ")
}
// OptClasslessStaticRoute returns a new DHCPv4 Classless Static Route
// option.
//
// The Classless Static Route option is described by RFC 3442.
func OptClasslessStaticRoute(routes ...*Route) Option {
return Option{
Code: OptionClasslessStaticRoute,
Value: Routes(routes),
}
}

View File

@@ -0,0 +1,84 @@
package dhcpv4
// String represents an option encapsulating a string in IPv4 DHCP.
//
// This representation is shared by multiple options specified by RFC 2132,
// Sections 3.14, 3.16, 3.17, 3.19, and 3.20.
type String string
// ToBytes returns a serialized stream of bytes for this option.
func (o String) ToBytes() []byte {
return []byte(o)
}
// String returns a human-readable string.
func (o String) String() string {
return string(o)
}
// FromBytes parses a serialized stream of bytes into o.
func (o *String) FromBytes(data []byte) error {
*o = String(string(data))
return nil
}
// GetString parses an RFC 2132 string from o[code].
func GetString(code OptionCode, o Options) string {
v := o.Get(code)
if v == nil {
return ""
}
return string(v)
}
// OptDomainName returns a new DHCPv4 Domain Name option.
//
// The Domain Name option is described by RFC 2132, Section 3.17.
func OptDomainName(name string) Option {
return Option{Code: OptionDomainName, Value: String(name)}
}
// OptHostName returns a new DHCPv4 Host Name option.
//
// The Host Name option is described by RFC 2132, Section 3.14.
func OptHostName(name string) Option {
return Option{Code: OptionHostName, Value: String(name)}
}
// OptRootPath returns a new DHCPv4 Root Path option.
//
// The Root Path option is described by RFC 2132, Section 3.19.
func OptRootPath(name string) Option {
return Option{Code: OptionRootPath, Value: String(name)}
}
// OptBootFileName returns a new DHCPv4 Boot File Name option.
//
// The Bootfile Name option is described by RFC 2132, Section 9.5.
func OptBootFileName(name string) Option {
return Option{Code: OptionBootfileName, Value: String(name)}
}
// OptTFTPServerName returns a new DHCPv4 TFTP Server Name option.
//
// The TFTP Server Name option is described by RFC 2132, Section 9.4.
func OptTFTPServerName(name string) Option {
return Option{Code: OptionTFTPServerName, Value: String(name)}
}
// OptClassIdentifier returns a new DHCPv4 Class Identifier option.
//
// The Vendor Class Identifier option is described by RFC 2132, Section 9.13.
func OptClassIdentifier(name string) Option {
return Option{Code: OptionClassIdentifier, Value: String(name)}
}
// OptUserClass returns a new DHCPv4 User Class option.
func OptUserClass(name string) Option {
return Option{Code: OptionUserClassInformation, Value: String(name)}
}
// OptMessage returns a new DHCPv4 (Error) Message option.
func OptMessage(msg string) Option {
return Option{Code: OptionMessage, Value: String(msg)}
}

View File

@@ -0,0 +1,55 @@
package dhcpv4
import (
"fmt"
"strings"
"github.com/u-root/uio/uio"
)
// Strings represents an option encapsulating a list of strings in IPv4 DHCP as
// specified in RFC 3004
//
// Strings implements the OptionValue type.
type Strings []string
// FromBytes parses Strings from a DHCP packet as specified by RFC 3004.
func (o *Strings) FromBytes(data []byte) error {
buf := uio.NewBigEndianBuffer(data)
if buf.Len() == 0 {
return fmt.Errorf("Strings DHCP option must always list at least one String")
}
*o = make(Strings, 0)
for buf.Has(1) {
ucLen := buf.Read8()
if ucLen == 0 {
return fmt.Errorf("DHCP Strings must have length greater than 0")
}
*o = append(*o, string(buf.CopyN(int(ucLen))))
}
return buf.FinError()
}
// ToBytes marshals Strings to a DHCP packet as specified by RFC 3004.
func (o Strings) ToBytes() []byte {
buf := uio.NewBigEndianBuffer(nil)
for _, uc := range o {
buf.Write8(uint8(len(uc)))
buf.WriteBytes([]byte(uc))
}
return buf.Data()
}
// String returns a human-readable representation of a list of Strings.
func (o Strings) String() string {
return strings.Join(o, ", ")
}
// OptRFC3004UserClass returns a new user class option according to RFC 3004.
func OptRFC3004UserClass(v []string) Option {
return Option{
Code: OptionUserClassInformation,
Value: Strings(v),
}
}

View File

@@ -0,0 +1,40 @@
package dhcpv4
import (
"net"
"github.com/u-root/uio/uio"
)
// IPMask represents an option encapsulating the subnet mask.
//
// This option implements the subnet mask option in RFC 2132, Section 3.3.
type IPMask net.IPMask
// ToBytes returns a serialized stream of bytes for this option.
func (im IPMask) ToBytes() []byte {
if len(im) > net.IPv4len {
return im[:net.IPv4len]
}
return im
}
// String returns a human-readable string.
func (im IPMask) String() string {
return net.IPMask(im).String()
}
// FromBytes parses im from data per RFC 2132.
func (im *IPMask) FromBytes(data []byte) error {
buf := uio.NewBigEndianBuffer(data)
*im = IPMask(buf.CopyN(net.IPv4len))
return buf.FinError()
}
// OptSubnetMask returns a new DHCPv4 SubnetMask option per RFC 2132, Section 3.3.
func OptSubnetMask(mask net.IPMask) Option {
return Option{
Code: OptionSubnetMask,
Value: IPMask(mask),
}
}

View File

@@ -0,0 +1,65 @@
package dhcpv4
import (
"bytes"
"fmt"
"github.com/insomniacslk/dhcp/iana"
"github.com/u-root/uio/uio"
)
// VIVCIdentifier implements the vendor-identifying vendor class option
// described by RFC 3925.
type VIVCIdentifier struct {
// EntID is the enterprise ID.
EntID iana.EnterpriseID
Data []byte
}
// OptVIVC returns a new vendor-identifying vendor class option.
//
// The option is described by RFC 3925.
func OptVIVC(identifiers ...VIVCIdentifier) Option {
return Option{
Code: OptionVendorIdentifyingVendorClass,
Value: VIVCIdentifiers(identifiers),
}
}
// VIVCIdentifiers implements encoding and decoding methods for a DHCP option
// described in RFC 3925.
type VIVCIdentifiers []VIVCIdentifier
// FromBytes parses data into ids per RFC 3925.
func (ids *VIVCIdentifiers) FromBytes(data []byte) error {
buf := uio.NewBigEndianBuffer(data)
for buf.Has(5) {
entID := iana.EnterpriseID(buf.Read32())
idLen := int(buf.Read8())
*ids = append(*ids, VIVCIdentifier{EntID: entID, Data: buf.CopyN(idLen)})
}
return buf.FinError()
}
// ToBytes returns a serialized stream of bytes for this option.
func (ids VIVCIdentifiers) ToBytes() []byte {
buf := uio.NewBigEndianBuffer(nil)
for _, id := range ids {
buf.Write32(uint32(id.EntID))
buf.Write8(uint8(len(id.Data)))
buf.WriteBytes(id.Data)
}
return buf.Data()
}
// String returns a human-readable string for this option.
func (ids VIVCIdentifiers) String() string {
if len(ids) == 0 {
return ""
}
buf := bytes.Buffer{}
for _, id := range ids {
fmt.Fprintf(&buf, " %d:'%s',", id.EntID, id.Data)
}
return buf.String()[1 : buf.Len()-1]
}

368
vendor/github.com/insomniacslk/dhcp/dhcpv4/options.go generated vendored Normal file
View File

@@ -0,0 +1,368 @@
package dhcpv4
import (
"errors"
"fmt"
"io"
"math"
"sort"
"strings"
"github.com/insomniacslk/dhcp/iana"
"github.com/insomniacslk/dhcp/rfc1035label"
"github.com/u-root/uio/uio"
)
var (
// ErrShortByteStream is an error that is thrown any time a short byte stream is
// detected during option parsing.
ErrShortByteStream = errors.New("short byte stream")
// ErrZeroLengthByteStream is an error that is thrown any time a zero-length
// byte stream is encountered.
ErrZeroLengthByteStream = errors.New("zero-length byte stream")
// ErrInvalidOptions is returned when invalid options data is
// encountered during parsing. The data could report an incorrect
// length or have trailing bytes which are not part of the option.
ErrInvalidOptions = errors.New("invalid options data")
)
// OptionValue is an interface that all DHCP v4 options adhere to.
type OptionValue interface {
ToBytes() []byte
String() string
}
// Option is a DHCPv4 option and consists of a 1-byte option code and a value
// stream of bytes.
//
// The value is to be interpreted based on the option code.
type Option struct {
Code OptionCode
Value OptionValue
}
// String returns a human-readable version of this option.
func (o Option) String() string {
v := o.Value.String()
if strings.Contains(v, "\n") {
return fmt.Sprintf("%s:\n%s", o.Code, v)
}
return fmt.Sprintf("%s: %s", o.Code, v)
}
// Options is a collection of options.
type Options map[uint8][]byte
// OptionsFromList adds all given options to an options map.
func OptionsFromList(o ...Option) Options {
opts := make(Options)
for _, opt := range o {
opts.Update(opt)
}
return opts
}
// Get will attempt to get all options that match a DHCPv4 option
// from its OptionCode. If the option was not found it will return an
// empty list.
//
// According to RFC 3396, options that are specified more than once are
// concatenated, and hence this should always just return one option. This
// currently returns a list to be API compatible.
func (o Options) Get(code OptionCode) []byte {
return o[code.Code()]
}
// Has checks whether o has the given opcode.
func (o Options) Has(opcode OptionCode) bool {
_, ok := o[opcode.Code()]
return ok
}
// Del deletes the option matching the option code.
func (o Options) Del(opcode OptionCode) {
delete(o, opcode.Code())
}
// Update updates the existing options with the passed option, adding it
// at the end if not present already
func (o Options) Update(option Option) {
o[option.Code.Code()] = option.Value.ToBytes()
}
// ToBytes makes Options usable as an OptionValue as well.
//
// Used in the case of vendor-specific and relay agent options.
func (o Options) ToBytes() []byte {
return uio.ToBigEndian(o)
}
// FromBytes parses a sequence of bytes until the end and builds a list of
// options from it.
//
// The sequence should not contain the DHCP magic cookie.
//
// Returns an error if any invalid option or length is found.
func (o Options) FromBytes(data []byte) error {
return o.fromBytesCheckEnd(data, false)
}
const (
optPad = 0
optEnd = 255
)
// FromBytesCheckEnd parses Options from byte sequences using the
// parsing function that is passed in as a paremeter
func (o Options) fromBytesCheckEnd(data []byte, checkEndOption bool) error {
if len(data) == 0 {
return nil
}
buf := uio.NewBigEndianBuffer(data)
var end bool
for buf.Len() >= 1 {
// 1 byte: option code
// 1 byte: option length n
// n bytes: data
code := buf.Read8()
if code == optPad {
continue
} else if code == optEnd {
end = true
break
}
length := int(buf.Read8())
// N bytes: option data
data := buf.Consume(length)
if data == nil {
return fmt.Errorf("error collecting options: %v", buf.Error())
}
data = data[:length:length]
// RFC 2131, Section 4.1 "Options may appear only once, [...].
// The client concatenates the values of multiple instances of
// the same option into a single parameter list for
// configuration."
//
// See also RFC 3396 for concatenation order and options longer
// than 255 bytes.
o[code] = append(o[code], data...)
}
// If we never read the End option, the sender of this packet screwed
// up.
if !end && checkEndOption {
return io.ErrUnexpectedEOF
}
// Any bytes left must be padding.
var pad uint8
for buf.Len() >= 1 {
pad = buf.Read8()
if pad != optPad && pad != optEnd {
return ErrInvalidOptions
}
}
return nil
}
// sortedKeys returns an ordered slice of option keys from the Options map, for
// use in serializing options to binary.
func (o Options) sortedKeys() []int {
// Send all values for a given key
var codes []int
for k := range o {
codes = append(codes, int(k))
}
sort.Ints(codes)
return codes
}
// Marshal writes options binary representations to b.
func (o Options) Marshal(b *uio.Lexer) {
for _, c := range o.sortedKeys() {
code := uint8(c)
// Even if the End option is in there, don't marshal it until
// the end.
// Don't write padding either, since the options are sorted
// it would always be written first which isn't useful
if code == optEnd || code == optPad {
continue
}
data := o[code]
// Ensure even 0-length options are written out
if len(data) == 0 {
b.Write8(code)
b.Write8(0)
continue
}
// RFC 3396: If more than 256 bytes of data are given, the
// option is simply listed multiple times.
for len(data) > 0 {
// 1 byte: option code
b.Write8(code)
n := len(data)
if n > math.MaxUint8 {
n = math.MaxUint8
}
// 1 byte: option length
b.Write8(uint8(n))
// N bytes: option data
b.WriteBytes(data[:n])
data = data[n:]
}
}
}
// String prints options using DHCP-specified option codes.
func (o Options) String() string {
return o.ToString(dhcpHumanizer)
}
// Summary prints options in human-readable values.
//
// Summary uses vendorParser to interpret the OptionVendorSpecificInformation option.
func (o Options) Summary(vendorDecoder OptionDecoder) string {
return o.ToString(OptionHumanizer{
ValueHumanizer: parserFor(vendorDecoder),
CodeHumanizer: func(c uint8) OptionCode {
return optionCode(c)
},
})
}
// OptionParser gives a human-legible interpretation of data for the given option code.
type OptionParser func(code OptionCode, data []byte) fmt.Stringer
// OptionHumanizer is used to interpret a set of Options for their option code
// name and values.
//
// There should be separate OptionHumanizers for each Option "space": DHCP,
// BSDP, Relay Agent Info, and others.
type OptionHumanizer struct {
ValueHumanizer OptionParser
CodeHumanizer func(code uint8) OptionCode
}
// Stringify returns a human-readable interpretation of the option code and its
// associated data.
func (oh OptionHumanizer) Stringify(code uint8, data []byte) string {
c := oh.CodeHumanizer(code)
val := oh.ValueHumanizer(c, data)
return fmt.Sprintf("%s: %s", c, val)
}
// dhcpHumanizer humanizes the set of DHCP option codes.
var dhcpHumanizer = OptionHumanizer{
ValueHumanizer: parseOption,
CodeHumanizer: func(c uint8) OptionCode {
return optionCode(c)
},
}
// ToString uses parse to parse options into human-readable values.
func (o Options) ToString(humanizer OptionHumanizer) string {
var ret string
for _, c := range o.sortedKeys() {
code := uint8(c)
v := o[code]
optString := humanizer.Stringify(code, v)
// If this option has sub structures, offset them accordingly.
if strings.Contains(optString, "\n") {
optString = strings.Replace(optString, "\n ", "\n ", -1)
}
ret += fmt.Sprintf(" %v\n", optString)
}
return ret
}
func parseOption(code OptionCode, data []byte) fmt.Stringer {
return parserFor(nil)(code, data)
}
func parserFor(vendorParser OptionDecoder) OptionParser {
return func(code OptionCode, data []byte) fmt.Stringer {
return getOption(code, data, vendorParser)
}
}
// OptionDecoder can decode a byte stream into a human-readable option.
type OptionDecoder interface {
fmt.Stringer
FromBytes([]byte) error
}
func getOption(code OptionCode, data []byte, vendorDecoder OptionDecoder) fmt.Stringer {
var d OptionDecoder
switch code {
case OptionRouter, OptionDomainNameServer, OptionNTPServers, OptionServerIdentifier:
d = &IPs{}
case OptionBroadcastAddress, OptionRequestedIPAddress:
d = &IP{}
case OptionClientSystemArchitectureType:
d = &iana.Archs{}
case OptionSubnetMask:
d = &IPMask{}
case OptionDHCPMessageType:
var mt MessageType
d = &mt
case OptionParameterRequestList:
d = &OptionCodeList{}
case OptionHostName, OptionDomainName, OptionRootPath,
OptionClassIdentifier, OptionTFTPServerName, OptionBootfileName:
var s String
d = &s
case OptionRelayAgentInformation:
d = &RelayOptions{}
case OptionDNSDomainSearchList:
d = &rfc1035label.Labels{}
case OptionIPAddressLeaseTime:
var dur Duration
d = &dur
case OptionMaximumDHCPMessageSize:
var u Uint16
d = &u
case OptionUserClassInformation:
var s Strings
d = &s
if s.FromBytes(data) != nil {
var s String
d = &s
}
case OptionVendorIdentifyingVendorClass:
d = &VIVCIdentifiers{}
case OptionVendorSpecificInformation:
d = vendorDecoder
case OptionClasslessStaticRoute:
d = &Routes{}
}
if d != nil && d.FromBytes(data) == nil {
return d
}
return OptionGeneric{data}
}

463
vendor/github.com/insomniacslk/dhcp/dhcpv4/types.go generated vendored Normal file
View File

@@ -0,0 +1,463 @@
package dhcpv4
import (
"fmt"
"github.com/u-root/uio/uio"
)
// values from http://www.networksorcery.com/enp/protocol/dhcp.htm and
// http://www.networksorcery.com/enp/protocol/bootp/options.htm
// TransactionID represents a 4-byte DHCP transaction ID as defined in RFC 951,
// Section 3.
//
// The TransactionID is used to match DHCP replies to their original request.
type TransactionID [4]byte
// String prints a hex transaction ID.
func (xid TransactionID) String() string {
return fmt.Sprintf("0x%x", xid[:])
}
// MessageType represents the possible DHCP message types - DISCOVER, OFFER, etc
type MessageType byte
// DHCP message types
const (
// MessageTypeNone is not a real message type, it is used by certain
// functions to signal that no explicit message type is requested
MessageTypeNone MessageType = 0
MessageTypeDiscover MessageType = 1
MessageTypeOffer MessageType = 2
MessageTypeRequest MessageType = 3
MessageTypeDecline MessageType = 4
MessageTypeAck MessageType = 5
MessageTypeNak MessageType = 6
MessageTypeRelease MessageType = 7
MessageTypeInform MessageType = 8
)
// ToBytes returns the serialized version of this option described by RFC 2132,
// Section 9.6.
func (m MessageType) ToBytes() []byte {
return []byte{byte(m)}
}
// String prints a human-readable message type name.
func (m MessageType) String() string {
if s, ok := messageTypeToString[m]; ok {
return s
}
return fmt.Sprintf("unknown (%d)", byte(m))
}
// FromBytes reads a message type from data as described by RFC 2132, Section
// 9.6.
func (m *MessageType) FromBytes(data []byte) error {
buf := uio.NewBigEndianBuffer(data)
*m = MessageType(buf.Read8())
return buf.FinError()
}
var messageTypeToString = map[MessageType]string{
MessageTypeDiscover: "DISCOVER",
MessageTypeOffer: "OFFER",
MessageTypeRequest: "REQUEST",
MessageTypeDecline: "DECLINE",
MessageTypeAck: "ACK",
MessageTypeNak: "NAK",
MessageTypeRelease: "RELEASE",
MessageTypeInform: "INFORM",
}
// OpcodeType represents a DHCPv4 opcode.
type OpcodeType uint8
// constants that represent valid values for OpcodeType
const (
OpcodeBootRequest OpcodeType = 1
OpcodeBootReply OpcodeType = 2
)
func (o OpcodeType) String() string {
if s, ok := opcodeToString[o]; ok {
return s
}
return fmt.Sprintf("unknown (%d)", uint8(o))
}
var opcodeToString = map[OpcodeType]string{
OpcodeBootRequest: "BootRequest",
OpcodeBootReply: "BootReply",
}
// OptionCode is a single byte representing the code for a given Option.
//
// OptionCode is an interface purely to support different stringers on options
// with the same Code value, as vendor-specific options use option codes that
// have the same value, but mean a different thing.
type OptionCode interface {
// Code is the 1 byte option code for the wire.
Code() uint8
// String returns the option's name.
String() string
}
// optionCode is a DHCP option code.
type optionCode uint8
// Code implements OptionCode.Code.
func (o optionCode) Code() uint8 {
return uint8(o)
}
// String returns an option name.
func (o optionCode) String() string {
if s, ok := optionCodeToString[o]; ok {
return s
}
return fmt.Sprintf("unknown (%d)", uint8(o))
}
// GenericOptionCode is an unnamed option code.
type GenericOptionCode uint8
// Code implements OptionCode.Code.
func (o GenericOptionCode) Code() uint8 {
return uint8(o)
}
// String returns the option's name.
func (o GenericOptionCode) String() string {
return fmt.Sprintf("unknown (%d)", uint8(o))
}
// DHCPv4 Options
const (
OptionPad optionCode = 0
OptionSubnetMask optionCode = 1
OptionTimeOffset optionCode = 2
OptionRouter optionCode = 3
OptionTimeServer optionCode = 4
OptionNameServer optionCode = 5
OptionDomainNameServer optionCode = 6
OptionLogServer optionCode = 7
OptionQuoteServer optionCode = 8
OptionLPRServer optionCode = 9
OptionImpressServer optionCode = 10
OptionResourceLocationServer optionCode = 11
OptionHostName optionCode = 12
OptionBootFileSize optionCode = 13
OptionMeritDumpFile optionCode = 14
OptionDomainName optionCode = 15
OptionSwapServer optionCode = 16
OptionRootPath optionCode = 17
OptionExtensionsPath optionCode = 18
OptionIPForwarding optionCode = 19
OptionNonLocalSourceRouting optionCode = 20
OptionPolicyFilter optionCode = 21
OptionMaximumDatagramAssemblySize optionCode = 22
OptionDefaultIPTTL optionCode = 23
OptionPathMTUAgingTimeout optionCode = 24
OptionPathMTUPlateauTable optionCode = 25
OptionInterfaceMTU optionCode = 26
OptionAllSubnetsAreLocal optionCode = 27
OptionBroadcastAddress optionCode = 28
OptionPerformMaskDiscovery optionCode = 29
OptionMaskSupplier optionCode = 30
OptionPerformRouterDiscovery optionCode = 31
OptionRouterSolicitationAddress optionCode = 32
OptionStaticRoutingTable optionCode = 33
OptionTrailerEncapsulation optionCode = 34
OptionArpCacheTimeout optionCode = 35
OptionEthernetEncapsulation optionCode = 36
OptionDefaulTCPTTL optionCode = 37
OptionTCPKeepaliveInterval optionCode = 38
OptionTCPKeepaliveGarbage optionCode = 39
OptionNetworkInformationServiceDomain optionCode = 40
OptionNetworkInformationServers optionCode = 41
OptionNTPServers optionCode = 42
OptionVendorSpecificInformation optionCode = 43
OptionNetBIOSOverTCPIPNameServer optionCode = 44
OptionNetBIOSOverTCPIPDatagramDistributionServer optionCode = 45
OptionNetBIOSOverTCPIPNodeType optionCode = 46
OptionNetBIOSOverTCPIPScope optionCode = 47
OptionXWindowSystemFontServer optionCode = 48
OptionXWindowSystemDisplayManger optionCode = 49
OptionRequestedIPAddress optionCode = 50
OptionIPAddressLeaseTime optionCode = 51
OptionOptionOverload optionCode = 52
OptionDHCPMessageType optionCode = 53
OptionServerIdentifier optionCode = 54
OptionParameterRequestList optionCode = 55
OptionMessage optionCode = 56
OptionMaximumDHCPMessageSize optionCode = 57
OptionRenewTimeValue optionCode = 58
OptionRebindingTimeValue optionCode = 59
OptionClassIdentifier optionCode = 60
OptionClientIdentifier optionCode = 61
OptionNetWareIPDomainName optionCode = 62
OptionNetWareIPInformation optionCode = 63
OptionNetworkInformationServicePlusDomain optionCode = 64
OptionNetworkInformationServicePlusServers optionCode = 65
OptionTFTPServerName optionCode = 66
OptionBootfileName optionCode = 67
OptionMobileIPHomeAgent optionCode = 68
OptionSimpleMailTransportProtocolServer optionCode = 69
OptionPostOfficeProtocolServer optionCode = 70
OptionNetworkNewsTransportProtocolServer optionCode = 71
OptionDefaultWorldWideWebServer optionCode = 72
OptionDefaultFingerServer optionCode = 73
OptionDefaultInternetRelayChatServer optionCode = 74
OptionStreetTalkServer optionCode = 75
OptionStreetTalkDirectoryAssistanceServer optionCode = 76
OptionUserClassInformation optionCode = 77
OptionSLPDirectoryAgent optionCode = 78
OptionSLPServiceScope optionCode = 79
OptionRapidCommit optionCode = 80
OptionFQDN optionCode = 81
OptionRelayAgentInformation optionCode = 82
OptionInternetStorageNameService optionCode = 83
// Option 84 returned in RFC 3679
OptionNDSServers optionCode = 85
OptionNDSTreeName optionCode = 86
OptionNDSContext optionCode = 87
OptionBCMCSControllerDomainNameList optionCode = 88
OptionBCMCSControllerIPv4AddressList optionCode = 89
OptionAuthentication optionCode = 90
OptionClientLastTransactionTime optionCode = 91
OptionAssociatedIP optionCode = 92
OptionClientSystemArchitectureType optionCode = 93
OptionClientNetworkInterfaceIdentifier optionCode = 94
OptionLDAP optionCode = 95
// Option 96 returned in RFC 3679
OptionClientMachineIdentifier optionCode = 97
OptionOpenGroupUserAuthentication optionCode = 98
OptionGeoConfCivic optionCode = 99
OptionIEEE10031TZString optionCode = 100
OptionReferenceToTZDatabase optionCode = 101
// Options 102-111 returned in RFC 3679
OptionNetInfoParentServerAddress optionCode = 112
OptionNetInfoParentServerTag optionCode = 113
OptionURL optionCode = 114
// Option 115 returned in RFC 3679
OptionAutoConfigure optionCode = 116
OptionNameServiceSearch optionCode = 117
OptionSubnetSelection optionCode = 118
OptionDNSDomainSearchList optionCode = 119
OptionSIPServers optionCode = 120
OptionClasslessStaticRoute optionCode = 121
OptionCCC optionCode = 122
OptionGeoConf optionCode = 123
OptionVendorIdentifyingVendorClass optionCode = 124
OptionVendorIdentifyingVendorSpecific optionCode = 125
// Options 126-127 returned in RFC 3679
OptionTFTPServerIPAddress optionCode = 128
OptionCallServerIPAddress optionCode = 129
OptionDiscriminationString optionCode = 130
OptionRemoteStatisticsServerIPAddress optionCode = 131
Option8021PVLANID optionCode = 132
Option8021QL2Priority optionCode = 133
OptionDiffservCodePoint optionCode = 134
OptionHTTPProxyForPhoneSpecificApplications optionCode = 135
OptionPANAAuthenticationAgent optionCode = 136
OptionLoSTServer optionCode = 137
OptionCAPWAPAccessControllerAddresses optionCode = 138
OptionOPTIONIPv4AddressMoS optionCode = 139
OptionOPTIONIPv4FQDNMoS optionCode = 140
OptionSIPUAConfigurationServiceDomains optionCode = 141
OptionOPTIONIPv4AddressANDSF optionCode = 142
OptionOPTIONIPv6AddressANDSF optionCode = 143
// Options 144-149 returned in RFC 3679
OptionTFTPServerAddress optionCode = 150
OptionStatusCode optionCode = 151
OptionBaseTime optionCode = 152
OptionStartTimeOfState optionCode = 153
OptionQueryStartTime optionCode = 154
OptionQueryEndTime optionCode = 155
OptionDHCPState optionCode = 156
OptionDataSource optionCode = 157
// Options 158-174 returned in RFC 3679
OptionEtherboot optionCode = 175
OptionIPTelephone optionCode = 176
OptionEtherbootPacketCableAndCableHome optionCode = 177
// Options 178-207 returned in RFC 3679
OptionPXELinuxMagicString optionCode = 208
OptionPXELinuxConfigFile optionCode = 209
OptionPXELinuxPathPrefix optionCode = 210
OptionPXELinuxRebootTime optionCode = 211
OptionOPTION6RD optionCode = 212
OptionOPTIONv4AccessDomain optionCode = 213
// Options 214-219 returned in RFC 3679
OptionSubnetAllocation optionCode = 220
OptionVirtualSubnetAllocation optionCode = 221
// Options 222-223 returned in RFC 3679
// Options 224-254 are reserved for private use
OptionEnd optionCode = 255
)
var optionCodeToString = map[OptionCode]string{
OptionPad: "Pad",
OptionSubnetMask: "Subnet Mask",
OptionTimeOffset: "Time Offset",
OptionRouter: "Router",
OptionTimeServer: "Time Server",
OptionNameServer: "Name Server",
OptionDomainNameServer: "Domain Name Server",
OptionLogServer: "Log Server",
OptionQuoteServer: "Quote Server",
OptionLPRServer: "LPR Server",
OptionImpressServer: "Impress Server",
OptionResourceLocationServer: "Resource Location Server",
OptionHostName: "Host Name",
OptionBootFileSize: "Boot File Size",
OptionMeritDumpFile: "Merit Dump File",
OptionDomainName: "Domain Name",
OptionSwapServer: "Swap Server",
OptionRootPath: "Root Path",
OptionExtensionsPath: "Extensions Path",
OptionIPForwarding: "IP Forwarding enable/disable",
OptionNonLocalSourceRouting: "Non-local Source Routing enable/disable",
OptionPolicyFilter: "Policy Filter",
OptionMaximumDatagramAssemblySize: "Maximum Datagram Reassembly Size",
OptionDefaultIPTTL: "Default IP Time-to-live",
OptionPathMTUAgingTimeout: "Path MTU Aging Timeout",
OptionPathMTUPlateauTable: "Path MTU Plateau Table",
OptionInterfaceMTU: "Interface MTU",
OptionAllSubnetsAreLocal: "All Subnets Are Local",
OptionBroadcastAddress: "Broadcast Address",
OptionPerformMaskDiscovery: "Perform Mask Discovery",
OptionMaskSupplier: "Mask Supplier",
OptionPerformRouterDiscovery: "Perform Router Discovery",
OptionRouterSolicitationAddress: "Router Solicitation Address",
OptionStaticRoutingTable: "Static Routing Table",
OptionTrailerEncapsulation: "Trailer Encapsulation",
OptionArpCacheTimeout: "ARP Cache Timeout",
OptionEthernetEncapsulation: "Ethernet Encapsulation",
OptionDefaulTCPTTL: "Default TCP TTL",
OptionTCPKeepaliveInterval: "TCP Keepalive Interval",
OptionTCPKeepaliveGarbage: "TCP Keepalive Garbage",
OptionNetworkInformationServiceDomain: "Network Information Service Domain",
OptionNetworkInformationServers: "Network Information Servers",
OptionNTPServers: "NTP Servers",
OptionVendorSpecificInformation: "Vendor Specific Information",
OptionNetBIOSOverTCPIPNameServer: "NetBIOS over TCP/IP Name Server",
OptionNetBIOSOverTCPIPDatagramDistributionServer: "NetBIOS over TCP/IP Datagram Distribution Server",
OptionNetBIOSOverTCPIPNodeType: "NetBIOS over TCP/IP Node Type",
OptionNetBIOSOverTCPIPScope: "NetBIOS over TCP/IP Scope",
OptionXWindowSystemFontServer: "X Window System Font Server",
OptionXWindowSystemDisplayManger: "X Window System Display Manager",
OptionRequestedIPAddress: "Requested IP Address",
OptionIPAddressLeaseTime: "IP Addresses Lease Time",
OptionOptionOverload: "Option Overload",
OptionDHCPMessageType: "DHCP Message Type",
OptionServerIdentifier: "Server Identifier",
OptionParameterRequestList: "Parameter Request List",
OptionMessage: "Message",
OptionMaximumDHCPMessageSize: "Maximum DHCP Message Size",
OptionRenewTimeValue: "Renew Time Value",
OptionRebindingTimeValue: "Rebinding Time Value",
OptionClassIdentifier: "Class Identifier",
OptionClientIdentifier: "Client identifier",
OptionNetWareIPDomainName: "NetWare/IP Domain Name",
OptionNetWareIPInformation: "NetWare/IP Information",
OptionNetworkInformationServicePlusDomain: "Network Information Service+ Domain",
OptionNetworkInformationServicePlusServers: "Network Information Service+ Servers",
OptionTFTPServerName: "TFTP Server Name",
OptionBootfileName: "Bootfile Name",
OptionMobileIPHomeAgent: "Mobile IP Home Agent",
OptionSimpleMailTransportProtocolServer: "SMTP Server",
OptionPostOfficeProtocolServer: "POP Server",
OptionNetworkNewsTransportProtocolServer: "NNTP Server",
OptionDefaultWorldWideWebServer: "Default WWW Server",
OptionDefaultFingerServer: "Default Finger Server",
OptionDefaultInternetRelayChatServer: "Default IRC Server",
OptionStreetTalkServer: "StreetTalk Server",
OptionStreetTalkDirectoryAssistanceServer: "StreetTalk Directory Assistance Server",
OptionUserClassInformation: "User Class Information",
OptionSLPDirectoryAgent: "SLP DIrectory Agent",
OptionSLPServiceScope: "SLP Service Scope",
OptionRapidCommit: "Rapid Commit",
OptionFQDN: "FQDN",
OptionRelayAgentInformation: "Relay Agent Information",
OptionInternetStorageNameService: "Internet Storage Name Service",
// Option 84 returned in RFC 3679
OptionNDSServers: "NDS Servers",
OptionNDSTreeName: "NDS Tree Name",
OptionNDSContext: "NDS Context",
OptionBCMCSControllerDomainNameList: "BCMCS Controller Domain Name List",
OptionBCMCSControllerIPv4AddressList: "BCMCS Controller IPv4 Address List",
OptionAuthentication: "Authentication",
OptionClientLastTransactionTime: "Client Last Transaction Time",
OptionAssociatedIP: "Associated IP",
OptionClientSystemArchitectureType: "Client System Architecture Type",
OptionClientNetworkInterfaceIdentifier: "Client Network Interface Identifier",
OptionLDAP: "LDAP",
// Option 96 returned in RFC 3679
OptionClientMachineIdentifier: "Client Machine Identifier",
OptionOpenGroupUserAuthentication: "OpenGroup's User Authentication",
OptionGeoConfCivic: "GEOCONF_CIVIC",
OptionIEEE10031TZString: "IEEE 1003.1 TZ String",
OptionReferenceToTZDatabase: "Reference to the TZ Database",
// Options 102-111 returned in RFC 3679
OptionNetInfoParentServerAddress: "NetInfo Parent Server Address",
OptionNetInfoParentServerTag: "NetInfo Parent Server Tag",
OptionURL: "URL",
// Option 115 returned in RFC 3679
OptionAutoConfigure: "Auto-Configure",
OptionNameServiceSearch: "Name Service Search",
OptionSubnetSelection: "Subnet Selection",
OptionDNSDomainSearchList: "DNS Domain Search List",
OptionSIPServers: "SIP Servers",
OptionClasslessStaticRoute: "Classless Static Route",
OptionCCC: "CCC, CableLabs Client Configuration",
OptionGeoConf: "GeoConf",
OptionVendorIdentifyingVendorClass: "Vendor-Identifying Vendor Class",
OptionVendorIdentifyingVendorSpecific: "Vendor-Identifying Vendor-Specific",
// Options 126-127 returned in RFC 3679
OptionTFTPServerIPAddress: "TFTP Server IP Address",
OptionCallServerIPAddress: "Call Server IP Address",
OptionDiscriminationString: "Discrimination String",
OptionRemoteStatisticsServerIPAddress: "RemoteStatistics Server IP Address",
Option8021PVLANID: "802.1P VLAN ID",
Option8021QL2Priority: "802.1Q L2 Priority",
OptionDiffservCodePoint: "Diffserv Code Point",
OptionHTTPProxyForPhoneSpecificApplications: "HTTP Proxy for phone-specific applications",
OptionPANAAuthenticationAgent: "PANA Authentication Agent",
OptionLoSTServer: "LoST Server",
OptionCAPWAPAccessControllerAddresses: "CAPWAP Access Controller Addresses",
OptionOPTIONIPv4AddressMoS: "OPTION-IPv4_Address-MoS",
OptionOPTIONIPv4FQDNMoS: "OPTION-IPv4_FQDN-MoS",
OptionSIPUAConfigurationServiceDomains: "SIP UA Configuration Service Domains",
OptionOPTIONIPv4AddressANDSF: "OPTION-IPv4_Address-ANDSF",
OptionOPTIONIPv6AddressANDSF: "OPTION-IPv6_Address-ANDSF",
// Options 144-149 returned in RFC 3679
OptionTFTPServerAddress: "TFTP Server Address",
OptionStatusCode: "Status Code",
OptionBaseTime: "Base Time",
OptionStartTimeOfState: "Start Time of State",
OptionQueryStartTime: "Query Start Time",
OptionQueryEndTime: "Query End Time",
OptionDHCPState: "DHCP Staet",
OptionDataSource: "Data Source",
// Options 158-174 returned in RFC 3679
OptionEtherboot: "Etherboot",
OptionIPTelephone: "IP Telephone",
OptionEtherbootPacketCableAndCableHome: "Etherboot / PacketCable and CableHome",
// Options 178-207 returned in RFC 3679
OptionPXELinuxMagicString: "PXELinux Magic String",
OptionPXELinuxConfigFile: "PXELinux Config File",
OptionPXELinuxPathPrefix: "PXELinux Path Prefix",
OptionPXELinuxRebootTime: "PXELinux Reboot Time",
OptionOPTION6RD: "OPTION_6RD",
OptionOPTIONv4AccessDomain: "OPTION_V4_ACCESS_DOMAIN",
// Options 214-219 returned in RFC 3679
OptionSubnetAllocation: "Subnet Allocation",
OptionVirtualSubnetAllocation: "Virtual Subnet Selection",
// Options 222-223 returned in RFC 3679
// Options 224-254 are reserved for private use
OptionEnd: "End",
}

148
vendor/github.com/insomniacslk/dhcp/iana/archtype.go generated vendored Normal file
View File

@@ -0,0 +1,148 @@
package iana
import (
"fmt"
"strings"
"github.com/u-root/uio/uio"
)
// Arch encodes an architecture type per RFC 4578, Section 2.1.
type Arch uint16
// See RFC 4578, 5970, and http://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml#processor-architecture
const (
INTEL_X86PC Arch = 0
NEC_PC98 Arch = 1
EFI_ITANIUM Arch = 2
DEC_ALPHA Arch = 3
ARC_X86 Arch = 4
INTEL_LEAN_CLIENT Arch = 5
EFI_IA32 Arch = 6
EFI_X86_64 Arch = 7
EFI_XSCALE Arch = 8
EFI_BC Arch = 9
EFI_ARM32 Arch = 10
EFI_ARM64 Arch = 11
PPC_OPEN_FIRMWARE Arch = 12
PPC_EPAPR Arch = 13
PPC_OPAL Arch = 14
EFI_X86_HTTP Arch = 15
EFI_X86_64_HTTP Arch = 16
EFI_BC_HTTP Arch = 17
EFI_ARM32_HTTP Arch = 18
EFI_ARM64_HTTP Arch = 19
INTEL_X86PC_HTTP Arch = 20
UBOOT_ARM32 Arch = 21
UBOOT_ARM64 Arch = 22
UBOOT_ARM32_HTTP Arch = 23
UBOOT_ARM64_HTTP Arch = 24
EFI_RISCV32 Arch = 25
EFI_RISCV32_HTTP Arch = 26
EFI_RISCV64 Arch = 27
EFI_RISCV64_HTTP Arch = 28
EFI_RISCV128 Arch = 29
EFI_RISCV128_HTTP Arch = 30
S390_BASIC Arch = 31
S390_EXTENDED Arch = 32
EFI_MIPS32 Arch = 33
EFI_MIPS64 Arch = 34
EFI_SUNWAY32 Arch = 35
EFI_SUNWAY64 Arch = 36
)
// archTypeToStringMap maps an Arch to a mnemonic name
var archTypeToStringMap = map[Arch]string{
INTEL_X86PC: "Intel x86PC",
NEC_PC98: "NEC/PC98",
EFI_ITANIUM: "EFI Itanium",
DEC_ALPHA: "DEC Alpha",
ARC_X86: "Arc x86",
INTEL_LEAN_CLIENT: "Intel Lean Client",
EFI_IA32: "EFI IA32",
EFI_XSCALE: "EFI Xscale",
EFI_X86_64: "EFI x86-64",
EFI_BC: "EFI BC",
EFI_ARM32: "EFI ARM32",
EFI_ARM64: "EFI ARM64",
PPC_OPEN_FIRMWARE: "PowerPC Open Firmware",
PPC_EPAPR: "PowerPC ePAPR",
PPC_OPAL: "POWER OPAL v3",
EFI_X86_HTTP: "EFI x86 boot from HTTP",
EFI_X86_64_HTTP: "EFI x86-64 boot from HTTP",
EFI_BC_HTTP: "EFI BC boot from HTTP",
EFI_ARM32_HTTP: "EFI ARM32 boot from HTTP",
EFI_ARM64_HTTP: "EFI ARM64 boot from HTTP",
INTEL_X86PC_HTTP: "Intel x86PC boot from HTTP",
UBOOT_ARM32: "U-Boot ARM32",
UBOOT_ARM64: "U-Boot ARM64",
UBOOT_ARM32_HTTP: "U-boot ARM32 boot from HTTP",
UBOOT_ARM64_HTTP: "U-Boot ARM64 boot from HTTP",
EFI_RISCV32: "EFI RISC-V 32-bit",
EFI_RISCV32_HTTP: "EFI RISC-V 32-bit boot from HTTP",
EFI_RISCV64: "EFI RISC-V 64-bit",
EFI_RISCV64_HTTP: "EFI RISC-V 64-bit boot from HTTP",
EFI_RISCV128: "EFI RISC-V 128-bit",
EFI_RISCV128_HTTP: "EFI RISC-V 128-bit boot from HTTP",
S390_BASIC: "s390 Basic",
S390_EXTENDED: "s390 Extended",
EFI_MIPS32: "EFI MIPS32",
EFI_MIPS64: "EFI MIPS64",
EFI_SUNWAY32: "EFI Sunway 32-bit",
EFI_SUNWAY64: "EFI Sunway 64-bit",
}
// String returns a mnemonic name for a given architecture type.
func (a Arch) String() string {
if at := archTypeToStringMap[a]; at != "" {
return at
}
return "unknown"
}
// Archs represents multiple Arch values.
type Archs []Arch
// Contains returns whether b is one of the Archs in a.
func (a Archs) Contains(b Arch) bool {
for _, t := range a {
if t == b {
return true
}
}
return false
}
// ToBytes returns the serialized option defined by RFC 4578 (DHCPv4) and RFC
// 5970 (DHCPv6) as the Client System Architecture Option.
func (a Archs) ToBytes() []byte {
buf := uio.NewBigEndianBuffer(nil)
for _, at := range a {
buf.Write16(uint16(at))
}
return buf.Data()
}
// String returns the list of archs in a human-readable manner.
func (a Archs) String() string {
s := make([]string, 0, len(a))
for _, arch := range a {
s = append(s, arch.String())
}
return strings.Join(s, ", ")
}
// FromBytes parses a DHCP list of architecture types as defined by RFC 4578
// and RFC 5970.
func (a *Archs) FromBytes(data []byte) error {
buf := uio.NewBigEndianBuffer(data)
if buf.Len() == 0 {
return fmt.Errorf("must have at least one archtype if option is present")
}
*a = make([]Arch, 0, buf.Len()/2)
for buf.Has(2) {
*a = append(*a, Arch(buf.Read16()))
}
return buf.FinError()
}

25
vendor/github.com/insomniacslk/dhcp/iana/entid.go generated vendored Normal file
View File

@@ -0,0 +1,25 @@
package iana
// EnterpriseID represents the Enterprise IDs as set by IANA
type EnterpriseID int
// See https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers for values
const (
EnterpriseIDCiscoSystems EnterpriseID = 9
EnterpriseIDCienaCorporation EnterpriseID = 1271
EnterpriseIDMellanoxTechnologiesLTD EnterpriseID = 33049
)
var enterpriseIDToStringMap = map[EnterpriseID]string{
EnterpriseIDCiscoSystems: "Cisco Systems",
EnterpriseIDCienaCorporation: "Ciena Corporation",
EnterpriseIDMellanoxTechnologiesLTD: "Mellanox Technologies LTD",
}
// String returns the vendor name for a given Enterprise ID
func (e EnterpriseID) String() string {
if vendor := enterpriseIDToStringMap[e]; vendor != "" {
return vendor
}
return "Unknown"
}

91
vendor/github.com/insomniacslk/dhcp/iana/hwtypes.go generated vendored Normal file
View File

@@ -0,0 +1,91 @@
package iana
// HWType is a hardware type as per RFC 2132 and defined by the IANA.
type HWType uint16
// See IANA for values.
const (
_ HWType = iota // skip 0
HWTypeEthernet
HWTypeExperimentalEthernet
HWTypeAmateurRadioAX25
HWTypeProteonTokenRing
HWTypeChaos
HWTypeIEEE802
HWTypeARCNET
HWTypeHyperchannel
HWTypeLanstar
HWTypeAutonet
HWTypeLocalTalk
HWTypeLocalNet
HWTypeUltraLink
HWTypeSMDS
HWTypeFrameRelay
HWTypeATM
HWTypeHDLC
HWTypeFibreChannel
HWTypeATM2
HWTypeSerialLine
HWTypeATM3
HWTypeMILSTD188220
HWTypeMetricom
HWTypeIEEE1394
HWTypeMAPOS
HWTypeTwinaxial
HWTypeEUI64
HWTypeHIPARP
HWTypeISO7816
HWTypeARPSec
HWTypeIPsec
HWTypeInfiniband
HWTypeCAI
HWTypeWiegandInterface
HWTypePureIP
)
var hwTypeToString = map[HWType]string{
HWTypeEthernet: "Ethernet",
HWTypeExperimentalEthernet: "Experimental Ethernet",
HWTypeAmateurRadioAX25: "Amateur Radio AX.25",
HWTypeProteonTokenRing: "Proteon ProNET Token Ring",
HWTypeChaos: "Chaos",
HWTypeIEEE802: "IEEE 802",
HWTypeARCNET: "ARCNET",
HWTypeHyperchannel: "Hyperchannel",
HWTypeLanstar: "Lanstar",
HWTypeAutonet: "Autonet Short Address",
HWTypeLocalTalk: "LocalTalk",
HWTypeLocalNet: "LocalNet",
HWTypeUltraLink: "Ultra link",
HWTypeSMDS: "SMDS",
HWTypeFrameRelay: "Frame Relay",
HWTypeATM: "ATM",
HWTypeHDLC: "HDLC",
HWTypeFibreChannel: "Fibre Channel",
HWTypeATM2: "ATM 2",
HWTypeSerialLine: "Serial Line",
HWTypeATM3: "ATM 3",
HWTypeMILSTD188220: "MIL-STD-188-220",
HWTypeMetricom: "Metricom",
HWTypeIEEE1394: "IEEE 1394.1995",
HWTypeMAPOS: "MAPOS",
HWTypeTwinaxial: "Twinaxial",
HWTypeEUI64: "EUI-64",
HWTypeHIPARP: "HIPARP",
HWTypeISO7816: "IP and ARP over ISO 7816-3",
HWTypeARPSec: "ARPSec",
HWTypeIPsec: "IPsec tunnel",
HWTypeInfiniband: "Infiniband",
HWTypeCAI: "CAI, TIA-102 Project 125 Common Air Interface",
HWTypeWiegandInterface: "Wiegand Interface",
HWTypePureIP: "Pure IP",
}
// String implements fmt.Stringer.
func (h HWType) String() string {
hwtype := hwTypeToString[h]
if hwtype == "" {
hwtype = "unknown"
}
return hwtype
}

2
vendor/github.com/insomniacslk/dhcp/iana/iana.go generated vendored Normal file
View File

@@ -0,0 +1,2 @@
// Package iana contains constants defined by IANA.
package iana

View File

@@ -0,0 +1,77 @@
package iana
// StatusCode represents a IANA status code for DHCPv6
//
// IANA Status Codes for DHCPv6
// https://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml#dhcpv6-parameters-5
type StatusCode uint16
// IANA status codes
const (
// RFC 3315 par. 24..4
StatusSuccess StatusCode = 0
StatusUnspecFail StatusCode = 1
StatusNoAddrsAvail StatusCode = 2
StatusNoBinding StatusCode = 3
StatusNotOnLink StatusCode = 4
StatusUseMulticast StatusCode = 5
StatusNoPrefixAvail StatusCode = 6
// RFC 5007
StatusUnknownQueryType StatusCode = 7
StatusMalformedQuery StatusCode = 8
StatusNotConfigured StatusCode = 9
StatusNotAllowed StatusCode = 10
// RFC 5460
StatusQueryTerminated StatusCode = 11
// RFC 7653
StatusDataMissing StatusCode = 12
StatusCatchUpComplete StatusCode = 13
StatusNotSupported StatusCode = 14
StatusTLSConnectionRefused StatusCode = 15
// RFC 8156
StatusAddressInUse StatusCode = 16
StatusConfigurationConflict StatusCode = 17
StatusMissingBindingInformation StatusCode = 18
StatusOutdatedBindingInformation StatusCode = 19
StatusServerShuttingDown StatusCode = 20
StatusDNSUpdateNotSupported StatusCode = 21
StatusExcessiveTimeSkew StatusCode = 22
)
// String returns a mnemonic name for a given status code
func (s StatusCode) String() string {
if sc := statusCodeToStringMap[s]; sc != "" {
return sc
}
return "Unknown"
}
var statusCodeToStringMap = map[StatusCode]string{
StatusSuccess: "Success",
StatusUnspecFail: "UnspecFail",
StatusNoAddrsAvail: "NoAddrsAvail",
StatusNoBinding: "NoBinding",
StatusNotOnLink: "NotOnLink",
StatusUseMulticast: "UseMulticast",
StatusNoPrefixAvail: "NoPrefixAvail",
// RFC 5007
StatusUnknownQueryType: "UnknownQueryType",
StatusMalformedQuery: "MalformedQuery",
StatusNotConfigured: "NotConfigured",
StatusNotAllowed: "NotAllowed",
// RFC 5460
StatusQueryTerminated: "QueryTerminated",
// RFC 7653
StatusDataMissing: "DataMissing",
StatusCatchUpComplete: "CatchUpComplete",
StatusNotSupported: "NotSupported",
StatusTLSConnectionRefused: "TLSConnectionRefused",
// RFC 8156
StatusAddressInUse: "AddressInUse",
StatusConfigurationConflict: "ConfigurationConflict",
StatusMissingBindingInformation: "MissingBindingInformation",
StatusOutdatedBindingInformation: "OutdatedBindingInformation",
StatusServerShuttingDown: "ServerShuttingDown",
StatusDNSUpdateNotSupported: "DNSUpdateNotSupported",
StatusExcessiveTimeSkew: "ExcessiveTimeSkew",
}

View File

@@ -0,0 +1,19 @@
// +build aix freebsd openbsd netbsd dragonfly
package interfaces
import (
"net"
"golang.org/x/sys/unix"
)
// BindToInterface emulates linux's SO_BINDTODEVICE option for a socket by using
// IP_RECVIF.
func BindToInterface(fd int, ifname string) error {
iface, err := net.InterfaceByName(ifname)
if err != nil {
return err
}
return unix.SetsockoptInt(fd, unix.IPPROTO_IP, unix.IP_RECVIF, iface.Index)
}

View File

@@ -0,0 +1,19 @@
// +build darwin
package interfaces
import (
"net"
"golang.org/x/sys/unix"
)
// BindToInterface emulates linux's SO_BINDTODEVICE option for a socket by using
// IP_BOUND_IF.
func BindToInterface(fd int, ifname string) error {
iface, err := net.InterfaceByName(ifname)
if err != nil {
return err
}
return unix.SetsockoptInt(fd, unix.IPPROTO_IP, unix.IP_BOUND_IF, iface.Index)
}

View File

@@ -0,0 +1,9 @@
// +build linux
package interfaces
import "golang.org/x/sys/unix"
func BindToInterface(fd int, ifname string) error {
return unix.BindToDevice(fd, ifname)
}

View File

@@ -0,0 +1,8 @@
package interfaces
import "errors"
// BindToInterface fails on Windows.
func BindToInterface(fd int, ifname string) error {
return errors.New("not implemented on Windows")
}

View File

@@ -0,0 +1,41 @@
package interfaces
import "net"
// InterfaceMatcher is a function type used to match the interfaces we want. See
// GetInterfacesFunc below for usage.
type InterfaceMatcher func(net.Interface) bool
// interfaceGetter is used for testing purposes
var interfaceGetter = net.Interfaces
// GetInterfacesFunc loops through the available network interfaces, and returns
// a list of interfaces for which the passed InterfaceMatcher function returns
// true.
func GetInterfacesFunc(matcher InterfaceMatcher) ([]net.Interface, error) {
ifaces, err := interfaceGetter()
if err != nil {
return nil, err
}
ret := make([]net.Interface, 0)
for _, iface := range ifaces {
if matcher(iface) {
ret = append(ret, iface)
}
}
return ret, nil
}
// GetLoopbackInterfaces returns a list of loopback interfaces.
func GetLoopbackInterfaces() ([]net.Interface, error) {
return GetInterfacesFunc(func(iface net.Interface) bool {
return iface.Flags&net.FlagLoopback != 0
})
}
// GetNonLoopbackInterfaces returns a list of non-loopback interfaces.
func GetNonLoopbackInterfaces() ([]net.Interface, error) {
return GetInterfacesFunc(func(iface net.Interface) bool {
return iface.Flags&net.FlagLoopback == 0
})
}

View File

@@ -0,0 +1,173 @@
package rfc1035label
import (
"errors"
"fmt"
"strings"
)
// Labels represents RFC1035 labels
//
// This implements RFC 1035 labels, including compression.
// https://tools.ietf.org/html/rfc1035#section-4.1.4
type Labels struct {
// original contains the original bytes if the object was parsed from a byte
// sequence, or nil otherwise. The `original` field is necessary to deal
// with compressed labels. If the labels are further modified, the original
// content is invalidated and no compression will be used.
original []byte
// Labels contains the parsed labels. A change here invalidates the
// `original` object.
Labels []string
}
// same compares two string arrays
func same(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i := 0; i < len(a); i++ {
if a[i] != b[i] {
return false
}
}
return true
}
// String prints labels.
func (l *Labels) String() string {
return fmt.Sprintf("%v", l.Labels)
}
// ToBytes returns a byte sequence representing the labels. If the original
// sequence is modified, the labels are parsed again, otherwise the original
// byte sequence is returned.
func (l *Labels) ToBytes() []byte {
// if the original byte sequence has been modified, invalidate it and
// serialize again.
// NOTE: this function is not thread-safe. If multiple threads modify
// the `Labels` field, the result may be wrong.
originalLabels, err := labelsFromBytes(l.original)
// if the original object has not been modified, or we cannot parse it,
// return the original bytes.
if err != nil || (l.original != nil && same(originalLabels, l.Labels)) {
return l.original
}
return labelsToBytes(l.Labels)
}
// Length returns the length in bytes of the serialized labels
func (l *Labels) Length() int {
return len(l.ToBytes())
}
// NewLabels returns an initialized Labels object.
func NewLabels() *Labels {
return &Labels{
Labels: make([]string, 0),
}
}
// FromBytes reads labels from a bytes stream according to RFC 1035.
func (l *Labels) FromBytes(data []byte) error {
labs, err := labelsFromBytes(data)
if err != nil {
return err
}
l.original = data
l.Labels = labs
return nil
}
// FromBytes returns a Labels object from the given byte sequence, or an error if
// any.
func FromBytes(data []byte) (*Labels, error) {
var l Labels
if err := l.FromBytes(data); err != nil {
return nil, err
}
return &l, nil
}
// ErrBufferTooShort is returned when the label cannot be parsed due to a wrong
// length or missing bytes.
var ErrBufferTooShort = errors.New("rfc1035label: buffer too short")
// fromBytes decodes a serialized stream and returns a list of labels
func labelsFromBytes(buf []byte) ([]string, error) {
var (
labels = make([]string, 0)
pos, oldPos int
label string
handlingPointer bool
)
for {
if pos >= len(buf) {
// interpret label without trailing zero-length byte as a partial
// domain name field as per RFC 4704 Section 4.2
if label != "" {
labels = append(labels, label)
}
break
}
length := int(buf[pos])
pos++
var chunk string
if length == 0 {
labels = append(labels, label)
label = ""
if handlingPointer {
pos = oldPos
handlingPointer = false
}
} else if length&0xc0 == 0xc0 {
// compression pointer
if handlingPointer {
return nil, errors.New("rfc1035label: cannot handle nested pointers")
}
handlingPointer = true
if pos+1 > len(buf) {
return nil, errors.New("rfc1035label: pointer buffer too short")
}
off := int(buf[pos-1]&^0xc0)<<8 + int(buf[pos])
oldPos = pos + 1
pos = off
} else {
if pos+length > len(buf) {
return nil, ErrBufferTooShort
}
chunk = string(buf[pos : pos+length])
if label != "" {
label += "."
}
label += chunk
pos += length
}
}
return labels, nil
}
// labelToBytes encodes a label and returns a serialized stream of bytes
func labelToBytes(label string) []byte {
var encodedLabel []byte
if len(label) == 0 {
return []byte{0}
}
for _, part := range strings.Split(label, ".") {
encodedLabel = append(encodedLabel, byte(len(part)))
encodedLabel = append(encodedLabel, []byte(part)...)
}
return append(encodedLabel, 0)
}
// labelsToBytes encodes a list of labels and returns a serialized stream of
// bytes
func labelsToBytes(labels []string) []byte {
var encodedLabels []byte
for _, label := range labels {
encodedLabels = append(encodedLabels, labelToBytes(label)...)
}
return encodedLabels
}