[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1559933708-13947-4-git-send-email-tom@quantonium.net>
Date: Fri, 7 Jun 2019 11:55:06 -0700
From: Tom Herbert <tom@...bertland.com>
To: davem@...emloft.net, netdev@...r.kernel.org, dlebrun@...gle.com
Cc: Tom Herbert <tom@...ntonium.net>
Subject: [RFC v2 PATCH 3/5] ipv6: Paramterize TLV parsing
Add parameters to ip6_parse_tlv that will allow leveraging the function
for parsing segment routing TLVs. The new parameters are offset of
TLVs, length of the TLV block, and a function that is called in the case
of an unrecognized option.
Signed-off-by: Tom Herbert <tom@...ntonium.net>
---
net/ipv6/exthdrs.c | 35 ++++++++++++++++++++++++-----------
1 file changed, 24 insertions(+), 11 deletions(-)
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 20291c2..a394d20 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -112,15 +112,26 @@ static bool ip6_tlvopt_unknown(struct sk_buff *skb, int optoff,
return false;
}
-/* Parse tlv encoded option header (hop-by-hop or destination) */
+/* Parse tlv encoded option header (hop-by-hop or destination)
+ *
+ * Arguments:
+ * procs - TLV proc structure
+ * skb - skbuff containing TLVs
+ * max_count - absolute value is maximum nuber of TLVs. If less than zero
+ * then unknown TLVs are disallowed regardless of disposition
+ * indicated by TLV type
+ * off - offset of first TLV relative to the first byte of the extension
+ * header which is transport header of the skb
+ * len - length of TLV block
+ * unknown_opt - function called when unknown option is encountered
+ */
static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
- struct sk_buff *skb,
- int max_count)
+ struct sk_buff *skb, int max_count, int off, int len,
+ bool (*unknown_opt)(struct sk_buff *skb, int optoff,
+ bool disallow_unknowns))
{
- int len = (skb_transport_header(skb)[1] + 1) << 3;
const unsigned char *nh = skb_network_header(skb);
- int off = skb_network_header_len(skb);
const struct tlvtype_proc *curr;
bool disallow_unknowns = false;
int tlv_count = 0;
@@ -131,11 +142,11 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
max_count = -max_count;
}
- if (skb_transport_offset(skb) + len > skb_headlen(skb))
+ if (skb_transport_offset(skb) + off + len > skb_headlen(skb))
goto bad;
- off += 2;
- len -= 2;
+ /* Offset relative to network header for parse loop */
+ off += skb_network_header_len(skb);
while (len > 0) {
int optlen = nh[off + 1] + 2;
@@ -187,7 +198,7 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
}
}
if (curr->type < 0 &&
- !ip6_tlvopt_unknown(skb, off, disallow_unknowns))
+ !unknown_opt(skb, off, disallow_unknowns))
return false;
padlen = 0;
@@ -309,7 +320,8 @@ static int ipv6_destopt_rcv(struct sk_buff *skb)
#endif
if (ip6_parse_tlv(tlvprocdestopt_lst, skb,
- init_net.ipv6.sysctl.max_dst_opts_cnt)) {
+ init_net.ipv6.sysctl.max_dst_opts_cnt,
+ 2, extlen - 2, ip6_tlvopt_unknown)) {
skb->transport_header += extlen;
opt = IP6CB(skb);
#if IS_ENABLED(CONFIG_IPV6_MIP6)
@@ -848,7 +860,8 @@ int ipv6_parse_hopopts(struct sk_buff *skb)
opt->flags |= IP6SKB_HOPBYHOP;
if (ip6_parse_tlv(tlvprochopopt_lst, skb,
- init_net.ipv6.sysctl.max_hbh_opts_cnt)) {
+ init_net.ipv6.sysctl.max_hbh_opts_cnt,
+ 2, extlen - 2, ip6_tlvopt_unknown)) {
skb->transport_header += extlen;
opt = IP6CB(skb);
opt->nhoff = sizeof(struct ipv6hdr);
--
2.7.4
Powered by blists - more mailing lists