[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

(usagi-users 00922) ISATAP implementation...



To the USAGI core members,

My name is Fred Templin, author of the current ISATAP IETF NGTRANS
draft found at:

  http://www.ietf.org/internet-drafts/draft-ietf-ngtrans-isatap-01.txt

As stated in the document abstract:

 "This document specifies an intra-site automatic tunneling protocol
  (ISATAP) for connecting IPv6 hosts and routers (nodes) within
  predominantly IPv4-based networks. This method is based on an IPv6
  aggregatable global unicast address format (described herein) that
  embeds the IPv4 address of a node within the EUI-64 format interface
  identifier."

Attached to this message, please find diff's relative to the current
USAGI CVS tree that implement the ISATAP functionality as extensions
to the existing IPv6-in-IPv4 tunnel driver found in:
 
./kernel/linux24/net/ipv6/sit.c

Some features of the new code include:

 - testing at two independent sites has verified basic functionality
 - can be selected as an "experimental" feature under network configuration
 - works with both the "legacy" 'sit.c' tunnel driver and with the 'ipip.c'
   driver when the 'CONFIG_NET_IPIP_IPV6' option is chosen.
 - fixes bugs in the existing 'sit.c' driver (was calling 'read_lock()'
   instead of 'read_unlock()' at the *end* of a routine
 - provides user-level support code in 'src/iproute2/ip/iptunnel.c' and
   'src/net-tools/iptunnel.c'

At this time, I would like to request that the diff's be folded into the
USAGI CVS repository. Can one of the core members please advise on how
to proceed?

Regards,

Fred Templin
templin@xxxxxxxxxxx
Index: kernel/linux24/include/linux/if_tunnel.h
===================================================================
RCS file: /cvsroot/usagi/usagi/kernel/linux24/include/linux/if_tunnel.h,v
retrieving revision 1.1.1.1
diff -r1.1.1.1 if_tunnel.h
22,25c22,33
< 	__u16			i_flags;
< 	__u16			o_flags;
< 	__u32			i_key;
< 	__u32			o_key;
---
> 	union {
> 		struct {
> 			__u16	i_flags;
> 			__u16	o_flags;
> 			__u32	i_key;
> 			__u32	o_key;
> 		} gre_un;
> 		struct {
> 			__u16	sit_mode;
> 			__u32	sit_v4any;
> 		} sit_un;
> 	} u;
27a36,47
> #define i_flags		u.gre_un.i_flags
> #define o_flags		u.gre_un.o_flags
> #define i_key		u.gre_un.i_key
> #define o_key		u.gre_un.o_key
> 
> #define	sit_mode	u.sit_un.sit_mode
> #define	sit_v4any	u.sit_un.sit_v4any
> 
> #define	SITMODE_GENERIC	0
> #define	SITMODE_6TO4	1
> #define	SITMODE_ISATAP	2
> #define	SITMODE_MAX	2
Index: kernel/linux24/include/net/addrconf.h
===================================================================
RCS file: /cvsroot/usagi/usagi/kernel/linux24/include/net/addrconf.h,v
retrieving revision 1.21
diff -r1.21 addrconf.h
311a312,320
> #ifdef CONFIG_IPV6_ISATAP
> static inline int ipv6_addr_is_ll_all_rtrs(struct in6_addr *addr)
> {
> 	return (addr->s6_addr32[0] == __constant_htonl(0xff020000) &&
> 		addr->s6_addr32[1] == 0 &&
> 		addr->s6_addr32[2] == 0 &&
> 		addr->s6_addr32[3] == __constant_htonl(0x00000002));
> }
> #endif
Index: kernel/linux24/net/ipv4/ipip.c
===================================================================
RCS file: /cvsroot/usagi/usagi/kernel/linux24/net/ipv4/ipip.c,v
retrieving revision 1.16
diff -r1.16 ipip.c
114a115,118
> #ifdef CONFIG_NET_IPIP_IPV6
> #include <net/ipv6.h>
> #include <net/addrconf.h>
> #endif
589a594,643
> #ifdef CONFIG_IPV6_ISATAP
> 		/*
> 		 * Intra-Site Automatic Tunnel Addressing Protocol (ISATAP)
> 		 * (draft-ietf-ngtrans-isatap-01.txt). Connects IPv6 hosts
> 		 * and routers within predominantly IPv4-based networks.
> 		 *
> 		 * Fred Templin  <templin@xxxxxxxxxxx>
> 		 * Nathan Lutchansky <lutchann@xxxxxxxxxx>
> 		 */
> 		if (tunnel->parms.sit_mode == SITMODE_ISATAP) {
> 		    int v6type = ipv6_addr_type(&iph6->daddr);
> 
> 		    /*
> 		     * Unicast. Assume source address selection already 
> 		     * performed by ipv6_get_saddr(). If v6dst on-link with 
> 		     * v6src (matches to /96), tunnel to V4ADDR encapsulated 
> 		     * in v6dst. Else, check if v6dst on-link with nexthop. 
> 		     * Else, tx_error. Accepts link/site-local or global
> 		     * unicast; excludes all others.
> 		     */
> 		    if (v6type & IPV6_ADDR_UNICAST) {
> 
> 			if (iph6->daddr.s6_addr32[2] == __constant_htonl(0x5efe)) {
> 			    dst = iph6->daddr.s6_addr32[3];
> 			} else {
> 			    struct in6_addr *nexthop;
> 			    struct neighbour *neigh;
> 
> 			    if ((v6type == IPV6_ADDR_UNICAST) &&
> 				skb->dst && (neigh = skb->dst->neighbour)) {
> 				nexthop = (struct in6_addr*)&neigh->primary_key;
> 				if (nexthop->s6_addr32[2] == __constant_htonl(0x5efe))
> 				    dst = nexthop->s6_addr32[3];
> 			    }
> 			}
> 		    } else {
> 			/*
> 			 * Multicast. If 'All-Rtrs-Multicast', send to v4any. 
> 			 * Else, tx_error. (If we are the ISATAP router or an 
> 			 * ISATAP host with no 'sit_v4any', tx_error.)
> 			 */
> 			if (v6type & IPV6_ADDR_MULTICAST) {
> 			    if (ipv6_addr_is_ll_all_rtrs(&iph6->daddr))
> 				dst = tunnel->parms.sit_v4any;
> 			}
> 		    }
> 		    if (!dst)
> 			goto tx_error;
> 		}
> #endif	/* CONFIG_IPV6_ISATAP */
842a897,908
> #ifdef CONFIG_NET_IPIP_IPV6
> 				if (p.iph.protocol == IPPROTO_IPV6) {
> #ifdef	CONFIG_IPV6_ISATAP
> 				    /* ISATAP tunnel MUST NOT have daddr */
> 				    if (p.sit_mode == SITMODE_ISATAP) {
> 					if (p.iph.daddr) {err = -EINVAL; break;}
> 					t->parms.sit_v4any = p.sit_v4any;
> 				    }
> 				    t->parms.sit_mode = p.sit_mode;
> #endif
> 				}
> #endif
Index: kernel/linux24/net/ipv6/Config.in
===================================================================
RCS file: /cvsroot/usagi/usagi/kernel/linux24/net/ipv6/Config.in,v
retrieving revision 1.46
diff -r1.46 Config.in
31a32,36
> # --- ISATAP interface ---
> if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
>     bool '    IPv6: ISATAP interface support (EXPERIMENTAL)' CONFIG_IPV6_ISATAP
> fi
> 
Index: kernel/linux24/net/ipv6/addrconf.c
===================================================================
RCS file: /cvsroot/usagi/usagi/kernel/linux24/net/ipv6/addrconf.c,v
retrieving revision 1.109
diff -r1.109 addrconf.c
69a70,72
> #ifdef CONFIG_IPV6_ISATAP
> #include <net/ipip.h>
> #else
70a74
> #endif
1255a1260,1262
> #ifdef CONFIG_IPV6_ISATAP
> 	struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
> #endif
1274a1282,1295
> #ifdef CONFIG_IPV6_ISATAP
> #ifdef CONFIG_NET_IPIP_IPV6
> 	case ARPHRD_TUNNEL:
> #else
> 	case ARPHRD_SIT:
> #endif
> 		/* EUI64 autoconfiguration support for ISATAP */
> 		if (tunnel->parms.sit_mode == SITMODE_ISATAP) {
> 			if( dev->addr_len != 4) return -1;
> 			eui[0] = eui[1] = 0; eui[2] = 0x5E; eui[3] = 0xFE;
> 			memcpy( eui + 4, dev->dev_addr, 4 );
> 			return 0;
> 		}
> #endif
2006a2028,2034
> #ifdef CONFIG_IPV6_ISATAP
> #ifdef CONFIG_NET_IPIP_IPV6
> 	case ARPHRD_TUNNEL:
> #else
> 	case ARPHRD_SIT:
> #endif
> #endif
2027a2056,2057
> #ifdef CONFIG_IPV6_ISATAP
> 	struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
2028a2059,2062
> 	/* ISATAP is configured like a normal device */
> 	if (tunnel->parms.sit_mode == SITMODE_ISATAP)
> 		return (addrconf_dev_config(dev));
> #endif
Index: kernel/linux24/net/ipv6/sit.c
===================================================================
RCS file: /cvsroot/usagi/usagi/kernel/linux24/net/ipv6/sit.c,v
retrieving revision 1.12
diff -r1.12 sit.c
412a413,449
> #ifdef CONFIG_IPV6_ISATAP
> 		/*
> 		 * Intra-Site Automatic Tunnel Addressing Protocol (ISATAP)
> 		 * (draft-ietf-ngtrans-isatap-01.txt). Connects IPv6 hosts
> 		 * and routers within predominantly IPv4-based networks.
> 		 *
>  		 * Fred Templin  <templin@xxxxxxxxxxx>
>  		 * Nathan Lutchansky <lutchann@xxxxxxxxxx>
> 		 */
> 		if (tunnel->parms.sit_mode == SITMODE_ISATAP) {
> 		    struct ipv6hdr *iph6 = skb->nh.ipv6h;
> 		    int v6type = ipv6_addr_type(&iph6->saddr);
> 
> 		    /*
> 		     * v6src MUST be link/site-local or global UNICAST. If
> 		     * v4any is set (client-side only) and v4src != v4any,
> 		     * v6src MUST be on-link with v6dst and v6src MUST
> 		     * encapsulate a V4ADDR identical to v4src.
> 		     */
> 		    v6type &= ~(IPV6_ADDR_LINKLOCAL|IPV6_ADDR_SITELOCAL);
> 		    if (tunnel->parms.sit_v4any &&
> 			iph->saddr != tunnel->parms.sit_v4any &&
> 			    (v6type != IPV6_ADDR_UNICAST ||
> 			     memcmp(&iph6->saddr, &iph6->daddr, 12) ||
> 			     iph6->saddr.s6_addr32[3] != iph->saddr)) {
> 
> 				tunnel->stat.rx_dropped++;
> 				kfree_skb(skb);
> #ifdef CONFIG_NET_IPIP_IPV6
> 				read_unlock(&ipip_lock);
> #else
> 				read_unlock(&ipip6_lock);
> #endif
> 				return 0;
> 		    }
> 		}
> #endif /* CONFIG_IPV6_ISATAP */
431c468
< 		read_lock(&ipip_lock);
---
> 		read_unlock(&ipip_lock);
441c478
< 	read_lock(&ipip_lock);
---
> 	read_unlock(&ipip_lock);
499a537,583
> #ifdef CONFIG_IPV6_ISATAP
> 	if (tunnel->parms.sit_mode == SITMODE_ISATAP) {
> 	    int v6type = ipv6_addr_type(&iph6->daddr);
> 
> 	    /*
> 	     * Unicast. Assume source address selection already
> 	     * performed by ipv6_get_saddr(). If v6dst on-link with
> 	     * v6src (matches to /96), tunnel to V4ADDR encapsulated
> 	     * in v6dst. Else, check if v6dst on-link with nexthop.
> 	     * Else, tx_error. Accepts link/site-local or global
> 	     * unicast; excludes all others.
> 	     */
> 	    if (v6type & IPV6_ADDR_UNICAST) {
> 
> 		/* 
> 		 * XXX - we don't check the entire /96 prefix
> 		 * here, because we assume that ip6_route_output()
> 		 * has done the right thing.
> 		 */
> 		if (iph6->daddr.s6_addr32[2] == __constant_htonl(0x5efe)) {
> 		    dst = iph6->daddr.s6_addr32[3];
> 		} else {
> 		    struct in6_addr *nexthop;
> 		    struct neighbour *neigh;
> 
> 		    if ((v6type == IPV6_ADDR_UNICAST) &&
> 		        skb->dst && (neigh = skb->dst->neighbour)) {
> 			nexthop = (struct in6_addr*)&neigh->primary_key;
> 			if (nexthop->s6_addr32[2] == __constant_htonl(0x5efe))
> 			    dst = nexthop->s6_addr32[3];
> 		    }
> 		}
> 	    } else {
> 		/*
> 		 * Multicast. If 'All-Rtrs-Multicast', send to v4any.
> 		 * Else, tx_error. (If we are the ISATAP router or an
> 		 * ISATAP host with no 'sit_v4any', tx_error.)
> 		 */
> 		if (v6type & IPV6_ADDR_MULTICAST) {
> 		    if (ipv6_addr_is_ll_all_rtrs(&iph6->daddr))
> 			dst = tunnel->parms.sit_v4any;
> 		}
> 	    }
> 	    if (!dst)
> 		goto tx_error;
> 	}
> #endif	/* CONFIG_IPV6_ISATAP */
706a791,798
> #ifdef	CONFIG_IPV6_ISATAP
> 				/* ISATAP tunnel MUST NOT have daddr */
> 				if (p.sit_mode == SITMODE_ISATAP) {
> 				    if (p.iph.daddr) {err = -EINVAL; break;}
> 				    t->parms.sit_v4any = p.sit_v4any;
> 				}
> 				t->parms.sit_mode = p.sit_mode;
> #endif /* CONFIG_IPV6_ISATAP */
Index: src/iproute2/ip/iptunnel.c
===================================================================
RCS file: /cvsroot/usagi/usagi/src/iproute2/ip/iptunnel.c,v
retrieving revision 1.2
diff -r1.2 iptunnel.c
41a42,46
> #define	ISATAP
> #ifdef	ISATAP
> 	fprintf(stderr, "          [ mode { ipip | gre | sit | isatap } ]\n");
> 	fprintf(stderr, "          [ remote ADDR ] [ local ADDR ] [ v4any ADDR ]\n");
> #else
42a48
> #endif
136a143,149
> #ifdef	ISATAP
> 	if (err && cmd == SIOCADDTUNNEL &&
> 	    strcmp(ifr.ifr_name, "sit0") == 0) {
> 		strcpy(ifr.ifr_name, "tunl0");
> 		err = ioctl(fd, cmd, &ifr);
> 	}
> #endif
166a180,183
> #ifdef	ISATAP
> 	/* XXX - Below may eventually use IANA-assigned default */
> 	__u32 v4any = 0;
> #endif
211a229,239
> #ifdef	ISATAP
> 				p->sit_mode = SITMODE_GENERIC;
> 			} else if (strcmp(*argv, "isatap") == 0) {
> 				if ((p->iph.protocol && p->iph.protocol != IPPROTO_IPV6) || mode[0]) {
> 					fprintf(stderr,"You managed to ask for more than one tunnel mode.\n");
> 					exit(-1);
> 				}
> 				mode = "isatap";
> 				p->iph.protocol = IPPROTO_IPV6;
> 				p->sit_mode = SITMODE_ISATAP;
> #endif
212a241
> 
281a311,316
> #ifdef	ISATAP
> 		} else if (strcmp(*argv, "v4any") == 0) {
> 			NEXT_ARG();
> 			if (strcmp(*argv, "any"))
> 				v4any = get_addr32(*argv);
> #endif
363a399,407
> #ifdef	ISATAP
> 	if (p->iph.protocol == IPPROTO_IPV6 && p->sit_mode == SITMODE_ISATAP) {
> 		if (p->iph.daddr) {
> 			fprintf(stderr, "No dst address with ISATAP tunnel\n");
> 			return NULL;
> 		}
> 		p->sit_v4any = v4any;
> 	}
> #endif
Index: src/net-tools/iptunnel.c
===================================================================
RCS file: /cvsroot/usagi/usagi/src/net-tools/iptunnel.c,v
retrieving revision 1.2
diff -r1.2 iptunnel.c
85a86,90
> #define	ISATAP
> #ifdef	ISATAP
> 	fprintf(stderr, _("          [ mode { ipip | gre | sit | isatap } ]\n"));
> 	fprintf(stderr, _("          [ remote ADDR ] [ local ADDR ] [ v4any ADDR ]\n"));
> #else
86a92
> #endif
177a184,190
> #ifdef  ISATAP
> 	if (err && cmd == SIOCADDTUNNEL &&
> 	    strcmp(ifr.ifr_name, "sit0") == 0) {
> 		strcpy(ifr.ifr_name, "tunl0");
> 		err = ioctl(fd, cmd, &ifr);
> 	}
> #endif
203a217,219
> #ifdef	ISATAP
> 	__u32 v4any = 0;
> #endif
239a256,265
> #ifdef	ISATAP
> 				p->sit_mode = SITMODE_GENERIC;
> 			} else if (strcmp(*argv, "isatap") == 0) {
>                                 if (p->iph.protocol || mode[0])
> 					usage();
> 
> 				mode = "isatap";
> 				p->iph.protocol = IPPROTO_IPV6;
> 				p->sit_mode = SITMODE_ISATAP;
> #endif
299a326,331
> #ifdef	ISATAP
> 		} else if (strcmp(*argv, "v4any") == 0) {
> 			NEXT_ARG();
> 			if (strcmp(*argv, "any"))
> 				v4any = get_addr32(*argv);
> #endif
368a401,409
> #ifdef	ISATAP
> 	if (p->iph.protocol == IPPROTO_IPV6 && p->sit_mode == SITMODE_ISATAP) {
> 		if (p->iph.daddr) {
> 			fprintf(stderr, "No dst address with ISATAP tunnel\n");
> 			return NULL;
> 		}
> 		p->sit_v4any = v4any;
> 	}
> #endif