Version: v0.0.0-...-c97c800 Latest Latest

This package is not in the latest version of its module.

Go to latest
Published: Feb 6, 2019 License: BSD-3-Clause Imports: 11 Imported by: 0



Package dhcp6client implements a DHCPv6 client as per RFC 3315.



View Source
const (
	// ClientPort is the port clients use to listen for DHCP messages.
	ClientPort = 546

	// ServerPort is the port servers and relay agents use to listen for
	// DHCP messages.
	ServerPort = 547

RFC 3315 Section 5.2.


View Source
var (
	// AllServers is all DHCP servers and relay agents on the local network
	// segment (RFC 3315, Section 5.1.).
	AllServers = net.ParseIP("ff02::1:2")

	// DefaultServers is the default AllServers IP combined with the
	// ServerPort.
	DefaultServers = &net.UDPAddr{
		IP:   AllServers,
		Port: ServerPort,


func NewPacket

func NewPacket(typ dhcp6.MessageType, opts dhcp6.Options) *dhcp6.Packet

NewPacket creates a new DHCPv6 packet using the given message type and options.

A transaction ID will be generated.

func NewRapidSolicit

func NewRapidSolicit(mac net.HardwareAddr) (*dhcp6.Packet, error)

NewRapidSolicit returns a Solicit packet with the RapidCommit option.

func NewSolicitPacket

func NewSolicitPacket(mac net.HardwareAddr) (*dhcp6.Packet, error)

NewSolicitPacket returns a Solicit packet.

TODO(hugelgupf): Conform to RFC 3315 Section 17.1.1.

func RequestIANAFrom

func RequestIANAFrom(ad *dhcp6.Packet) (*dhcp6.Packet, error)

RequestIANAFrom returns a Request packet to request an IANA from the server that sent the given `ad` Advertisement.

RFC 3315 Section 18.1.1. determines how a Request packet should be created.

func SuitableReply

func SuitableReply(reqIANAs []*dhcp6opts.IANA, pkt *dhcp6.Packet) ([]*dhcp6opts.IANA, error)

SuitableReply validates whether a pkt is a valid Reply message as defined by RFC 3315, Section 18.1.8.

It returns all valid IANAs corresponding to requested IANAs.


type Client

type Client struct {
	// contains filtered or unexported fields

Client is a simple DHCPv6 client implementing RFC 3315.

Shortest Example:

c, err := dhcp6client.New(iface)
iana, packet, err := c.RapidSolicit()
// iana now contains the IP assigned in the IAAddr option.

Example selecting which advertising server to request from:

c, err := dhcp6client.New(iface)
ctx, cancel := context.WithTimeout(context.Background(), 5 * time.Second)
defer cancel()

ads, err := c.Solicit(ctx)
// Selecting the advertisement of server 3.
request, err := dhcp6client.RequestIANAFrom(ads[2])
iana, packet, err := c.RequestOne(request)
// iana now contains the IP assigned in the IAAddr option.

func New

func New(iface netlink.Link, opts ...ClientOpt) (*Client, error)

New returns a new DHCPv6 client based on the given parameters.

func (*Client) RapidSolicit

func (c *Client) RapidSolicit() (*dhcp6opts.IANA, *dhcp6.Packet, error)

RapidSolicit solicits one non-temporary address assignment by multicasting a DHCPv6 solicitation message with the rapid commit option.

RapidSolicit returns the first valid, suitable response by any remote server.

func (*Client) Request

func (c *Client) Request(request *dhcp6.Packet) ([]*dhcp6opts.IANA, *dhcp6.Packet, error)

Request requests non-temporary address assignments by multicasting the given message.

This request message may be any DHCPv6 request message type; e.g. a Solicit with the Rapid Commit option or a Rebind message.

func (*Client) RequestOne

func (c *Client) RequestOne(request *dhcp6.Packet) (*dhcp6opts.IANA, *dhcp6.Packet, error)

RequestOne multicasts the `request` and returns the first matching IANA and its associated Packet returned by any server.

func (*Client) SendAndRead

func (c *Client) SendAndRead(ctx context.Context, dest *net.UDPAddr, p *dhcp6.Packet, out chan<- *ClientPacket, errCh chan<- *ClientError)

SendAndRead sends the given packet `dest` to `to` and reads responses on the UDP connection. Any valid DHCP reply with the correct Transaction ID is sent on `out`.

SendAndRead blocks reading response packets until either: - `ctx` is canceled; or - we have exhausted all configured retries and timeouts.

SendAndRead retries sending the packet and receiving responses according to the configured number of c.retry, using a response timeout of c.timeout.

TODO(hugelgupf): SendAndRead should follow RFC 3315 Section 14 for retransmission behavior. Also conform to Section 15 for what kind of messages must be discarded.

func (*Client) SimpleSendAndRead

func (c *Client) SimpleSendAndRead(ctx context.Context, dest *net.UDPAddr, p *dhcp6.Packet) (*sync.WaitGroup, <-chan *ClientPacket, <-chan *ClientError)

SimpleSendAndRead multicasts a DHCPv6 packet and launches a goroutine to read response packets. Those response packets will be sent on the channel returned. The sender will close both goroutines when it stops reading packets, for example when the context is canceled.

Callers must cancel ctx when they have received the packet they are looking for. Otherwise, the spawned goroutine will keep reading until it times out. More importantly, if you send another packet, the spawned goroutine may read the response faster than the one launched for the other packet.

See Client.Solicit for an example use of SendAndRead.

Callers sending a packet on one interface should use this. Callers intending to send packets on many interface at the same time, should look at using SendAndRead instead.

Example Usage:

func sendRequest(someRequest *Packet...) (*Packet, error) {
  ctx, cancel := context.WithCancel(context.Background())
  defer cancel()

  out, errCh := c.SimpleSendAndRead(ctx, DefaultServers, someRequest)

  for response := range out {
    if response == What You Want {
      // Context cancelation will stop the reading goroutine.
      return response, ...

  if err, ok := <-errCh; ok && err != nil {
    return nil, err
  return nil, fmt.Errorf("got no valid responses")

TODO(hugelgupf): since the client only has one connection, maybe it should just have one dedicated goroutine for reading from the UDP socket, and use a request and response queue.

func (*Client) Solicit

func (c *Client) Solicit(ctx context.Context) ([]*dhcp6.Packet, error)

Solicit multicasts a Solicit message and collects all Advertise responses received before c.timeout expires.

Solicit blocks until either: - `ctx` is canceled; or - we have exhausted all configured retries and timeouts.

type ClientError

type ClientError struct {
	Interface netlink.Link
	Err       error

ClientError is an error that occurred on the associated interface.

func (*ClientError) Error

func (ce *ClientError) Error() string

Error implements error.

type ClientOpt

type ClientOpt func(*Client) error

ClientOpt is a function that configures the client.

func WithRetry

func WithRetry(retry int) ClientOpt

WithRetry configures the retransmission counts.

Default is 3.

TODO(hugelgupf): Check RFC for retransmission behavior.

func WithTimeout

func WithTimeout(d time.Duration) ClientOpt

WithTimeout configures the retransmission timeout.

Default is 10 seconds.

TODO(hugelgupf): Check RFC for retransmission behavior.

type ClientPacket

type ClientPacket struct {
	Interface netlink.Link
	Packet    *dhcp6.Packet

ClientPacket is a DHCP packet and the interface it corresponds to.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL