示例#1
0
func DeserializeRtab(b []byte) [256]uint32 {
	var rtab [256]uint32
	native := nl.NativeEndian()
	r := bytes.NewReader(b)
	_ = binary.Read(r, native, &rtab)
	return rtab
}
示例#2
0
func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
	native = nl.NativeEndian()
	fw := filter.(*Fw)
	detailed := true
	for _, datum := range data {
		switch datum.Attr.Type {
		case nl.TCA_FW_MASK:
			fw.Mask = native.Uint32(datum.Value[0:4])
		case nl.TCA_FW_CLASSID:
			fw.ClassId = native.Uint32(datum.Value[0:4])
		case nl.TCA_FW_INDEV:
			fw.InDev = string(datum.Value[:len(datum.Value)-1])
		case nl.TCA_FW_POLICE:
			adata, _ := nl.ParseRouteAttr(datum.Value)
			for _, aattr := range adata {
				switch aattr.Attr.Type {
				case nl.TCA_POLICE_TBF:
					fw.Police = *nl.DeserializeTcPolice(aattr.Value)
				case nl.TCA_POLICE_RATE:
					fw.Rtab = DeserializeRtab(aattr.Value)
				case nl.TCA_POLICE_PEAKRATE:
					fw.Ptab = DeserializeRtab(aattr.Value)
				}
			}
		}
	}
	return detailed, nil
}
示例#3
0
// deserializeRoute decodes a binary netlink message into a Route struct
func deserializeRoute(m []byte) (Route, error) {
	route := Route{}
	msg := nl.DeserializeRtMsg(m)
	attrs, err := nl.ParseRouteAttr(m[msg.Len():])
	if err != nil {
		return route, err
	}
	route.Scope = Scope(msg.Scope)
	route.Flags = int(msg.Flags)

	native := nl.NativeEndian()
	for _, attr := range attrs {
		switch attr.Attr.Type {
		case syscall.RTA_GATEWAY:
			route.Gw = net.IP(attr.Value)
		case syscall.RTA_PREFSRC:
			route.Src = net.IP(attr.Value)
		case syscall.RTA_DST:
			route.Dst = &net.IPNet{
				IP:   attr.Value,
				Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)),
			}
		case syscall.RTA_OIF:
			routeIndex := int(native.Uint32(attr.Value[0:4]))
			route.LinkIndex = routeIndex
		}
	}
	return route, nil
}
示例#4
0
// RouteGet gets a route to a specific destination from the host system.
// Equivalent to: 'ip route get'.
func RouteGet(destination net.IP) ([]Route, error) {
	req := nl.NewNetlinkRequest(syscall.RTM_GETROUTE, syscall.NLM_F_REQUEST)
	family := nl.GetIPFamily(destination)
	var destinationData []byte
	var bitlen uint8
	if family == FAMILY_V4 {
		destinationData = destination.To4()
		bitlen = 32
	} else {
		destinationData = destination.To16()
		bitlen = 128
	}
	msg := &nl.RtMsg{}
	msg.Family = uint8(family)
	msg.Dst_len = bitlen
	req.AddData(msg)

	rtaDst := nl.NewRtAttr(syscall.RTA_DST, destinationData)
	req.AddData(rtaDst)

	msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWROUTE)
	if err != nil {
		return nil, err
	}

	native := nl.NativeEndian()
	res := make([]Route, 0)
	for _, m := range msgs {
		msg := nl.DeserializeRtMsg(m)
		attrs, err := nl.ParseRouteAttr(m[msg.Len():])
		if err != nil {
			return nil, err
		}

		route := Route{}
		for _, attr := range attrs {
			switch attr.Attr.Type {
			case syscall.RTA_GATEWAY:
				route.Gw = net.IP(attr.Value)
			case syscall.RTA_PREFSRC:
				route.Src = net.IP(attr.Value)
			case syscall.RTA_DST:
				route.Dst = &net.IPNet{
					IP:   attr.Value,
					Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)),
				}
			case syscall.RTA_OIF:
				routeIndex := int(native.Uint32(attr.Value[0:4]))
				route.LinkIndex = routeIndex
			}
		}
		res = append(res, route)
	}
	return res, nil

}
示例#5
0
func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
	native = nl.NativeEndian()
	u32 := filter.(*U32)
	detailed := false
	for _, datum := range data {
		switch datum.Attr.Type {
		case nl.TCA_U32_SEL:
			detailed = true
			sel := nl.DeserializeTcU32Sel(datum.Value)
			// only parse if we have a very basic redirect
			if sel.Flags&nl.TC_U32_TERMINAL == 0 || sel.Nkeys != 1 {
				return detailed, nil
			}
		case nl.TCA_U32_ACT:
			table, err := nl.ParseRouteAttr(datum.Value)
			if err != nil {
				return detailed, err
			}
			if len(table) != 1 || table[0].Attr.Type != nl.TCA_ACT_TAB {
				return detailed, fmt.Errorf("Action table not formed properly")
			}
			aattrs, err := nl.ParseRouteAttr(table[0].Value)
			for _, aattr := range aattrs {
				switch aattr.Attr.Type {
				case nl.TCA_KIND:
					actionType := string(aattr.Value[:len(aattr.Value)-1])
					// only parse if the action is mirred
					if actionType != "mirred" {
						return detailed, nil
					}
				case nl.TCA_OPTIONS:
					adata, err := nl.ParseRouteAttr(aattr.Value)
					if err != nil {
						return detailed, err
					}
					for _, adatum := range adata {
						switch adatum.Attr.Type {
						case nl.TCA_MIRRED_PARMS:
							mir := nl.DeserializeTcMirred(adatum.Value)
							u32.RedirIndex = int(mir.Ifindex)
						}
					}
				}
			}
		}
	}
	return detailed, nil
}
func parseTbfData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
	native = nl.NativeEndian()
	tbf := qdisc.(*Tbf)
	for _, datum := range data {
		switch datum.Attr.Type {
		case nl.TCA_TBF_PARMS:
			opt := nl.DeserializeTcTbfQopt(datum.Value)
			tbf.Rate = uint64(opt.Rate.Rate)
			tbf.Limit = opt.Limit
			tbf.Buffer = opt.Buffer
		case nl.TCA_TBF_RATE64:
			tbf.Rate = native.Uint64(datum.Value[0:4])
		}
	}
	return nil
}
func parseHtbData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
	native = nl.NativeEndian()
	htb := qdisc.(*Htb)
	for _, datum := range data {
		switch datum.Attr.Type {
		case nl.TCA_HTB_INIT:
			opt := nl.DeserializeTcHtbGlob(datum.Value)
			htb.Version = opt.Version
			htb.Rate2Quantum = opt.Rate2Quantum
			htb.Defcls = opt.Defcls
			htb.Debug = opt.Debug
			htb.DirectPkts = opt.DirectPkts
		case nl.TCA_HTB_DIRECT_QLEN:
			// TODO
			//htb.DirectQlen = native.uint32(datum.Value)
		}
	}
	return nil
}
示例#8
0
package netlink

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"net"
	"os"
	"syscall"
	"unsafe"

	"github.com/coreos/flannel/Godeps/_workspace/src/github.com/vishvananda/netlink/nl"
)

