github.com/sagernet/netlink@v0.0.0-20240612041022-b9a21c07ac6a/protinfo_linux.go (about) 1 package netlink 2 3 import ( 4 "fmt" 5 "syscall" 6 7 "github.com/sagernet/netlink/nl" 8 "golang.org/x/sys/unix" 9 ) 10 11 func LinkGetProtinfo(link Link) (Protinfo, error) { 12 return pkgHandle.LinkGetProtinfo(link) 13 } 14 15 func (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 52 func 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 }