diff options
author | Fred L. Templin <fred.l.templin@boeing.com> | 2007-11-29 06:11:40 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:55:09 -0500 |
commit | c7dc89c0ac8e7c3796bff91becf58ccdbcaf9f18 (patch) | |
tree | e876ccadf29a90b7a211522aeccfd42255dab586 /net | |
parent | df97c708d5e6eebdd9ded1fa588eae09acf53793 (diff) |
[IPV6]: Add RFC4214 support
This patch includes support for the Intra-Site Automatic Tunnel
Addressing Protocol (ISATAP) per RFC4214. It uses the SIT
module, and is configured using extensions to the "iproute2"
utility. The diffs are specific to the Linux 2.6.24-rc2 kernel
distribution.
This version includes the diff for ./include/linux/if.h which was
missing in the v2.4 submission and is needed to make the
patch compile. The patch has been installed, compiled and
tested in a clean 2.6.24-rc2 kernel build area.
Signed-off-by: Fred L. Templin <fred.l.templin@boeing.com>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/addrconf.c | 22 | ||||
-rw-r--r-- | net/ipv6/route.c | 2 | ||||
-rw-r--r-- | net/ipv6/sit.c | 77 |
3 files changed, 100 insertions, 1 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 6c8b193474ba..f177424c186f 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -377,6 +377,13 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
377 | "%s: Disabled Privacy Extensions\n", | 377 | "%s: Disabled Privacy Extensions\n", |
378 | dev->name); | 378 | dev->name); |
379 | ndev->cnf.use_tempaddr = -1; | 379 | ndev->cnf.use_tempaddr = -1; |
380 | |||
381 | if (dev->type == ARPHRD_SIT && (dev->priv_flags & IFF_ISATAP)) { | ||
382 | printk(KERN_INFO | ||
383 | "%s: Disabled Multicast RS\n", | ||
384 | dev->name); | ||
385 | ndev->cnf.rtr_solicits = 0; | ||
386 | } | ||
380 | } else { | 387 | } else { |
381 | in6_dev_hold(ndev); | 388 | in6_dev_hold(ndev); |
382 | ipv6_regen_rndid((unsigned long) ndev); | 389 | ipv6_regen_rndid((unsigned long) ndev); |
@@ -1409,6 +1416,9 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) | |||
1409 | return addrconf_ifid_arcnet(eui, dev); | 1416 | return addrconf_ifid_arcnet(eui, dev); |
1410 | case ARPHRD_INFINIBAND: | 1417 | case ARPHRD_INFINIBAND: |
1411 | return addrconf_ifid_infiniband(eui, dev); | 1418 | return addrconf_ifid_infiniband(eui, dev); |
1419 | case ARPHRD_SIT: | ||
1420 | if (dev->priv_flags & IFF_ISATAP) | ||
1421 | return ipv6_isatap_eui64(eui, *(__be32 *)dev->dev_addr); | ||
1412 | } | 1422 | } |
1413 | return -1; | 1423 | return -1; |
1414 | } | 1424 | } |
@@ -1444,7 +1454,7 @@ regen: | |||
1444 | * | 1454 | * |
1445 | * - Reserved subnet anycast (RFC 2526) | 1455 | * - Reserved subnet anycast (RFC 2526) |
1446 | * 11111101 11....11 1xxxxxxx | 1456 | * 11111101 11....11 1xxxxxxx |
1447 | * - ISATAP (draft-ietf-ngtrans-isatap-13.txt) 5.1 | 1457 | * - ISATAP (RFC4214) 6.1 |
1448 | * 00-00-5E-FE-xx-xx-xx-xx | 1458 | * 00-00-5E-FE-xx-xx-xx-xx |
1449 | * - value 0 | 1459 | * - value 0 |
1450 | * - XXX: already assigned to an address on the device | 1460 | * - XXX: already assigned to an address on the device |
@@ -2175,6 +2185,16 @@ static void addrconf_sit_config(struct net_device *dev) | |||
2175 | return; | 2185 | return; |
2176 | } | 2186 | } |
2177 | 2187 | ||
2188 | if (dev->priv_flags & IFF_ISATAP) { | ||
2189 | struct in6_addr addr; | ||
2190 | |||
2191 | ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); | ||
2192 | addrconf_prefix_route(&addr, 64, dev, 0, 0); | ||
2193 | if (!ipv6_generate_eui64(addr.s6_addr + 8, dev)) | ||
2194 | addrconf_add_linklocal(idev, &addr); | ||
2195 | return; | ||
2196 | } | ||
2197 | |||
2178 | sit_add_v4_addrs(idev); | 2198 | sit_add_v4_addrs(idev); |
2179 | 2199 | ||
2180 | if (dev->flags&IFF_POINTOPOINT) { | 2200 | if (dev->flags&IFF_POINTOPOINT) { |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index d7ec4c9ffc4b..e2c980dbe52d 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -1659,6 +1659,8 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d | |||
1659 | return rt; | 1659 | return rt; |
1660 | } | 1660 | } |
1661 | 1661 | ||
1662 | EXPORT_SYMBOL(rt6_get_dflt_router); | ||
1663 | |||
1662 | struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, | 1664 | struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, |
1663 | struct net_device *dev, | 1665 | struct net_device *dev, |
1664 | unsigned int pref) | 1666 | unsigned int pref) |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 71433d29d884..b3b8513e9cb7 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * Changes: | 16 | * Changes: |
17 | * Roger Venning <r.venning@telstra.com>: 6to4 support | 17 | * Roger Venning <r.venning@telstra.com>: 6to4 support |
18 | * Nate Thompson <nate@thebog.net>: 6to4 support | 18 | * Nate Thompson <nate@thebog.net>: 6to4 support |
19 | * Fred L. Templin <fltemplin@acm.org>: isatap support | ||
19 | */ | 20 | */ |
20 | 21 | ||
21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
@@ -182,6 +183,9 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int | |||
182 | dev->init = ipip6_tunnel_init; | 183 | dev->init = ipip6_tunnel_init; |
183 | nt->parms = *parms; | 184 | nt->parms = *parms; |
184 | 185 | ||
186 | if (parms->i_flags & SIT_ISATAP) | ||
187 | dev->priv_flags |= IFF_ISATAP; | ||
188 | |||
185 | if (register_netdevice(dev) < 0) { | 189 | if (register_netdevice(dev) < 0) { |
186 | free_netdev(dev); | 190 | free_netdev(dev); |
187 | goto failed; | 191 | goto failed; |
@@ -364,6 +368,48 @@ static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) | |||
364 | IP6_ECN_set_ce(ipv6_hdr(skb)); | 368 | IP6_ECN_set_ce(ipv6_hdr(skb)); |
365 | } | 369 | } |
366 | 370 | ||
371 | /* ISATAP (RFC4214) - check source address */ | ||
372 | static int | ||
373 | isatap_srcok(struct sk_buff *skb, struct iphdr *iph, struct net_device *dev) | ||
374 | { | ||
375 | struct neighbour *neigh; | ||
376 | struct dst_entry *dst; | ||
377 | struct rt6_info *rt; | ||
378 | struct flowi fl; | ||
379 | struct in6_addr *addr6; | ||
380 | struct in6_addr rtr; | ||
381 | struct ipv6hdr *iph6; | ||
382 | int ok = 0; | ||
383 | |||
384 | /* from onlink default router */ | ||
385 | ipv6_addr_set(&rtr, htonl(0xFE800000), 0, 0, 0); | ||
386 | ipv6_isatap_eui64(rtr.s6_addr + 8, iph->saddr); | ||
387 | if ((rt = rt6_get_dflt_router(&rtr, dev))) { | ||
388 | dst_release(&rt->u.dst); | ||
389 | return 1; | ||
390 | } | ||
391 | |||
392 | iph6 = ipv6_hdr(skb); | ||
393 | memset(&fl, 0, sizeof(fl)); | ||
394 | fl.proto = iph6->nexthdr; | ||
395 | ipv6_addr_copy(&fl.fl6_dst, &iph6->saddr); | ||
396 | fl.oif = dev->ifindex; | ||
397 | security_skb_classify_flow(skb, &fl); | ||
398 | |||
399 | dst = ip6_route_output(NULL, &fl); | ||
400 | if (!dst->error && (dst->dev == dev) && (neigh = dst->neighbour)) { | ||
401 | |||
402 | addr6 = (struct in6_addr*)&neigh->primary_key; | ||
403 | |||
404 | /* from correct previous hop */ | ||
405 | if (ipv6_addr_is_isatap(addr6) && | ||
406 | (addr6->s6_addr32[3] == iph->saddr)) | ||
407 | ok = 1; | ||
408 | } | ||
409 | dst_release(dst); | ||
410 | return ok; | ||
411 | } | ||
412 | |||
367 | static int ipip6_rcv(struct sk_buff *skb) | 413 | static int ipip6_rcv(struct sk_buff *skb) |
368 | { | 414 | { |
369 | struct iphdr *iph; | 415 | struct iphdr *iph; |
@@ -382,6 +428,14 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
382 | IPCB(skb)->flags = 0; | 428 | IPCB(skb)->flags = 0; |
383 | skb->protocol = htons(ETH_P_IPV6); | 429 | skb->protocol = htons(ETH_P_IPV6); |
384 | skb->pkt_type = PACKET_HOST; | 430 | skb->pkt_type = PACKET_HOST; |
431 | |||
432 | if ((tunnel->dev->priv_flags & IFF_ISATAP) && | ||
433 | !isatap_srcok(skb, iph, tunnel->dev)) { | ||
434 | tunnel->stat.rx_errors++; | ||
435 | read_unlock(&ipip6_lock); | ||
436 | kfree_skb(skb); | ||
437 | return 0; | ||
438 | } | ||
385 | tunnel->stat.rx_packets++; | 439 | tunnel->stat.rx_packets++; |
386 | tunnel->stat.rx_bytes += skb->len; | 440 | tunnel->stat.rx_bytes += skb->len; |
387 | skb->dev = tunnel->dev; | 441 | skb->dev = tunnel->dev; |
@@ -444,6 +498,29 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
444 | if (skb->protocol != htons(ETH_P_IPV6)) | 498 | if (skb->protocol != htons(ETH_P_IPV6)) |
445 | goto tx_error; | 499 | goto tx_error; |
446 | 500 | ||
501 | /* ISATAP (RFC4214) - must come before 6to4 */ | ||
502 | if (dev->priv_flags & IFF_ISATAP) { | ||
503 | struct neighbour *neigh = NULL; | ||
504 | |||
505 | if (skb->dst) | ||
506 | neigh = skb->dst->neighbour; | ||
507 | |||
508 | if (neigh == NULL) { | ||
509 | if (net_ratelimit()) | ||
510 | printk(KERN_DEBUG "sit: nexthop == NULL\n"); | ||
511 | goto tx_error; | ||
512 | } | ||
513 | |||
514 | addr6 = (struct in6_addr*)&neigh->primary_key; | ||
515 | addr_type = ipv6_addr_type(addr6); | ||
516 | |||
517 | if ((addr_type & IPV6_ADDR_UNICAST) && | ||
518 | ipv6_addr_is_isatap(addr6)) | ||
519 | dst = addr6->s6_addr32[3]; | ||
520 | else | ||
521 | goto tx_error; | ||
522 | } | ||
523 | |||
447 | if (!dst) | 524 | if (!dst) |
448 | dst = try_6to4(&iph6->daddr); | 525 | dst = try_6to4(&iph6->daddr); |
449 | 526 | ||