diff options
-rw-r--r-- | dhcpv4/bsdp/client.go | 19 | ||||
-rw-r--r-- | dhcpv4/client.go | 96 |
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 -} |