-
Notifications
You must be signed in to change notification settings - Fork 17
/
packet.go
64 lines (54 loc) · 1.73 KB
/
packet.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package dhcp6
import (
"github.com/mdlayher/dhcp6/internal/buffer"
)
// Packet represents a raw DHCPv6 packet, using the format described in RFC 3315,
// Section 6.
//
// The Packet type is typically only needed for low-level operations within the
// client, server, or in tests.
type Packet struct {
// MessageType specifies the DHCP message type constant, such as
// MessageTypeSolicit, MessageTypeAdvertise, etc.
MessageType MessageType
// TransactionID specifies the DHCP transaction ID. The transaction ID must
// be the same for all message exchanges in one DHCP transaction.
TransactionID [3]byte
// Options specifies a map of DHCP options. Its methods can be used to
// retrieve data from an incoming packet, or send data with an outgoing
// packet.
Options Options
}
// MarshalBinary allocates a byte slice containing the data
// from a Packet.
func (p *Packet) MarshalBinary() ([]byte, error) {
// 1 byte: message type
// 3 bytes: transaction ID
// N bytes: options slice byte count
b := buffer.New(nil)
b.Write8(uint8(p.MessageType))
b.WriteBytes(p.TransactionID[:])
opts, err := p.Options.MarshalBinary()
if err != nil {
return nil, err
}
b.WriteBytes(opts)
return b.Data(), nil
}
// UnmarshalBinary unmarshals a raw byte slice into a Packet.
//
// If the byte slice does not contain enough data to form a valid Packet,
// ErrInvalidPacket is returned.
func (p *Packet) UnmarshalBinary(q []byte) error {
b := buffer.New(q)
// Packet must contain at least a message type and transaction ID
if b.Len() < 4 {
return ErrInvalidPacket
}
p.MessageType = MessageType(b.Read8())
b.ReadBytes(p.TransactionID[:])
if err := (&p.Options).UnmarshalBinary(b.Remaining()); err != nil {
return ErrInvalidPacket
}
return nil
}