summaryrefslogtreecommitdiffhomepage
path: root/dhcpv4
diff options
context:
space:
mode:
Diffstat (limited to 'dhcpv4')
-rw-r--r--dhcpv4/bsdp/client.go19
-rw-r--r--dhcpv4/client.go96
2 files changed, 12 insertions, 103 deletions
diff --git a/dhcpv4/bsdp/client.go b/dhcpv4/bsdp/client.go
index 255d54b..8131bec 100644
--- a/dhcpv4/bsdp/client.go
+++ b/dhcpv4/bsdp/client.go
@@ -8,16 +8,14 @@ import (
// Client represents a BSDP client that can perform BSDP exchanges via the
// broadcast address.
-type Client dhcpv4.Client
+type Client struct {
+ dhcpv4.Client
+}
// NewClient constructs a new client with default read and write timeouts from
// dhcpv4.Client.
func NewClient() *Client {
- c := dhcpv4.NewClient()
- return &Client{
- ReadTimeout: c.ReadTimeout,
- WriteTimeout: c.WriteTimeout,
- }
+ return &Client{Client: dhcpv4.Client{}}
}
func castVendorOpt(ack *dhcpv4.DHCPv4) {
@@ -37,8 +35,7 @@ func castVendorOpt(ack *dhcpv4.DHCPv4) {
// Exchange runs a full BSDP exchange (Inform[list], Ack, Inform[select],
// Ack). Returns a list of DHCPv4 structures representing the exchange.
func (c *Client) Exchange(ifname string, informList *dhcpv4.DHCPv4) ([]*dhcpv4.DHCPv4, error) {
- conversation := make([]*dhcpv4.DHCPv4, 1)
- var err error
+ conversation := make([]*dhcpv4.DHCPv4, 0)
// Get our file descriptor for the broadcast socket.
sendFd, err := dhcpv4.MakeBroadcastSocket(ifname)
@@ -57,10 +54,10 @@ func (c *Client) Exchange(ifname string, informList *dhcpv4.DHCPv4) ([]*dhcpv4.D
return conversation, err
}
}
- conversation[0] = informList
+ conversation = append(conversation, informList)
// ACK[LIST]
- ackForList, err := dhcpv4.BroadcastSendReceive(sendFd, recvFd, informList, c.ReadTimeout, c.WriteTimeout, dhcpv4.MessageTypeAck)
+ ackForList, err := c.Client.SendReceive(sendFd, recvFd, informList, dhcpv4.MessageTypeAck)
if err != nil {
return conversation, err
}
@@ -86,7 +83,7 @@ func (c *Client) Exchange(ifname string, informList *dhcpv4.DHCPv4) ([]*dhcpv4.D
conversation = append(conversation, informSelect)
// ACK[SELECT]
- ackForSelect, err := dhcpv4.BroadcastSendReceive(sendFd, recvFd, informSelect, c.ReadTimeout, c.WriteTimeout, dhcpv4.MessageTypeAck)
+ ackForSelect, err := c.Client.SendReceive(sendFd, recvFd, informSelect, dhcpv4.MessageTypeAck)
castVendorOpt(ackForSelect)
if err != nil {
return conversation, err
diff --git a/dhcpv4/client.go b/dhcpv4/client.go
index 3370ecf..e9a9ff5 100644
--- a/dhcpv4/client.go
+++ b/dhcpv4/client.go
@@ -6,7 +6,6 @@ import (
"fmt"
"log"
"net"
- "os"
"reflect"
"time"
@@ -48,15 +47,6 @@ func NewClient() *Client {
}
}
-// MakeRawBroadcastPacket leverages MakeRawPacket to create a raw packet suitable
-// for UDP broadcast.
-func MakeRawBroadcastPacket(payload []byte) ([]byte, error) {
- log.Printf("Warning: dhcpv4.MakeRawBroadcastPacket() is deprecated and will be removed.")
- serverAddr := net.UDPAddr{IP: net.IPv4bcast, Port: ServerPort}
- clientAddr := net.UDPAddr{IP: net.IPv4zero, Port: ClientPort}
- return MakeRawUDPPacket(payload, serverAddr, clientAddr)
-}
-
// MakeRawUDPPacket converts a payload (a serialized DHCPv4 packet) into a
// raw UDP packet for the specified serverAddr from the specified clientAddr.
func MakeRawUDPPacket(payload []byte, serverAddr, clientAddr net.UDPAddr) ([]byte, error) {
@@ -191,7 +181,6 @@ func (c *Client) getRemoteUDPAddr() (*net.UDPAddr, error) {
// containing all the sent and received DHCPv4 messages.
func (c *Client) Exchange(ifname string, discover *DHCPv4, modifiers ...Modifier) ([]*DHCPv4, error) {
conversation := make([]*DHCPv4, 0)
- var err error
raddr, err := c.getRemoteUDPAddr()
if err != nil {
return nil, err
@@ -243,7 +232,7 @@ func (c *Client) Exchange(ifname string, discover *DHCPv4, modifiers ...Modifier
conversation = append(conversation, discover)
// Offer
- offer, err := c.sendReceive(sfd, rfd, discover, MessageTypeOffer)
+ offer, err := c.SendReceive(sfd, rfd, discover, MessageTypeOffer)
if err != nil {
return conversation, err
}
@@ -257,7 +246,7 @@ func (c *Client) Exchange(ifname string, discover *DHCPv4, modifiers ...Modifier
conversation = append(conversation, request)
// Ack
- ack, err := c.sendReceive(sfd, rfd, request, MessageTypeAck)
+ ack, err := c.SendReceive(sfd, rfd, request, MessageTypeAck)
if err != nil {
return conversation, err
}
@@ -266,10 +255,10 @@ func (c *Client) Exchange(ifname string, discover *DHCPv4, modifiers ...Modifier
return conversation, nil
}
-// sendReceive sends a packet (with some write timeout) and waits for a
+// SendReceive sends a packet (with some write timeout) and waits for a
// response up to some read timeout value. If the message type is not
// MessageTypeNone, it will wait for a specific message type
-func (c *Client) sendReceive(sendFd, recvFd int, packet *DHCPv4, messageType MessageType) (*DHCPv4, error) {
+func (c *Client) SendReceive(sendFd, recvFd int, packet *DHCPv4, messageType MessageType) (*DHCPv4, error) {
raddr, err := c.getRemoteUDPAddr()
if err != nil {
return nil, err
@@ -383,80 +372,3 @@ func (c *Client) sendReceive(sendFd, recvFd int, packet *DHCPv4, messageType Mes
return response, nil
}
-
-// BroadcastSendReceive broadcasts packet (with some write timeout) and waits for a
-// response up to some read timeout value. If the message type is not
-// MessageTypeNone, it will wait for a specific message type
-func BroadcastSendReceive(sendFd, recvFd int, packet *DHCPv4, readTimeout, writeTimeout time.Duration, messageType MessageType) (*DHCPv4, error) {
- log.Printf("Warning: dhcpv4.BroadcastSendAndReceive() is deprecated and will be removed. You should use dhcpv4.client.Exchange() instead.")
- packetBytes, err := MakeRawBroadcastPacket(packet.ToBytes())
- if err != nil {
- return nil, err
- }
-
- // Create a goroutine to perform the blocking send, and time it out after
- // a certain amount of time.
- var (
- destination [4]byte
- response *DHCPv4
- )
- copy(destination[:], net.IPv4bcast.To4())
- remoteAddr := unix.SockaddrInet4{Port: ClientPort, Addr: destination}
- recvErrors := make(chan error, 1)
- go func(errs chan<- error) {
- conn, innerErr := net.FileConn(os.NewFile(uintptr(recvFd), ""))
- if err != nil {
- errs <- innerErr
- return
- }
- defer conn.Close()
- conn.SetReadDeadline(time.Now().Add(readTimeout))
-
- for {
- buf := make([]byte, MaxUDPReceivedPacketSize)
- n, _, _, _, innerErr := conn.(*net.UDPConn).ReadMsgUDP(buf, []byte{})
- if innerErr != nil {
- errs <- innerErr
- return
- }
-
- response, innerErr = FromBytes(buf[:n])
- if err != nil {
- errs <- innerErr
- return
- }
- // check that this is a response to our message
- if response.TransactionID() != packet.TransactionID() {
- continue
- }
- // wait for a response message
- if response.Opcode() != OpcodeBootReply {
- continue
- }
- // if we are not requested to wait for a specific message type,
- // return what we have
- if messageType == MessageTypeNone {
- break
- }
- // break if it's a reply of the desired type, continue otherwise
- if response.MessageType() != nil && *response.MessageType() == messageType {
- break
- }
- }
- recvErrors <- nil
- }(recvErrors)
- if err = unix.Sendto(sendFd, packetBytes, 0, &remoteAddr); err != nil {
- return nil, err
- }
-
- select {
- case err = <-recvErrors:
- if err != nil {
- return nil, err
- }
- case <-time.After(readTimeout):
- return nil, errors.New("timed out while listening for replies")
- }
-
- return response, nil
-}