Documentation
¶
Overview ¶
Package dhcp4client is a small, minimum-functionality client for DHCPv4.
It only supports the 4-way DHCPv4 Discover-Offer-Request-Ack handshake as well as the Request-Ack renewal process.
Index ¶
- Constants
- Variables
- func Checksum(buf []byte, initial uint16) uint16
- func ChecksumCombine(a, b uint16) uint16
- func IPVersion(b []byte) int
- func IsV4MulticastAddress(addr net.IP) bool
- func NewBroadcastUDPConn(rawPacketConn net.PacketConn, boundAddr *net.UDPAddr) net.PacketConn
- func NewIPv4UDPConn(iface string, port int) (net.PacketConn, error)
- func NewPacketUDPConn(iface string, port int) (net.PacketConn, error)
- func PseudoHeaderChecksum(protocol TransportProtocolNumber, srcAddr net.IP, dstAddr net.IP) uint16
- type Client
- func (c *Client) Close() error
- func (c *Client) DiscoverOffer() (*dhcp4.Packet, error)
- func (c *Client) DiscoverPacket() *dhcp4.Packet
- func (c *Client) Renew(ack *dhcp4.Packet) (*dhcp4.Packet, error)
- func (c *Client) Request() (*dhcp4.Packet, error)
- func (c *Client) RequestPacket(offer *dhcp4.Packet) *dhcp4.Packet
- func (c *Client) SendAndRead(ctx context.Context, dest *net.UDPAddr, p *dhcp4.Packet, ...)
- func (c *Client) SendAndReadOne(packet *dhcp4.Packet) (*dhcp4.Packet, error)
- func (c *Client) SimpleSendAndRead(ctx context.Context, dest *net.UDPAddr, p *dhcp4.Packet) (*sync.WaitGroup, <-chan *ClientPacket, <-chan *ClientError)
- type ClientError
- type ClientOpt
- type ClientPacket
- type IPv4
- func (b IPv4) CalculateChecksum() uint16
- func (b IPv4) Checksum() uint16
- func (b IPv4) DestinationAddress() net.IP
- func (b IPv4) Encode(i *IPv4Fields)
- func (b IPv4) EncodePartial(partialChecksum, totalLength uint16)
- func (b IPv4) Flags() uint8
- func (b IPv4) FragmentOffset() uint16
- func (b IPv4) HeaderLength() uint8
- func (b IPv4) ID() uint16
- func (b IPv4) IsValid(pktSize int) bool
- func (b IPv4) Payload() []byte
- func (b IPv4) PayloadLength() uint16
- func (b IPv4) Protocol() uint8
- func (b IPv4) SetChecksum(v uint16)
- func (b IPv4) SetDestinationAddress(addr net.IP)
- func (b IPv4) SetFlagsFragmentOffset(flags uint8, offset uint16)
- func (b IPv4) SetID(v uint16)
- func (b IPv4) SetSourceAddress(addr net.IP)
- func (b IPv4) SetTOS(v uint8, _ uint32)
- func (b IPv4) SetTotalLength(totalLength uint16)
- func (b IPv4) SourceAddress() net.IP
- func (b IPv4) TOS() (uint8, uint32)
- func (b IPv4) TTL() uint8
- func (b IPv4) TotalLength() uint16
- func (b IPv4) TransportProtocol() TransportProtocolNumber
- type IPv4Fields
- type TransportProtocolNumber
- type UDP
- func (b UDP) CalculateChecksum(partialChecksum uint16, totalLen uint16) uint16
- func (b UDP) Checksum() uint16
- func (b UDP) DestinationPort() uint16
- func (b UDP) Encode(u *UDPFields)
- func (b UDP) Length() uint16
- func (b UDP) Payload() []byte
- func (b UDP) SetChecksum(checksum uint16)
- func (b UDP) SetDestinationPort(port uint16)
- func (b UDP) SetSourcePort(port uint16)
- func (b UDP) SourcePort() uint16
- type UDPFields
- type UDPPacketConn
Constants ¶
const ( // ClientPort is the port that DHCP clients listen on. ClientPort = 68 // ServerPort is the port that DHCP servers and relay agents listen on. ServerPort = 67 )
const ( // IPv4MinimumSize is the minimum size of a valid IPv4 packet. IPv4MinimumSize = 20 // IPv4MaximumHeaderSize is the maximum size of an IPv4 header. Given // that there are only 4 bits to represents the header length in 32-bit // units, the header cannot exceed 15*4 = 60 bytes. IPv4MaximumHeaderSize = 60 // IPv4AddressSize is the size, in bytes, of an IPv4 address. IPv4AddressSize = 4 // IPv4Version is the version of the ipv4 protocol. IPv4Version = 4 )
const ( IPv4FlagMoreFragments = 1 << iota IPv4FlagDontFragment )
Flags that may be set in an IPv4 packet.
Variables ¶
var ( // IPv4Broadcast is the broadcast address of the IPv4 procotol. IPv4Broadcast = net.IP{0xff, 0xff, 0xff, 0xff} // IPv4Any is the non-routable IPv4 "any" meta address. IPv4Any = net.IP{0, 0, 0, 0} )
var (
BroadcastMac = net.HardwareAddr([]byte{255, 255, 255, 255, 255, 255})
)
var ( // DefaultServers is the address of all link-local DHCP servers and // relay agents. DefaultServers = &net.UDPAddr{ IP: net.IPv4bcast, Port: ServerPort, } )
Functions ¶
func Checksum ¶
Checksum calculates the checksum (as defined in RFC 1071) of the bytes in the given byte array.
The initial checksum must have been computed on an even number of bytes.
func ChecksumCombine ¶
ChecksumCombine combines the two uint16 to form their checksum. This is done by adding them and the carry.
Note that checksum a must have been computed on an even number of bytes.
func IPVersion ¶
IPVersion returns the version of IP used in the given packet. It returns -1 if the packet is not large enough to contain the version field.
func IsV4MulticastAddress ¶
IsV4MulticastAddress determines if the provided address is an IPv4 multicast address (range 224.0.0.0 to 239.255.255.255). The four most significant bits will be 1110 = 0xe0.
func NewBroadcastUDPConn ¶
func NewBroadcastUDPConn(rawPacketConn net.PacketConn, boundAddr *net.UDPAddr) net.PacketConn
NewBroadcastUDPConn returns a PacketConn that marshals and unmarshals UDP packets, sending them to the broadcast MAC at on rawPacketConn.
Calls to ReadFrom will only return packets destined to boundAddr.
func NewIPv4UDPConn ¶
func NewIPv4UDPConn(iface string, port int) (net.PacketConn, error)
NewIPv4UDPConn returns a UDP connection bound to both the interface and port given based on a IPv4 DGRAM socket. The UDP connection allows broadcasting.
func NewPacketUDPConn ¶
func NewPacketUDPConn(iface string, port int) (net.PacketConn, error)
NewPacketUDPConn returns a UDP connection bound to the interface and port given based on a raw packet socket. All packets are broadcasted.
func PseudoHeaderChecksum ¶
PseudoHeaderChecksum calculates the pseudo-header checksum for the given destination protocol and network address, ignoring the length field. Pseudo-headers are needed by transport layers when calculating their own checksum.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is an IPv4 DHCP client.
func (*Client) DiscoverOffer ¶
DiscoverOffer sends a DHCPDiscover message and returns the first valid offer received.
func (*Client) DiscoverPacket ¶
DiscoverPacket returns a valid Discover packet for this client.
TODO: Look at RFC and confirm.
func (*Client) Renew ¶
Renew sends a renewal request packet and waits for the corresponding response.
func (*Client) RequestPacket ¶
RequestPacket returns a valid DHCPRequest packet for the given offer.
TODO: Look at RFC and confirm.
func (*Client) SendAndRead ¶
func (c *Client) SendAndRead(ctx context.Context, dest *net.UDPAddr, p *dhcp4.Packet, out chan<- *ClientPacket, errCh chan<- *ClientError)
SendAndRead sends the given packet `p` to `dest` and reads responses on the UDP connection. Any valid DHCP reply packet is sent to `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): Make this a little state machine of packet types. See RFC 2131, Section 4.4, Figure 5.
func (*Client) SendAndReadOne ¶
SendAndReadOne sends one packet and returns the first response returned by any server.
func (*Client) SimpleSendAndRead ¶
func (c *Client) SimpleSendAndRead(ctx context.Context, dest *net.UDPAddr, p *dhcp4.Packet) (*sync.WaitGroup, <-chan *ClientPacket, <-chan *ClientError)
SimpleSendAndRead broadcasts a DHCP packet and launches a goroutine to read response packets. Those response packets will be sent on the channel returned.
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.
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.
type ClientError ¶
ClientError is an error that occured on the associated interface.
type ClientOpt ¶
ClientOpt is a function that configures the Client.
func WithConn ¶
func WithConn(conn net.PacketConn) ClientOpt
WithConn configures the packet connection to use.
func WithRetry ¶
WithRetry configures the number of retransmissions to attempt.
Default is 3.
TODO(hugelgupf): Check RFC for retransmission behavior.
func WithTimeout ¶
WithTimeout configures the retransmission timeout.
Default is 10 seconds.
TODO(hugelgupf): Check RFC for retransmission behavior.
type ClientPacket ¶
ClientPacket is a DHCP packet and the interface it corresponds to.
type IPv4 ¶
type IPv4 []byte
IPv4 represents an ipv4 header stored in a byte array. Most of the methods of IPv4 access to the underlying slice without checking the boundaries and could panic because of 'index out of range'. Always call IsValid() to validate an instance of IPv4 before using other methods.
func (IPv4) CalculateChecksum ¶
CalculateChecksum calculates the checksum of the ipv4 header.
func (IPv4) DestinationAddress ¶
DestinationAddress returns the "destination address" field of the ipv4 header.
func (IPv4) Encode ¶
func (b IPv4) Encode(i *IPv4Fields)
Encode encodes all the fields of the ipv4 header.
func (IPv4) EncodePartial ¶
EncodePartial updates the total length and checksum fields of ipv4 header, taking in the partial checksum, which is the checksum of the header without the total length and checksum fields. It is useful in cases when similar packets are produced.
func (IPv4) FragmentOffset ¶
FragmentOffset returns the "fragment offset" field of the ipv4 header.
func (IPv4) HeaderLength ¶
HeaderLength returns the value of the "header length" field of the ipv4 header.
func (IPv4) PayloadLength ¶
PayloadLength returns the length of the payload portion of the ipv4 packet.
func (IPv4) SetChecksum ¶
SetChecksum sets the checksum field of the ipv4 header.
func (IPv4) SetDestinationAddress ¶
SetDestinationAddress sets the "destination address" field of the ipv4 header.
func (IPv4) SetFlagsFragmentOffset ¶
SetFlagsFragmentOffset sets the "flags" and "fragment offset" fields of the ipv4 header.
func (IPv4) SetSourceAddress ¶
SetSourceAddress sets the "source address" field of the ipv4 header.
func (IPv4) SetTotalLength ¶
SetTotalLength sets the "total length" field of the ipv4 header.
func (IPv4) SourceAddress ¶
SourceAddress returns the "source address" field of the ipv4 header.
func (IPv4) TotalLength ¶
TotalLength returns the "total length" field of the ipv4 header.
func (IPv4) TransportProtocol ¶
func (b IPv4) TransportProtocol() TransportProtocolNumber
TransportProtocol implements Network.TransportProtocol.
type IPv4Fields ¶
type IPv4Fields struct { // IHL is the "internet header length" field of an IPv4 packet. IHL uint8 // TOS is the "type of service" field of an IPv4 packet. TOS uint8 // TotalLength is the "total length" field of an IPv4 packet. TotalLength uint16 // ID is the "identification" field of an IPv4 packet. ID uint16 // Flags is the "flags" field of an IPv4 packet. Flags uint8 // FragmentOffset is the "fragment offset" field of an IPv4 packet. FragmentOffset uint16 // TTL is the "time to live" field of an IPv4 packet. TTL uint8 // Protocol is the "protocol" field of an IPv4 packet. Protocol uint8 // Checksum is the "checksum" field of an IPv4 packet. Checksum uint16 // SrcAddr is the "source ip address" of an IPv4 packet. SrcAddr net.IP // DstAddr is the "destination ip address" of an IPv4 packet. DstAddr net.IP }
IPv4Fields contains the fields of an IPv4 packet. It is used to describe the fields of a packet that needs to be encoded.
type TransportProtocolNumber ¶
type TransportProtocolNumber uint32
TransportProtocolNumber is the number of a transport protocol.
const ( // UDPMinimumSize is the minimum size of a valid UDP packet. UDPMinimumSize = 8 // UDPProtocolNumber is UDP's transport protocol number. UDPProtocolNumber TransportProtocolNumber = 17 )
type UDP ¶
type UDP []byte
UDP represents a UDP header stored in a byte array.
func (UDP) CalculateChecksum ¶
CalculateChecksum calculates the checksum of the udp packet, given the total length of the packet and the checksum of the network-layer pseudo-header (excluding the total length) and the checksum of the payload.
func (UDP) DestinationPort ¶
DestinationPort returns the "destination port" field of the udp header.
func (UDP) SetChecksum ¶
SetChecksum sets the "checksum" field of the udp header.
func (UDP) SetDestinationPort ¶
SetDestinationPort sets the "destination port" field of the udp header.
func (UDP) SetSourcePort ¶
SetSourcePort sets the "source port" field of the udp header.
func (UDP) SourcePort ¶
SourcePort returns the "source port" field of the udp header.
type UDPFields ¶
type UDPFields struct { // SrcPort is the "source port" field of a UDP packet. SrcPort uint16 // DstPort is the "destination port" field of a UDP packet. DstPort uint16 // Length is the "length" field of a UDP packet. Length uint16 // Checksum is the "checksum" field of a UDP packet. Checksum uint16 }
UDPFields contains the fields of a UDP packet. It is used to describe the fields of a packet that needs to be encoded.
type UDPPacketConn ¶
type UDPPacketConn struct { net.PacketConn // contains filtered or unexported fields }
UDPPacketConn implements net.PacketConn and marshals and unmarshals UDP packets.
func (*UDPPacketConn) ReadFrom ¶
ReadFrom implements net.PacketConn.ReadFrom.
ReadFrom reads raw IP packets and will try to match them against upc.boundAddr. Any matching packets are returned via the given buffer.