1package netlink
2
3import (
4	"fmt"
5	"syscall"
6
7	"github.com/vishvananda/netlink/nl"
8	"golang.org/x/sys/unix"
9)
10
11func LinkGetProtinfo(link Link) (Protinfo, error) {
12	return pkgHandle.LinkGetProtinfo(link)
13}
14
15func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) {
16	base := link.Attrs()
17	h.ensureIndex(base)
18	var pi Protinfo
19	req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP)
20	msg := nl.NewIfInfomsg(unix.AF_BRIDGE)
21	req.AddData(msg)
22	msgs, err := req.Execute(unix.NETLINK_ROUTE, 0)
23	if err != nil {
24		return pi, err
25	}
26
27	for _, m := range msgs {
28		ans := nl.DeserializeIfInfomsg(m)
29		if int(ans.Index) != base.Index {
30			continue
31		}
32		attrs, err := nl.ParseRouteAttr(m[ans.Len():])
33		if err != nil {
34			return pi, err
35		}
36		for _, attr := range attrs {
37			if attr.Attr.Type != unix.IFLA_PROTINFO|unix.NLA_F_NESTED {
38				continue
39			}
40			infos, err := nl.ParseRouteAttr(attr.Value)
41			if err != nil {
42				return pi, err
43			}
44			pi = parseProtinfo(infos)
45
46			return pi, nil
47		}
48	}
49	return pi, fmt.Errorf("Device with index %d not found", base.Index)
50}
51
52func parseProtinfo(infos []syscall.NetlinkRouteAttr) (pi Protinfo) {
53	for _, info := range infos {
54		switch info.Attr.Type {
55		case nl.IFLA_BRPORT_MODE:
56			pi.Hairpin = byteToBool(info.Value[0])
57		case nl.IFLA_BRPORT_GUARD:
58			pi.Guard = byteToBool(info.Value[0])
59		case nl.IFLA_BRPORT_FAST_LEAVE:
60			pi.FastLeave = byteToBool(info.Value[0])
61		case nl.IFLA_BRPORT_PROTECT:
62			pi.RootBlock = byteToBool(info.Value[0])
63		case nl.IFLA_BRPORT_LEARNING:
64			pi.Learning = byteToBool(info.Value[0])
65		case nl.IFLA_BRPORT_UNICAST_FLOOD:
66			pi.Flood = byteToBool(info.Value[0])
67		case nl.IFLA_BRPORT_PROXYARP:
68			pi.ProxyArp = byteToBool(info.Value[0])
69		case nl.IFLA_BRPORT_PROXYARP_WIFI:
70			pi.ProxyArpWiFi = byteToBool(info.Value[0])
71		}
72	}
73	return
74}
75