All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] libnetlink: add rtattr_for_each_nested() iteration macro
@ 2020-08-19 10:29 Johannes Berg
  2020-08-19 10:29 ` [PATCH 2/2] genl: ctrl: support dumping netlink policy Johannes Berg
  0 siblings, 1 reply; 5+ messages in thread
From: Johannes Berg @ 2020-08-19 10:29 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger

This is useful for iterating elements in a nested attribute,
if they're not parsed with a strict length limit or such.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 include/libnetlink.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/libnetlink.h b/include/libnetlink.h
index e27516f7648f..0d4a9f29afbd 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -284,4 +284,9 @@ int rtnl_from_file(FILE *, rtnl_listen_filter_t handler,
  * messages from dump file */
 #define NLMSG_TSTAMP	15
 
+#define rtattr_for_each_nested(attr, nest) \
+	for ((attr) = (void *)RTA_DATA(nest); \
+	     RTA_OK(attr, RTA_PAYLOAD(nest) - ((char *)(attr) - (char *)RTA_DATA((nest)))); \
+	     (attr) = RTA_TAIL((attr)))
+
 #endif /* __LIBNETLINK_H__ */
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/2] genl: ctrl: support dumping netlink policy
  2020-08-19 10:29 [PATCH 1/2] libnetlink: add rtattr_for_each_nested() iteration macro Johannes Berg
@ 2020-08-19 10:29 ` Johannes Berg
  2020-08-24  1:45   ` David Ahern
  0 siblings, 1 reply; 5+ messages in thread
From: Johannes Berg @ 2020-08-19 10:29 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger

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>
---
 genl/ctrl.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 85 insertions(+), 6 deletions(-)

diff --git a/genl/ctrl.c b/genl/ctrl.c
index 0fb464b01cfb..7767fffe63ea 100644
--- a/genl/ctrl.c
+++ b/genl/ctrl.c
@@ -28,13 +28,15 @@
 static int usage(void)
 {
 	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" \
 		       "Examples:\n" \
 		       "\tctrl ls\n" \
 		       "\tctrl monitor\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;
 }
 
@@ -100,6 +102,30 @@ static int print_ctrl_grp(FILE *fp, struct rtattr *arg, __u32 ctrl_ver)
 
 }
 
+static const char *get_nla_type_str(unsigned int attr)
+{
+	switch (attr) {
+#define C(x) case NL_ATTR_TYPE_ ## x: return #x
+	C(U8);
+	C(U16);
+	C(U32);
+	C(U64);
+	C(STRING);
+	C(FLAG);
+	C(NESTED);
+	C(NESTED_ARRAY);
+	C(NUL_STRING);
+	C(BINARY);
+	C(S8);
+	C(S16);
+	C(S32);
+	C(S64);
+	C(BITFIELD32);
+	default:
+		return "unknown";
+	}
+}
+
 /*
  * The controller sends one nlmsg per family
 */
@@ -123,7 +149,8 @@ static int print_ctrl(struct rtnl_ctrl_data *ctrl,
 	    ghdr->cmd != CTRL_CMD_DELFAMILY &&
 	    ghdr->cmd != CTRL_CMD_NEWFAMILY &&
 	    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);
 		return 0;
 	}
@@ -136,7 +163,7 @@ static int print_ctrl(struct rtnl_ctrl_data *ctrl,
 	}
 
 	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]) {
 		char *name = RTA_DATA(tb[CTRL_ATTR_FAMILY_NAME]);
@@ -159,6 +186,52 @@ static int print_ctrl(struct rtnl_ctrl_data *ctrl,
 		__u32 *ma = RTA_DATA(tb[CTRL_ATTR_MAXATTR]);
 		fprintf(fp, " max attribs: %d ",*ma);
 	}
+	if (tb[CTRL_ATTR_POLICY]) {
+		const struct rtattr *pos;
+
+		rtattr_for_each_nested(pos, tb[CTRL_ATTR_POLICY]) {
+			const struct rtattr *attr;
+
+			fprintf(fp, " policy[%u]:", pos->rta_type & ~NLA_F_NESTED);
+
+			rtattr_for_each_nested(attr, pos) {
+				struct rtattr *tp[NL_POLICY_TYPE_ATTR_MAX + 1];
+
+				parse_rtattr_nested(tp, ARRAY_SIZE(tp) - 1, attr);
+
+				if (tp[NL_POLICY_TYPE_ATTR_TYPE])
+					fprintf(fp, "attr[%u]: type=%s",
+						attr->rta_type & ~NLA_F_NESTED,
+						get_nla_type_str(rta_getattr_u32(tp[NL_POLICY_TYPE_ATTR_TYPE])));
+
+				if (tp[NL_POLICY_TYPE_ATTR_POLICY_IDX])
+					fprintf(fp, " policy:%u",
+						rta_getattr_u32(tp[NL_POLICY_TYPE_ATTR_POLICY_IDX]));
+
+				if (tp[NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE])
+					fprintf(fp, " maxattr:%u",
+						rta_getattr_u32(tp[NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE]));
+
+				if (tp[NL_POLICY_TYPE_ATTR_MIN_VALUE_S] && tp[NL_POLICY_TYPE_ATTR_MAX_VALUE_S])
+					fprintf(fp, " range:[%lld,%lld]",
+						(signed long long)rta_getattr_u64(tp[NL_POLICY_TYPE_ATTR_MIN_VALUE_S]),
+						(signed long long)rta_getattr_u64(tp[NL_POLICY_TYPE_ATTR_MAX_VALUE_S]));
+
+				if (tp[NL_POLICY_TYPE_ATTR_MIN_VALUE_U] && tp[NL_POLICY_TYPE_ATTR_MAX_VALUE_U])
+					fprintf(fp, " range:[%llu,%llu]",
+						(unsigned long long)rta_getattr_u64(tp[NL_POLICY_TYPE_ATTR_MIN_VALUE_U]),
+						(unsigned long long)rta_getattr_u64(tp[NL_POLICY_TYPE_ATTR_MAX_VALUE_U]));
+
+				if (tp[NL_POLICY_TYPE_ATTR_MIN_LENGTH])
+					fprintf(fp, " min len:%u",
+						rta_getattr_u32(tp[NL_POLICY_TYPE_ATTR_MIN_LENGTH]));
+
+				if (tp[NL_POLICY_TYPE_ATTR_MAX_LENGTH])
+					fprintf(fp, " max len:%u",
+						rta_getattr_u32(tp[NL_POLICY_TYPE_ATTR_MAX_LENGTH]));
+			}
+		}
+	}
 	/* end of family definitions .. */
 	fprintf(fp,"\n");
 	if (tb[CTRL_ATTR_OPS]) {
@@ -235,7 +308,9 @@ static int ctrl_list(int cmd, int argc, char **argv)
 		exit(1);
 	}
 
-	if (cmd == CTRL_CMD_GETFAMILY) {
+	if (cmd == CTRL_CMD_GETFAMILY || cmd == CTRL_CMD_GETPOLICY) {
+		req.g.cmd = cmd;
+
 		if (argc != 2) {
 			fprintf(stderr, "Wrong number of params\n");
 			return -1;
@@ -260,7 +335,9 @@ static int ctrl_list(int cmd, int argc, char **argv)
 			fprintf(stderr, "Wrong params\n");
 			goto ctrl_done;
 		}
+	}
 
+	if (cmd == CTRL_CMD_GETFAMILY) {
 		if (rtnl_talk(&rth, nlh, &answer) < 0) {
 			fprintf(stderr, "Error talking to the kernel\n");
 			goto ctrl_done;
@@ -273,7 +350,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_seq = rth.dump = ++rth.seq;
 
@@ -324,6 +401,8 @@ static int parse_ctrl(struct genl_util *a, int argc, char **argv)
 	    matches(*argv, "show") == 0 ||
 	    matches(*argv, "lst") == 0)
 		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)
 		return usage();
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2] genl: ctrl: support dumping netlink policy
  2020-08-19 10:29 ` [PATCH 2/2] genl: ctrl: support dumping netlink policy Johannes Berg
