Example #1
0
func LinkGetProtinfo(link Link) (Protinfo, error) {
	base := link.Attrs()
	ensureIndex(base)
	var pi Protinfo
	req := nl.NewNetlinkRequest(syscall.RTM_GETLINK, syscall.NLM_F_DUMP)
	msg := nl.NewIfInfomsg(syscall.AF_BRIDGE)
	req.AddData(msg)
	msgs, err := req.Execute(syscall.NETLINK_ROUTE, 0)
	if err != nil {
		return pi, err
	}

	for _, m := range msgs {
		ans := nl.DeserializeIfInfomsg(m)
		if int(ans.Index) != base.Index {
			continue
		}
		attrs, err := nl.ParseRouteAttr(m[ans.Len():])
		if err != nil {
			return pi, err
		}
		for _, attr := range attrs {
			if attr.Attr.Type != syscall.IFLA_PROTINFO|syscall.NLA_F_NESTED {
				continue
			}
			infos, err := nl.ParseRouteAttr(attr.Value)
			if err != nil {
				return pi, err
			}
			var pi Protinfo
			for _, info := range infos {
				switch info.Attr.Type {
				case nl.IFLA_BRPORT_MODE:
					pi.Hairpin = byteToBool(info.Value[0])
				case nl.IFLA_BRPORT_GUARD:
					pi.Guard = byteToBool(info.Value[0])
				case nl.IFLA_BRPORT_FAST_LEAVE:
					pi.FastLeave = byteToBool(info.Value[0])
				case nl.IFLA_BRPORT_PROTECT:
					pi.RootBlock = byteToBool(info.Value[0])
				case nl.IFLA_BRPORT_LEARNING:
					pi.Learning = byteToBool(info.Value[0])
				case nl.IFLA_BRPORT_UNICAST_FLOOD:
					pi.Flood = byteToBool(info.Value[0])
				}
			}
			return pi, nil
		}
	}
	return pi, fmt.Errorf("Device with index %d not found", base.Index)
}
Example #2
0
func NeighDeserialize(m []byte) (*Neigh, error) {
	msg := deserializeNdmsg(m)

	neigh := Neigh{
		LinkIndex: int(msg.Index),
		Family:    int(msg.Family),
		State:     int(msg.State),
		Type:      int(msg.Type),
		Flags:     int(msg.Flags),
	}

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

	for _, attr := range attrs {
		switch attr.Attr.Type {
		case NDA_DST:
			neigh.IP = net.IP(attr.Value)
		case NDA_LLADDR:
			neigh.HardwareAddr = net.HardwareAddr(attr.Value)
		}
	}

	return &neigh, nil
}
Example #3
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

}
Example #4
0
// XfrmPolicyList gets a list of xfrm policies in the system.
// Equivalent to: `ip xfrm policy show`.
// The list can be filtered by ip family.
func XfrmPolicyList(family int) ([]XfrmPolicy, error) {
	req := nl.NewNetlinkRequest(nl.XFRM_MSG_GETPOLICY, syscall.NLM_F_DUMP)

	msg := nl.NewIfInfomsg(family)
	req.AddData(msg)

	msgs, err := req.Execute(syscall.NETLINK_XFRM, nl.XFRM_MSG_NEWPOLICY)
	if err != nil {
		return nil, err
	}

	res := make([]XfrmPolicy, 0)
	for _, m := range msgs {
		msg := nl.DeserializeXfrmUserpolicyInfo(m)

		if family != FAMILY_ALL && family != int(msg.Sel.Family) {
			continue
		}

		var policy XfrmPolicy

		policy.Dst = msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD)
		policy.Src = msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS)
		policy.Priority = int(msg.Priority)
		policy.Index = int(msg.Index)
		policy.Dir = Dir(msg.Dir)

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

		for _, attr := range attrs {
			switch attr.Attr.Type {
			case nl.XFRMA_TMPL:
				max := len(attr.Value)
				for i := 0; i < max; i += nl.SizeofXfrmUserTmpl {
					var resTmpl XfrmPolicyTmpl
					tmpl := nl.DeserializeXfrmUserTmpl(attr.Value[i : i+nl.SizeofXfrmUserTmpl])
					resTmpl.Dst = tmpl.XfrmId.Daddr.ToIP()
					resTmpl.Src = tmpl.Saddr.ToIP()
					resTmpl.Proto = Proto(tmpl.XfrmId.Proto)
					resTmpl.Mode = Mode(tmpl.Mode)
					resTmpl.Reqid = int(tmpl.Reqid)
					policy.Tmpls = append(policy.Tmpls, resTmpl)
				}
			}
		}
		res = append(res, policy)
	}
	return res, nil
}
Example #5
0
// AddrList gets a list of IP addresses in the system.
// Equivalent to: `ip addr show`.
// The list can be filtered by link and ip family.
func AddrList(link Link, family int) ([]Addr, error) {
	req := nl.NewNetlinkRequest(syscall.RTM_GETADDR, syscall.NLM_F_DUMP)
	msg := nl.NewIfInfomsg(family)
	req.AddData(msg)

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

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

	res := make([]Addr, 0)
	for _, m := range msgs {
		msg := nl.DeserializeIfAddrmsg(m)

		if link != nil && msg.Index != uint32(index) {
			// Ignore messages from other interfaces
			continue
		}

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

		var addr Addr
		for _, attr := range attrs {
			switch attr.Attr.Type {
			case syscall.IFA_ADDRESS:
				addr.IPNet = &net.IPNet{
					IP:   attr.Value,
					Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
				}
			case syscall.IFA_LABEL:
				addr.Label = string(attr.Value[:len(attr.Value)-1])
			}
		}
		res = append(res, addr)
	}

	return res, nil
}
Example #6
0
// linkDeserialize deserializes a raw message received from netlink into
// a link object.
func linkDeserialize(m []byte) (Link, error) {
	msg := nl.DeserializeIfInfomsg(m)

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

	base := LinkAttrs{Index: int(msg.Index), Flags: linkFlags(msg.Flags)}
	var link Link
	linkType := ""
	for _, attr := range attrs {
		switch attr.Attr.Type {
		case syscall.IFLA_LINKINFO:
			infos, err := nl.ParseRouteAttr(attr.Value)
			if err != nil {
				return nil, err
			}
			for _, info := range infos {
				switch info.Attr.Type {
				case nl.IFLA_INFO_KIND:
					linkType = string(info.Value[:len(info.Value)-1])
					switch linkType {
					case "dummy":
						link = &Dummy{}
					case "bridge":
						link = &Bridge{}
					case "vlan":
						link = &Vlan{}
					case "veth":
						link = &Veth{}
					case "vxlan":
						link = &Vxlan{}
					case "ipvlan":
						link = &IPVlan{}
					default:
						link = &Generic{LinkType: linkType}
					}
				case nl.IFLA_INFO_DATA:
					data, err := nl.ParseRouteAttr(info.Value)
					if err != nil {
						return nil, err
					}
					switch linkType {
					case "vlan":
						parseVlanData(link, data)
					case "vxlan":
						parseVxlanData(link, data)
					case "ipvlan":
						parseIPVlanData(link, data)
					}
				}
			}
		case syscall.IFLA_ADDRESS:
			var nonzero bool
			for _, b := range attr.Value {
				if b != 0 {
					nonzero = true
				}
			}
			if nonzero {
				base.HardwareAddr = attr.Value[:]
			}
		case syscall.IFLA_IFNAME:
			base.Name = string(attr.Value[:len(attr.Value)-1])
		case syscall.IFLA_MTU:
			base.MTU = int(native.Uint32(attr.Value[0:4]))
		case syscall.IFLA_LINK:
			base.ParentIndex = int(native.Uint32(attr.Value[0:4]))
		case syscall.IFLA_MASTER:
			base.MasterIndex = int(native.Uint32(attr.Value[0:4]))
		case syscall.IFLA_TXQLEN:
			base.TxQLen = native.Uint32(attr.Value[0:4])
		}
	}
	// Links that don't have IFLA_INFO_KIND are hardware devices
	if link == nil {
		link = &Device{}
	}
	*link.Attrs() = base

	return link, nil
}
Example #7
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
}
Example #8
0
// XfrmStateList gets a list of xfrm states in the system.
// Equivalent to: `ip xfrm state show`.
// The list can be filtered by ip family.
func XfrmStateList(family int) ([]XfrmState, error) {
	req := nl.NewNetlinkRequest(nl.XFRM_MSG_GETSA, syscall.NLM_F_DUMP)

	msg := nl.NewIfInfomsg(family)
	req.AddData(msg)

	msgs, err := req.Execute(syscall.NETLINK_XFRM, nl.XFRM_MSG_NEWSA)
	if err != nil {
		return nil, err
	}

	res := make([]XfrmState, 0)
	for _, m := range msgs {
		msg := nl.DeserializeXfrmUsersaInfo(m)

		if family != FAMILY_ALL && family != int(msg.Family) {
			continue
		}

		var state XfrmState

		state.Dst = msg.Id.Daddr.ToIP()
		state.Src = msg.Saddr.ToIP()
		state.Proto = Proto(msg.Id.Proto)
		state.Mode = Mode(msg.Mode)
		state.Spi = int(nl.Swap32(msg.Id.Spi))
		state.Reqid = int(msg.Reqid)
		state.ReplayWindow = int(msg.ReplayWindow)

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

		for _, attr := range attrs {
			switch attr.Attr.Type {
			case nl.XFRMA_ALG_AUTH, nl.XFRMA_ALG_CRYPT:
				var resAlgo *XfrmStateAlgo
				if attr.Attr.Type == nl.XFRMA_ALG_AUTH {
					if state.Auth == nil {
						state.Auth = new(XfrmStateAlgo)
					}
					resAlgo = state.Auth
				} else {
					state.Crypt = new(XfrmStateAlgo)
					resAlgo = state.Crypt
				}
				algo := nl.DeserializeXfrmAlgo(attr.Value[:])
				(*resAlgo).Name = nl.BytesToString(algo.AlgName[:])
				(*resAlgo).Key = algo.AlgKey
			case nl.XFRMA_ALG_AUTH_TRUNC:
				if state.Auth == nil {
					state.Auth = new(XfrmStateAlgo)
				}
				algo := nl.DeserializeXfrmAlgoAuth(attr.Value[:])
				state.Auth.Name = nl.BytesToString(algo.AlgName[:])
				state.Auth.Key = algo.AlgKey
				state.Auth.TruncateLen = int(algo.AlgTruncLen)
			case nl.XFRMA_ENCAP:
				encap := nl.DeserializeXfrmEncapTmpl(attr.Value[:])
				state.Encap = new(XfrmStateEncap)
				state.Encap.Type = EncapType(encap.EncapType)
				state.Encap.SrcPort = int(nl.Swap16(encap.EncapSport))
				state.Encap.DstPort = int(nl.Swap16(encap.EncapDport))
				state.Encap.OriginalAddress = encap.EncapOa.ToIP()
			}

		}
		res = append(res, state)
	}
	return res, nil
}