genl: ctrl: support dumping netlink policy

Support dumping the netlink policy of a given generic netlink
family, the policy (with any sub-policies if appropriate) is
exported by the kernel in a general fashion.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
Johannes Berg 2020-08-24 19:51:08 +02:00 committed by David Ahern
parent d5acae244f
commit cc889b8241
1 changed files with 18 additions and 6 deletions

View File

@ -28,13 +28,15 @@
static int usage(void) static int usage(void)
{ {
fprintf(stderr,"Usage: ctrl <CMD>\n" \ fprintf(stderr,"Usage: ctrl <CMD>\n" \
"CMD := get <PARMS> | list | monitor\n" \ "CMD := get <PARMS> | list | monitor | policy <PARMS>\n" \
"PARMS := name <name> | id <id>\n" \ "PARMS := name <name> | id <id>\n" \
"Examples:\n" \ "Examples:\n" \
"\tctrl ls\n" \ "\tctrl ls\n" \
"\tctrl monitor\n" \ "\tctrl monitor\n" \
"\tctrl get name foobar\n" \ "\tctrl get name foobar\n" \
"\tctrl get id 0xF\n"); "\tctrl get id 0xF\n"
"\tctrl policy name foobar\n"
"\tctrl policy id 0xF\n");
return -1; return -1;
} }
@ -123,7 +125,8 @@ static int print_ctrl(struct rtnl_ctrl_data *ctrl,
ghdr->cmd != CTRL_CMD_DELFAMILY && ghdr->cmd != CTRL_CMD_DELFAMILY &&
ghdr->cmd != CTRL_CMD_NEWFAMILY && ghdr->cmd != CTRL_CMD_NEWFAMILY &&
ghdr->cmd != CTRL_CMD_NEWMCAST_GRP && ghdr->cmd != CTRL_CMD_NEWMCAST_GRP &&
ghdr->cmd != CTRL_CMD_DELMCAST_GRP) { ghdr->cmd != CTRL_CMD_DELMCAST_GRP &&
ghdr->cmd != CTRL_CMD_GETPOLICY) {
fprintf(stderr, "Unknown controller command %d\n", ghdr->cmd); fprintf(stderr, "Unknown controller command %d\n", ghdr->cmd);
return 0; return 0;
} }
@ -136,7 +139,7 @@ static int print_ctrl(struct rtnl_ctrl_data *ctrl,
} }
attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN); attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len); parse_rtattr_flags(tb, CTRL_ATTR_MAX, attrs, len, NLA_F_NESTED);
if (tb[CTRL_ATTR_FAMILY_NAME]) { if (tb[CTRL_ATTR_FAMILY_NAME]) {
char *name = RTA_DATA(tb[CTRL_ATTR_FAMILY_NAME]); char *name = RTA_DATA(tb[CTRL_ATTR_FAMILY_NAME]);
@ -159,6 +162,9 @@ static int print_ctrl(struct rtnl_ctrl_data *ctrl,
__u32 *ma = RTA_DATA(tb[CTRL_ATTR_MAXATTR]); __u32 *ma = RTA_DATA(tb[CTRL_ATTR_MAXATTR]);
fprintf(fp, " max attribs: %d ",*ma); fprintf(fp, " max attribs: %d ",*ma);
} }
if (tb[CTRL_ATTR_POLICY])
nl_print_policy(tb[CTRL_ATTR_POLICY], fp);
/* end of family definitions .. */ /* end of family definitions .. */
fprintf(fp,"\n"); fprintf(fp,"\n");
if (tb[CTRL_ATTR_OPS]) { if (tb[CTRL_ATTR_OPS]) {
@ -235,7 +241,9 @@ static int ctrl_list(int cmd, int argc, char **argv)
exit(1); exit(1);
} }
if (cmd == CTRL_CMD_GETFAMILY) { if (cmd == CTRL_CMD_GETFAMILY || cmd == CTRL_CMD_GETPOLICY) {
req.g.cmd = cmd;
if (argc != 2) { if (argc != 2) {
fprintf(stderr, "Wrong number of params\n"); fprintf(stderr, "Wrong number of params\n");
return -1; return -1;
@ -260,7 +268,9 @@ static int ctrl_list(int cmd, int argc, char **argv)
fprintf(stderr, "Wrong params\n"); fprintf(stderr, "Wrong params\n");
goto ctrl_done; goto ctrl_done;
} }
}
if (cmd == CTRL_CMD_GETFAMILY) {
if (rtnl_talk(&rth, nlh, &answer) < 0) { if (rtnl_talk(&rth, nlh, &answer) < 0) {
fprintf(stderr, "Error talking to the kernel\n"); fprintf(stderr, "Error talking to the kernel\n");
goto ctrl_done; goto ctrl_done;
@ -273,7 +283,7 @@ static int ctrl_list(int cmd, int argc, char **argv)
} }
if (cmd == CTRL_CMD_UNSPEC) { if (cmd == CTRL_CMD_UNSPEC || cmd == CTRL_CMD_GETPOLICY) {
nlh->nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; nlh->nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
nlh->nlmsg_seq = rth.dump = ++rth.seq; nlh->nlmsg_seq = rth.dump = ++rth.seq;
@ -324,6 +334,8 @@ static int parse_ctrl(struct genl_util *a, int argc, char **argv)
matches(*argv, "show") == 0 || matches(*argv, "show") == 0 ||
matches(*argv, "lst") == 0) matches(*argv, "lst") == 0)
return ctrl_list(CTRL_CMD_UNSPEC, argc-1, argv+1); return ctrl_list(CTRL_CMD_UNSPEC, argc-1, argv+1);
if (matches(*argv, "policy") == 0)
return ctrl_list(CTRL_CMD_GETPOLICY, argc-1, argv+1);
if (matches(*argv, "help") == 0) if (matches(*argv, "help") == 0)
return usage(); return usage();