diff mbox series

[RFC,v2,3/5] ipv6: Paramterize TLV parsing

Message ID 1559933708-13947-4-git-send-email-tom@quantonium.net
State RFC
Delegated to: David Miller
Headers show
Series seg6: Segment routing fixes | expand

Commit Message

Tom Herbert June 7, 2019, 6:55 p.m. UTC
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@quantonium.net>
---
 net/ipv6/exthdrs.c | 35 ++++++++++++++++++++++++-----------
 1 file changed, 24 insertions(+), 11 deletions(-)

Comments

David Lebrun June 8, 2019, 10:15 a.m. UTC | #1
On 07/06/2019 19:55, Tom Herbert wrote:
> +			  bool (*unknown_opt)(struct sk_buff *skb, int optoff,
> +					      bool disallow_unknowns))

What about changing this boolean argument to 'allow_unknowns' (here, in 
ip6_tlvopt_unknown() and ip6_parse_tlv()) to avoid using negative names ?
diff mbox series

Patch

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);