Simplify code + Allow more generic attr children + remove prefix
Docker-DCO-1.1-Signed-off-by: Guillaume J. Charmes <guillaume.charmes@docker.com> (github: creack)
This commit is contained in:
parent
19445d3dfc
commit
a890f18e9a
2 changed files with 79 additions and 62 deletions
|
@ -5,7 +5,15 @@
|
||||||
// netlink_darwin.go
|
// netlink_darwin.go
|
||||||
package netlink
|
package netlink
|
||||||
|
|
||||||
import "net"
|
import (
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrWrongSockType = errors.New("Wrong socket type")
|
||||||
|
ErrShortResponse = errors.New("Got short response from netlink")
|
||||||
|
)
|
||||||
|
|
||||||
// A Route is a subnet associated with the interface to reach it.
|
// A Route is a subnet associated with the interface to reach it.
|
||||||
type Route struct {
|
type Route struct {
|
||||||
|
|
|
@ -45,6 +45,7 @@ func getIpFamily(ip net.IP) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
type NetlinkRequestData interface {
|
type NetlinkRequestData interface {
|
||||||
|
Len() int
|
||||||
ToWireFormat() []byte
|
ToWireFormat() []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,21 +54,24 @@ type IfInfomsg struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newIfInfomsg(family int) *IfInfomsg {
|
func newIfInfomsg(family int) *IfInfomsg {
|
||||||
msg := &IfInfomsg{}
|
return &IfInfomsg{
|
||||||
msg.Family = uint8(family)
|
IfInfomsg: syscall.IfInfomsg{
|
||||||
msg.Type = uint16(0)
|
Family: uint8(family),
|
||||||
msg.Index = int32(0)
|
},
|
||||||
msg.Flags = uint32(0)
|
}
|
||||||
msg.Change = uint32(0)
|
}
|
||||||
|
|
||||||
|
func newIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg {
|
||||||
|
msg := newIfInfomsg(family)
|
||||||
|
parent.children = append(parent.children, msg)
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *IfInfomsg) ToWireFormat() []byte {
|
func (msg *IfInfomsg) ToWireFormat() []byte {
|
||||||
native := nativeEndian()
|
native := nativeEndian()
|
||||||
|
|
||||||
len := syscall.SizeofIfInfomsg
|
length := syscall.SizeofIfInfomsg
|
||||||
b := make([]byte, len)
|
b := make([]byte, length)
|
||||||
b[0] = msg.Family
|
b[0] = msg.Family
|
||||||
b[1] = 0
|
b[1] = 0
|
||||||
native.PutUint16(b[2:4], msg.Type)
|
native.PutUint16(b[2:4], msg.Type)
|
||||||
|
@ -77,26 +81,27 @@ func (msg *IfInfomsg) ToWireFormat() []byte {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (msg *IfInfomsg) Len() int {
|
||||||
|
return syscall.SizeofIfInfomsg
|
||||||
|
}
|
||||||
|
|
||||||
type IfAddrmsg struct {
|
type IfAddrmsg struct {
|
||||||
syscall.IfAddrmsg
|
syscall.IfAddrmsg
|
||||||
}
|
}
|
||||||
|
|
||||||
func newIfAddrmsg(family int) *IfAddrmsg {
|
func newIfAddrmsg(family int) *IfAddrmsg {
|
||||||
msg := &IfAddrmsg{}
|
return &IfAddrmsg{
|
||||||
msg.Family = uint8(family)
|
IfAddrmsg: syscall.IfAddrmsg{
|
||||||
msg.Prefixlen = uint8(0)
|
Family: uint8(family),
|
||||||
msg.Flags = uint8(0)
|
},
|
||||||
msg.Scope = uint8(0)
|
}
|
||||||
msg.Index = uint32(0)
|
|
||||||
|
|
||||||
return msg
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *IfAddrmsg) ToWireFormat() []byte {
|
func (msg *IfAddrmsg) ToWireFormat() []byte {
|
||||||
native := nativeEndian()
|
native := nativeEndian()
|
||||||
|
|
||||||
len := syscall.SizeofIfAddrmsg
|
length := syscall.SizeofIfAddrmsg
|
||||||
b := make([]byte, len)
|
b := make([]byte, length)
|
||||||
b[0] = msg.Family
|
b[0] = msg.Family
|
||||||
b[1] = msg.Prefixlen
|
b[1] = msg.Prefixlen
|
||||||
b[2] = msg.Flags
|
b[2] = msg.Flags
|
||||||
|
@ -105,26 +110,31 @@ func (msg *IfAddrmsg) ToWireFormat() []byte {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (msg *IfAddrmsg) Len() int {
|
||||||
|
return syscall.SizeofIfAddrmsg
|
||||||
|
}
|
||||||
|
|
||||||
type RtMsg struct {
|
type RtMsg struct {
|
||||||
syscall.RtMsg
|
syscall.RtMsg
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRtMsg(family int) *RtMsg {
|
func newRtMsg(family int) *RtMsg {
|
||||||
msg := &RtMsg{}
|
return &RtMsg{
|
||||||
msg.Family = uint8(family)
|
RtMsg: syscall.RtMsg{
|
||||||
msg.Table = syscall.RT_TABLE_MAIN
|
Family: uint8(family),
|
||||||
msg.Scope = syscall.RT_SCOPE_UNIVERSE
|
Table: syscall.RT_TABLE_MAIN,
|
||||||
msg.Protocol = syscall.RTPROT_BOOT
|
Scope: syscall.RT_SCOPE_UNIVERSE,
|
||||||
msg.Type = syscall.RTN_UNICAST
|
Protocol: syscall.RTPROT_BOOT,
|
||||||
|
Type: syscall.RTN_UNICAST,
|
||||||
return msg
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *RtMsg) ToWireFormat() []byte {
|
func (msg *RtMsg) ToWireFormat() []byte {
|
||||||
native := nativeEndian()
|
native := nativeEndian()
|
||||||
|
|
||||||
len := syscall.SizeofRtMsg
|
length := syscall.SizeofRtMsg
|
||||||
b := make([]byte, len)
|
b := make([]byte, length)
|
||||||
b[0] = msg.Family
|
b[0] = msg.Family
|
||||||
b[1] = msg.Dst_len
|
b[1] = msg.Dst_len
|
||||||
b[2] = msg.Src_len
|
b[2] = msg.Src_len
|
||||||
|
@ -137,6 +147,10 @@ func (msg *RtMsg) ToWireFormat() []byte {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (msg *RtMsg) Len() int {
|
||||||
|
return syscall.SizeofRtMsg
|
||||||
|
}
|
||||||
|
|
||||||
func rtaAlignOf(attrlen int) int {
|
func rtaAlignOf(attrlen int) int {
|
||||||
return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1)
|
return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1)
|
||||||
}
|
}
|
||||||
|
@ -144,18 +158,17 @@ func rtaAlignOf(attrlen int) int {
|
||||||
type RtAttr struct {
|
type RtAttr struct {
|
||||||
syscall.RtAttr
|
syscall.RtAttr
|
||||||
Data []byte
|
Data []byte
|
||||||
children []*RtAttr
|
children []NetlinkRequestData
|
||||||
prefix int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRtAttr(attrType int, data []byte) *RtAttr {
|
func newRtAttr(attrType int, data []byte) *RtAttr {
|
||||||
attr := &RtAttr{
|
return &RtAttr{
|
||||||
children: []*RtAttr{},
|
RtAttr: syscall.RtAttr{
|
||||||
|
Type: uint16(attrType),
|
||||||
|
},
|
||||||
|
children: []NetlinkRequestData{},
|
||||||
|
Data: data,
|
||||||
}
|
}
|
||||||
attr.Type = uint16(attrType)
|
|
||||||
attr.Data = data
|
|
||||||
|
|
||||||
return attr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRtAttrChild(parent *RtAttr, attrType int, data []byte) *RtAttr {
|
func newRtAttrChild(parent *RtAttr, attrType int, data []byte) *RtAttr {
|
||||||
|
@ -164,10 +177,10 @@ func newRtAttrChild(parent *RtAttr, attrType int, data []byte) *RtAttr {
|
||||||
return attr
|
return attr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *RtAttr) length() int {
|
func (a *RtAttr) Len() int {
|
||||||
l := 0
|
l := 0
|
||||||
for _, child := range a.children {
|
for _, child := range a.children {
|
||||||
l += child.length() + syscall.SizeofRtAttr + child.prefix
|
l += child.Len() + syscall.SizeofRtAttr
|
||||||
}
|
}
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
l++
|
l++
|
||||||
|
@ -178,7 +191,7 @@ func (a *RtAttr) length() int {
|
||||||
func (a *RtAttr) ToWireFormat() []byte {
|
func (a *RtAttr) ToWireFormat() []byte {
|
||||||
native := nativeEndian()
|
native := nativeEndian()
|
||||||
|
|
||||||
length := a.length()
|
length := a.Len()
|
||||||
buf := make([]byte, rtaAlignOf(length+syscall.SizeofRtAttr))
|
buf := make([]byte, rtaAlignOf(length+syscall.SizeofRtAttr))
|
||||||
|
|
||||||
if a.Data != nil {
|
if a.Data != nil {
|
||||||
|
@ -187,7 +200,7 @@ func (a *RtAttr) ToWireFormat() []byte {
|
||||||
next := 4
|
next := 4
|
||||||
for _, child := range a.children {
|
for _, child := range a.children {
|
||||||
childBuf := child.ToWireFormat()
|
childBuf := child.ToWireFormat()
|
||||||
copy(buf[next+child.prefix:], childBuf)
|
copy(buf[next:], childBuf)
|
||||||
next += rtaAlignOf(len(childBuf))
|
next += rtaAlignOf(len(childBuf))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,7 +225,7 @@ func (rr *NetlinkRequest) ToWireFormat() []byte {
|
||||||
dataBytes := make([][]byte, len(rr.Data))
|
dataBytes := make([][]byte, len(rr.Data))
|
||||||
for i, data := range rr.Data {
|
for i, data := range rr.Data {
|
||||||
dataBytes[i] = data.ToWireFormat()
|
dataBytes[i] = data.ToWireFormat()
|
||||||
length = length + uint32(len(dataBytes[i]))
|
length += uint32(len(dataBytes[i]))
|
||||||
}
|
}
|
||||||
b := make([]byte, length)
|
b := make([]byte, length)
|
||||||
native.PutUint32(b[0:4], length)
|
native.PutUint32(b[0:4], length)
|
||||||
|
@ -221,12 +234,10 @@ func (rr *NetlinkRequest) ToWireFormat() []byte {
|
||||||
native.PutUint32(b[8:12], rr.Seq)
|
native.PutUint32(b[8:12], rr.Seq)
|
||||||
native.PutUint32(b[12:16], rr.Pid)
|
native.PutUint32(b[12:16], rr.Pid)
|
||||||
|
|
||||||
i := 16
|
next := 16
|
||||||
for _, data := range dataBytes {
|
for _, data := range dataBytes {
|
||||||
for _, dataByte := range data {
|
copy(b[next:], data)
|
||||||
b[i] = dataByte
|
next += len(data)
|
||||||
i = i + 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
@ -238,12 +249,14 @@ func (rr *NetlinkRequest) AddData(data NetlinkRequestData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newNetlinkRequest(proto, flags int) *NetlinkRequest {
|
func newNetlinkRequest(proto, flags int) *NetlinkRequest {
|
||||||
rr := &NetlinkRequest{}
|
return &NetlinkRequest{
|
||||||
rr.Len = uint32(syscall.NLMSG_HDRLEN)
|
NlMsghdr: syscall.NlMsghdr{
|
||||||
rr.Type = uint16(proto)
|
Len: uint32(syscall.NLMSG_HDRLEN),
|
||||||
rr.Flags = syscall.NLM_F_REQUEST | uint16(flags)
|
Type: uint16(proto),
|
||||||
rr.Seq = uint32(getSeq())
|
Flags: syscall.NLM_F_REQUEST | uint16(flags),
|
||||||
return rr
|
Seq: uint32(getSeq()),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type NetlinkSocket struct {
|
type NetlinkSocket struct {
|
||||||
|
@ -286,7 +299,7 @@ func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if nr < syscall.NLMSG_HDRLEN {
|
if nr < syscall.NLMSG_HDRLEN {
|
||||||
return nil, fmt.Errorf("Got short response from netlink")
|
return nil, ErrShortResponse
|
||||||
}
|
}
|
||||||
rb = rb[:nr]
|
rb = rb[:nr]
|
||||||
return syscall.ParseNetlinkMessage(rb)
|
return syscall.ParseNetlinkMessage(rb)
|
||||||
|
@ -301,7 +314,7 @@ func (s *NetlinkSocket) GetPid() (uint32, error) {
|
||||||
case *syscall.SockaddrNetlink:
|
case *syscall.SockaddrNetlink:
|
||||||
return v.Pid, nil
|
return v.Pid, nil
|
||||||
}
|
}
|
||||||
return 0, fmt.Errorf("Wrong socket type")
|
return 0, ErrWrongSockType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *NetlinkSocket) HandleAck(seq uint32) error {
|
func (s *NetlinkSocket) HandleAck(seq uint32) error {
|
||||||
|
@ -592,11 +605,7 @@ func zeroTerminated(s string) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
func nonZeroTerminated(s string) []byte {
|
func nonZeroTerminated(s string) []byte {
|
||||||
bytes := make([]byte, len(s))
|
return []byte(s)
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
bytes[i] = s[i]
|
|
||||||
}
|
|
||||||
return bytes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a new network link of a specified type. This is identical to
|
// Add a new network link of a specified type. This is identical to
|
||||||
|
@ -789,8 +798,8 @@ func NetworkCreateVethPair(name1, name2 string) error {
|
||||||
nest2 := newRtAttrChild(nest1, IFLA_INFO_DATA, nil)
|
nest2 := newRtAttrChild(nest1, IFLA_INFO_DATA, nil)
|
||||||
nest3 := newRtAttrChild(nest2, VETH_INFO_PEER, nil)
|
nest3 := newRtAttrChild(nest2, VETH_INFO_PEER, nil)
|
||||||
|
|
||||||
last := newRtAttrChild(nest3, syscall.IFLA_IFNAME, zeroTerminated(name2))
|
newIfInfomsgChild(nest3, syscall.AF_UNSPEC)
|
||||||
last.prefix = syscall.SizeofIfInfomsg
|
newRtAttrChild(nest3, syscall.IFLA_IFNAME, zeroTerminated(name2))
|
||||||
|
|
||||||
wb.AddData(nest1)
|
wb.AddData(nest1)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue