18#include <netlink-private/genl.h> 
   19#include <netlink/netlink.h> 
   20#include <netlink/genl/genl.h> 
   21#include <netlink/genl/family.h> 
   22#include <netlink/genl/mngt.h> 
   23#include <netlink/genl/ctrl.h> 
   24#include <netlink/utils.h> 
   27#define CTRL_VERSION            0x0001 
   29static struct nl_cache_ops genl_ctrl_ops;
 
   31static int ctrl_request_update(
struct nl_cache *c, 
struct nl_sock *h)
 
   34                                CTRL_VERSION, NLM_F_DUMP);
 
   37static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
 
   39        [CTRL_ATTR_FAMILY_NAME] = { .type = 
NLA_STRING,
 
   40                                    .maxlen = GENL_NAMSIZ },
 
   41        [CTRL_ATTR_VERSION]     = { .type = 
NLA_U32 },
 
   42        [CTRL_ATTR_HDRSIZE]     = { .type = 
NLA_U32 },
 
   43        [CTRL_ATTR_MAXATTR]     = { .type = 
NLA_U32 },
 
   45        [CTRL_ATTR_MCAST_GROUPS] = { .type = 
NLA_NESTED },
 
   48static struct nla_policy family_op_policy[CTRL_ATTR_OP_MAX+1] = {
 
   50        [CTRL_ATTR_OP_FLAGS]    = { .type = 
NLA_U32 },
 
   53static struct nla_policy family_grp_policy[CTRL_ATTR_MCAST_GRP_MAX+1] = {
 
   55        [CTRL_ATTR_MCAST_GRP_ID]   = { .type = 
NLA_U32 },
 
   58static int parse_mcast_grps(
struct genl_family *family, 
struct nlattr *grp_attr)
 
   67                struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX+1];
 
   76                if (tb[CTRL_ATTR_MCAST_GRP_ID] == NULL) {
 
   77                        err = -NLE_MISSING_ATTR;
 
   82                if (tb[CTRL_ATTR_MCAST_GRP_NAME] == NULL) {
 
   83                        err = -NLE_MISSING_ATTR;
 
   88                err = genl_family_add_grp(family, 
id, name);
 
   99static int ctrl_msg_parser(
struct nl_cache_ops *ops, 
struct genl_cmd *cmd,
 
  102        struct genl_family *family;
 
  103        struct nl_parser_param *pp = arg;
 
  107        if (family == NULL) {
 
  112        if (info->
attrs[CTRL_ATTR_FAMILY_NAME] == NULL) {
 
  113                err = -NLE_MISSING_ATTR;
 
  117        if (info->
attrs[CTRL_ATTR_FAMILY_ID] == NULL) {
 
  118                err = -NLE_MISSING_ATTR;
 
  122        family->ce_msgtype = info->
nlh->nlmsg_type;
 
  128        if (info->
attrs[CTRL_ATTR_VERSION]) {
 
  133        if (info->
attrs[CTRL_ATTR_HDRSIZE]) {
 
  135                genl_family_set_hdrsize(family, hdrsize);
 
  138        if (info->
attrs[CTRL_ATTR_MAXATTR]) {
 
  140                genl_family_set_maxattr(family, maxattr);
 
  143        if (info->
attrs[CTRL_ATTR_OPS]) {
 
  144                struct nlattr *nla, *nla_ops;
 
  147                nla_ops = info->
attrs[CTRL_ATTR_OPS];
 
  149                        struct nlattr *tb[CTRL_ATTR_OP_MAX+1];
 
  157                        if (tb[CTRL_ATTR_OP_ID] == NULL) {
 
  158                                err = -NLE_MISSING_ATTR;
 
  164                        if (tb[CTRL_ATTR_OP_FLAGS])
 
  167                        err = genl_family_add_op(family, 
id, flags);
 
  174        if (info->
attrs[CTRL_ATTR_MCAST_GROUPS]) {
 
  175                err = parse_mcast_grps(family, info->
attrs[CTRL_ATTR_MCAST_GROUPS]);
 
  180        err = pp->pp_cb((
struct nl_object *) family, pp);
 
  197static int probe_response(
struct nl_msg *msg, 
void *arg)
 
  199        struct nlattr *tb[CTRL_ATTR_MAX+1];
 
  201        struct genl_family *ret = (
struct genl_family *)arg;
 
  206        if (tb[CTRL_ATTR_FAMILY_ID])
 
  209        if (tb[CTRL_ATTR_MCAST_GROUPS])
 
  210                if (parse_mcast_grps(ret, tb[CTRL_ATTR_MCAST_GROUPS]) < 0)
 
  231static struct genl_family *genl_ctrl_probe_by_name(
struct nl_sock *sk,
 
  235        struct genl_family *ret;
 
  236        struct nl_cb *cb, *orig;
 
  249        if (!(orig = nl_socket_get_cb(sk)))
 
  258                        0, 0, CTRL_CMD_GETFAMILY, 1)) {
 
  280        rc = wait_for_ack(sk);
 
  350        struct genl_family *fam;
 
  352        if (cache->c_ops != &genl_ctrl_ops)
 
  355        nl_list_for_each_entry(fam, &cache->c_items, ce_list) {
 
  356                if (fam->gf_id == 
id) {
 
  384        struct genl_family *fam;
 
  386        if (cache->c_ops != &genl_ctrl_ops)
 
  389        nl_list_for_each_entry(fam, &cache->c_items, ce_list) {
 
  390                if (!strcmp(name, fam->gf_name)) {
 
  425        struct genl_family *family;
 
  428        family = genl_ctrl_probe_by_name(sk, name);
 
  429        if (family == NULL) {
 
  430                err = -NLE_OBJ_NOTFOUND;
 
  440static int genl_ctrl_grp_by_name(
const struct genl_family *family,
 
  441                                 const char *grp_name)
 
  443        struct genl_family_grp *grp;
 
  445        nl_list_for_each_entry(grp, &family->gf_mc_grps, list) {
 
  446                if (!strcmp(grp->name, grp_name)) {
 
  451        return -NLE_OBJ_NOTFOUND;
 
  466                          const char *grp_name)
 
  469        struct genl_family *family;
 
  472        family = genl_ctrl_probe_by_name(sk, family_name);
 
  473        if (family == NULL) {
 
  474                err = -NLE_OBJ_NOTFOUND;
 
  478        err = genl_ctrl_grp_by_name(family, grp_name);
 
  487static struct genl_cmd genl_cmds[] = {
 
  489                .
c_id           = CTRL_CMD_NEWFAMILY,
 
  490                .c_name         = 
"NEWFAMILY" ,
 
  491                .c_maxattr      = CTRL_ATTR_MAX,
 
  492                .c_attr_policy  = ctrl_policy,
 
  493                .c_msg_parser   = ctrl_msg_parser,
 
  496                .c_id           = CTRL_CMD_DELFAMILY,
 
  497                .c_name         = 
"DELFAMILY" ,
 
  500                .c_id           = CTRL_CMD_GETFAMILY,
 
  501                .c_name         = 
"GETFAMILY" ,
 
  504                .c_id           = CTRL_CMD_NEWOPS,
 
  508                .c_id           = CTRL_CMD_DELOPS,
 
  515        .o_ncmds                = ARRAY_SIZE(genl_cmds),
 
  518extern struct nl_object_ops genl_family_ops;
 
  520static struct nl_cache_ops genl_ctrl_ops = {
 
  521        .co_name                = 
"genl/family",
 
  522        .co_hdrsize             = GENL_HDRSIZE(0),
 
  523        .co_msgtypes            = GENL_FAMILY(GENL_ID_CTRL, 
"nlctrl"),
 
  525        .co_protocol            = NETLINK_GENERIC,
 
  526        .co_request_update      = ctrl_request_update,
 
  527        .co_obj_ops             = &genl_family_ops,
 
  530static void __init ctrl_init(
void)
 
  535static void __exit ctrl_exit(
void)
 
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
 
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
 
int nla_put_string(struct nl_msg *msg, int attrtype, const char *str)
Add string attribute to netlink message.
 
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
 
char * nla_get_string(const struct nlattr *nla)
Return payload of string attribute.
 
#define nla_for_each_nested(pos, nla, rem)
Iterate over a stream of nested attributes.
 
@ NLA_STRING
NUL terminated character string.
 
@ NLA_NESTED
Nested attributes.
 
int nl_cache_alloc_and_fill(struct nl_cache_ops *ops, struct nl_sock *sock, struct nl_cache **result)
Allocate new cache and fill it.
 
int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind, nl_recvmsg_msg_cb_t func, void *arg)
Set up a callback.
 
struct nl_cb * nl_cb_clone(struct nl_cb *orig)
Clone an existing callback handle.
 
@ NL_STOP
Stop parsing altogether and discard remaining messages.
 
@ NL_SKIP
Skip this message.
 
@ NL_CB_VALID
Message is valid.
 
@ NL_CB_CUSTOM
Customized handler specified by the user.
 
int genl_ctrl_resolve(struct nl_sock *sk, const char *name)
Resolve Generic Netlink family name to numeric identifier.
 
int genl_ctrl_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
Allocate a new controller cache.
 
struct genl_family * genl_ctrl_search_by_name(struct nl_cache *cache, const char *name)
Search controller cache for a family name match.
 
struct genl_family * genl_ctrl_search(struct nl_cache *cache, int id)
Search controller cache for a numeric address match.
 
int genl_ctrl_resolve_grp(struct nl_sock *sk, const char *family_name, const char *grp_name)
Resolve Generic Netlink family group name.
 
void genl_family_set_name(struct genl_family *family, const char *name)
Set human readable name.
 
void genl_family_set_version(struct genl_family *family, uint8_t version)
Set interface version.
 
struct genl_family * genl_family_alloc(void)
Allocate new Generic Netlink family object.
 
void genl_family_put(struct genl_family *family)
Release reference on Generic Netlink family object.
 
unsigned int genl_family_get_id(struct genl_family *family)
Return numeric identifier.
 
void genl_family_set_id(struct genl_family *family, unsigned int id)
Set the numeric identifier.
 
int genl_register(struct nl_cache_ops *ops)
Register Generic Netlink family backed cache.
 
void genl_unregister(struct nl_cache_ops *ops)
Unregister cache based Generic Netlink family.
 
void * genlmsg_put(struct nl_msg *msg, uint32_t port, uint32_t seq, int family, int hdrlen, int flags, uint8_t cmd, uint8_t version)
Add Generic Netlink headers to Netlink message.
 
int genl_send_simple(struct nl_sock *sk, int family, int cmd, int version, int flags)
Send a Generic Netlink message consisting only of a header.
 
int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, const struct nla_policy *policy)
Parse Generic Netlink message including attributes.
 
#define NL_AUTO_PORT
Will cause the netlink port to be set to the port assigned to the netlink icoket ust before sending t...
 
struct nlmsghdr * nlmsg_hdr(struct nl_msg *n)
Return actual netlink message.
 
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
 
struct nl_msg * nlmsg_alloc(void)
Allocate a new netlink message with the default maximum payload size.
 
#define NL_AUTO_SEQ
May be used to refer to a sequence number which should be automatically set just before sending the m...
 
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
 
int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
 
int nl_recvmsgs(struct nl_sock *sk, struct nl_cb *cb)
Receive a set of messages from a netlink socket.
 
Definition of a Generic Netlink command.
 
int c_id
Numeric command identifier (required)
 
Informative structure passed on to message parser callbacks.
 
struct nlmsghdr * nlh
Pointer to Netlink message header.
 
struct nlattr ** attrs
Pointer to array of parsed attributes.
 
Definition of a Generic Netlink family.
 
struct genl_cmd * o_cmds
Optional array defining the available Generic Netlink commands.
 
Attribute validation policy.
 
uint16_t type
Type of attribute or NLA_UNSPEC.