diff mbox series

[v7,net-next,4/6] exthdrs: Add TX parameters

Message ID 1556563576-31157-5-git-send-email-tom@quantonium.net
State Changes Requested
Delegated to: David Miller
Headers show
Series exthdrs: Make ext. headers & options useful - Part I | expand

Commit Message

Tom Herbert April 29, 2019, 6:46 p.m. UTC
Define a number of transmit parameters for TLV Parameter table
definitions. These will be used for validating TLVs that are set
on a socket.

Signed-off-by: Tom Herbert <tom@quantonium.net>
---
 include/net/ipv6.h         | 26 ++++++++++++++++++++-
 include/uapi/linux/in6.h   |  8 +++++++
 net/ipv6/exthdrs.c         |  2 +-
 net/ipv6/exthdrs_common.c  | 22 +++++++++++++++++-
 net/ipv6/exthdrs_options.c | 57 ++++++++++++++++++++++++++++++++++++++++++----
 5 files changed, 108 insertions(+), 7 deletions(-)

Comments

Stephen Hemminger April 29, 2019, 7:35 p.m. UTC | #1
On Mon, 29 Apr 2019 11:46:14 -0700
Tom Herbert <tom@herbertland.com> wrote:

>  /* Default (unset) values for TLV parameters */
>  static const struct tlv_proc tlv_default_proc = {
> -	.params.rx_class = 0,
> +	.params.r.class = 0,
> +
> +	.params.t.preferred_order = 0,
> +	.params.t.admin_perm = IPV6_TLV_PERM_NO_CHECK,
> +	.params.t.user_perm = IPV6_TLV_PERM_NONE,
> +	.params.t.class = 0,
> +	.params.t.align_mult = (4 - 1), /* Default alignment: 4n + 2 */
> +	.params.t.align_off = 2,
> +	.params.t.min_data_len = 0,
> +	.params.t.max_data_len = 255,
> +	.params.t.data_len_mult = (1 - 1), /* No default length align */
> +	.params.t.data_len_off = 0,
>  };

This looks cleaner if you skip the unnecessary 0 entries
and also use additional {}.

static const struct tlv_proc tlv_default_proc = {
	.params.t = {
		.admin_perm = IPV6_TLV_PERM_NO_CHECK,
		.user_perm = IPV6_TLV_PERM_NONE,
		.align_mult = 3,  /* Default alignment: 4n + 2 */
		.align_off = 2,
		.max_data_len = 255,
	},
};
Tom Herbert April 29, 2019, 8:36 p.m. UTC | #2
On Mon, Apr 29, 2019 at 12:35 PM Stephen Hemminger
<stephen@networkplumber.org> wrote:
>
> On Mon, 29 Apr 2019 11:46:14 -0700
> Tom Herbert <tom@herbertland.com> wrote:
>
> >  /* Default (unset) values for TLV parameters */
> >  static const struct tlv_proc tlv_default_proc = {
> > -     .params.rx_class = 0,
> > +     .params.r.class = 0,
> > +
> > +     .params.t.preferred_order = 0,
> > +     .params.t.admin_perm = IPV6_TLV_PERM_NO_CHECK,
> > +     .params.t.user_perm = IPV6_TLV_PERM_NONE,
> > +     .params.t.class = 0,
> > +     .params.t.align_mult = (4 - 1), /* Default alignment: 4n + 2 */
> > +     .params.t.align_off = 2,
> > +     .params.t.min_data_len = 0,
> > +     .params.t.max_data_len = 255,
> > +     .params.t.data_len_mult = (1 - 1), /* No default length align */
> > +     .params.t.data_len_off = 0,
> >  };
>
> This looks cleaner if you skip the unnecessary 0 entries
> and also use additional {}.

Hi Stephen,

I sort of like being explict here to list all the fields to make it
easy to use as a template for adding new structures.

Tom

>
> static const struct tlv_proc tlv_default_proc = {
>         .params.t = {
>                 .admin_perm = IPV6_TLV_PERM_NO_CHECK,
>                 .user_perm = IPV6_TLV_PERM_NONE,
>                 .align_mult = 3,  /* Default alignment: 4n + 2 */
>                 .align_off = 2,
>                 .max_data_len = 255,
>         },
> };
>
>
David Miller April 29, 2019, 8:38 p.m. UTC | #3
From: Tom Herbert <tom@quantonium.net>
Date: Mon, 29 Apr 2019 13:36:03 -0700

> I sort of like being explict here to list all the fields to make it
> easy to use as a template for adding new structures.

Someone doing a sweep over the tree with automated tools is going to
remove it.

So kill these zero initializers from the start please.
diff mbox series

Patch

diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index bb667ed..4cebc48 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -390,8 +390,26 @@  struct tlv_ops {
 	bool	(*func)(unsigned int class, struct sk_buff *skb, int offset);
 };
 
+struct tlv_rx_params {
+	unsigned char class : 3;
+};
+
+struct tlv_tx_params {
+	unsigned char admin_perm : 2;
+	unsigned char user_perm : 2;
+	unsigned char class : 3;
+	unsigned char align_mult : 4;
+	unsigned char align_off : 4;
+	unsigned char data_len_mult : 4;
+	unsigned char data_len_off : 4;
+	unsigned char min_data_len;
+	unsigned char max_data_len;
+	unsigned char preferred_order;
+};
+
 struct tlv_params {
-	unsigned char rx_class : 3;
+	struct tlv_rx_params r;
+	struct tlv_tx_params t;
 };
 
 struct tlv_proc {
@@ -417,6 +435,12 @@  struct tlv_param_table {
 
 extern struct tlv_param_table ipv6_tlv_param_table;
 
+/* Preferred TLV ordering (placed by increasing order) */
+#define TLV_PREF_ORDER_HAO		10
+#define TLV_PREF_ORDER_ROUTERALERT	20
+#define TLV_PREF_ORDER_JUMBO		30
+#define TLV_PREF_ORDER_CALIPSO		40
+
 int tlv_set_proc(struct tlv_param_table *tlv_param_table,
 		 unsigned char type, const struct tlv_proc *proc);
 int tlv_unset_proc(struct tlv_param_table *tlv_param_table, unsigned char type);
diff --git a/include/uapi/linux/in6.h b/include/uapi/linux/in6.h
index 8b9ac7f..6a99ee1 100644
--- a/include/uapi/linux/in6.h
+++ b/include/uapi/linux/in6.h
@@ -307,4 +307,12 @@  struct in6_flowlabel_req {
 #define IPV6_TLV_CLASS_ANY_DSTOPT      (IPV6_TLV_CLASS_FLAG_RTRDSTOPT | \
 					IPV6_TLV_CLASS_FLAG_DSTOPT)
 
+/* TLV permissions values */
+enum {
+	IPV6_TLV_PERM_NONE,
+	IPV6_TLV_PERM_WITH_CHECK,
+	IPV6_TLV_PERM_NO_CHECK,
+	IPV6_TLV_PERM_MAX = IPV6_TLV_PERM_NO_CHECK
+};
+
 #endif /* _UAPI_LINUX_IN6_H */
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 71a12a7..92a777f 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -166,7 +166,7 @@  static bool ip6_parse_tlv(unsigned int class, struct sk_buff *skb,
 				goto bad;
 
 			curr = tlv_get_proc(&ipv6_tlv_param_table, nh[off]);
-			if ((curr->params.rx_class & class) && curr->ops.func) {
+			if ((curr->params.r.class & class) && curr->ops.func) {
 				/* Handler will apply additional checks to
 				 * the TLV
 				 */
diff --git a/net/ipv6/exthdrs_common.c b/net/ipv6/exthdrs_common.c
index 0d2aa89f..c0ccb0a 100644
--- a/net/ipv6/exthdrs_common.c
+++ b/net/ipv6/exthdrs_common.c
@@ -155,7 +155,18 @@  static void tlv_param_table_release(struct rcu_head *rcu)
 
 /* Default (unset) values for TLV parameters */
 static const struct tlv_proc tlv_default_proc = {
-	.params.rx_class = 0,
+	.params.r.class = 0,
+
+	.params.t.preferred_order = 0,
+	.params.t.admin_perm = IPV6_TLV_PERM_NO_CHECK,
+	.params.t.user_perm = IPV6_TLV_PERM_NONE,
+	.params.t.class = 0,
+	.params.t.align_mult = (4 - 1), /* Default alignment: 4n + 2 */
+	.params.t.align_off = 2,
+	.params.t.min_data_len = 0,
+	.params.t.max_data_len = 255,
+	.params.t.data_len_mult = (1 - 1), /* No default length align */
+	.params.t.data_len_off = 0,
 };
 
 static size_t tlv_param_table_size(unsigned char count)
@@ -374,10 +385,13 @@  int exthdrs_init(struct tlv_param_table *tlv_param_table,
 		 const struct tlv_proc_init *tlv_init_params,
 		 int num_init_params)
 {
+	unsigned long check_map[BITS_TO_LONGS(256)];
 	struct tlv_param_table_data *tpt;
 	size_t tsize;
 	int i;
 
+	memset(check_map, 0, sizeof(check_map));
+
 	tsize = tlv_param_table_size(num_init_params + 1);
 
 	tpt = kvmalloc(tsize, GFP_KERNEL);
@@ -391,6 +405,7 @@  int exthdrs_init(struct tlv_param_table *tlv_param_table,
 
 	for (i = 0; i < num_init_params; i++) {
 		const struct tlv_proc_init *tpi = &tlv_init_params[i];
+		unsigned int order = tpi->proc.params.t.preferred_order;
 		struct tlv_proc *tp = &tpt->procs[i + 1];
 
 		if (WARN_ON(tpi->type < 2)) {
@@ -404,6 +419,11 @@  int exthdrs_init(struct tlv_param_table *tlv_param_table,
 			return -EINVAL;
 		}
 
+		if (order) {
+			WARN_ON(test_bit(order, check_map));
+			set_bit(order, check_map);
+		}
+
 		*tp = tpi->proc;
 		tpt->entries[tpi->type] = i + 1;
 	}
diff --git a/net/ipv6/exthdrs_options.c b/net/ipv6/exthdrs_options.c
index eb3ae2a..0c69d7f 100644
--- a/net/ipv6/exthdrs_options.c
+++ b/net/ipv6/exthdrs_options.c
@@ -181,26 +181,75 @@  static const struct tlv_proc_init tlv_init_params[] __initconst = {
 		.type = IPV6_TLV_HAO,
 
 		.proc.ops.func = ipv6_dest_hao,
-		.proc.params.rx_class = IPV6_TLV_CLASS_FLAG_DSTOPT,
+
+		.proc.params.r.class = IPV6_TLV_CLASS_FLAG_DSTOPT,
+
+		.proc.params.t.preferred_order = TLV_PREF_ORDER_HAO,
+		.proc.params.t.admin_perm = IPV6_TLV_PERM_NO_CHECK,
+		.proc.params.t.user_perm = IPV6_TLV_PERM_NONE,
+		.proc.params.t.class = IPV6_TLV_CLASS_FLAG_DSTOPT,
+		.proc.params.t.align_mult = (8 - 1), /* Align to 8n + 6 */
+		.proc.params.t.align_off = 6,
+		.proc.params.t.min_data_len = 16,
+		.proc.params.t.max_data_len = 16,
+		.proc.params.t.data_len_mult = (1 - 1), /* Fixed length */
+		.proc.params.t.data_len_off = 0,
 	},
 #endif
 	{
 		.type = IPV6_TLV_ROUTERALERT,
 
 		.proc.ops.func = ipv6_hop_ra,
-		.proc.params.rx_class = IPV6_TLV_CLASS_FLAG_HOPOPT,
+
+		.proc.params.r.class = IPV6_TLV_CLASS_FLAG_HOPOPT,
+
+		.proc.params.t.preferred_order = TLV_PREF_ORDER_ROUTERALERT,
+		.proc.params.t.admin_perm = IPV6_TLV_PERM_NO_CHECK,
+		.proc.params.t.user_perm = IPV6_TLV_PERM_NONE,
+		.proc.params.t.class = IPV6_TLV_CLASS_FLAG_HOPOPT,
+		.proc.params.t.align_mult = (2 - 1), /* Align to 2n */
+		.proc.params.t.align_off = 0,
+		.proc.params.t.min_data_len = 2,
+		.proc.params.t.max_data_len = 2,
+		.proc.params.t.data_len_mult = (1 - 1), /* Fixed length */
+		.proc.params.t.data_len_off = 0,
+
 	},
 	{
 		.type = IPV6_TLV_JUMBO,
 
 		.proc.ops.func	= ipv6_hop_jumbo,
-		.proc.params.rx_class = IPV6_TLV_CLASS_FLAG_HOPOPT,
+
+		.proc.params.r.class = IPV6_TLV_CLASS_FLAG_HOPOPT,
+
+		.proc.params.t.preferred_order = TLV_PREF_ORDER_JUMBO,
+		.proc.params.t.admin_perm = IPV6_TLV_PERM_NO_CHECK,
+		.proc.params.t.user_perm = IPV6_TLV_PERM_NONE,
+		.proc.params.t.class = IPV6_TLV_CLASS_FLAG_HOPOPT,
+		.proc.params.t.align_mult = (4 - 1), /* Align to 4n + 2 */
+		.proc.params.t.align_off = 2,
+		.proc.params.t.min_data_len = 4,
+		.proc.params.t.max_data_len = 4,
+		.proc.params.t.data_len_mult = (1 - 1), /* Fixed length */
+		.proc.params.t.data_len_off = 0,
 	},
 	{
 		.type = IPV6_TLV_CALIPSO,
 
 		.proc.ops.func = ipv6_hop_calipso,
-		.proc.params.rx_class = IPV6_TLV_CLASS_FLAG_HOPOPT,
+		.proc.params.r.class = IPV6_TLV_CLASS_FLAG_HOPOPT,
+
+		.proc.params.t.preferred_order = TLV_PREF_ORDER_CALIPSO,
+		.proc.params.t.admin_perm = IPV6_TLV_PERM_NO_CHECK,
+		.proc.params.t.user_perm = IPV6_TLV_PERM_NONE,
+		.proc.params.t.class = IPV6_TLV_CLASS_FLAG_HOPOPT,
+		.proc.params.t.align_mult = (4 - 1), /* Align to 4n + 2 */
+		.proc.params.t.align_off = 2,
+		.proc.params.t.min_data_len = 8,
+		.proc.params.t.max_data_len = 252,
+		.proc.params.t.data_len_mult = (4 - 1),
+					/* Length is multiple of 4 */
+		.proc.params.t.data_len_off = 0,
 	},
 };