From e408762f5d16370d9308c22f8f9853d911e92a95 Mon Sep 17 00:00:00 2001 From: Ethan Jackson Date: Tue, 23 Aug 2011 13:13:34 -0700 Subject: [PATCH] netlink-socket: New function nl_lookup_genl_mcgroup(). --- lib/netlink-socket.c | 54 +++++++++++++++++++++++++++++++++++++++++--- lib/netlink-socket.h | 2 ++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/lib/netlink-socket.c b/lib/netlink-socket.c index 719f6589..394107e4 100644 --- a/lib/netlink-socket.c +++ b/lib/netlink-socket.c @@ -680,6 +680,7 @@ static struct hmap genl_families = HMAP_INITIALIZER(&genl_families); static const struct nl_policy family_policy[CTRL_ATTR_MAX + 1] = { [CTRL_ATTR_FAMILY_ID] = {.type = NL_A_U16}, + [CTRL_ATTR_MCAST_GROUPS] = {.type = NL_A_NESTED}, }; static struct genl_family * @@ -725,11 +726,11 @@ genl_family_to_name(uint16_t id) } } -static int do_lookup_genl_family(const char *name) +static int +do_lookup_genl_family(const char *name, struct nlattr **attrs) { struct nl_sock *sock; struct ofpbuf request, *reply; - struct nlattr *attrs[ARRAY_SIZE(family_policy)]; int retval; retval = nl_sock_create(NETLINK_GENERIC, &sock); @@ -767,6 +768,51 @@ static int do_lookup_genl_family(const char *name) return retval; } +/* Finds the multicast group called 'group_name' in genl family 'family_name'. + * When successful, writes its result to 'multicast_group' and returns 0. + * Otherwise, clears 'multicast_group' and returns a positive error code. */ +int +nl_lookup_genl_mcgroup(const char *family_name, const char *group_name, + unsigned int *multicast_group) +{ + struct nlattr *family_attrs[ARRAY_SIZE(family_policy)]; + struct ofpbuf all_mcs; + struct nlattr *mc; + unsigned int left; + int retval; + + *multicast_group = 0; + retval = do_lookup_genl_family(family_name, family_attrs); + if (retval <= 0) { + assert(retval); + return -retval; + } + + nl_attr_get_nested(family_attrs[CTRL_ATTR_MCAST_GROUPS], &all_mcs); + NL_ATTR_FOR_EACH (mc, left, all_mcs.data, all_mcs.size) { + static const struct nl_policy mc_policy[] = { + [CTRL_ATTR_MCAST_GRP_ID] = {.type = NL_A_U32}, + [CTRL_ATTR_MCAST_GRP_NAME] = {.type = NL_A_STRING}, + }; + + struct nlattr *mc_attrs[ARRAY_SIZE(mc_policy)]; + const char *mc_name; + + if (!nl_parse_nested(mc, mc_policy, mc_attrs, ARRAY_SIZE(mc_policy))) { + return EPROTO; + } + + mc_name = nl_attr_get_string(mc_attrs[CTRL_ATTR_MCAST_GRP_NAME]); + if (!strcmp(group_name, mc_name)) { + *multicast_group = + nl_attr_get_u32(mc_attrs[CTRL_ATTR_MCAST_GRP_ID]); + return 0; + } + } + + return EPROTO; +} + /* If '*number' is 0, translates the given Generic Netlink family 'name' to a * number and stores it in '*number'. If successful, returns 0 and the caller * may use '*number' as the family number. On failure, returns a positive @@ -774,8 +820,10 @@ static int do_lookup_genl_family(const char *name) int nl_lookup_genl_family(const char *name, int *number) { + struct nlattr *attrs[ARRAY_SIZE(family_policy)]; + if (*number == 0) { - *number = do_lookup_genl_family(name); + *number = do_lookup_genl_family(name, attrs); assert(*number != 0); } return *number > 0 ? 0 : -*number; diff --git a/lib/netlink-socket.h b/lib/netlink-socket.h index 43b4b023..f43c3d00 100644 --- a/lib/netlink-socket.h +++ b/lib/netlink-socket.h @@ -75,5 +75,7 @@ int nl_dump_done(struct nl_dump *); /* Miscellaneous */ int nl_lookup_genl_family(const char *name, int *number); +int nl_lookup_genl_mcgroup(const char *family_name, const char *group_name, + unsigned int *multicast_group); #endif /* netlink-socket.h */ -- 2.30.2