@ 2020-08-24  1:45   ` David Ahern
  2020-08-24  7:54     ` Johannes Berg
  0 siblings, 1 reply; 5+ messages in thread
From: David Ahern @ 2020-08-24  1:45 UTC (permalink / raw)
  To: Johannes Berg, netdev; +Cc: Stephen Hemminger

On 8/19/20 4:29 AM, Johannes Berg wrote:
> @@ -100,6 +102,30 @@ static int print_ctrl_grp(FILE *fp, struct rtattr *arg, __u32 ctrl_ver)
>  
>  }
>  
> +static const char *get_nla_type_str(unsigned int attr)
> +{
> +	switch (attr) {
> +#define C(x) case NL_ATTR_TYPE_ ## x: return #x
> +	C(U8);
> +	C(U16);
> +	C(U32);
> +	C(U64);
> +	C(STRING);
> +	C(FLAG);
> +	C(NESTED);
> +	C(NESTED_ARRAY);
> +	C(NUL_STRING);
> +	C(BINARY);
> +	C(S8);
> +	C(S16);
> +	C(S32);
> +	C(S64);
> +	C(BITFIELD32);
> +	default:
> +		return "unknown";
> +	}
> +}
> +

This should go in libnetlink since it generic NLA type strings.

>  /*
>   * The controller sends one nlmsg per family
>  */


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2] genl: ctrl: support dumping netlink policy
  2020-08-24  1:45   ` David Ahern
@ 2020-08-24  7:54     ` Johannes Berg
  2020-08-24 16:54       ` David Ahern
  0 siblings, 1 reply; 5+ messages in thread
From: Johannes Berg @ 2020-08-24  7:54 UTC (permalink / raw)
  To: David Ahern, netdev; +Cc: Stephen Hemminger

On Sun, 2020-08-23 at 19:45 -0600, David Ahern wrote:
> On 8/19/20 4:29 AM, Johannes Berg wrote:
> > @@ -100,6 +102,30 @@ static int print_ctrl_grp(FILE *fp, struct rtattr *arg, __u32 ctrl_ver)
> >  
> >  }
> >  
> > +static const char *get_nla_type_str(unsigned int attr)
> > +{
> > +	switch (attr) {
> > +#define C(x) case NL_ATTR_TYPE_ ## x: return #x
> > +	C(U8);
> > +	C(U16);
> > +	C(U32);
> > +	C(U64);
> > +	C(STRING);
> > +	C(FLAG);
> > +	C(NESTED);
> > +	C(NESTED_ARRAY);
> > +	C(NUL_STRING);
> > +	C(BINARY);
> > +	C(S8);
> > +	C(S16);
> > +	C(S32);
> > +	C(S64);
> > +	C(BITFIELD32);
> > +	default:
> > +		return "unknown";
> > +	}
> > +}
> > +
> 
> This should go in libnetlink since it generic NLA type strings.

Arguably, pretty much all of the code here should go into libnetlink
then, since the kernel facility was expressly written in a way that
would allow dumping out arbitrary (not just generic netlink) policies,
just needs wiring up in the appropriate netlink family (or perhaps some
additional "policy netlink" family?)

I can make that change, but I sort of assumed it'd be nicer to do that
when someone else actually picked it up.

johannes


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2] genl: ctrl: support dumping netlink policy
  2020-08-24  7:54     ` Johannes Berg
@ 2020-08-24 16:54       ` David Ahern
  0 siblings, 0 replies; 5+ messages in thread
From: David Ahern @ 2020-08-24 16:54 UTC (permalink / raw)
  To: Johannes Berg, netdev; +Cc: Stephen Hemminger

On 8/24/20 1:54 AM, Johannes Berg wrote:
> Arguably, pretty much all of the code here should go into libnetlink
> then, since the kernel facility was expressly written in a way that
> would allow dumping out arbitrary (not just generic netlink) policies,
> just needs wiring up in the appropriate netlink family (or perhaps some
> additional "policy netlink" family?)

good point.

> 
> I can make that change, but I sort of assumed it'd be nicer to do that
> when someone else actually picked it up.

I think it would be better to put this into libnetlink from the start.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-08-24 16:55 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-19 10:29 [PATCH 1/2] libnetlink: add rtattr_for_each_nested() iteration macro Johannes Berg
2020-08-19 10:29 ` [PATCH 2/2] genl: ctrl: support dumping netlink policy Johannes Berg
2020-08-24  1:45   ` David Ahern
2020-08-24  7:54     ` Johannes Berg
2020-08-24 16:54       ` David Ahern

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.