diff --git a/package/libs/libnl-tiny/src/genl_ctrl.c b/package/libs/libnl-tiny/src/genl_ctrl.c index 13016420d1..0045459b2f 100644 --- a/package/libs/libnl-tiny/src/genl_ctrl.c +++ b/package/libs/libnl-tiny/src/genl_ctrl.c @@ -45,6 +45,7 @@ static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = { [CTRL_ATTR_HDRSIZE] = { .type = NLA_U32 }, [CTRL_ATTR_MAXATTR] = { .type = NLA_U32 }, [CTRL_ATTR_OPS] = { .type = NLA_NESTED }, + [CTRL_ATTR_MCAST_GROUPS] = { .type = NLA_NESTED }, }; static struct nla_policy family_op_policy[CTRL_ATTR_OP_MAX+1] = { @@ -52,6 +53,11 @@ static struct nla_policy family_op_policy[CTRL_ATTR_OP_MAX+1] = { [CTRL_ATTR_OP_FLAGS] = { .type = NLA_U32 }, }; +static struct nla_policy family_grp_policy[CTRL_ATTR_MCAST_GRP_MAX+1] = { + [CTRL_ATTR_MCAST_GRP_NAME] = { .type = NLA_STRING }, + [CTRL_ATTR_MCAST_GRP_ID] = { .type = NLA_U32 }, +}; + static int ctrl_msg_parser(struct nl_cache_ops *ops, struct genl_cmd *cmd, struct genl_info *info, void *arg) { @@ -127,6 +133,40 @@ static int ctrl_msg_parser(struct nl_cache_ops *ops, struct genl_cmd *cmd, } } + if (info->attrs[CTRL_ATTR_MCAST_GROUPS]) { + struct nlattr *nla, *nla_grps; + int remaining; + + nla_grps = info->attrs[CTRL_ATTR_MCAST_GROUPS]; + nla_for_each_nested(nla, nla_grps, remaining) { + struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX+1]; + int id; + const char * name; + + err = nla_parse_nested(tb, CTRL_ATTR_MCAST_GRP_MAX, nla, + family_grp_policy); + if (err < 0) + goto errout; + + if (tb[CTRL_ATTR_MCAST_GRP_ID] == NULL) { + err = -NLE_MISSING_ATTR; + goto errout; + } + id = nla_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID]); + + if (tb[CTRL_ATTR_MCAST_GRP_NAME] == NULL) { + err = -NLE_MISSING_ATTR; + goto errout; + } + name = nla_get_string(tb[CTRL_ATTR_MCAST_GRP_NAME]); + + err = genl_family_add_grp(family, id, name); + if (err < 0) + goto errout; + } + + } + err = pp->pp_cb((struct nl_object *) family, pp); errout: genl_family_put(family); @@ -242,6 +282,44 @@ errout: return err; } +static int genl_ctrl_grp_by_name(const struct genl_family *family, + const char *grp_name) +{ + struct genl_family_grp *grp; + + nl_list_for_each_entry(grp, &family->gf_mc_grps, list) { + if (!strcmp(grp->name, grp_name)) { + return grp->id; + } + } + + return -NLE_OBJ_NOTFOUND; +} + +int genl_ctrl_resolve_grp(struct nl_sock *sk, const char *family_name, + const char *grp_name) +{ + struct nl_cache *cache; + struct genl_family *family; + int err; + + if ((err = genl_ctrl_alloc_cache(sk, &cache)) < 0) + return err; + + family = genl_ctrl_search_by_name(cache, family_name); + if (family == NULL) { + err = -NLE_OBJ_NOTFOUND; + goto errout; + } + + err = genl_ctrl_grp_by_name(family, grp_name); + genl_family_put(family); +errout: + nl_cache_free(cache); + + return err; +} + /** @} */ static struct genl_cmd genl_cmds[] = { diff --git a/package/libs/libnl-tiny/src/genl_family.c b/package/libs/libnl-tiny/src/genl_family.c index 88aaad9b77..221acfa1a7 100644 --- a/package/libs/libnl-tiny/src/genl_family.c +++ b/package/libs/libnl-tiny/src/genl_family.c @@ -31,12 +31,14 @@ static void family_constructor(struct nl_object *c) struct genl_family *family = (struct genl_family *) c; nl_init_list_head(&family->gf_ops); + nl_init_list_head(&family->gf_mc_grps); } static void family_free_data(struct nl_object *c) { struct genl_family *family = (struct genl_family *) c; struct genl_family_op *ops, *tmp; + struct genl_family_grp *grp, *t_grp; if (family == NULL) return; @@ -45,6 +47,12 @@ static void family_free_data(struct nl_object *c) nl_list_del(&ops->o_list); free(ops); } + + nl_list_for_each_entry_safe(grp, t_grp, &family->gf_mc_grps, list) { + nl_list_del(&grp->list); + free(grp); + } + } static int family_clone(struct nl_object *_dst, struct nl_object *_src) @@ -52,6 +60,7 @@ static int family_clone(struct nl_object *_dst, struct nl_object *_src) struct genl_family *dst = nl_object_priv(_dst); struct genl_family *src = nl_object_priv(_src); struct genl_family_op *ops; + struct genl_family_grp *grp; int err; nl_list_for_each_entry(ops, &src->gf_ops, o_list) { @@ -59,6 +68,13 @@ static int family_clone(struct nl_object *_dst, struct nl_object *_src) if (err < 0) return err; } + + nl_list_for_each_entry(grp, &src->gf_mc_grps, list) { + err = genl_family_add_grp(dst, grp->id, grp->name); + if (err < 0) + return err; + } + return 0; } @@ -119,6 +135,23 @@ int genl_family_add_op(struct genl_family *family, int id, int flags) return 0; } +int genl_family_add_grp(struct genl_family *family, uint32_t id, + const char *name) +{ + struct genl_family_grp *grp; + + grp = calloc(1, sizeof(*grp)); + if (grp == NULL) + return -NLE_NOMEM; + + grp->id = id; + strncpy(grp->name, name, GENL_NAMSIZ - 1); + + nl_list_add_tail(&grp->list, &family->gf_mc_grps); + + return 0; +} + /** @} */ /** @cond SKIP */ diff --git a/package/libs/libnl-tiny/src/include/netlink-types.h b/package/libs/libnl-tiny/src/include/netlink-types.h index 0d005935c3..65f7f6c0b8 100644 --- a/package/libs/libnl-tiny/src/include/netlink-types.h +++ b/package/libs/libnl-tiny/src/include/netlink-types.h @@ -69,6 +69,13 @@ struct nl_addr #define GENL_OP_HAS_DOIT 2 #define GENL_OP_HAS_DUMPIT 4 +struct genl_family_grp { + struct genl_family *family; /* private */ + struct nl_list_head list; /* private */ + char name[GENL_NAMSIZ]; + u_int32_t id; +}; + struct genl_family_op { uint32_t o_id; diff --git a/package/libs/libnl-tiny/src/include/netlink/genl/ctrl.h b/package/libs/libnl-tiny/src/include/netlink/genl/ctrl.h index 1ae62f4480..26a0a9967b 100644 --- a/package/libs/libnl-tiny/src/include/netlink/genl/ctrl.h +++ b/package/libs/libnl-tiny/src/include/netlink/genl/ctrl.h @@ -29,6 +29,9 @@ extern struct genl_family * genl_ctrl_search_by_name(struct nl_cache *, const char *); extern int genl_ctrl_resolve(struct nl_sock *, const char *); +extern int genl_ctrl_resolve_grp(struct nl_sock *sk, + const char *family, + const char *grp); #ifdef __cplusplus } diff --git a/package/libs/libnl-tiny/src/include/netlink/genl/family.h b/package/libs/libnl-tiny/src/include/netlink/genl/family.h index 0257cbe273..b7cf48fb78 100644 --- a/package/libs/libnl-tiny/src/include/netlink/genl/family.h +++ b/package/libs/libnl-tiny/src/include/netlink/genl/family.h @@ -39,6 +39,7 @@ struct genl_family uint32_t gf_maxattr; struct nl_list_head gf_ops; + struct nl_list_head gf_mc_grps; }; @@ -47,6 +48,9 @@ extern void genl_family_put(struct genl_family *); extern int genl_family_add_op(struct genl_family *, int, int); +extern int genl_family_add_grp(struct genl_family *, + uint32_t , const char *); + /** * @name Attributes diff --git a/package/libs/libnl-tiny/src/include/netlink/socket.h b/package/libs/libnl-tiny/src/include/netlink/socket.h index 9f7f4220aa..bcb934c50b 100644 --- a/package/libs/libnl-tiny/src/include/netlink/socket.h +++ b/package/libs/libnl-tiny/src/include/netlink/socket.h @@ -166,6 +166,16 @@ static inline void nl_socket_disable_msg_peek(struct nl_sock *sk) sk->s_flags &= ~NL_MSG_PEEK; } +static inline uint32_t nl_socket_get_peer_groups(struct nl_sock *sk) +{ + return sk->s_peer.nl_groups; +} + +static inline void nl_socket_set_peer_groups(struct nl_sock *sk, uint32_t groups) +{ + sk->s_peer.nl_groups = groups; +} + /** * @name Callback Handler * @{ diff --git a/package/libs/libnl-tiny/src/nl.c b/package/libs/libnl-tiny/src/nl.c index ea7d96898b..2fb866eca9 100644 --- a/package/libs/libnl-tiny/src/nl.c +++ b/package/libs/libnl-tiny/src/nl.c @@ -366,7 +366,7 @@ errout: * Receives a netlink message, allocates a buffer in \c *buf and * stores the message content. The peer's netlink address is stored * in \c *nla. The caller is responsible for freeing the buffer allocated - * in \c *buf if a positive value is returned. Interruped system calls + * in \c *buf if a positive value is returned. Interrupted system calls * are handled by repeating the read. The input buffer size is determined * by peeking before the actual read is done. *