github.com/contiv/libOpenflow@v0.0.0-20210609050114-d967b14cc688/protocol/arp.go (about)

     1  package protocol
     2  
     3  import (
     4  	"encoding/binary"
     5  	"errors"
     6  	"net"
     7  )
     8  
     9  const (
    10  	Type_Request = 1
    11  	Type_Reply   = 2
    12  )
    13  
    14  type ARP struct {
    15  	HWType      uint16
    16  	ProtoType   uint16
    17  	HWLength    uint8
    18  	ProtoLength uint8
    19  	Operation   uint16
    20  	HWSrc       net.HardwareAddr
    21  	IPSrc       net.IP
    22  	HWDst       net.HardwareAddr
    23  	IPDst       net.IP
    24  }
    25  
    26  func NewARP(opt int) (*ARP, error) {
    27  	if opt != Type_Request && opt != Type_Reply {
    28  		return nil, errors.New("Invalid ARP Operation.")
    29  	}
    30  	a := new(ARP)
    31  	a.HWType = 1
    32  	a.ProtoType = 0x800
    33  	a.HWLength = 6
    34  	a.ProtoLength = 4
    35  	a.Operation = uint16(opt)
    36  	a.HWSrc = net.HardwareAddr(make([]byte, 6))
    37  	a.IPSrc = net.IP(make([]byte, 4))
    38  	a.HWDst = net.HardwareAddr(make([]byte, 6))
    39  	a.IPDst = net.IP(make([]byte, 4))
    40  	return a, nil
    41  }
    42  
    43  func (a *ARP) Len() (n uint16) {
    44  	n = 8
    45  	n += uint16(a.HWLength*2 + a.ProtoLength*2)
    46  	return
    47  }
    48  
    49  func (a *ARP) MarshalBinary() (data []byte, err error) {
    50  	data = make([]byte, int(a.Len()))
    51  	binary.BigEndian.PutUint16(data[:2], a.HWType)
    52  	binary.BigEndian.PutUint16(data[2:4], a.ProtoType)
    53  	data[4] = a.HWLength
    54  	data[5] = a.ProtoLength
    55  	binary.BigEndian.PutUint16(data[6:8], a.Operation)
    56  
    57  	n := 8
    58  
    59  	copy(data[n:n+int(a.HWLength)], a.HWSrc)
    60  	n += int(a.HWLength)
    61  	copy(data[n:n+int(a.ProtoLength)], a.IPSrc.To4())
    62  	n += int(a.ProtoLength)
    63  	copy(data[n:n+int(a.HWLength)], a.HWDst)
    64  	n += int(a.HWLength)
    65  	copy(data[n:n+int(a.ProtoLength)], a.IPDst.To4())
    66  	return data, nil
    67  }
    68  
    69  func (a *ARP) UnmarshalBinary(data []byte) error {
    70  	if len(data) < 8 {
    71  		return errors.New("The []byte is too short to unmarshal a full ARP message.")
    72  	}
    73  	a.HWType = binary.BigEndian.Uint16(data[:2])
    74  	a.ProtoType = binary.BigEndian.Uint16(data[2:4])
    75  	a.HWLength = data[4]
    76  	a.ProtoLength = data[5]
    77  	a.Operation = binary.BigEndian.Uint16(data[6:8])
    78  
    79  	n := 8
    80  	if len(data[n:]) < (int(a.HWLength)*2 + int(a.ProtoLength)*2) {
    81  		return errors.New("The []byte is too short to unmarshal a full ARP message.")
    82  	}
    83  	a.HWSrc = data[n : n+int(a.HWLength)]
    84  	n += int(a.HWLength)
    85  	a.IPSrc = data[n : n+int(a.ProtoLength)]
    86  	n += int(a.ProtoLength)
    87  	a.HWDst = data[n : n+int(a.HWLength)]
    88  	n += int(a.HWLength)
    89  	a.IPDst = data[n : n+int(a.ProtoLength)]
    90  	return nil
    91  }