aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink/genetlink.c
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2006-09-18 03:01:59 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 18:18:51 -0400
commiteb328111efde7bca782f340fe805756039ec6a0c (patch)
tree77c38b0a7ee67703c95caf16c6691576e2f77d03 /net/netlink/genetlink.c
parent78e5b8916e7db119850f57ce8548fbb9767078fc (diff)
[GENL]: Provide more information to userspace about registered genl families
Additionaly exports the following information when providing the list of registered generic netlink families: - protocol version - header size - maximum number of attributes - list of available operations including - id - flags - avaiability of policy and doit/dumpit function libnl HEAD provides a utility to read this new information: 0x0010 nlctrl version 1 hdrsize 0 maxattr 6 op GETFAMILY (0x03) [POLICY,DOIT,DUMPIT] 0x0011 NLBL_MGMT version 1 hdrsize 0 maxattr 0 op unknown (0x02) [DOIT] op unknown (0x03) [DOIT] .... Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlink/genetlink.c')
-rw-r--r--net/netlink/genetlink.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 3ac942cdb677..49bc2db7982b 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -387,7 +387,10 @@ static void genl_rcv(struct sock *sk, int len)
387static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq, 387static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq,
388 u32 flags, struct sk_buff *skb, u8 cmd) 388 u32 flags, struct sk_buff *skb, u8 cmd)
389{ 389{
390 struct nlattr *nla_ops;
391 struct genl_ops *ops;
390 void *hdr; 392 void *hdr;
393 int idx = 1;
391 394
392 hdr = genlmsg_put(skb, pid, seq, GENL_ID_CTRL, 0, flags, cmd, 395 hdr = genlmsg_put(skb, pid, seq, GENL_ID_CTRL, 0, flags, cmd,
393 family->version); 396 family->version);
@@ -396,6 +399,37 @@ static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq,
396 399
397 NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, family->name); 400 NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, family->name);
398 NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, family->id); 401 NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, family->id);
402 NLA_PUT_U32(skb, CTRL_ATTR_VERSION, family->version);
403 NLA_PUT_U32(skb, CTRL_ATTR_HDRSIZE, family->hdrsize);
404 NLA_PUT_U32(skb, CTRL_ATTR_MAXATTR, family->maxattr);
405
406 nla_ops = nla_nest_start(skb, CTRL_ATTR_OPS);
407 if (nla_ops == NULL)
408 goto nla_put_failure;
409
410 list_for_each_entry(ops, &family->ops_list, ops_list) {
411 struct nlattr *nest;
412
413 nest = nla_nest_start(skb, idx++);
414 if (nest == NULL)
415 goto nla_put_failure;
416
417 NLA_PUT_U32(skb, CTRL_ATTR_OP_ID, ops->cmd);
418 NLA_PUT_U32(skb, CTRL_ATTR_OP_FLAGS, ops->flags);
419
420 if (ops->policy)
421 NLA_PUT_FLAG(skb, CTRL_ATTR_OP_POLICY);
422
423 if (ops->doit)
424 NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DOIT);
425
426 if (ops->dumpit)
427 NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DUMPIT);
428
429 nla_nest_end(skb, nest);
430 }
431
432 nla_nest_end(skb, nla_ops);
399 433
400 return genlmsg_end(skb, hdr); 434 return genlmsg_end(skb, hdr);
401 435
@@ -411,6 +445,9 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
411 int chains_to_skip = cb->args[0]; 445 int chains_to_skip = cb->args[0];
412 int fams_to_skip = cb->args[1]; 446 int fams_to_skip = cb->args[1];
413 447
448 if (chains_to_skip != 0)
449 genl_lock();
450
414 for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { 451 for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {
415 if (i < chains_to_skip) 452 if (i < chains_to_skip)
416 continue; 453 continue;
@@ -428,6 +465,9 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
428 } 465 }
429 466
430errout: 467errout:
468 if (chains_to_skip != 0)
469 genl_unlock();
470
431 cb->args[0] = i; 471 cb->args[0] = i;
432 cb->args[1] = n; 472 cb->args[1] = n;
433 473