github.com/mem/u-root@v2.0.1-0.20181004165302-9b18b4636a33+incompatible/pkg/dhclient/dhcp4.go (about)

     1  // Copyright 2017-2018 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package dhclient
     6  
     7  import (
     8  	"net"
     9  	"net/url"
    10  
    11  	"github.com/u-root/dhcp4"
    12  	"github.com/u-root/dhcp4/dhcp4opts"
    13  )
    14  
    15  // Packet4 implements convenience functions for DHCPv4 packets.
    16  type Packet4 struct {
    17  	P *dhcp4.Packet
    18  }
    19  
    20  // NewPacket4 wraps a DHCPv4 packet with some convenience methods.
    21  func NewPacket4(p *dhcp4.Packet) *Packet4 {
    22  	return &Packet4{
    23  		P: p,
    24  	}
    25  }
    26  
    27  // Lease returns the IPNet assigned.
    28  func (p *Packet4) Lease() *net.IPNet {
    29  	netmask := dhcp4opts.GetSubnetMask(p.P.Options)
    30  	if netmask == nil {
    31  		// If they did not offer a subnet mask, we choose the most
    32  		// restrictive option.
    33  		netmask = []byte{255, 255, 255, 255}
    34  	}
    35  
    36  	return &net.IPNet{
    37  		IP:   p.P.YIAddr,
    38  		Mask: net.IPMask(netmask),
    39  	}
    40  }
    41  
    42  // Gateway returns the gateway IP assigned.
    43  //
    44  // OptionRouter is used as opposed to GIAddr, which seems unused by most DHCP
    45  // servers?
    46  func (p *Packet4) Gateway() net.IP {
    47  	gw := dhcp4opts.GetRouters(p.P.Options)
    48  	if gw == nil {
    49  		return nil
    50  	}
    51  	return gw[0]
    52  }
    53  
    54  // DNS returns DNS IPs assigned.
    55  func (p *Packet4) DNS() []net.IP {
    56  	ips := dhcp4opts.GetDomainNameServers(p.P.Options)
    57  	if ips == nil {
    58  		return nil
    59  	}
    60  	return []net.IP(ips)
    61  }
    62  
    63  // Boot returns the boot file assigned.
    64  func (p *Packet4) Boot() (url.URL, error) {
    65  	// TODO: This is not 100% right -- if a certain option is set, this
    66  	// stuff is encoded in options instead of in the packet's BootFile and
    67  	// ServerName fields.
    68  
    69  	// While the default is tftp, servers may specify HTTP or FTP URIs.
    70  	u, err := url.Parse(p.P.BootFile)
    71  	if err != nil {
    72  		return url.URL{}, err
    73  	}
    74  
    75  	if len(u.Scheme) == 0 {
    76  		// Defaults to tftp is not specified.
    77  		u.Scheme = "tftp"
    78  		u.Path = p.P.BootFile
    79  		if len(p.P.ServerName) == 0 {
    80  			server := dhcp4opts.GetServerIdentifier(p.P.Options)
    81  			if server == nil {
    82  				return url.URL{}, err
    83  			}
    84  			u.Host = net.IP(server).String()
    85  		} else {
    86  			u.Host = p.P.ServerName
    87  		}
    88  	}
    89  	return *u, nil
    90  }