github.com/system-transparency/u-root@v6.0.1-0.20190919065413-ed07a650de4c+incompatible/pkg/dhclient/dhcp6.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 "fmt" 9 "net" 10 "net/url" 11 12 "github.com/insomniacslk/dhcp/dhcpv6" 13 "github.com/vishvananda/netlink" 14 ) 15 16 // Packet6 implements Packet for IPv6 DHCP. 17 type Packet6 struct { 18 p *dhcpv6.Message 19 iface netlink.Link 20 } 21 22 // NewPacket6 wraps a DHCPv6 packet with some convenience methods. 23 func NewPacket6(iface netlink.Link, p *dhcpv6.Message) *Packet6 { 24 return &Packet6{ 25 p: p, 26 iface: iface, 27 } 28 } 29 30 func (p *Packet6) Link() netlink.Link { 31 return p.iface 32 } 33 34 // Configure configures interface using this packet. 35 func (p *Packet6) Configure() error { 36 return Configure6(p.iface, p.p) 37 } 38 39 func (p *Packet6) String() string { 40 return fmt.Sprintf("IPv6 DHCP Lease IP %s", p.Lease().IPv6Addr) 41 } 42 43 // Lease returns lease information assigned. 44 func (p *Packet6) Lease() *dhcpv6.OptIAAddress { 45 // TODO(chrisko): Reform dhcpv6 option handling to be like dhcpv4. 46 ianaOpt := p.p.GetOneOption(dhcpv6.OptionIANA) 47 iana, ok := ianaOpt.(*dhcpv6.OptIANA) 48 if !ok { 49 return nil 50 } 51 52 iaAddrOpt := iana.Options.GetOne(dhcpv6.OptionIAAddr) 53 iaAddr, ok := iaAddrOpt.(*dhcpv6.OptIAAddress) 54 if !ok { 55 return nil 56 } 57 return iaAddr 58 } 59 60 // DNS returns DNS servers assigned. 61 func (p *Packet6) DNS() []net.IP { 62 // TODO: Would the IANA contain this, or the packet? 63 dnsOpt := p.p.GetOneOption(dhcpv6.OptionDNSRecursiveNameServer) 64 dns, ok := dnsOpt.(*dhcpv6.OptDNSRecursiveNameServer) 65 if !ok { 66 return nil 67 } 68 return dns.NameServers 69 } 70 71 // Boot returns the boot file URL and parameters assigned. 72 // 73 // TODO: RFC 5970 is helpfully avoidant of where these options are used. Are 74 // they added to the packet? Are they added to an IANA? It *seems* like it's 75 // in the packet. 76 func (p *Packet6) Boot() (*url.URL, error) { 77 uriOpt := p.p.GetOneOption(dhcpv6.OptionBootfileURL) 78 uri, ok := uriOpt.(*dhcpv6.OptBootFileURL) 79 if !ok { 80 return nil, fmt.Errorf("packet does not contain boot file URL") 81 } 82 // Srsly, a []byte? 83 return url.Parse(string(uri.BootFileURL)) 84 } 85 86 // ISCSIBoot returns the target address and volume name to boot from if 87 // they were part of the DHCP message. 88 // 89 // Parses the DHCPv6 Boot File for iSCSI target and volume as specified by RFC 90 // 4173 and RFC 5970. 91 func (p *Packet6) ISCSIBoot() (*net.TCPAddr, string, error) { 92 uriOpt := p.p.GetOneOption(dhcpv6.OptionBootfileURL) 93 uri, ok := uriOpt.(*dhcpv6.OptBootFileURL) 94 if !ok { 95 return nil, "", fmt.Errorf("packet does not contain boot file URL") 96 } 97 return parseISCSIURI(string(uri.BootFileURL)) 98 }