Skip to content

Commit

Permalink
dhcpv6: moved client into dhcpv6/client6
Browse files Browse the repository at this point in the history
  • Loading branch information
insomniacslk committed Jan 28, 2019
1 parent 64f2946 commit c04d263
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 64 deletions.
15 changes: 8 additions & 7 deletions dhcpv6/async/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import (
"sync"
"time"

"github.com/fanliao/go-promise"
promise "github.com/fanliao/go-promise"
"github.com/insomniacslk/dhcp/dhcpv6"
"github.com/insomniacslk/dhcp/dhcpv6/client6"
)

// Client implements an asynchronous DHCPv6 client
Expand All @@ -32,20 +33,20 @@ type Client struct {
// NewClient creates an asynchronous client
func NewClient() *Client {
return &Client{
ReadTimeout: dhcpv6.DefaultReadTimeout,
WriteTimeout: dhcpv6.DefaultWriteTimeout,
ReadTimeout: client6.DefaultReadTimeout,
WriteTimeout: client6.DefaultWriteTimeout,
}
}

// OpenForInterface starts the client on the specified interface, replacing
// client LocalAddr with a link-local address of the given interface and
// standard DHCP port (546).
func (c *Client) OpenForInterface(ifname string, bufferSize int) error {
addr, err := dhcpv6.GetLinkLocalAddr(ifname)
addr, err := client6.GetLinkLocalAddr(ifname)
if err != nil {
return err
}
c.LocalAddr = &net.UDPAddr{IP: addr, Port: dhcpv6.DefaultClientPort, Zone: ifname}
c.LocalAddr = &net.UDPAddr{IP: addr, Port: client6.DefaultClientPort, Zone: ifname}
return c.Open(bufferSize)
}

Expand Down Expand Up @@ -164,7 +165,7 @@ func (c *Client) receive(_ dhcpv6.DHCPv6) {

c.connection.SetReadDeadline(time.Now().Add(c.ReadTimeout))
for {
buffer := make([]byte, dhcpv6.MaxUDPReceivedPacketSize)
buffer := make([]byte, client6.MaxUDPReceivedPacketSize)
n, _, _, _, err := c.connection.ReadMsgUDP(buffer, oobdata)
if err != nil {
if err, ok := err.(net.Error); !ok || !err.Timeout() {
Expand Down Expand Up @@ -196,7 +197,7 @@ func (c *Client) receive(_ dhcpv6.DHCPv6) {

func (c *Client) remoteAddr() (*net.UDPAddr, error) {
if c.RemoteAddr == nil {
return &net.UDPAddr{IP: dhcpv6.AllDHCPRelayAgentsAndServers, Port: dhcpv6.DefaultServerPort}, nil
return &net.UDPAddr{IP: client6.AllDHCPRelayAgentsAndServers, Port: client6.DefaultServerPort}, nil
}

if addr, ok := c.RemoteAddr.(*net.UDPAddr); ok {
Expand Down
7 changes: 4 additions & 3 deletions dhcpv6/async/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"time"

"github.com/insomniacslk/dhcp/dhcpv6"
"github.com/insomniacslk/dhcp/dhcpv6/client6"
"github.com/insomniacslk/dhcp/iana"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -37,7 +38,7 @@ func serve(ctx context.Context, addr *net.UDPAddr, response dhcpv6.DHCPv6) error
go func() {
defer conn.Close()
oobdata := []byte{}
buffer := make([]byte, dhcpv6.MaxUDPReceivedPacketSize)
buffer := make([]byte, client6.MaxUDPReceivedPacketSize)
for {
select {
case <-ctx.Done():
Expand Down Expand Up @@ -66,8 +67,8 @@ func serve(ctx context.Context, addr *net.UDPAddr, response dhcpv6.DHCPv6) error
func TestNewClient(t *testing.T) {
c := NewClient()
require.NotNil(t, c)
require.Equal(t, c.ReadTimeout, dhcpv6.DefaultReadTimeout)
require.Equal(t, c.ReadTimeout, dhcpv6.DefaultWriteTimeout)
require.Equal(t, c.ReadTimeout, client6.DefaultReadTimeout)
require.Equal(t, c.ReadTimeout, client6.DefaultWriteTimeout)
}

func TestOpenInvalidAddrFailes(t *testing.T) {
Expand Down
52 changes: 27 additions & 25 deletions dhcpv6/client.go → dhcpv6/client6/client.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package dhcpv6
package client6

import (
"errors"
"fmt"
"net"
"time"

"github.com/insomniacslk/dhcp/dhcpv6"
)

// Client constants
Expand Down Expand Up @@ -41,8 +43,8 @@ func NewClient() *Client {
// Reply). The modifiers will be applied to the Solicit and Request packets.
// A common use is to make sure that the Solicit packet has the right options,
// see modifiers.go
func (c *Client) Exchange(ifname string, modifiers ...Modifier) ([]DHCPv6, error) {
conversation := make([]DHCPv6, 0)
func (c *Client) Exchange(ifname string, modifiers ...dhcpv6.Modifier) ([]dhcpv6.DHCPv6, error) {
conversation := make([]dhcpv6.DHCPv6, 0)
var err error

// Solicit
Expand All @@ -57,7 +59,7 @@ func (c *Client) Exchange(ifname string, modifiers ...Modifier) ([]DHCPv6, error

// Decapsulate advertise if it's relayed before passing it to Request
if advertise.IsRelay() {
advertiseRelay := advertise.(*DHCPv6Relay)
advertiseRelay := advertise.(*dhcpv6.DHCPv6Relay)
advertise, err = advertiseRelay.GetInnerMessage()
if err != nil {
return conversation, err
Expand All @@ -74,20 +76,20 @@ func (c *Client) Exchange(ifname string, modifiers ...Modifier) ([]DHCPv6, error
return conversation, nil
}

func (c *Client) sendReceive(ifname string, packet DHCPv6, expectedType MessageType) (DHCPv6, error) {
func (c *Client) sendReceive(ifname string, packet dhcpv6.DHCPv6, expectedType dhcpv6.MessageType) (dhcpv6.DHCPv6, error) {
if packet == nil {
return nil, fmt.Errorf("Packet to send cannot be nil")
}
if expectedType == MessageTypeNone {
if expectedType == dhcpv6.MessageTypeNone {
// infer the expected type from the packet being sent
if packet.Type() == MessageTypeSolicit {
expectedType = MessageTypeAdvertise
} else if packet.Type() == MessageTypeRequest {
expectedType = MessageTypeReply
} else if packet.Type() == MessageTypeRelayForward {
expectedType = MessageTypeRelayReply
} else if packet.Type() == MessageTypeLeaseQuery {
expectedType = MessageTypeLeaseQueryReply
if packet.Type() == dhcpv6.MessageTypeSolicit {
expectedType = dhcpv6.MessageTypeAdvertise
} else if packet.Type() == dhcpv6.MessageTypeRequest {
expectedType = dhcpv6.MessageTypeReply
} else if packet.Type() == dhcpv6.MessageTypeRelayForward {
expectedType = dhcpv6.MessageTypeRelayReply
} else if packet.Type() == dhcpv6.MessageTypeLeaseQuery {
expectedType = dhcpv6.MessageTypeLeaseQueryReply
} // and probably more
}
// if no LocalAddr is specified, get the interface's link-local address
Expand Down Expand Up @@ -147,11 +149,11 @@ func (c *Client) sendReceive(ifname string, packet DHCPv6, expectedType MessageT
oobdata := []byte{} // ignoring oob data
conn.SetReadDeadline(time.Now().Add(c.ReadTimeout))
var (
adv DHCPv6
adv dhcpv6.DHCPv6
isMessage bool
)
defer conn.Close()
msg, ok := packet.(*DHCPv6Message)
msg, ok := packet.(*dhcpv6.DHCPv6Message)
if ok {
isMessage = true
}
Expand All @@ -161,12 +163,12 @@ func (c *Client) sendReceive(ifname string, packet DHCPv6, expectedType MessageT
if err != nil {
return nil, err
}
adv, err = FromBytes(buf[:n])
adv, err = dhcpv6.FromBytes(buf[:n])
if err != nil {
// skip non-DHCP packets
continue
}
if recvMsg, ok := adv.(*DHCPv6Message); ok && isMessage {
if recvMsg, ok := adv.(*dhcpv6.DHCPv6Message); ok && isMessage {
// if a regular message, check the transaction ID first
// XXX should this unpack relay messages and check the XID of the
// inner packet too?
Expand All @@ -175,7 +177,7 @@ func (c *Client) sendReceive(ifname string, packet DHCPv6, expectedType MessageT
continue
}
}
if expectedType == MessageTypeNone {
if expectedType == dhcpv6.MessageTypeNone {
// just take whatever arrived
break
} else if adv.Type() == expectedType {
Expand All @@ -188,29 +190,29 @@ func (c *Client) sendReceive(ifname string, packet DHCPv6, expectedType MessageT
// Solicit sends a Solicit, returns the Solicit, an Advertise (if not nil), and
// an error if any. The modifiers will be applied to the Solicit before sending
// it, see modifiers.go
func (c *Client) Solicit(ifname string, modifiers ...Modifier) (DHCPv6, DHCPv6, error) {
solicit, err := NewSolicitForInterface(ifname)
func (c *Client) Solicit(ifname string, modifiers ...dhcpv6.Modifier) (dhcpv6.DHCPv6, dhcpv6.DHCPv6, error) {
solicit, err := dhcpv6.NewSolicitForInterface(ifname)
if err != nil {
return nil, nil, err
}
for _, mod := range modifiers {
solicit = mod(solicit)
}
advertise, err := c.sendReceive(ifname, solicit, MessageTypeNone)
advertise, err := c.sendReceive(ifname, solicit, dhcpv6.MessageTypeNone)
return solicit, advertise, err
}

// Request sends a Request built from an Advertise. It returns the Request, a
// Reply (if not nil), and an error if any. The modifiers will be applied to
// the Request before sending it, see modifiers.go
func (c *Client) Request(ifname string, advertise DHCPv6, modifiers ...Modifier) (DHCPv6, DHCPv6, error) {
request, err := NewRequestFromAdvertise(advertise)
func (c *Client) Request(ifname string, advertise dhcpv6.DHCPv6, modifiers ...dhcpv6.Modifier) (dhcpv6.DHCPv6, dhcpv6.DHCPv6, error) {
request, err := dhcpv6.NewRequestFromAdvertise(advertise)
if err != nil {
return nil, nil, err
}
for _, mod := range modifiers {
request = mod(request)
}
reply, err := c.sendReceive(ifname, request, MessageTypeNone)
reply, err := c.sendReceive(ifname, request, dhcpv6.MessageTypeNone)
return request, reply, err
}
2 changes: 1 addition & 1 deletion dhcpv6/client_test.go → dhcpv6/client6/client_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dhcpv6
package client6

import (
"testing"
Expand Down
2 changes: 1 addition & 1 deletion dhcpv6/defaults.go → dhcpv6/client6/defaults.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dhcpv6
package client6

const (
DefaultClientPort = 546
Expand Down
16 changes: 9 additions & 7 deletions dhcpv6/iputils.go → dhcpv6/client6/iputils.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package dhcpv6
package client6

import (
"fmt"
"net"

"github.com/insomniacslk/dhcp/dhcpv6"
)

// InterfaceAddresses is used to fetch addresses of an interface with given name
Expand Down Expand Up @@ -67,27 +69,27 @@ func GetMacAddressFromEUI64(ip net.IP) (net.HardwareAddr, error) {
// If that fails, it looks for the MAC addressed embededded in the DUID.
// Note that this only works with type DuidLL and DuidLLT.
// If a mac address cannot be found an error will be returned.
func ExtractMAC(packet DHCPv6) (net.HardwareAddr, error) {
func ExtractMAC(packet dhcpv6.DHCPv6) (net.HardwareAddr, error) {
msg := packet
if packet.IsRelay() {
inner, err := DecapsulateRelayIndex(packet, -1)
inner, err := dhcpv6.DecapsulateRelayIndex(packet, -1)
if err != nil {
return nil, err
}
ip := inner.(*DHCPv6Relay).PeerAddr()
ip := inner.(*dhcpv6.DHCPv6Relay).PeerAddr()
if mac, err := GetMacAddressFromEUI64(ip); err == nil {
return mac, nil
}
msg, err = msg.(*DHCPv6Relay).GetInnerMessage()
msg, err = msg.(*dhcpv6.DHCPv6Relay).GetInnerMessage()
if err != nil {
return nil, err
}
}
optclientid := msg.GetOneOption(OptionClientID)
optclientid := msg.GetOneOption(dhcpv6.OptionClientID)
if optclientid == nil {
return nil, fmt.Errorf("client ID not found in packet")
}
duid := optclientid.(*OptClientId).Cid
duid := optclientid.(*dhcpv6.OptClientId).Cid
if duid.LinkLayerAddr == nil {
return nil, fmt.Errorf("failed to extract MAC")
}
Expand Down
19 changes: 10 additions & 9 deletions dhcpv6/iputils_test.go → dhcpv6/client6/iputils_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package dhcpv6
package client6

import (
"errors"
"fmt"
"net"
"testing"

"github.com/insomniacslk/dhcp/dhcpv6"
"github.com/insomniacslk/dhcp/iana"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -125,35 +126,35 @@ func Test_ExtractMAC(t *testing.T) {
0x90, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xaf, 0xa0, 0x00, 0x00, 0x1c, 0x20, 0x00, 0x00,
0x1d, 0x4c}
packet, err := FromBytes(relayForwBytesDuidUUID)
packet, err := dhcpv6.FromBytes(relayForwBytesDuidUUID)
require.NoError(t, err)
mac, err := ExtractMAC(packet)
require.NoError(t, err)
require.Equal(t, mac.String(), "24:8a:07:56:dc:a4")

// MAC extracted from DUID
duid := Duid{
Type: DUID_LL,
duid := dhcpv6.Duid{
Type: dhcpv6.DUID_LL,
HwType: iana.HWTypeEthernet,
LinkLayerAddr: []byte{0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa},
}
solicit, err := NewMessage(WithClientID(duid))
solicit, err := dhcpv6.NewMessage(dhcpv6.WithClientID(duid))
require.NoError(t, err)
relay, err := EncapsulateRelay(solicit, MessageTypeRelayForward, net.IPv6zero, net.IPv6zero)
relay, err := dhcpv6.EncapsulateRelay(solicit, dhcpv6.MessageTypeRelayForward, net.IPv6zero, net.IPv6zero)
require.NoError(t, err)
mac, err = ExtractMAC(relay)
require.NoError(t, err)
require.Equal(t, mac.String(), "aa:aa:aa:aa:aa:aa")

// no client ID
solicit, err = NewMessage()
solicit, err = dhcpv6.NewMessage()
require.NoError(t, err)
mac, err = ExtractMAC(solicit)
require.Error(t, err)

// DUID is not DuidLL or DuidLLT
duid = Duid{}
solicit, err = NewMessage(WithClientID(duid))
duid = dhcpv6.Duid{}
solicit, err = dhcpv6.NewMessage(dhcpv6.WithClientID(duid))
require.NoError(t, err)
mac, err = ExtractMAC(solicit)
require.Error(t, err)
Expand Down
6 changes: 4 additions & 2 deletions dhcpv6/server.go → dhcpv6/server6/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"net"
"sync"
"time"

"github.com/insomniacslk/dhcp/dhcpv6"
)

/*
Expand Down Expand Up @@ -56,7 +58,7 @@ func main() {

// Handler is a type that defines the handler function to be called every time a
// valid DHCPv6 message is received
type Handler func(conn net.PacketConn, peer net.Addr, m DHCPv6)
type Handler func(conn net.PacketConn, peer net.Addr, m dhcpv6.DHCPv6)

// Server represents a DHCPv6 server object
type Server struct {
Expand Down Expand Up @@ -129,7 +131,7 @@ func (s *Server) ActivateAndServe() error {
continue
}
log.Printf("Handling request from %v", peer)
m, err := FromBytes(rbuf[:n])
m, err := dhcpv6.FromBytes(rbuf[:n])
if err != nil {
log.Printf("Error parsing DHCPv6 request: %v", err)
continue
Expand Down
Loading

0 comments on commit c04d263

Please sign in to comment.