Switch to new vendor directory layout
Fixes #113 Signed-off-by: Marcos Lilljedahl <marcosnils@gmail.com>
This commit is contained in:
		
							
								
								
									
										424
									
								
								vendor/github.com/vishvananda/netlink/nl/nl_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										424
									
								
								vendor/github.com/vishvananda/netlink/nl/nl_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,424 @@
 | 
			
		||||
// Package nl has low level primitives for making Netlink calls.
 | 
			
		||||
package nl
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// Family type definitions
 | 
			
		||||
	FAMILY_ALL = syscall.AF_UNSPEC
 | 
			
		||||
	FAMILY_V4  = syscall.AF_INET
 | 
			
		||||
	FAMILY_V6  = syscall.AF_INET6
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var nextSeqNr uint32
 | 
			
		||||
 | 
			
		||||
// GetIPFamily returns the family type of a net.IP.
 | 
			
		||||
func GetIPFamily(ip net.IP) int {
 | 
			
		||||
	if len(ip) <= net.IPv4len {
 | 
			
		||||
		return FAMILY_V4
 | 
			
		||||
	}
 | 
			
		||||
	if ip.To4() != nil {
 | 
			
		||||
		return FAMILY_V4
 | 
			
		||||
	}
 | 
			
		||||
	return FAMILY_V6
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var nativeEndian binary.ByteOrder
 | 
			
		||||
 | 
			
		||||
// Get native endianness for the system
 | 
			
		||||
func NativeEndian() binary.ByteOrder {
 | 
			
		||||
	if nativeEndian == nil {
 | 
			
		||||
		var x uint32 = 0x01020304
 | 
			
		||||
		if *(*byte)(unsafe.Pointer(&x)) == 0x01 {
 | 
			
		||||
			nativeEndian = binary.BigEndian
 | 
			
		||||
		} else {
 | 
			
		||||
			nativeEndian = binary.LittleEndian
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nativeEndian
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Byte swap a 16 bit value if we aren't big endian
 | 
			
		||||
func Swap16(i uint16) uint16 {
 | 
			
		||||
	if NativeEndian() == binary.BigEndian {
 | 
			
		||||
		return i
 | 
			
		||||
	}
 | 
			
		||||
	return (i&0xff00)>>8 | (i&0xff)<<8
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Byte swap a 32 bit value if aren't big endian
 | 
			
		||||
func Swap32(i uint32) uint32 {
 | 
			
		||||
	if NativeEndian() == binary.BigEndian {
 | 
			
		||||
		return i
 | 
			
		||||
	}
 | 
			
		||||
	return (i&0xff000000)>>24 | (i&0xff0000)>>8 | (i&0xff00)<<8 | (i&0xff)<<24
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type NetlinkRequestData interface {
 | 
			
		||||
	Len() int
 | 
			
		||||
	Serialize() []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IfInfomsg is related to links, but it is used for list requests as well
 | 
			
		||||
type IfInfomsg struct {
 | 
			
		||||
	syscall.IfInfomsg
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create an IfInfomsg with family specified
 | 
			
		||||
func NewIfInfomsg(family int) *IfInfomsg {
 | 
			
		||||
	return &IfInfomsg{
 | 
			
		||||
		IfInfomsg: syscall.IfInfomsg{
 | 
			
		||||
			Family: uint8(family),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func DeserializeIfInfomsg(b []byte) *IfInfomsg {
 | 
			
		||||
	return (*IfInfomsg)(unsafe.Pointer(&b[0:syscall.SizeofIfInfomsg][0]))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (msg *IfInfomsg) Serialize() []byte {
 | 
			
		||||
	return (*(*[syscall.SizeofIfInfomsg]byte)(unsafe.Pointer(msg)))[:]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (msg *IfInfomsg) Len() int {
 | 
			
		||||
	return syscall.SizeofIfInfomsg
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func rtaAlignOf(attrlen int) int {
 | 
			
		||||
	return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg {
 | 
			
		||||
	msg := NewIfInfomsg(family)
 | 
			
		||||
	parent.children = append(parent.children, msg)
 | 
			
		||||
	return msg
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Extend RtAttr to handle data and children
 | 
			
		||||
type RtAttr struct {
 | 
			
		||||
	syscall.RtAttr
 | 
			
		||||
	Data     []byte
 | 
			
		||||
	children []NetlinkRequestData
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create a new Extended RtAttr object
 | 
			
		||||
func NewRtAttr(attrType int, data []byte) *RtAttr {
 | 
			
		||||
	return &RtAttr{
 | 
			
		||||
		RtAttr: syscall.RtAttr{
 | 
			
		||||
			Type: uint16(attrType),
 | 
			
		||||
		},
 | 
			
		||||
		children: []NetlinkRequestData{},
 | 
			
		||||
		Data:     data,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create a new RtAttr obj anc add it as a child of an existing object
 | 
			
		||||
func NewRtAttrChild(parent *RtAttr, attrType int, data []byte) *RtAttr {
 | 
			
		||||
	attr := NewRtAttr(attrType, data)
 | 
			
		||||
	parent.children = append(parent.children, attr)
 | 
			
		||||
	return attr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *RtAttr) Len() int {
 | 
			
		||||
	if len(a.children) == 0 {
 | 
			
		||||
		return (syscall.SizeofRtAttr + len(a.Data))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	l := 0
 | 
			
		||||
	for _, child := range a.children {
 | 
			
		||||
		l += rtaAlignOf(child.Len())
 | 
			
		||||
	}
 | 
			
		||||
	l += syscall.SizeofRtAttr
 | 
			
		||||
	return rtaAlignOf(l + len(a.Data))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Serialize the RtAttr into a byte array
 | 
			
		||||
// This can't just unsafe.cast because it must iterate through children.
 | 
			
		||||
func (a *RtAttr) Serialize() []byte {
 | 
			
		||||
	native := NativeEndian()
 | 
			
		||||
 | 
			
		||||
	length := a.Len()
 | 
			
		||||
	buf := make([]byte, rtaAlignOf(length))
 | 
			
		||||
 | 
			
		||||
	next := 4
 | 
			
		||||
	if a.Data != nil {
 | 
			
		||||
		copy(buf[next:], a.Data)
 | 
			
		||||
		next += rtaAlignOf(len(a.Data))
 | 
			
		||||
	}
 | 
			
		||||
	if len(a.children) > 0 {
 | 
			
		||||
		for _, child := range a.children {
 | 
			
		||||
			childBuf := child.Serialize()
 | 
			
		||||
			copy(buf[next:], childBuf)
 | 
			
		||||
			next += rtaAlignOf(len(childBuf))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if l := uint16(length); l != 0 {
 | 
			
		||||
		native.PutUint16(buf[0:2], l)
 | 
			
		||||
	}
 | 
			
		||||
	native.PutUint16(buf[2:4], a.Type)
 | 
			
		||||
	return buf
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type NetlinkRequest struct {
 | 
			
		||||
	syscall.NlMsghdr
 | 
			
		||||
	Data []NetlinkRequestData
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Serialize the Netlink Request into a byte array
 | 
			
		||||
func (req *NetlinkRequest) Serialize() []byte {
 | 
			
		||||
	length := syscall.SizeofNlMsghdr
 | 
			
		||||
	dataBytes := make([][]byte, len(req.Data))
 | 
			
		||||
	for i, data := range req.Data {
 | 
			
		||||
		dataBytes[i] = data.Serialize()
 | 
			
		||||
		length = length + len(dataBytes[i])
 | 
			
		||||
	}
 | 
			
		||||
	req.Len = uint32(length)
 | 
			
		||||
	b := make([]byte, length)
 | 
			
		||||
	hdr := (*(*[syscall.SizeofNlMsghdr]byte)(unsafe.Pointer(req)))[:]
 | 
			
		||||
	next := syscall.SizeofNlMsghdr
 | 
			
		||||
	copy(b[0:next], hdr)
 | 
			
		||||
	for _, data := range dataBytes {
 | 
			
		||||
		for _, dataByte := range data {
 | 
			
		||||
			b[next] = dataByte
 | 
			
		||||
			next = next + 1
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (req *NetlinkRequest) AddData(data NetlinkRequestData) {
 | 
			
		||||
	if data != nil {
 | 
			
		||||
		req.Data = append(req.Data, data)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Execute the request against a the given sockType.
 | 
			
		||||
// Returns a list of netlink messages in seriaized format, optionally filtered
 | 
			
		||||
// by resType.
 | 
			
		||||
func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, error) {
 | 
			
		||||
	s, err := getNetlinkSocket(sockType)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer s.Close()
 | 
			
		||||
 | 
			
		||||
	if err := s.Send(req); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pid, err := s.GetPid()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var res [][]byte
 | 
			
		||||
 | 
			
		||||
done:
 | 
			
		||||
	for {
 | 
			
		||||
		msgs, err := s.Receive()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		for _, m := range msgs {
 | 
			
		||||
			if m.Header.Seq != req.Seq {
 | 
			
		||||
				return nil, fmt.Errorf("Wrong Seq nr %d, expected 1", m.Header.Seq)
 | 
			
		||||
			}
 | 
			
		||||
			if m.Header.Pid != pid {
 | 
			
		||||
				return nil, fmt.Errorf("Wrong pid %d, expected %d", m.Header.Pid, pid)
 | 
			
		||||
			}
 | 
			
		||||
			if m.Header.Type == syscall.NLMSG_DONE {
 | 
			
		||||
				break done
 | 
			
		||||
			}
 | 
			
		||||
			if m.Header.Type == syscall.NLMSG_ERROR {
 | 
			
		||||
				native := NativeEndian()
 | 
			
		||||
				error := int32(native.Uint32(m.Data[0:4]))
 | 
			
		||||
				if error == 0 {
 | 
			
		||||
					break done
 | 
			
		||||
				}
 | 
			
		||||
				return nil, syscall.Errno(-error)
 | 
			
		||||
			}
 | 
			
		||||
			if resType != 0 && m.Header.Type != resType {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			res = append(res, m.Data)
 | 
			
		||||
			if m.Header.Flags&syscall.NLM_F_MULTI == 0 {
 | 
			
		||||
				break done
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return res, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create a new netlink request from proto and flags
 | 
			
		||||
// Note the Len value will be inaccurate once data is added until
 | 
			
		||||
// the message is serialized
 | 
			
		||||
func NewNetlinkRequest(proto, flags int) *NetlinkRequest {
 | 
			
		||||
	return &NetlinkRequest{
 | 
			
		||||
		NlMsghdr: syscall.NlMsghdr{
 | 
			
		||||
			Len:   uint32(syscall.SizeofNlMsghdr),
 | 
			
		||||
			Type:  uint16(proto),
 | 
			
		||||
			Flags: syscall.NLM_F_REQUEST | uint16(flags),
 | 
			
		||||
			Seq:   atomic.AddUint32(&nextSeqNr, 1),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type NetlinkSocket struct {
 | 
			
		||||
	fd  int
 | 
			
		||||
	lsa syscall.SockaddrNetlink
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getNetlinkSocket(protocol int) (*NetlinkSocket, error) {
 | 
			
		||||
	fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, protocol)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	s := &NetlinkSocket{
 | 
			
		||||
		fd: fd,
 | 
			
		||||
	}
 | 
			
		||||
	s.lsa.Family = syscall.AF_NETLINK
 | 
			
		||||
	if err := syscall.Bind(fd, &s.lsa); err != nil {
 | 
			
		||||
		syscall.Close(fd)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return s, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create a netlink socket with a given protocol (e.g. NETLINK_ROUTE)
 | 
			
		||||
// and subscribe it to multicast groups passed in variable argument list.
 | 
			
		||||
// Returns the netlink socket on which Receive() method can be called
 | 
			
		||||
// to retrieve the messages from the kernel.
 | 
			
		||||
func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
 | 
			
		||||
	fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, protocol)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	s := &NetlinkSocket{
 | 
			
		||||
		fd: fd,
 | 
			
		||||
	}
 | 
			
		||||
	s.lsa.Family = syscall.AF_NETLINK
 | 
			
		||||
 | 
			
		||||
	for _, g := range groups {
 | 
			
		||||
		s.lsa.Groups |= (1 << (g - 1))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := syscall.Bind(fd, &s.lsa); err != nil {
 | 
			
		||||
		syscall.Close(fd)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return s, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *NetlinkSocket) Close() {
 | 
			
		||||
	syscall.Close(s.fd)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *NetlinkSocket) GetFd() int {
 | 
			
		||||
	return s.fd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
 | 
			
		||||
	if err := syscall.Sendto(s.fd, request.Serialize(), 0, &s.lsa); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) {
 | 
			
		||||
	rb := make([]byte, syscall.Getpagesize())
 | 
			
		||||
	nr, _, err := syscall.Recvfrom(s.fd, rb, 0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if nr < syscall.NLMSG_HDRLEN {
 | 
			
		||||
		return nil, fmt.Errorf("Got short response from netlink")
 | 
			
		||||
	}
 | 
			
		||||
	rb = rb[:nr]
 | 
			
		||||
	return syscall.ParseNetlinkMessage(rb)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *NetlinkSocket) GetPid() (uint32, error) {
 | 
			
		||||
	lsa, err := syscall.Getsockname(s.fd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	switch v := lsa.(type) {
 | 
			
		||||
	case *syscall.SockaddrNetlink:
 | 
			
		||||
		return v.Pid, nil
 | 
			
		||||
	}
 | 
			
		||||
	return 0, fmt.Errorf("Wrong socket type")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ZeroTerminated(s string) []byte {
 | 
			
		||||
	bytes := make([]byte, len(s)+1)
 | 
			
		||||
	for i := 0; i < len(s); i++ {
 | 
			
		||||
		bytes[i] = s[i]
 | 
			
		||||
	}
 | 
			
		||||
	bytes[len(s)] = 0
 | 
			
		||||
	return bytes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NonZeroTerminated(s string) []byte {
 | 
			
		||||
	bytes := make([]byte, len(s))
 | 
			
		||||
	for i := 0; i < len(s); i++ {
 | 
			
		||||
		bytes[i] = s[i]
 | 
			
		||||
	}
 | 
			
		||||
	return bytes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BytesToString(b []byte) string {
 | 
			
		||||
	n := bytes.Index(b, []byte{0})
 | 
			
		||||
	return string(b[:n])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Uint8Attr(v uint8) []byte {
 | 
			
		||||
	return []byte{byte(v)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Uint16Attr(v uint16) []byte {
 | 
			
		||||
	native := NativeEndian()
 | 
			
		||||
	bytes := make([]byte, 2)
 | 
			
		||||
	native.PutUint16(bytes, v)
 | 
			
		||||
	return bytes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Uint32Attr(v uint32) []byte {
 | 
			
		||||
	native := NativeEndian()
 | 
			
		||||
	bytes := make([]byte, 4)
 | 
			
		||||
	native.PutUint32(bytes, v)
 | 
			
		||||
	return bytes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) {
 | 
			
		||||
	var attrs []syscall.NetlinkRouteAttr
 | 
			
		||||
	for len(b) >= syscall.SizeofRtAttr {
 | 
			
		||||
		a, vbuf, alen, err := netlinkRouteAttrAndValue(b)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		ra := syscall.NetlinkRouteAttr{Attr: *a, Value: vbuf[:int(a.Len)-syscall.SizeofRtAttr]}
 | 
			
		||||
		attrs = append(attrs, ra)
 | 
			
		||||
		b = b[alen:]
 | 
			
		||||
	}
 | 
			
		||||
	return attrs, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func netlinkRouteAttrAndValue(b []byte) (*syscall.RtAttr, []byte, int, error) {
 | 
			
		||||
	a := (*syscall.RtAttr)(unsafe.Pointer(&b[0]))
 | 
			
		||||
	if int(a.Len) < syscall.SizeofRtAttr || int(a.Len) > len(b) {
 | 
			
		||||
		return nil, nil, 0, syscall.EINVAL
 | 
			
		||||
	}
 | 
			
		||||
	return a, b[syscall.SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user