diff options
author | Thomas Graf <tgraf@suug.ch> | 2006-09-18 03:01:59 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-22 18:18:51 -0400 |
commit | eb328111efde7bca782f340fe805756039ec6a0c (patch) | |
tree | 77c38b0a7ee67703c95caf16c6691576e2f77d03 | |
parent | 78e5b8916e7db119850f57ce8548fbb9767078fc (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>
-rw-r--r-- | include/linux/genetlink.h | 18 | ||||
-rw-r--r-- | include/net/genetlink.h | 2 | ||||
-rw-r--r-- | net/netlink/genetlink.c | 40 |
3 files changed, 58 insertions, 2 deletions
diff --git a/include/linux/genetlink.h b/include/linux/genetlink.h index 84f12a41dc01..9049dc65ae51 100644 --- a/include/linux/genetlink.h +++ b/include/linux/genetlink.h | |||
@@ -16,6 +16,8 @@ struct genlmsghdr { | |||
16 | 16 | ||
17 | #define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr)) | 17 | #define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr)) |
18 | 18 | ||
19 | #define GENL_ADMIN_PERM 0x01 | ||
20 | |||
19 | /* | 21 | /* |
20 | * List of reserved static generic netlink identifiers: | 22 | * List of reserved static generic netlink identifiers: |
21 | */ | 23 | */ |
@@ -43,9 +45,25 @@ enum { | |||
43 | CTRL_ATTR_UNSPEC, | 45 | CTRL_ATTR_UNSPEC, |
44 | CTRL_ATTR_FAMILY_ID, | 46 | CTRL_ATTR_FAMILY_ID, |
45 | CTRL_ATTR_FAMILY_NAME, | 47 | CTRL_ATTR_FAMILY_NAME, |
48 | CTRL_ATTR_VERSION, | ||
49 | CTRL_ATTR_HDRSIZE, | ||
50 | CTRL_ATTR_MAXATTR, | ||
51 | CTRL_ATTR_OPS, | ||
46 | __CTRL_ATTR_MAX, | 52 | __CTRL_ATTR_MAX, |
47 | }; | 53 | }; |
48 | 54 | ||
49 | #define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1) | 55 | #define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1) |
50 | 56 | ||
57 | enum { | ||
58 | CTRL_ATTR_OP_UNSPEC, | ||
59 | CTRL_ATTR_OP_ID, | ||
60 | CTRL_ATTR_OP_FLAGS, | ||
61 | CTRL_ATTR_OP_POLICY, | ||
62 | CTRL_ATTR_OP_DOIT, | ||
63 | CTRL_ATTR_OP_DUMPIT, | ||
64 | __CTRL_ATTR_OP_MAX, | ||
65 | }; | ||
66 | |||
67 | #define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1) | ||
68 | |||
51 | #endif /* __LINUX_GENERIC_NETLINK_H */ | 69 | #endif /* __LINUX_GENERIC_NETLINK_H */ |
diff --git a/include/net/genetlink.h b/include/net/genetlink.h index 97d6d3aba9d2..4a38d85e4e25 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h | |||
@@ -27,8 +27,6 @@ struct genl_family | |||
27 | struct list_head family_list; /* private */ | 27 | struct list_head family_list; /* private */ |
28 | }; | 28 | }; |
29 | 29 | ||
30 | #define GENL_ADMIN_PERM 0x01 | ||
31 | |||
32 | /** | 30 | /** |
33 | * struct genl_info - receiving information | 31 | * struct genl_info - receiving information |
34 | * @snd_seq: sending sequence number | 32 | * @snd_seq: sending sequence number |
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) | |||
387 | static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq, | 387 | static 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 | ||
430 | errout: | 467 | errout: |
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 | ||