var native = nl.NativeEndian()
var lookupByDump = false

var macvlanModes = [...]uint32{
	0,
	nl.MACVLAN_MODE_PRIVATE,
	nl.MACVLAN_MODE_VEPA,
	nl.MACVLAN_MODE_BRIDGE,
	nl.MACVLAN_MODE_PASSTHRU,
	nl.MACVLAN_MODE_SOURCE,
}

func ensureIndex(link *LinkAttrs) {
	if link != nil && link.Index == 0 {
		newlink, _ := LinkByName(link.Name)
		if newlink != nil {
			link.Index = newlink.Attrs().Index
示例#9
0
func routeHandle(route *Route, req *nl.NetlinkRequest) error {
	if (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil {
		return fmt.Errorf("one of Dst.IP, Src, or Gw must not be nil")
	}

	msg := nl.NewRtMsg()
	msg.Scope = uint8(route.Scope)
	family := -1
	var rtAttrs []*nl.RtAttr

	if route.Dst != nil && route.Dst.IP != nil {
		dstLen, _ := route.Dst.Mask.Size()
		msg.Dst_len = uint8(dstLen)
		dstFamily := nl.GetIPFamily(route.Dst.IP)
		family = dstFamily
		var dstData []byte
		if dstFamily == FAMILY_V4 {
			dstData = route.Dst.IP.To4()
		} else {
			dstData = route.Dst.IP.To16()
		}
		rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_DST, dstData))
	}

	if route.Src != nil {
		srcFamily := nl.GetIPFamily(route.Src)
		if family != -1 && family != srcFamily {
			return fmt.Errorf("source and destination ip are not the same IP family")
		}
		family = srcFamily
		var srcData []byte
		if srcFamily == FAMILY_V4 {
			srcData = route.Src.To4()
		} else {
			srcData = route.Src.To16()
		}
		// The commonly used src ip for routes is actually PREFSRC
		rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_PREFSRC, srcData))
	}

	if route.Gw != nil {
		gwFamily := nl.GetIPFamily(route.Gw)
		if family != -1 && family != gwFamily {
			return fmt.Errorf("gateway, source, and destination ip are not the same IP family")
		}
		family = gwFamily
		var gwData []byte
		if gwFamily == FAMILY_V4 {
			gwData = route.Gw.To4()
		} else {
			gwData = route.Gw.To16()
		}
		rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_GATEWAY, gwData))
	}

	msg.Family = uint8(family)

	req.AddData(msg)
	for _, attr := range rtAttrs {
		req.AddData(attr)
	}

	var (
		b      = make([]byte, 4)
		native = nl.NativeEndian()
	)
	native.PutUint32(b, uint32(route.LinkIndex))

	req.AddData(nl.NewRtAttr(syscall.RTA_OIF, b))

	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
	return err
}
示例#10
0
// RouteList gets a list of routes in the system.
// Equivalent to: `ip route show`.
// The list can be filtered by link and ip family.
func RouteList(link Link, family int) ([]Route, error) {
	req := nl.NewNetlinkRequest(syscall.RTM_GETROUTE, syscall.NLM_F_DUMP)
	msg := nl.NewIfInfomsg(family)
	req.AddData(msg)

	msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWROUTE)
	if err != nil {
		return nil, err
	}

	index := 0
	if link != nil {
		base := link.Attrs()
		ensureIndex(base)
		index = base.Index
	}

	native := nl.NativeEndian()
	res := make([]Route, 0)
	for _, m := range msgs {
		msg := nl.DeserializeRtMsg(m)

		if msg.Flags&syscall.RTM_F_CLONED != 0 {
			// Ignore cloned routes
			continue
		}

		if msg.Table != syscall.RT_TABLE_MAIN {
			// Ignore non-main tables
			continue
		}

		attrs, err := nl.ParseRouteAttr(m[msg.Len():])
		if err != nil {
			return nil, err
		}

		route := Route{Scope: Scope(msg.Scope)}
		for _, attr := range attrs {
			switch attr.Attr.Type {
			case syscall.RTA_GATEWAY:
				route.Gw = net.IP(attr.Value)
			case syscall.RTA_PREFSRC:
				route.Src = net.IP(attr.Value)
			case syscall.RTA_DST:
				route.Dst = &net.IPNet{
					IP:   attr.Value,
					Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attr.Value)),
				}
			case syscall.RTA_OIF:
				routeIndex := int(native.Uint32(attr.Value[0:4]))
				if link != nil && routeIndex != index {
					// Ignore routes from other interfaces
					continue
				}
				route.LinkIndex = routeIndex
			}
		}
		res = append(res, route)
	}

	return res, nil
}
示例#11
0
func SerializeRtab(rtab [256]uint32) []byte {
	native := nl.NativeEndian()
	var w bytes.Buffer
	_ = binary.Write(&w, native, rtab)
	return w.Bytes()
}
示例#12
0
// FilterAdd will add a filter to the system.
// Equivalent to: `tc filter add $filter`
func FilterAdd(filter Filter) error {
	native = nl.NativeEndian()
	req := nl.NewNetlinkRequest(syscall.RTM_NEWTFILTER, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
	base := filter.Attrs()
	msg := &nl.TcMsg{
		Family:  nl.FAMILY_ALL,
		Ifindex: int32(base.LinkIndex),
		Handle:  base.Handle,
		Parent:  base.Parent,
		Info:    MakeHandle(base.Priority, nl.Swap16(base.Protocol)),
	}
	req.AddData(msg)
	req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(filter.Type())))

	options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
	if u32, ok := filter.(*U32); ok {
		// match all
		sel := nl.TcU32Sel{
			Nkeys: 1,
			Flags: nl.TC_U32_TERMINAL,
		}
		sel.Keys = append(sel.Keys, nl.TcU32Key{})
		nl.NewRtAttrChild(options, nl.TCA_U32_SEL, sel.Serialize())
		actions := nl.NewRtAttrChild(options, nl.TCA_U32_ACT, nil)
		table := nl.NewRtAttrChild(actions, nl.TCA_ACT_TAB, nil)
		nl.NewRtAttrChild(table, nl.TCA_KIND, nl.ZeroTerminated("mirred"))
		// redirect to other interface
		mir := nl.TcMirred{
			Action:  nl.TC_ACT_STOLEN,
			Eaction: nl.TCA_EGRESS_REDIR,
			Ifindex: uint32(u32.RedirIndex),
		}
		aopts := nl.NewRtAttrChild(table, nl.TCA_OPTIONS, nil)
		nl.NewRtAttrChild(aopts, nl.TCA_MIRRED_PARMS, mir.Serialize())
	} else if fw, ok := filter.(*Fw); ok {
		if fw.Mask != 0 {
			b := make([]byte, 4)
			native.PutUint32(b, fw.Mask)
			nl.NewRtAttrChild(options, nl.TCA_FW_MASK, b)
		}
		if fw.InDev != "" {
			nl.NewRtAttrChild(options, nl.TCA_FW_INDEV, nl.ZeroTerminated(fw.InDev))
		}
		if (fw.Police != nl.TcPolice{}) {

			police := nl.NewRtAttrChild(options, nl.TCA_FW_POLICE, nil)
			nl.NewRtAttrChild(police, nl.TCA_POLICE_TBF, fw.Police.Serialize())
			if (fw.Police.Rate != nl.TcRateSpec{}) {
				payload := SerializeRtab(fw.Rtab)
				nl.NewRtAttrChild(police, nl.TCA_POLICE_RATE, payload)
			}
			if (fw.Police.PeakRate != nl.TcRateSpec{}) {
				payload := SerializeRtab(fw.Ptab)
				nl.NewRtAttrChild(police, nl.TCA_POLICE_PEAKRATE, payload)
			}
		}
		if fw.ClassId != 0 {
			b := make([]byte, 4)
			native.PutUint32(b, fw.ClassId)
			nl.NewRtAttrChild(options, nl.TCA_FW_CLASSID, b)
		}
	}

	req.AddData(options)
	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
	return err
}