summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--dhcpv4/bsdp/client.go20
-rw-r--r--dhcpv4/client.go45
2 files changed, 39 insertions, 26 deletions
diff --git a/dhcpv4/bsdp/client.go b/dhcpv4/bsdp/client.go
index 00e5ad5..f64f035 100644
--- a/dhcpv4/bsdp/client.go
+++ b/dhcpv4/bsdp/client.go
@@ -8,9 +8,23 @@ import (
"github.com/insomniacslk/dhcp/dhcpv4"
)
+// Client represents a BSDP client that can perform BSDP exchanges via the
+// broadcast address.
+type Client 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,
+ }
+}
+
// Exchange runs a full BSDP exchange (Inform[list], Ack, Inform[select],
// Ack). Returns a list of DHCPv4 structures representing the exchange.
-func Exchange(client *dhcpv4.Client, ifname string, informList *dhcpv4.DHCPv4) ([]dhcpv4.DHCPv4, error) {
+func (c *Client) Exchange(ifname string, informList *dhcpv4.DHCPv4) ([]dhcpv4.DHCPv4, error) {
conversation := make([]dhcpv4.DHCPv4, 1)
var err error
@@ -30,7 +44,7 @@ func Exchange(client *dhcpv4.Client, ifname string, informList *dhcpv4.DHCPv4) (
conversation[0] = *informList
// ACK[LIST]
- ackForList, err := dhcpv4.SendReceive(client, fd, informList)
+ ackForList, err := dhcpv4.BroadcastSendReceive(fd, informList, c.ReadTimeout, c.WriteTimeout)
if err != nil {
return conversation, err
}
@@ -53,7 +67,7 @@ func Exchange(client *dhcpv4.Client, ifname string, informList *dhcpv4.DHCPv4) (
conversation = append(conversation, *informSelect)
// ACK[SELECT]
- ackForSelect, err := dhcpv4.SendReceive(client, fd, informSelect)
+ ackForSelect, err := dhcpv4.BroadcastSendReceive(fd, informSelect, c.ReadTimeout, c.WriteTimeout)
if err != nil {
return conversation, err
}
diff --git a/dhcpv4/client.go b/dhcpv4/client.go
index c132eaa..2962fc5 100644
--- a/dhcpv4/client.go
+++ b/dhcpv4/client.go
@@ -81,23 +81,23 @@ func MakeRawBroadcastPacket(payload []byte) ([]byte, error) {
func MakeBroadcastSocket(ifname string) (int, error) {
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
if err != nil {
- return -1, err
+ return fd, err
}
err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
if err != nil {
- return -1, err
+ return fd, err
}
err = syscall.SetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_HDRINCL, 1)
if err != nil {
- return -1, err
+ return fd, err
}
err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
if err != nil {
- return -1, err
+ return fd, err
}
err = BindToInterface(fd, ifname)
if err != nil {
- return -1, err
+ return fd, err
}
return fd, nil
}
@@ -108,15 +108,9 @@ func MakeBroadcastSocket(ifname string) (int, error) {
// ordered as Discovery, Offer, Request and Acknowledge. In case of errors, an
// error is returned, and the list of DHCPv4 objects will be shorted than 4,
// containing all the sent and received DHCPv4 messages.
-func Exchange(client *Client, ifname string, discover *DHCPv4) ([]DHCPv4, error) {
+func (c *Client) Exchange(ifname string, discover *DHCPv4) ([]DHCPv4, error) {
conversation := make([]DHCPv4, 1)
var err error
- if discover == nil {
- discover, err = NewDiscoveryForInterface(ifname)
- if err != nil {
- return conversation, err
- }
- }
// Get our file descriptor for the broadcast socket.
fd, err := MakeBroadcastSocket(ifname)
@@ -125,10 +119,16 @@ func Exchange(client *Client, ifname string, discover *DHCPv4) ([]DHCPv4, error)
}
// Discover
+ if discover == nil {
+ discover, err = NewDiscoveryForInterface(ifname)
+ if err != nil {
+ return conversation, err
+ }
+ }
conversation[0] = *discover
// Offer
- offer, err := SendReceive(client, fd, discover)
+ offer, err := BroadcastSendReceive(fd, discover, c.ReadTimeout, c.WriteTimeout)
if err != nil {
return conversation, err
}
@@ -142,7 +142,7 @@ func Exchange(client *Client, ifname string, discover *DHCPv4) ([]DHCPv4, error)
conversation = append(conversation, *request)
// Ack
- ack, err := SendReceive(client, fd, discover)
+ ack, err := BroadcastSendReceive(fd, discover, c.ReadTimeout, c.WriteTimeout)
if err != nil {
return conversation, err
}
@@ -150,10 +150,9 @@ func Exchange(client *Client, ifname string, discover *DHCPv4) ([]DHCPv4, error)
return conversation, nil
}
-// SendReceive broadcasts packet (with some write timeout) and waits for a
+// BroadcastSendReceive broadcasts packet (with some write timeout) and waits for a
// response up to some read timeout value.
-func SendReceive(client *Client, fd int, packet *DHCPv4) (*DHCPv4, error) {
- // Build up our packet bytes.
+func BroadcastSendReceive(fd int, packet *DHCPv4, readTimeout, writeTimeout time.Duration) (*DHCPv4, error) {
packetBytes, err := MakeRawBroadcastPacket(packet.ToBytes())
if err != nil {
return nil, err
@@ -170,23 +169,23 @@ func SendReceive(client *Client, fd int, packet *DHCPv4) (*DHCPv4, error) {
if err != nil {
return nil, err
}
- case <-time.After(client.WriteTimeout):
- return nil, errors.New("timed out while communicating with server")
+ case <-time.After(writeTimeout):
+ return nil, errors.New("timed out while sending broadcast")
}
- // Open up a connection to listen.
conn, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4zero, Port: ClientPort})
+ if err != nil {
+ return nil, err
+ }
defer conn.Close()
- conn.SetReadDeadline(time.Now().Add(client.ReadTimeout))
+ conn.SetReadDeadline(time.Now().Add(readTimeout))
- // Wait for a response from the server.
buf := make([]byte, MaxUDPReceivedPacketSize)
n, _, _, _, err := conn.ReadMsgUDP(buf, []byte{})
if err != nil {
return nil, err
}
- // Serialize to a DHCPv4 packet.
response, err := FromBytes(buf[:n])
if err != nil {
return nil, err