[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1577210148-7328-8-git-send-email-tom@herbertland.com>
Date: Tue, 24 Dec 2019 09:55:46 -0800
From: Tom Herbert <tom@...bertland.com>
To: davem@...emloft.net, netdev@...r.kernel.org,
simon.horman@...ronome.com, willemdebruijn.kernel@...il.com
Cc: Tom Herbert <tom@...ntonium.net>, Tom Herbert <tom@...bertland.com>
Subject: [PATCH v7 net-next 7/9] ip6tlvs: Add TX parameters
From: Tom Herbert <tom@...ntonium.net>
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@...bertland.com>
---
include/net/ipeh.h | 18 ++++++++++++++++
include/uapi/linux/ipeh.h | 8 +++++++
net/ipv6/exthdrs_common.c | 53 +++++++++++++++++++++++++++++++++++++++++++++-
net/ipv6/exthdrs_options.c | 45 +++++++++++++++++++++++++++++++++++++++
4 files changed, 123 insertions(+), 1 deletion(-)
diff --git a/include/net/ipeh.h b/include/net/ipeh.h
index fc7d543..6f46e2c 100644
--- a/include/net/ipeh.h
+++ b/include/net/ipeh.h
@@ -20,6 +20,17 @@ struct tlv_rx_params {
};
struct tlv_tx_params {
+ unsigned char admin_perm : 2;
+ unsigned char user_perm : 2;
+ unsigned char class : 3;
+ unsigned char rsvd : 1;
+ 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 short preferred_order;
};
struct tlv_params {
@@ -54,6 +65,13 @@ struct tlv_param_table {
extern struct tlv_param_table ipv6_tlv_param_table;
+/* Preferred TLV ordering for HBH and Dest options (placed by increasing order)
+ */
+#define IPEH_TLV_PREF_ORDER_HAO 10
+#define IPEH_TLV_PREF_ORDER_ROUTERALERT 20
+#define IPEH_TLV_PREF_ORDER_JUMBO 30
+#define IPEH_TLV_PREF_ORDER_CALIPSO 40
+
int __ipeh_tlv_set(struct tlv_param_table *tlv_param_table,
unsigned char type, const struct tlv_params *params,
const struct tlv_ops *ops);
diff --git a/include/uapi/linux/ipeh.h b/include/uapi/linux/ipeh.h
index c4302b7..dbf0728 100644
--- a/include/uapi/linux/ipeh.h
+++ b/include/uapi/linux/ipeh.h
@@ -13,4 +13,12 @@
IPEH_TLV_CLASS_FLAG_RTRDSTOPT | \
IPEH_TLV_CLASS_FLAG_DSTOPT)
+/* TLV permissions values */
+enum {
+ IPEH_TLV_PERM_NONE,
+ IPEH_TLV_PERM_WITH_CHECK,
+ IPEH_TLV_PERM_NO_CHECK,
+ IPEH_TLV_PERM_MAX = IPEH_TLV_PERM_NO_CHECK
+};
+
#endif /* _UAPI_LINUX_IPEH_H */
diff --git a/net/ipv6/exthdrs_common.c b/net/ipv6/exthdrs_common.c
index f36513d..e9309ea 100644
--- a/net/ipv6/exthdrs_common.c
+++ b/net/ipv6/exthdrs_common.c
@@ -3,6 +3,7 @@
/* Extension header and TLV library code that is not specific to IPv6. */
#include <linux/export.h>
#include <net/ipv6.h>
+#include <uapi/linux/ipeh.h>
struct ipv6_txoptions *
ipeh_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
@@ -268,6 +269,13 @@ EXPORT_SYMBOL(ipeh_parse_tlv);
/* Default (unset) values for TLV parameters */
static const struct tlv_proc tlv_default_proc = {
+ .params.t = {
+ .admin_perm = IPEH_TLV_PERM_NO_CHECK,
+ .user_perm = IPEH_TLV_PERM_NONE,
+ .align_mult = (4 - 1), /* Default alignment: 4n + 2 */
+ .align_off = 2,
+ .max_data_len = 255,
+ },
};
static DEFINE_MUTEX(tlv_mutex);
@@ -287,16 +295,45 @@ static void tlv_param_table_release(struct rcu_head *rcu)
}
/* mutex held */
+static int check_order(struct tlv_param_table_data *tpt, unsigned char type,
+ unsigned short order)
+{
+ int i;
+
+ if (!order)
+ return -EINVAL;
+
+ for (i = 2; i < 256; i++) {
+ struct tlv_type *ttype = &tpt->types[tpt->entries[i]];
+
+ if (!tpt->entries[i])
+ continue;
+
+ if (order == ttype->proc.params.t.preferred_order &&
+ i != type)
+ return -EALREADY;
+ }
+
+ return 0;
+}
+
+/* mutex held */
static int __tlv_set_one(struct tlv_param_table *tlv_param_table,
unsigned char type, const struct tlv_params *params,
const struct tlv_ops *ops)
{
struct tlv_param_table_data *tpt, *told;
struct tlv_type *ttype;
+ int retv;
told = rcu_dereference_protected(tlv_param_table->data,
lockdep_is_held(&tlv_mutex));
+ /* Check preferred order */
+ retv = check_order(told, type, params->t.preferred_order);
+ if (retv)
+ return retv;
+
/* Create new TLV table. If there is no exsiting entry then we are
* adding a new one to the table, else we're modifying an entry.
*/
@@ -425,7 +462,7 @@ int ipeh_exthdrs_init(struct tlv_param_table *tlv_param_table,
int num_init_params)
{
struct tlv_param_table_data *tpt;
- int pos = 0, i;
+ int pos = 0, i, j;
size_t tsize;
tsize = tlv_param_table_size(num_init_params + 1);
@@ -451,6 +488,20 @@ int ipeh_exthdrs_init(struct tlv_param_table *tlv_param_table,
goto err_inval;
}
+ if (WARN_ON(!tpi->proc.params.t.preferred_order)) {
+ /* Preferred order must be non-zero */
+ goto err_inval;
+ }
+
+ for (j = 0; j < i; j++) {
+ const struct tlv_proc_init *tpix = &tlv_init_params[j];
+
+ if (WARN_ON(tpi->proc.params.t.preferred_order ==
+ tpix->proc.params.t.preferred_order)) {
+ /* Preferred order must be unique */
+ goto err_inval;
+ }
+ }
tpt->types[pos].proc = tpi->proc;
tpt->entries[tpi->type] = pos;
}
diff --git a/net/ipv6/exthdrs_options.c b/net/ipv6/exthdrs_options.c
index d4b373e..3b50b58 100644
--- a/net/ipv6/exthdrs_options.c
+++ b/net/ipv6/exthdrs_options.c
@@ -183,6 +183,17 @@ static const struct tlv_proc_init tlv_ipv6_init_params[] __initconst = {
.proc.ops.func = ipv6_dest_hao,
.proc.params.r.class = IPEH_TLV_CLASS_FLAG_DSTOPT,
+
+ .proc.params.t = {
+ .preferred_order = IPEH_TLV_PREF_ORDER_HAO,
+ .admin_perm = IPEH_TLV_PERM_NO_CHECK,
+ .user_perm = IPEH_TLV_PERM_NONE,
+ .class = IPEH_TLV_CLASS_FLAG_DSTOPT,
+ .align_mult = (8 - 1), /* Align to 8n + 6 */
+ .align_off = 6,
+ .min_data_len = 16,
+ .max_data_len = 16,
+ },
},
#endif
{
@@ -190,18 +201,52 @@ static const struct tlv_proc_init tlv_ipv6_init_params[] __initconst = {
.proc.ops.func = ipv6_hop_ra,
.proc.params.r.class = IPEH_TLV_CLASS_FLAG_HOPOPT,
+
+ .proc.params.t = {
+ .preferred_order = IPEH_TLV_PREF_ORDER_ROUTERALERT,
+ .admin_perm = IPEH_TLV_PERM_NO_CHECK,
+ .user_perm = IPEH_TLV_PERM_NONE,
+ .class = IPEH_TLV_CLASS_FLAG_HOPOPT,
+ .align_mult = (2 - 1), /* Align to 2n */
+ .min_data_len = 2,
+ .max_data_len = 2,
+ },
},
{
.type = IPV6_TLV_JUMBO,
.proc.ops.func = ipv6_hop_jumbo,
.proc.params.r.class = IPEH_TLV_CLASS_FLAG_HOPOPT,
+
+ .proc.params.t = {
+ .preferred_order = IPEH_TLV_PREF_ORDER_JUMBO,
+ .admin_perm = IPEH_TLV_PERM_NO_CHECK,
+ .user_perm = IPEH_TLV_PERM_NONE,
+ .class = IPEH_TLV_CLASS_FLAG_HOPOPT,
+ .align_mult = (4 - 1), /* Align to 4n + 2 */
+ .align_off = 2,
+ .min_data_len = 4,
+ .max_data_len = 4,
+ },
},
{
.type = IPV6_TLV_CALIPSO,
.proc.ops.func = ipv6_hop_calipso,
.proc.params.r.class = IPEH_TLV_CLASS_FLAG_HOPOPT,
+
+ .proc.params.t = {
+ .preferred_order = IPEH_TLV_PREF_ORDER_CALIPSO,
+ .admin_perm = IPEH_TLV_PERM_NO_CHECK,
+ .user_perm = IPEH_TLV_PERM_NONE,
+ .class = IPEH_TLV_CLASS_FLAG_HOPOPT,
+ .align_mult = (4 - 1), /* Align to 4n + 2 */
+ .align_off = 2,
+ .min_data_len = 8,
+ .max_data_len = 252,
+ .data_len_mult = (4 - 1),
+ /* Length is multiple of 4 */
+ },
},
};
--
2.7.4
Powered by blists - more mailing lists