patch-2.1.100 linux/net/ipv6/exthdrs.c

Next file: linux/net/ipv6/icmp.c
Previous file: linux/net/ipv6/af_inet6.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.99/linux/net/ipv6/exthdrs.c linux/net/ipv6/exthdrs.c
@@ -4,8 +4,9 @@
  *
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>
+ *	Andi Kleen		<ak@muc.de>
  *
- *	$Id: exthdrs.c,v 1.5 1998/02/12 07:43:39 davem Exp $
+ *	$Id: exthdrs.c,v 1.6 1998/04/30 16:24:20 freitag Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -34,6 +35,10 @@
 #include <net/ip6_route.h>
 #include <net/addrconf.h>
 
+#include <asm/uaccess.h>
+
+#define swap(a,b) do { typeof (a) tmp; tmp = (a); (a) = (b); (b) = (tmp); } while(0)
+
 /*
  *	inbound
  */
@@ -135,7 +140,7 @@
  */
 
 int ipv6opt_bld_rthdr(struct sk_buff *skb, struct ipv6_options *opt,
-		      struct in6_addr *addr, int proto)		      
+		      struct in6_addr *addr)		      
 {
 	struct rt0_hdr *phdr, *ihdr;
 	int hops;
@@ -153,8 +158,76 @@
 
 	ipv6_addr_copy(phdr->addr + (hops - 1), addr);
 	
-	phdr->rt_hdr.nexthdr = proto;
-
+	phdr->rt_hdr.nexthdr = proto; 
 	return NEXTHDR_ROUTING;
 }
 #endif
+
+/* 
+ * find out if nexthdr is an extension header or a protocol
+ */
+
+static __inline__ int ipv6_ext_hdr(u8 nexthdr)
+{
+	/* 
+	 * find out if nexthdr is an extension header or a protocol
+	 */
+	return ( (nexthdr == NEXTHDR_HOP)	||
+		 (nexthdr == NEXTHDR_ROUTING)	||
+		 (nexthdr == NEXTHDR_FRAGMENT)	||
+		 (nexthdr == NEXTHDR_ESP)	||
+		 (nexthdr == NEXTHDR_AUTH)	||
+		 (nexthdr == NEXTHDR_NONE)	||
+		 (nexthdr == NEXTHDR_DEST) );
+		 
+}
+
+/*
+ * Skip any extension headers. This is used by the ICMP module.
+ *
+ * Note that strictly speaking this conflicts with RFC1883 4.0:
+ * ...The contents and semantics of each extension header determine whether 
+ * or not to proceed to the next header.  Therefore, extension headers must
+ * be processed strictly in the order they appear in the packet; a
+ * receiver must not, for example, scan through a packet looking for a
+ * particular kind of extension header and process that header prior to
+ * processing all preceding ones.
+ * 
+ * We do exactly this. This is a protocol bug. We can't decide after a
+ * seeing an unknown discard-with-error flavour TLV option if it's a 
+ * ICMP error message or not (errors should never be send in reply to
+ * ICMP error messages).
+ * 
+ * But I see no other way to do this. This might need to be reexamined
+ * when Linux implements ESP (and maybe AUTH) headers.
+ */
+struct ipv6_opt_hdr *ipv6_skip_exthdr(struct ipv6_opt_hdr *hdr, 
+				      u8 *nexthdrp, int len)
+{
+	u8 nexthdr = *nexthdrp;
+
+	while (ipv6_ext_hdr(nexthdr)) {
+		int hdrlen; 
+		
+		if (nexthdr == NEXTHDR_NONE)
+			return NULL;
+		if (len < sizeof(struct ipv6_opt_hdr)) /* be anal today */
+			return NULL;
+
+		hdrlen = ipv6_optlen(hdr); 
+		if (len < hdrlen)
+			return NULL; 
+
+		nexthdr = hdr->nexthdr;
+		hdr = (struct ipv6_opt_hdr *) ((u8*)hdr + hdrlen);
+		len -= hdrlen;
+	}
+
+	/* Hack.. Do the same for AUTH headers? */
+	if (nexthdr == NEXTHDR_ESP) 
+		return NULL; 
+
+	*nexthdrp = nexthdr;
+	return hdr;
+}
+

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov