[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1555713416-12209-5-git-send-email-tom@quantonium.net>
Date: Fri, 19 Apr 2019 15:36:54 -0700
From: Tom Herbert <tom@...bertland.com>
To: davem@...emloft.net, netdev@...r.kernel.org
Cc: Tom Herbert <tom@...ntonium.net>
Subject: [PATCH v5 net-next 4/6] exthdrs: Add TX parameters
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@...ntonium.net>
---
include/net/ipv6.h | 26 ++++++++++++++++++++-
include/uapi/linux/in6.h | 8 +++++++
net/ipv6/exthdrs.c | 2 +-
net/ipv6/exthdrs_core.c | 22 +++++++++++++++++-
net/ipv6/exthdrs_options.c | 57 ++++++++++++++++++++++++++++++++++++++++++----
5 files changed, 108 insertions(+), 7 deletions(-)
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 41da032..9b25d08 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 b28c108..520c2eb 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_core.c b/net/ipv6/exthdrs_core.c
index def52b5..53e92fd 100644
--- a/net/ipv6/exthdrs_core.c
+++ b/net/ipv6/exthdrs_core.c
@@ -431,7 +431,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)
@@ -650,10 +661,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);
@@ -667,6 +681,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)) {
@@ -680,6 +695,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 02d12c5..042ca14 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,
},
};
--
2.7.4
Powered by blists - more mailing lists