summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrea Barberio <insomniac@slackware.it>2017-12-06 19:53:13 +0000
committerAndrea Barberio <insomniac@slackware.it>2017-12-06 19:53:13 +0000
commita8db4e3c50790c83f8ba459517cc70481a014d83 (patch)
treea3f114c53d6d7a26ab1d525a51fb70f2b93ceb8e
parent5b10d4ccc61b730788ba80a1b1c3640ee1a960e6 (diff)
DHCPv6 is now an interface; DHCPv6Message and DHCPv6RelayMessage are implementations
-rw-r--r--dhcpv6/client.go18
-rw-r--r--dhcpv6/dhcpv6.go75
-rw-r--r--dhcpv6/dhcpv6_test.go22
3 files changed, 64 insertions, 51 deletions
diff --git a/dhcpv6/client.go b/dhcpv6/client.go
index 787439d..6bb1a91 100644
--- a/dhcpv6/client.go
+++ b/dhcpv6/client.go
@@ -25,29 +25,29 @@ type Client struct {
}
// Make a stateful DHCPv6 request
-func (c *Client) Exchange(ifname string, d *DHCPv6) ([]DHCPv6, error) {
- conversation := make([]DHCPv6, 1)
+func (c *Client) Exchange(ifname string, solicit DHCPv6) ([]DHCPv6, error) {
+ conversation := make([]DHCPv6, 0)
var err error
// Solicit
- if d == nil {
- d, err = NewSolicitForInterface(ifname)
+ if solicit == nil {
+ solicit, err = NewSolicitForInterface(ifname)
if err != nil {
return conversation, err
}
}
- conversation[0] = *d
- advertise, err := c.ExchangeSolicitAdvertise(ifname, d)
+ conversation = append(conversation, solicit)
+ advertise, err := c.ExchangeSolicitAdvertise(ifname, solicit)
if err != nil {
return conversation, err
}
- conversation = append(conversation, *advertise)
+ conversation = append(conversation, advertise)
// TODO request/reply
return conversation, nil
}
-func (c *Client) ExchangeSolicitAdvertise(ifname string, d *DHCPv6) (*DHCPv6, error) {
+func (c *Client) ExchangeSolicitAdvertise(ifname string, solicit DHCPv6) (DHCPv6, error) {
// if no LocalAddr is specified, get the interface's link-local address
var laddr net.UDPAddr
if c.LocalAddr == nil {
@@ -93,7 +93,7 @@ func (c *Client) ExchangeSolicitAdvertise(ifname string, d *DHCPv6) (*DHCPv6, er
conn.SetWriteDeadline(time.Now().Add(wtimeout))
// send the SOLICIT packet out
- _, err = conn.WriteTo(d.ToBytes(), &raddr)
+ _, err = conn.WriteTo(solicit.ToBytes(), &raddr)
if err != nil {
return nil, err
}
diff --git a/dhcpv6/dhcpv6.go b/dhcpv6/dhcpv6.go
index 6b664d2..0505301 100644
--- a/dhcpv6/dhcpv6.go
+++ b/dhcpv6/dhcpv6.go
@@ -13,12 +13,25 @@ import (
const HeaderSize = 4
-type DHCPv6 struct {
- message MessageType
+type DHCPv6 interface {
+ Type() MessageType
+ ToBytes() []byte
+ Summary() string
+}
+
+type DHCPv6Message struct {
+ messageType MessageType
transactionID uint32 // only 24 bits are used though
options []options.Option
}
+type DHCPv6RelayMessage struct {
+ messageType MessageType
+ hopCount uint8
+ linkAddr net.IP
+ peerAddr net.IP
+}
+
func BytesToTransactionID(data []byte) (*uint32, error) {
// return a uint32 from a sequence of bytes, representing a transaction ID.
// Transaction IDs are three-bytes long. If the provided data is shorter than
@@ -57,7 +70,7 @@ func GenerateTransactionID() (*uint32, error) {
return tid, nil
}
-func FromBytes(data []byte) (*DHCPv6, error) {
+func FromBytes(data []byte) (DHCPv6, error) {
if len(data) < HeaderSize {
return nil, fmt.Errorf("Invalid DHCPv6 header: shorter than %v bytes", HeaderSize)
}
@@ -65,8 +78,8 @@ func FromBytes(data []byte) (*DHCPv6, error) {
if err != nil {
return nil, err
}
- d := DHCPv6{
- message: MessageType(data[0]),
+ d := DHCPv6Message{
+ messageType: MessageType(data[0]),
transactionID: *tid,
}
options, err := options.FromBytes(data[4:])
@@ -77,13 +90,13 @@ func FromBytes(data []byte) (*DHCPv6, error) {
return &d, nil
}
-func New() (*DHCPv6, error) {
+func NewMessage() (*DHCPv6Message, error) {
tid, err := GenerateTransactionID()
if err != nil {
return nil, err
}
- d := DHCPv6{
- message: SOLICIT,
+ d := DHCPv6Message{
+ messageType: SOLICIT,
transactionID: *tid,
}
return &d, nil
@@ -98,8 +111,8 @@ func GetTime() uint32 {
// Create a new SOLICIT message with DUID-LLT, using the given network
// interface's hardware address and current time
-func NewSolicitForInterface(ifname string) (*DHCPv6, error) {
- d, err := New()
+func NewSolicitForInterface(ifname string) (*DHCPv6Message, error) {
+ d, err := NewMessage()
if err != nil {
return nil, err
}
@@ -133,29 +146,29 @@ func NewSolicitForInterface(ifname string) (*DHCPv6, error) {
return d, nil
}
-func (d *DHCPv6) Message() MessageType {
- return d.message
+func (d *DHCPv6Message) Type() MessageType {
+ return d.messageType
}
-func (d *DHCPv6) SetMessage(message MessageType) {
- if MessageToString[message] == "" {
- log.Printf("Warning: unknown DHCPv6 message: %v", message)
+func (d *DHCPv6Message) SetMessage(messageType MessageType) {
+ if MessageToString[messageType] == "" {
+ log.Printf("Warning: unknown DHCPv6 message type: %v", messageType)
}
- d.message = message
+ d.messageType = messageType
}
-func (d *DHCPv6) MessageToString() string {
- if m := MessageToString[d.message]; m != "" {
+func (d *DHCPv6Message) MessageToString() string {
+ if m := MessageToString[d.messageType]; m != "" {
return m
}
return "Invalid"
}
-func (d *DHCPv6) TransactionID() uint32 {
+func (d *DHCPv6Message) TransactionID() uint32 {
return d.transactionID
}
-func (d *DHCPv6) SetTransactionID(tid uint32) {
+func (d *DHCPv6Message) SetTransactionID(tid uint32) {
ttid := tid & 0x00ffffff
if ttid != tid {
log.Printf("Warning: truncating transaction ID that is longer than 24 bits: %v", tid)
@@ -163,28 +176,28 @@ func (d *DHCPv6) SetTransactionID(tid uint32) {
d.transactionID = ttid
}
-func (d *DHCPv6) Options() []options.Option {
+func (d *DHCPv6Message) Options() []options.Option {
return d.options
}
-func (d *DHCPv6) SetOptions(options []options.Option) {
+func (d *DHCPv6Message) SetOptions(options []options.Option) {
d.options = options
}
-func (d *DHCPv6) AddOption(option options.Option) {
+func (d *DHCPv6Message) AddOption(option options.Option) {
d.options = append(d.options, option)
}
-func (d *DHCPv6) String() string {
- return fmt.Sprintf("DHCPv6(message=%v transactionID=0x%06x, %d options)",
+func (d *DHCPv6Message) String() string {
+ return fmt.Sprintf("DHCPv6Message(messageType=%v transactionID=0x%06x, %d options)",
d.MessageToString(), d.TransactionID(), len(d.options),
)
}
-func (d *DHCPv6) Summary() string {
+func (d *DHCPv6Message) Summary() string {
ret := fmt.Sprintf(
- "DHCPv6\n"+
- " message=%v\n"+
+ "DHCPv6Message\n"+
+ " messageType=%v\n"+
" transactionid=0x%06x\n",
d.MessageToString(),
d.TransactionID(),
@@ -200,11 +213,11 @@ func (d *DHCPv6) Summary() string {
return ret
}
-// Convert a DHCPv6 structure into its binary representation, suitable for being
+// Convert a DHCPv6Message structure into its binary representation, suitable for being
// sent over the network
-func (d *DHCPv6) ToBytes() []byte {
+func (d *DHCPv6Message) ToBytes() []byte {
var ret []byte
- ret = append(ret, byte(d.message))
+ ret = append(ret, byte(d.messageType))
tidBytes := make([]byte, 4)
binary.BigEndian.PutUint32(tidBytes, d.transactionID)
ret = append(ret, tidBytes[1:4]...) // discard the first byte
diff --git a/dhcpv6/dhcpv6_test.go b/dhcpv6/dhcpv6_test.go
index 084a8b4..3d0c5fc 100644
--- a/dhcpv6/dhcpv6_test.go
+++ b/dhcpv6/dhcpv6_test.go
@@ -45,16 +45,16 @@ func TestGenerateTransactionID(t *testing.T) {
}
}
-func TestNew(t *testing.T) {
- d, err := New()
+func TestNewMessage(t *testing.T) {
+ d, err := NewMessage()
if err != nil {
t.Fatal(err)
}
if d == nil {
t.Fatal("Expected non-nil DHCPv6, got nil instead")
}
- if d.message != SOLICIT {
- t.Fatalf("Invalid message type. Expected %v, got %v", SOLICIT, d.message)
+ if d.messageType != SOLICIT {
+ t.Fatalf("Invalid message type. Expected %v, got %v", SOLICIT, d.messageType)
}
if d.transactionID == 0 {
t.Fatal("Invalid Transaction ID, expected non-zero, got zero")
@@ -65,17 +65,17 @@ func TestNew(t *testing.T) {
}
func TestSettersAndGetters(t *testing.T) {
- d := DHCPv6{}
+ d := DHCPv6Message{}
// Message
d.SetMessage(SOLICIT)
- msg := d.Message()
+ msg := d.Type()
if msg != SOLICIT {
- t.Fatalf("Invalid Message. Expected %v, got %v", SOLICIT, msg)
+ t.Fatalf("Invalid message type. Expected %v, got %v", SOLICIT, msg)
}
d.SetMessage(ADVERTISE)
- msg = d.Message()
+ msg = d.Type()
if msg != ADVERTISE {
- t.Fatalf("Invalid Message. Expected %v, got %v", ADVERTISE, msg)
+ t.Fatalf("Invalid message type. Expected %v, got %v", ADVERTISE, msg)
}
// TransactionID
d.SetTransactionID(12345)
@@ -100,7 +100,7 @@ func TestSettersAndGetters(t *testing.T) {
}
func TestAddOption(t *testing.T) {
- d := DHCPv6{}
+ d := DHCPv6Message{}
opts := d.Options()
if len(opts) != 0 {
t.Fatalf("Invalid Options. Expected empty array, got %v", opts)
@@ -117,7 +117,7 @@ func TestAddOption(t *testing.T) {
}
func TestToBytes(t *testing.T) {
- d := DHCPv6{}
+ d := DHCPv6Message{}
d.SetMessage(SOLICIT)
d.SetTransactionID(0xabcdef)
opt := options.OptionGeneric{OptionCode: 0, OptionData: []byte{}}