Commit eb328111 authored by Thomas Graf's avatar Thomas Graf Committed by David S. Miller

[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: default avatarThomas Graf <tgraf@suug.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 78e5b891
...@@ -16,6 +16,8 @@ struct genlmsghdr { ...@@ -16,6 +16,8 @@ struct genlmsghdr {
#define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr)) #define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr))
#define GENL_ADMIN_PERM 0x01
/* /*
* List of reserved static generic netlink identifiers: * List of reserved static generic netlink identifiers:
*/ */
...@@ -43,9 +45,25 @@ enum { ...@@ -43,9 +45,25 @@ enum {
CTRL_ATTR_UNSPEC, CTRL_ATTR_UNSPEC,
CTRL_ATTR_FAMILY_ID, CTRL_ATTR_FAMILY_ID,
CTRL_ATTR_FAMILY_NAME, CTRL_ATTR_FAMILY_NAME,
CTRL_ATTR_VERSION,
CTRL_ATTR_HDRSIZE,
CTRL_ATTR_MAXATTR,
CTRL_ATTR_OPS,
__CTRL_ATTR_MAX, __CTRL_ATTR_MAX,
}; };
#define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1) #define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1)
enum {
CTRL_ATTR_OP_UNSPEC,
CTRL_ATTR_OP_ID,
CTRL_ATTR_OP_FLAGS,
CTRL_ATTR_OP_POLICY,
CTRL_ATTR_OP_DOIT,
CTRL_ATTR_OP_DUMPIT,
__CTRL_ATTR_OP_MAX,
};
#define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1)
#endif /* __LINUX_GENERIC_NETLINK_H */ #endif /* __LINUX_GENERIC_NETLINK_H */
...@@ -27,8 +27,6 @@ struct genl_family ...@@ -27,8 +27,6 @@ struct genl_family
struct list_head family_list; /* private */ struct list_head family_list; /* private */
}; };
#define GENL_ADMIN_PERM 0x01
/** /**
* struct genl_info - receiving information * struct genl_info - receiving information
* @snd_seq: sending sequence number * @snd_seq: sending sequence number
......
...@@ -387,7 +387,10 @@ static void genl_rcv(struct sock *sk, int len) ...@@ -387,7 +387,10 @@ static void genl_rcv(struct sock *sk, int len)
static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq, static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq,
u32 flags, struct sk_buff *skb, u8 cmd) u32 flags, struct sk_buff *skb, u8 cmd)
{ {
struct nlattr *nla_ops;
struct genl_ops *ops;
void *hdr; void *hdr;
int idx = 1;
hdr = genlmsg_put(skb, pid, seq, GENL_ID_CTRL, 0, flags, cmd, hdr = genlmsg_put(skb, pid, seq, GENL_ID_CTRL, 0, flags, cmd,
family->version); family->version);
...@@ -396,6 +399,37 @@ static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq, ...@@ -396,6 +399,37 @@ static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq,
NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, family->name); NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, family->name);
NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, family->id); NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, family->id);
NLA_PUT_U32(skb, CTRL_ATTR_VERSION, family->version);
NLA_PUT_U32(skb, CTRL_ATTR_HDRSIZE, family->hdrsize);
NLA_PUT_U32(skb, CTRL_ATTR_MAXATTR, family->maxattr);
nla_ops = nla_nest_start(skb, CTRL_ATTR_OPS);
if (nla_ops == NULL)
goto nla_put_failure;
list_for_each_entry(ops, &family->ops_list, ops_list) {
struct nlattr *nest;
nest = nla_nest_start(skb, idx++);
if (nest == NULL)
goto nla_put_failure;
NLA_PUT_U32(skb, CTRL_ATTR_OP_ID, ops->cmd);
NLA_PUT_U32(skb, CTRL_ATTR_OP_FLAGS, ops->flags);
if (ops->policy)
NLA_PUT_FLAG(skb, CTRL_ATTR_OP_POLICY);
if (ops->doit)
NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DOIT);
if (ops->dumpit)
NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DUMPIT);
nla_nest_end(skb, nest);
}
nla_nest_end(skb, nla_ops);
return genlmsg_end(skb, hdr); return genlmsg_end(skb, hdr);
...@@ -411,6 +445,9 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -411,6 +445,9 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
int chains_to_skip = cb->args[0]; int chains_to_skip = cb->args[0];
int fams_to_skip = cb->args[1]; int fams_to_skip = cb->args[1];
if (chains_to_skip != 0)
genl_lock();
for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {
if (i < chains_to_skip) if (i < chains_to_skip)
continue; continue;
...@@ -428,6 +465,9 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -428,6 +465,9 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
} }
errout: errout:
if (chains_to_skip != 0)
genl_unlock();
cb->args[0] = i; cb->args[0] = i;
cb->args[1] = n; cb->args[1] = n;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment