24 #include <netlink-generic.h>
25 #include <netlink/netlink.h>
26 #include <netlink/genl/genl.h>
27 #include <netlink/genl/family.h>
28 #include <netlink/genl/mngt.h>
29 #include <netlink/genl/ctrl.h>
30 #include <netlink/utils.h>
33 #define CTRL_VERSION 0x0001
37 static int ctrl_request_update(
struct nl_cache *c,
struct nl_sock *h)
40 CTRL_VERSION, NLM_F_DUMP);
43 static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
45 [CTRL_ATTR_FAMILY_NAME] = { .type =
NLA_STRING,
46 .maxlen = GENL_NAMSIZ },
47 [CTRL_ATTR_VERSION] = { .type =
NLA_U32 },
48 [CTRL_ATTR_HDRSIZE] = { .type =
NLA_U32 },
49 [CTRL_ATTR_MAXATTR] = { .type =
NLA_U32 },
51 [CTRL_ATTR_MCAST_GROUPS] = { .type =
NLA_NESTED },
54 static struct nla_policy family_op_policy[CTRL_ATTR_OP_MAX+1] = {
56 [CTRL_ATTR_OP_FLAGS] = { .type =
NLA_U32 },
59 static struct nla_policy family_grp_policy[CTRL_ATTR_MCAST_GRP_MAX+1] = {
61 [CTRL_ATTR_MCAST_GRP_ID] = { .type =
NLA_U32 },
64 static int parse_mcast_grps(
struct genl_family *family,
struct nlattr *grp_attr)
73 struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX+1];
82 if (tb[CTRL_ATTR_MCAST_GRP_ID] == NULL) {
83 err = -NLE_MISSING_ATTR;
88 if (tb[CTRL_ATTR_MCAST_GRP_NAME] == NULL) {
89 err = -NLE_MISSING_ATTR;
94 err = genl_family_add_grp(family,
id, name);
108 struct genl_family *family;
113 if (family == NULL) {
118 if (info->
attrs[CTRL_ATTR_FAMILY_NAME] == NULL) {
119 err = -NLE_MISSING_ATTR;
123 if (info->
attrs[CTRL_ATTR_FAMILY_ID] == NULL) {
124 err = -NLE_MISSING_ATTR;
128 family->ce_msgtype = info->
nlh->nlmsg_type;
134 if (info->
attrs[CTRL_ATTR_VERSION]) {
139 if (info->
attrs[CTRL_ATTR_HDRSIZE]) {
141 genl_family_set_hdrsize(family, hdrsize);
144 if (info->
attrs[CTRL_ATTR_MAXATTR]) {
146 genl_family_set_maxattr(family, maxattr);
149 if (info->
attrs[CTRL_ATTR_OPS]) {
150 struct nlattr *nla, *nla_ops;
153 nla_ops = info->
attrs[CTRL_ATTR_OPS];
155 struct nlattr *tb[CTRL_ATTR_OP_MAX+1];
163 if (tb[CTRL_ATTR_OP_ID] == NULL) {
164 err = -NLE_MISSING_ATTR;
170 if (tb[CTRL_ATTR_OP_FLAGS])
173 err = genl_family_add_op(family,
id, flags);
180 if (info->
attrs[CTRL_ATTR_MCAST_GROUPS]) {
181 err = parse_mcast_grps(family, info->
attrs[CTRL_ATTR_MCAST_GROUPS]);
203 static int probe_response(
struct nl_msg *msg,
void *arg)
205 struct nlattr *tb[CTRL_ATTR_MAX+1];
207 struct genl_family *ret = (
struct genl_family *)arg;
212 if (tb[CTRL_ATTR_FAMILY_ID])
215 if (tb[CTRL_ATTR_MCAST_GROUPS])
216 if (parse_mcast_grps(ret, tb[CTRL_ATTR_MCAST_GROUPS]) < 0)
237 static struct genl_family *genl_ctrl_probe_by_name(
struct nl_sock *sk,
241 struct genl_family *ret;
259 0, 0, CTRL_CMD_GETFAMILY, 1)) {
272 rc = nl_send_auto_complete(sk, msg);
281 rc = wait_for_ack(sk);
351 struct genl_family *fam;
353 if (cache->c_ops != &genl_ctrl_ops)
356 nl_list_for_each_entry(fam, &cache->c_items, ce_list) {
357 if (fam->gf_id ==
id) {
385 struct genl_family *fam;
387 if (cache->c_ops != &genl_ctrl_ops)
390 nl_list_for_each_entry(fam, &cache->c_items, ce_list) {
391 if (!strcmp(name, fam->gf_name)) {
426 struct genl_family *family;
429 family = genl_ctrl_probe_by_name(sk, name);
430 if (family == NULL) {
431 err = -NLE_OBJ_NOTFOUND;
441 static int genl_ctrl_grp_by_name(
const struct genl_family *family,
442 const char *grp_name)
444 struct genl_family_grp *grp;
446 nl_list_for_each_entry(grp, &family->gf_mc_grps, list) {
447 if (!strcmp(grp->name, grp_name)) {
452 return -NLE_OBJ_NOTFOUND;
467 const char *grp_name)
470 struct genl_family *family;
473 family = genl_ctrl_probe_by_name(sk, family_name);
474 if (family == NULL) {
475 err = -NLE_OBJ_NOTFOUND;
479 err = genl_ctrl_grp_by_name(family, grp_name);
488 static struct genl_cmd genl_cmds[] = {
490 .
c_id = CTRL_CMD_NEWFAMILY,
491 .c_name =
"NEWFAMILY" ,
492 .c_maxattr = CTRL_ATTR_MAX,
493 .c_attr_policy = ctrl_policy,
494 .c_msg_parser = ctrl_msg_parser,
497 .c_id = CTRL_CMD_DELFAMILY,
498 .c_name =
"DELFAMILY" ,
501 .c_id = CTRL_CMD_GETFAMILY,
502 .c_name =
"GETFAMILY" ,
505 .c_id = CTRL_CMD_NEWOPS,
509 .c_id = CTRL_CMD_DELOPS,
516 .o_ncmds = ARRAY_SIZE(genl_cmds),
523 .co_hdrsize = GENL_HDRSIZE(0),
524 .co_msgtypes = GENL_FAMILY(GENL_ID_CTRL,
"nlctrl"),
525 .co_genl = &genl_ops,
526 .co_protocol = NETLINK_GENERIC,
527 .co_request_update = ctrl_request_update,
528 .co_obj_ops = &genl_family_ops,
531 static void __init ctrl_init(
void)
536 static void __exit ctrl_exit(
void)