mirror of
https://github.com/vishvananda/netlink
synced 2024-12-18 04:34:42 +00:00
Add support for generic netlink
Signed-off-by: Wataru Ishida <ishida.wataru@lab.ntt.co.jp>
This commit is contained in:
parent
90380e4b76
commit
fe2e32c2fb
167
genetlink_linux.go
Normal file
167
genetlink_linux.go
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
package netlink
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/vishvananda/netlink/nl"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GenlOp struct {
|
||||||
|
ID uint32
|
||||||
|
Flags uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type GenlMulticastGroup struct {
|
||||||
|
ID uint32
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
type GenlFamily struct {
|
||||||
|
ID uint16
|
||||||
|
HdrSize uint32
|
||||||
|
Name string
|
||||||
|
Version uint32
|
||||||
|
MaxAttr uint32
|
||||||
|
Ops []GenlOp
|
||||||
|
Groups []GenlMulticastGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseOps(b []byte) ([]GenlOp, error) {
|
||||||
|
attrs, err := nl.ParseRouteAttr(b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ops := make([]GenlOp, 0, len(attrs))
|
||||||
|
for _, a := range attrs {
|
||||||
|
nattrs, err := nl.ParseRouteAttr(a.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var op GenlOp
|
||||||
|
for _, na := range nattrs {
|
||||||
|
switch na.Attr.Type {
|
||||||
|
case nl.GENL_CTRL_ATTR_OP_ID:
|
||||||
|
op.ID = native.Uint32(na.Value)
|
||||||
|
case nl.GENL_CTRL_ATTR_OP_FLAGS:
|
||||||
|
op.Flags = native.Uint32(na.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ops = append(ops, op)
|
||||||
|
}
|
||||||
|
return ops, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseMulticastGroups(b []byte) ([]GenlMulticastGroup, error) {
|
||||||
|
attrs, err := nl.ParseRouteAttr(b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
groups := make([]GenlMulticastGroup, 0, len(attrs))
|
||||||
|
for _, a := range attrs {
|
||||||
|
nattrs, err := nl.ParseRouteAttr(a.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var g GenlMulticastGroup
|
||||||
|
for _, na := range nattrs {
|
||||||
|
switch na.Attr.Type {
|
||||||
|
case nl.GENL_CTRL_ATTR_MCAST_GRP_NAME:
|
||||||
|
g.Name = nl.BytesToString(na.Value)
|
||||||
|
case nl.GENL_CTRL_ATTR_MCAST_GRP_ID:
|
||||||
|
g.ID = native.Uint32(na.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
groups = append(groups, g)
|
||||||
|
}
|
||||||
|
return groups, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *GenlFamily) parseAttributes(attrs []syscall.NetlinkRouteAttr) error {
|
||||||
|
for _, a := range attrs {
|
||||||
|
switch a.Attr.Type {
|
||||||
|
case nl.GENL_CTRL_ATTR_FAMILY_NAME:
|
||||||
|
f.Name = nl.BytesToString(a.Value)
|
||||||
|
case nl.GENL_CTRL_ATTR_FAMILY_ID:
|
||||||
|
f.ID = native.Uint16(a.Value)
|
||||||
|
case nl.GENL_CTRL_ATTR_VERSION:
|
||||||
|
f.Version = native.Uint32(a.Value)
|
||||||
|
case nl.GENL_CTRL_ATTR_HDRSIZE:
|
||||||
|
f.HdrSize = native.Uint32(a.Value)
|
||||||
|
case nl.GENL_CTRL_ATTR_MAXATTR:
|
||||||
|
f.MaxAttr = native.Uint32(a.Value)
|
||||||
|
case nl.GENL_CTRL_ATTR_OPS:
|
||||||
|
ops, err := parseOps(a.Value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f.Ops = ops
|
||||||
|
case nl.GENL_CTRL_ATTR_MCAST_GROUPS:
|
||||||
|
groups, err := parseMulticastGroups(a.Value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f.Groups = groups
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseFamilies(msgs [][]byte) ([]*GenlFamily, error) {
|
||||||
|
families := make([]*GenlFamily, 0, len(msgs))
|
||||||
|
for _, m := range msgs {
|
||||||
|
attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
family := &GenlFamily{}
|
||||||
|
if err := family.parseAttributes(attrs); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
families = append(families, family)
|
||||||
|
}
|
||||||
|
return families, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) GenlFamilyList() ([]*GenlFamily, error) {
|
||||||
|
msg := &nl.Genlmsg{
|
||||||
|
Command: nl.GENL_CTRL_CMD_GETFAMILY,
|
||||||
|
Version: nl.GENL_CTRL_VERSION,
|
||||||
|
}
|
||||||
|
req := h.newNetlinkRequest(nl.GENL_ID_CTRL, syscall.NLM_F_DUMP)
|
||||||
|
req.AddData(msg)
|
||||||
|
msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return parseFamilies(msgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenlFamilyList() ([]*GenlFamily, error) {
|
||||||
|
return pkgHandle.GenlFamilyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) GenlFamilyGet(name string) (*GenlFamily, error) {
|
||||||
|
msg := &nl.Genlmsg{
|
||||||
|
Command: nl.GENL_CTRL_CMD_GETFAMILY,
|
||||||
|
Version: nl.GENL_CTRL_VERSION,
|
||||||
|
}
|
||||||
|
req := h.newNetlinkRequest(nl.GENL_ID_CTRL, 0)
|
||||||
|
req.AddData(msg)
|
||||||
|
req.AddData(nl.NewRtAttr(nl.GENL_CTRL_ATTR_FAMILY_NAME, nl.ZeroTerminated(name)))
|
||||||
|
msgs, err := req.Execute(syscall.NETLINK_GENERIC, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
families, err := parseFamilies(msgs)
|
||||||
|
if len(families) != 1 {
|
||||||
|
return nil, fmt.Errorf("invalid response for GENL_CTRL_CMD_GETFAMILY")
|
||||||
|
}
|
||||||
|
return families[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenlFamilyGet(name string) (*GenlFamily, error) {
|
||||||
|
return pkgHandle.GenlFamilyGet(name)
|
||||||
|
}
|
25
genetlink_unspecified.go
Normal file
25
genetlink_unspecified.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package netlink
|
||||||
|
|
||||||
|
type GenlOp struct{}
|
||||||
|
|
||||||
|
type GenlMulticastGroup struct{}
|
||||||
|
|
||||||
|
type GenlFamily struct{}
|
||||||
|
|
||||||
|
func (h *Handle) GenlFamilyList() ([]*GenlFamily, error) {
|
||||||
|
return nil, ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenlFamilyList() ([]*GenlFamily, error) {
|
||||||
|
return nil, ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) GenlFamilyGet(name string) (*GenlFamily, error) {
|
||||||
|
return nil, ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenlFamilyGet(name string) (*GenlFamily, error) {
|
||||||
|
return nil, ErrNotImplemented
|
||||||
|
}
|
64
nl/genetlink_linux.go
Normal file
64
nl/genetlink_linux.go
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package nl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const SizeofGenlmsg = 4
|
||||||
|
|
||||||
|
const (
|
||||||
|
GENL_ID_CTRL = 0x10
|
||||||
|
GENL_CTRL_VERSION = 2
|
||||||
|
GENL_CTRL_NAME = "nlctrl"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
GENL_CTRL_CMD_GETFAMILY = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
GENL_CTRL_ATTR_UNSPEC = iota
|
||||||
|
GENL_CTRL_ATTR_FAMILY_ID
|
||||||
|
GENL_CTRL_ATTR_FAMILY_NAME
|
||||||
|
GENL_CTRL_ATTR_VERSION
|
||||||
|
GENL_CTRL_ATTR_HDRSIZE
|
||||||
|
GENL_CTRL_ATTR_MAXATTR
|
||||||
|
GENL_CTRL_ATTR_OPS
|
||||||
|
GENL_CTRL_ATTR_MCAST_GROUPS
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
GENL_CTRL_ATTR_OP_UNSPEC = iota
|
||||||
|
GENL_CTRL_ATTR_OP_ID
|
||||||
|
GENL_CTRL_ATTR_OP_FLAGS
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
GENL_ADMIN_PERM = 1 << iota
|
||||||
|
GENL_CMD_CAP_DO
|
||||||
|
GENL_CMD_CAP_DUMP
|
||||||
|
GENL_CMD_CAP_HASPOL
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
GENL_CTRL_ATTR_MCAST_GRP_UNSPEC = iota
|
||||||
|
GENL_CTRL_ATTR_MCAST_GRP_NAME
|
||||||
|
GENL_CTRL_ATTR_MCAST_GRP_ID
|
||||||
|
)
|
||||||
|
|
||||||
|
type Genlmsg struct {
|
||||||
|
Command uint8
|
||||||
|
Version uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *Genlmsg) Len() int {
|
||||||
|
return SizeofGenlmsg
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeserializeGenlmsg(b []byte) *Genlmsg {
|
||||||
|
return (*Genlmsg)(unsafe.Pointer(&b[0:SizeofGenlmsg][0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *Genlmsg) Serialize() []byte {
|
||||||
|
return (*(*[SizeofGenlmsg]byte)(unsafe.Pointer(msg)))[:]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user