[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
(usagi-users 00922) ISATAP implementation...
- To: usagi-users@xxxxxxxxxxxxxx
- Subject: (usagi-users 00922) ISATAP implementation...
- From: "Fred L. Templin" <templin@xxxxxxxxxxx>
- Date: Thu, 25 Oct 2001 17:16:23 -0700
- Cc: templin@xxxxxxxxxxx, lutchann@xxxxxxxxxx, sastry@xxxxxxxxxxx, jpm@xxxxxxxxxxx
- References: <200110240901.RAA00835@cwcsun41.cwc.nus.edu.sg>
- Reply-to: usagi-users@xxxxxxxxxxxxxx
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