aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink/genetlink.c
diff options
context:
space:
mode:
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