github.com/vishvananda/netlink@v1.3.0/genetlink_linux.go (about) 1 package netlink 2 3 import ( 4 "fmt" 5 "syscall" 6 7 "github.com/vishvananda/netlink/nl" 8 "golang.org/x/sys/unix" 9 ) 10 11 type GenlOp struct { 12 ID uint32 13 Flags uint32 14 } 15 16 type GenlMulticastGroup struct { 17 ID uint32 18 Name string 19 } 20 21 type GenlFamily struct { 22 ID uint16 23 HdrSize uint32 24 Name string 25 Version uint32 26 MaxAttr uint32 27 Ops []GenlOp 28 Groups []GenlMulticastGroup 29 } 30 31 func parseOps(b []byte) ([]GenlOp, error) { 32 attrs, err := nl.ParseRouteAttr(b) 33 if err != nil { 34 return nil, err 35 } 36 ops := make([]GenlOp, 0, len(attrs)) 37 for _, a := range attrs { 38 nattrs, err := nl.ParseRouteAttr(a.Value) 39 if err != nil { 40 return nil, err 41 } 42 var op GenlOp 43 for _, na := range nattrs { 44 switch na.Attr.Type { 45 case nl.GENL_CTRL_ATTR_OP_ID: 46 op.ID = native.Uint32(na.Value) 47 case nl.GENL_CTRL_ATTR_OP_FLAGS: 48 op.Flags = native.Uint32(na.Value) 49 } 50 } 51 ops = append(ops, op) 52 } 53 return ops, nil 54 } 55 56 func parseMulticastGroups(b []byte) ([]GenlMulticastGroup, error) { 57 attrs, err := nl.ParseRouteAttr(b) 58 if err != nil { 59 return nil, err 60 } 61 groups := make([]GenlMulticastGroup, 0, len(attrs)) 62 for _, a := range attrs { 63 nattrs, err := nl.ParseRouteAttr(a.Value) 64 if err != nil { 65 return nil, err 66 } 67 var g GenlMulticastGroup 68 for _, na := range nattrs { 69 switch na.Attr.Type { 70 case nl.GENL_CTRL_ATTR_MCAST_GRP_NAME: 71 g.Name = nl.BytesToString(na.Value) 72 case nl.GENL_CTRL_ATTR_MCAST_GRP_ID: 73 g.ID = native.Uint32(na.Value) 74 } 75 } 76 groups = append(groups, g) 77 } 78 return groups, nil 79 } 80 81 func (f *GenlFamily) parseAttributes(attrs []syscall.NetlinkRouteAttr) error { 82 for _, a := range attrs { 83 switch a.Attr.Type { 84 case nl.GENL_CTRL_ATTR_FAMILY_NAME: 85 f.Name = nl.BytesToString(a.Value) 86 case nl.GENL_CTRL_ATTR_FAMILY_ID: 87 f.ID = native.Uint16(a.Value) 88 case nl.GENL_CTRL_ATTR_VERSION: 89 f.Version = native.Uint32(a.Value) 90 case nl.GENL_CTRL_ATTR_HDRSIZE: 91 f.HdrSize = native.Uint32(a.Value) 92 case nl.GENL_CTRL_ATTR_MAXATTR: 93 f.MaxAttr = native.Uint32(a.Value) 94 case nl.GENL_CTRL_ATTR_OPS: 95 ops, err := parseOps(a.Value) 96 if err != nil { 97 return err 98 } 99 f.Ops = ops 100 case nl.GENL_CTRL_ATTR_MCAST_GROUPS: 101 groups, err := parseMulticastGroups(a.Value) 102 if err != nil { 103 return err 104 } 105 f.Groups = groups 106 } 107 } 108 109 return nil 110 } 111 112 func parseFamilies(msgs [][]byte) ([]*GenlFamily, error) { 113 families := make([]*GenlFamily, 0, len(msgs)) 114 for _, m := range msgs { 115 attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:]) 116 if err != nil { 117 return nil, err 118 } 119 family := &GenlFamily{} 120 if err := family.parseAttributes(attrs); err != nil { 121 return nil, err 122 } 123 124 families = append(families, family) 125 } 126 return families, nil 127 } 128 129 func (h *Handle) GenlFamilyList() ([]*GenlFamily, error) { 130 msg := &nl.Genlmsg{ 131 Command: nl.GENL_CTRL_CMD_GETFAMILY, 132 Version: nl.GENL_CTRL_VERSION, 133 } 134 req := h.newNetlinkRequest(nl.GENL_ID_CTRL, unix.NLM_F_DUMP) 135 req.AddData(msg) 136 msgs, err := req.Execute(unix.NETLINK_GENERIC, 0) 137 if err != nil { 138 return nil, err 139 } 140 return parseFamilies(msgs) 141 } 142 143 func GenlFamilyList() ([]*GenlFamily, error) { 144 return pkgHandle.GenlFamilyList() 145 } 146 147 func (h *Handle) GenlFamilyGet(name string) (*GenlFamily, error) { 148 msg := &nl.Genlmsg{ 149 Command: nl.GENL_CTRL_CMD_GETFAMILY, 150 Version: nl.GENL_CTRL_VERSION, 151 } 152 req := h.newNetlinkRequest(nl.GENL_ID_CTRL, 0) 153 req.AddData(msg) 154 req.AddData(nl.NewRtAttr(nl.GENL_CTRL_ATTR_FAMILY_NAME, nl.ZeroTerminated(name))) 155 msgs, err := req.Execute(unix.NETLINK_GENERIC, 0) 156 if err != nil { 157 return nil, err 158 } 159 families, err := parseFamilies(msgs) 160 if err != nil { 161 return nil, err 162 } 163 if len(families) != 1 { 164 return nil, fmt.Errorf("invalid response for GENL_CTRL_CMD_GETFAMILY") 165 } 166 return families[0], nil 167 } 168 169 func GenlFamilyGet(name string) (*GenlFamily, error) { 170 return pkgHandle.GenlFamilyGet(name) 171 }