linux-old/net/ipv6/sit.c
<<
>>
Prefs
   1/*
   2 *      IPv6 over IPv4 tunnel device - Simple Internet Transition (SIT)
   3 *      Linux INET6 implementation
   4 *
   5 *      Authors:
   6 *      Pedro Roque             <pedro_m@yahoo.com>     
   7 *      Alexey Kuznetsov        <kuznet@ms2.inr.ac.ru>
   8 *
   9 *      $Id: sit.c,v 1.53 2001/09/25 05:09:53 davem Exp $
  10 *
  11 *      This program is free software; you can redistribute it and/or
  12 *      modify it under the terms of the GNU General Public License
  13 *      as published by the Free Software Foundation; either version
  14 *      2 of the License, or (at your option) any later version.
  15 *
  16 *      Changes:
  17 * Roger Venning <r.venning@telstra.com>:       6to4 support
  18 * Nate Thompson <nate@thebog.net>:             6to4 support
  19 */
  20
  21#include <linux/config.h>
  22#include <linux/module.h>
  23#include <linux/errno.h>
  24#include <linux/types.h>
  25#include <linux/socket.h>
  26#include <linux/sockios.h>
  27#include <linux/sched.h>
  28#include <linux/net.h>
  29#include <linux/in6.h>
  30#include <linux/netdevice.h>
  31#include <linux/if_arp.h>
  32#include <linux/icmp.h>
  33#include <asm/uaccess.h>
  34#include <linux/init.h>
  35#include <linux/netfilter_ipv4.h>
  36
  37#include <net/sock.h>
  38#include <net/snmp.h>
  39
  40#include <net/ipv6.h>
  41#include <net/protocol.h>
  42#include <net/transp_v6.h>
  43#include <net/ip6_fib.h>
  44#include <net/ip6_route.h>
  45#include <net/ndisc.h>
  46#include <net/addrconf.h>
  47#include <net/ip.h>
  48#include <net/udp.h>
  49#include <net/icmp.h>
  50#include <net/ipip.h>
  51#include <net/inet_ecn.h>
  52
  53/*
  54   This version of net/ipv6/sit.c is cloned of net/ipv4/ip_gre.c
  55
  56   For comments look at net/ipv4/ip_gre.c --ANK
  57 */
  58
  59#define HASH_SIZE  16
  60#define HASH(addr) ((addr^(addr>>4))&0xF)
  61
  62static int ipip6_fb_tunnel_init(struct net_device *dev);
  63static int ipip6_tunnel_init(struct net_device *dev);
  64
  65static struct net_device ipip6_fb_tunnel_dev = {
  66        name:           "sit0", 
  67        init:           ipip6_fb_tunnel_init,
  68};
  69
  70static struct ip_tunnel ipip6_fb_tunnel = {
  71        NULL, &ipip6_fb_tunnel_dev, {0, }, 0, 0, 0, 0, 0, 0, 0, {"sit0", }
  72};
  73
  74static struct ip_tunnel *tunnels_r_l[HASH_SIZE];
  75static struct ip_tunnel *tunnels_r[HASH_SIZE];
  76static struct ip_tunnel *tunnels_l[HASH_SIZE];
  77static struct ip_tunnel *tunnels_wc[1];
  78static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l };
  79
  80static rwlock_t ipip6_lock = RW_LOCK_UNLOCKED;
  81
  82static struct ip_tunnel * ipip6_tunnel_lookup(u32 remote, u32 local)
  83{
  84        unsigned h0 = HASH(remote);
  85        unsigned h1 = HASH(local);
  86        struct ip_tunnel *t;
  87
  88        for (t = tunnels_r_l[h0^h1]; t; t = t->next) {
  89                if (local == t->parms.iph.saddr &&
  90                    remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
  91                        return t;
  92        }
  93        for (t = tunnels_r[h0]; t; t = t->next) {
  94                if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
  95                        return t;
  96        }
  97        for (t = tunnels_l[h1]; t; t = t->next) {
  98                if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP))
  99                        return t;
 100        }
 101        if ((t = tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP))
 102                return t;
 103        return NULL;
 104}
 105
 106static struct ip_tunnel ** ipip6_bucket(struct ip_tunnel *t)
 107{
 108        u32 remote = t->parms.iph.daddr;
 109        u32 local = t->parms.iph.saddr;
 110        unsigned h = 0;
 111        int prio = 0;
 112
 113        if (remote) {
 114                prio |= 2;
 115                h ^= HASH(remote);
 116        }
 117        if (local) {
 118                prio |= 1;
 119                h ^= HASH(local);
 120        }
 121        return &tunnels[prio][h];
 122}
 123
 124static void ipip6_tunnel_unlink(struct ip_tunnel *t)
 125{
 126        struct ip_tunnel **tp;
 127
 128        for (tp = ipip6_bucket(t); *tp; tp = &(*tp)->next) {
 129                if (t == *tp) {
 130                        write_lock_bh(&ipip6_lock);
 131                        *tp = t->next;
 132                        write_unlock_bh(&ipip6_lock);
 133                        break;
 134                }
 135        }
 136}
 137
 138static void ipip6_tunnel_link(struct ip_tunnel *t)
 139{
 140        struct ip_tunnel **tp = ipip6_bucket(t);
 141
 142        write_lock_bh(&ipip6_lock);
 143        t->next = *tp;
 144        write_unlock_bh(&ipip6_lock);
 145        *tp = t;
 146}
 147
 148struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create)
 149{
 150        u32 remote = parms->iph.daddr;
 151        u32 local = parms->iph.saddr;
 152        struct ip_tunnel *t, **tp, *nt;
 153        struct net_device *dev;
 154        unsigned h = 0;
 155        int prio = 0;
 156
 157        if (remote) {
 158                prio |= 2;
 159                h ^= HASH(remote);
 160        }
 161        if (local) {
 162                prio |= 1;
 163                h ^= HASH(local);
 164        }
 165        for (tp = &tunnels[prio][h]; (t = *tp) != NULL; tp = &t->next) {
 166                if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr)
 167                        return t;
 168        }
 169        if (!create)
 170                return NULL;
 171
 172        MOD_INC_USE_COUNT;
 173        dev = kmalloc(sizeof(*dev) + sizeof(*t), GFP_KERNEL);
 174        if (dev == NULL) {
 175                MOD_DEC_USE_COUNT;
 176                return NULL;
 177        }
 178        memset(dev, 0, sizeof(*dev) + sizeof(*t));
 179        dev->priv = (void*)(dev+1);
 180        nt = (struct ip_tunnel*)dev->priv;
 181        nt->dev = dev;
 182        dev->init = ipip6_tunnel_init;
 183        dev->features |= NETIF_F_DYNALLOC;
 184        memcpy(&nt->parms, parms, sizeof(*parms));
 185        nt->parms.name[IFNAMSIZ-1] = '\0';
 186        strcpy(dev->name, nt->parms.name);
 187        if (dev->name[0] == 0) {
 188                int i;
 189                for (i=1; i<100; i++) {
 190                        sprintf(dev->name, "sit%d", i);
 191                        if (__dev_get_by_name(dev->name) == NULL)
 192                                break;
 193                }
 194                if (i==100)
 195                        goto failed;
 196                memcpy(nt->parms.name, dev->name, IFNAMSIZ);
 197        }
 198        if (register_netdevice(dev) < 0)
 199                goto failed;
 200
 201        dev_hold(dev);
 202        ipip6_tunnel_link(nt);
 203        /* Do not decrement MOD_USE_COUNT here. */
 204        return nt;
 205
 206failed:
 207        kfree(dev);
 208        MOD_DEC_USE_COUNT;
 209        return NULL;
 210}
 211
 212static void ipip6_tunnel_destructor(struct net_device *dev)
 213{
 214        if (dev != &ipip6_fb_tunnel_dev) {
 215                MOD_DEC_USE_COUNT;
 216        }
 217}
 218
 219static void ipip6_tunnel_uninit(struct net_device *dev)
 220{
 221        if (dev == &ipip6_fb_tunnel_dev) {
 222                write_lock_bh(&ipip6_lock);
 223                tunnels_wc[0] = NULL;
 224                write_unlock_bh(&ipip6_lock);
 225                dev_put(dev);
 226        } else {
 227                ipip6_tunnel_unlink((struct ip_tunnel*)dev->priv);
 228                dev_put(dev);
 229        }
 230}
 231
 232
 233void ipip6_err(struct sk_buff *skb, u32 info)
 234{
 235#ifndef I_WISH_WORLD_WERE_PERFECT
 236
 237/* It is not :-( All the routers (except for Linux) return only
 238   8 bytes of packet payload. It means, that precise relaying of
 239   ICMP in the real Internet is absolutely infeasible.
 240 */
 241        struct iphdr *iph = (struct iphdr*)skb->data;
 242        int type = skb->h.icmph->type;
 243        int code = skb->h.icmph->code;
 244        struct ip_tunnel *t;
 245
 246        switch (type) {
 247        default:
 248        case ICMP_PARAMETERPROB:
 249                return;
 250
 251        case ICMP_DEST_UNREACH:
 252                switch (code) {
 253                case ICMP_SR_FAILED:
 254                case ICMP_PORT_UNREACH:
 255                        /* Impossible event. */
 256                        return;
 257                case ICMP_FRAG_NEEDED:
 258                        /* Soft state for pmtu is maintained by IP core. */
 259                        return;
 260                default:
 261                        /* All others are translated to HOST_UNREACH.
 262                           rfc2003 contains "deep thoughts" about NET_UNREACH,
 263                           I believe they are just ether pollution. --ANK
 264                         */
 265                        break;
 266                }
 267                break;
 268        case ICMP_TIME_EXCEEDED:
 269                if (code != ICMP_EXC_TTL)
 270                        return;
 271                break;
 272        }
 273
 274        read_lock(&ipip6_lock);
 275        t = ipip6_tunnel_lookup(iph->daddr, iph->saddr);
 276        if (t == NULL || t->parms.iph.daddr == 0)
 277                goto out;
 278        if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
 279                goto out;
 280
 281        if (jiffies - t->err_time < IPTUNNEL_ERR_TIMEO)
 282                t->err_count++;
 283        else
 284                t->err_count = 1;
 285        t->err_time = jiffies;
 286out:
 287        read_unlock(&ipip6_lock);
 288        return;
 289#else
 290        struct iphdr *iph = (struct iphdr*)dp;
 291        int hlen = iph->ihl<<2;
 292        struct ipv6hdr *iph6;
 293        int type = skb->h.icmph->type;
 294        int code = skb->h.icmph->code;
 295        int rel_type = 0;
 296        int rel_code = 0;
 297        int rel_info = 0;
 298        struct sk_buff *skb2;
 299        struct rt6_info *rt6i;
 300
 301        if (len < hlen + sizeof(struct ipv6hdr))
 302                return;
 303        iph6 = (struct ipv6hdr*)(dp + hlen);
 304
 305        switch (type) {
 306        default:
 307                return;
 308        case ICMP_PARAMETERPROB:
 309                if (skb->h.icmph->un.gateway < hlen)
 310                        return;
 311
 312                /* So... This guy found something strange INSIDE encapsulated
 313                   packet. Well, he is fool, but what can we do ?
 314                 */
 315                rel_type = ICMPV6_PARAMPROB;
 316                rel_info = skb->h.icmph->un.gateway - hlen;
 317                break;
 318
 319        case ICMP_DEST_UNREACH:
 320                switch (code) {
 321                case ICMP_SR_FAILED:
 322                case ICMP_PORT_UNREACH:
 323                        /* Impossible event. */
 324                        return;
 325                case ICMP_FRAG_NEEDED:
 326                        /* Too complicated case ... */
 327                        return;
 328                default:
 329                        /* All others are translated to HOST_UNREACH.
 330                           rfc2003 contains "deep thoughts" about NET_UNREACH,
 331                           I believe, it is just ether pollution. --ANK
 332                         */
 333                        rel_type = ICMPV6_DEST_UNREACH;
 334                        rel_code = ICMPV6_ADDR_UNREACH;
 335                        break;
 336                }
 337                break;
 338        case ICMP_TIME_EXCEEDED:
 339                if (code != ICMP_EXC_TTL)
 340                        return;
 341                rel_type = ICMPV6_TIME_EXCEED;
 342                rel_code = ICMPV6_EXC_HOPLIMIT;
 343                break;
 344        }
 345
 346        /* Prepare fake skb to feed it to icmpv6_send */
 347        skb2 = skb_clone(skb, GFP_ATOMIC);
 348        if (skb2 == NULL)
 349                return;
 350        dst_release(skb2->dst);
 351        skb2->dst = NULL;
 352        skb_pull(skb2, skb->data - (u8*)iph6);
 353        skb2->nh.raw = skb2->data;
 354
 355        /* Try to guess incoming interface */
 356        rt6i = rt6_lookup(&iph6->saddr, NULL, NULL, 0);
 357        if (rt6i && rt6i->rt6i_dev) {
 358                skb2->dev = rt6i->rt6i_dev;
 359
 360                rt6i = rt6_lookup(&iph6->daddr, &iph6->saddr, NULL, 0);
 361
 362                if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) {
 363                        struct ip_tunnel * t = (struct ip_tunnel*)rt6i->rt6i_dev->priv;
 364                        if (rel_type == ICMPV6_TIME_EXCEED && t->parms.iph.ttl) {
 365                                rel_type = ICMPV6_DEST_UNREACH;
 366                                rel_code = ICMPV6_ADDR_UNREACH;
 367                        }
 368                        icmpv6_send(skb2, rel_type, rel_code, rel_info, skb2->dev);
 369                }
 370        }
 371        kfree_skb(skb2);
 372        return;
 373#endif
 374}
 375
 376static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
 377{
 378        if (INET_ECN_is_ce(iph->tos) &&
 379            INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h)))
 380                IP6_ECN_set_ce(skb->nh.ipv6h);
 381}
 382
 383int ipip6_rcv(struct sk_buff *skb)
 384{
 385        struct iphdr *iph;
 386        struct ip_tunnel *tunnel;
 387
 388        if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
 389                goto out;
 390
 391        iph = skb->nh.iph;
 392
 393        read_lock(&ipip6_lock);
 394        if ((tunnel = ipip6_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
 395                skb->mac.raw = skb->nh.raw;
 396                skb->nh.raw = skb->data;
 397                memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
 398                skb->protocol = htons(ETH_P_IPV6);
 399                skb->pkt_type = PACKET_HOST;
 400                tunnel->stat.rx_packets++;
 401                tunnel->stat.rx_bytes += skb->len;
 402                skb->dev = tunnel->dev;
 403                dst_release(skb->dst);
 404                skb->dst = NULL;
 405                nf_reset(skb);
 406                ipip6_ecn_decapsulate(iph, skb);
 407                netif_rx(skb);
 408                read_unlock(&ipip6_lock);
 409                return 0;
 410        }
 411
 412        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
 413        kfree_skb(skb);
 414        read_unlock(&ipip6_lock);
 415out:
 416        return 0;
 417}
 418
 419/* Need this wrapper because NF_HOOK takes the function address */
 420static inline int do_ip_send(struct sk_buff *skb)
 421{
 422        return ip_send(skb);
 423}
 424
 425
 426/* Returns the embedded IPv4 address if the IPv6 address
 427   comes from 6to4 (draft-ietf-ngtrans-6to4-04) addr space */
 428
 429static inline u32 try_6to4(struct in6_addr *v6dst)
 430{
 431        u32 dst = 0;
 432
 433        if (v6dst->s6_addr16[0] == htons(0x2002)) {
 434                /* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */
 435                memcpy(&dst, &v6dst->s6_addr16[1], 4);
 436        }
 437        return dst;
 438}
 439
 440/*
 441 *      This function assumes it is being called from dev_queue_xmit()
 442 *      and that skb is filled properly by that function.
 443 */
 444
 445static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 446{
 447        struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
 448        struct net_device_stats *stats = &tunnel->stat;
 449        struct iphdr  *tiph = &tunnel->parms.iph;
 450        struct ipv6hdr *iph6 = skb->nh.ipv6h;
 451        u8     tos = tunnel->parms.iph.tos;
 452        struct rtable *rt;                      /* Route to the other host */
 453        struct net_device *tdev;                        /* Device to other host */
 454        struct iphdr  *iph;                     /* Our new IP header */
 455        int    max_headroom;                    /* The extra header space needed */
 456        u32    dst = tiph->daddr;
 457        int    mtu;
 458        struct in6_addr *addr6; 
 459        int addr_type;
 460
 461        if (tunnel->recursion++) {
 462                tunnel->stat.collisions++;
 463                goto tx_error;
 464        }
 465
 466        if (skb->protocol != htons(ETH_P_IPV6))
 467                goto tx_error;
 468
 469        if (!dst)
 470                dst = try_6to4(&iph6->daddr);
 471
 472        if (!dst) {
 473                struct neighbour *neigh = NULL;
 474
 475                if (skb->dst)
 476                        neigh = skb->dst->neighbour;
 477
 478                if (neigh == NULL) {
 479                        if (net_ratelimit())
 480                                printk(KERN_DEBUG "sit: nexthop == NULL\n");
 481                        goto tx_error;
 482                }
 483
 484                addr6 = (struct in6_addr*)&neigh->primary_key;
 485                addr_type = ipv6_addr_type(addr6);
 486
 487                if (addr_type == IPV6_ADDR_ANY) {
 488                        addr6 = &skb->nh.ipv6h->daddr;
 489                        addr_type = ipv6_addr_type(addr6);
 490                }
 491
 492                if ((addr_type & IPV6_ADDR_COMPATv4) == 0)
 493                        goto tx_error_icmp;
 494
 495                dst = addr6->s6_addr32[3];
 496        }
 497
 498        if (ip_route_output(&rt, dst, tiph->saddr, RT_TOS(tos), tunnel->parms.link)) {
 499                tunnel->stat.tx_carrier_errors++;
 500                goto tx_error_icmp;
 501        }
 502        if (rt->rt_type != RTN_UNICAST) {
 503                ip_rt_put(rt);
 504                tunnel->stat.tx_carrier_errors++;
 505                goto tx_error_icmp;
 506        }
 507        tdev = rt->u.dst.dev;
 508
 509        if (tdev == dev) {
 510                ip_rt_put(rt);
 511                tunnel->stat.collisions++;
 512                goto tx_error;
 513        }
 514
 515        if (tiph->frag_off)
 516                mtu = rt->u.dst.pmtu - sizeof(struct iphdr);
 517        else
 518                mtu = skb->dst ? skb->dst->pmtu : dev->mtu;
 519
 520        if (mtu < 68) {
 521                tunnel->stat.collisions++;
 522                ip_rt_put(rt);
 523                goto tx_error;
 524        }
 525        if (mtu < IPV6_MIN_MTU)
 526                mtu = IPV6_MIN_MTU;
 527        if (skb->dst && mtu < skb->dst->pmtu) {
 528                struct rt6_info *rt6 = (struct rt6_info*)skb->dst;
 529                if (mtu < rt6->u.dst.pmtu) {
 530                        if (tunnel->parms.iph.daddr || rt6->rt6i_dst.plen == 128) {
 531                                rt6->rt6i_flags |= RTF_MODIFIED;
 532                                rt6->u.dst.pmtu = mtu;
 533                        }
 534                }
 535        }
 536        if (skb->len > mtu) {
 537                icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev);
 538                ip_rt_put(rt);
 539                goto tx_error;
 540        }
 541
 542        if (tunnel->err_count > 0) {
 543                if (jiffies - tunnel->err_time < IPTUNNEL_ERR_TIMEO) {
 544                        tunnel->err_count--;
 545                        dst_link_failure(skb);
 546                } else
 547                        tunnel->err_count = 0;
 548        }
 549
 550        /*
 551         * Okay, now see if we can stuff it in the buffer as-is.
 552         */
 553        max_headroom = (((tdev->hard_header_len+15)&~15)+sizeof(struct iphdr));
 554
 555        if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
 556                struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
 557                if (!new_skb) {
 558                        ip_rt_put(rt);
 559                        stats->tx_dropped++;
 560                        dev_kfree_skb(skb);
 561                        tunnel->recursion--;
 562                        return 0;
 563                }
 564                if (skb->sk)
 565                        skb_set_owner_w(new_skb, skb->sk);
 566                dev_kfree_skb(skb);
 567                skb = new_skb;
 568                iph6 = skb->nh.ipv6h;
 569        }
 570
 571        skb->h.raw = skb->nh.raw;
 572        skb->nh.raw = skb_push(skb, sizeof(struct iphdr));
 573        memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
 574        dst_release(skb->dst);
 575        skb->dst = &rt->u.dst;
 576
 577        /*
 578         *      Push down and install the IPIP header.
 579         */
 580
 581        iph                     =       skb->nh.iph;
 582        iph->version            =       4;
 583        iph->ihl                =       sizeof(struct iphdr)>>2;
 584        if (mtu > IPV6_MIN_MTU)
 585                iph->frag_off   =       htons(IP_DF);
 586        else
 587                iph->frag_off   =       0;
 588
 589        iph->protocol           =       IPPROTO_IPV6;
 590        iph->tos                =       INET_ECN_encapsulate(tos, ip6_get_dsfield(iph6));
 591        iph->daddr              =       rt->rt_dst;
 592        iph->saddr              =       rt->rt_src;
 593
 594        if ((iph->ttl = tiph->ttl) == 0)
 595                iph->ttl        =       iph6->hop_limit;
 596
 597        nf_reset(skb);
 598
 599        IPTUNNEL_XMIT();
 600        tunnel->recursion--;
 601        return 0;
 602
 603tx_error_icmp:
 604        dst_link_failure(skb);
 605tx_error:
 606        stats->tx_errors++;
 607        dev_kfree_skb(skb);
 608        tunnel->recursion--;
 609        return 0;
 610}
 611
 612static int
 613ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 614{
 615        int err = 0;
 616        struct ip_tunnel_parm p;
 617        struct ip_tunnel *t;
 618
 619        MOD_INC_USE_COUNT;
 620
 621        switch (cmd) {
 622        case SIOCGETTUNNEL:
 623                t = NULL;
 624                if (dev == &ipip6_fb_tunnel_dev) {
 625                        if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
 626                                err = -EFAULT;
 627                                break;
 628                        }
 629                        t = ipip6_tunnel_locate(&p, 0);
 630                }
 631                if (t == NULL)
 632                        t = (struct ip_tunnel*)dev->priv;
 633                memcpy(&p, &t->parms, sizeof(p));
 634                if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
 635                        err = -EFAULT;
 636                break;
 637
 638        case SIOCADDTUNNEL:
 639        case SIOCCHGTUNNEL:
 640                err = -EPERM;
 641                if (!capable(CAP_NET_ADMIN))
 642                        goto done;
 643
 644                err = -EFAULT;
 645                if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
 646                        goto done;
 647
 648                err = -EINVAL;
 649                if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPV6 ||
 650                    p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)))
 651                        goto done;
 652                if (p.iph.ttl)
 653                        p.iph.frag_off |= htons(IP_DF);
 654
 655                t = ipip6_tunnel_locate(&p, cmd == SIOCADDTUNNEL);
 656
 657                if (dev != &ipip6_fb_tunnel_dev && cmd == SIOCCHGTUNNEL &&
 658                    t != &ipip6_fb_tunnel) {
 659                        if (t != NULL) {
 660                                if (t->dev != dev) {
 661                                        err = -EEXIST;
 662                                        break;
 663                                }
 664                        } else {
 665                                if (((dev->flags&IFF_POINTOPOINT) && !p.iph.daddr) ||
 666                                    (!(dev->flags&IFF_POINTOPOINT) && p.iph.daddr)) {
 667                                        err = -EINVAL;
 668                                        break;
 669                                }
 670                                t = (struct ip_tunnel*)dev->priv;
 671                                ipip6_tunnel_unlink(t);
 672                                t->parms.iph.saddr = p.iph.saddr;
 673                                t->parms.iph.daddr = p.iph.daddr;
 674                                memcpy(dev->dev_addr, &p.iph.saddr, 4);
 675                                memcpy(dev->broadcast, &p.iph.daddr, 4);
 676                                ipip6_tunnel_link(t);
 677                                netdev_state_change(dev);
 678                        }
 679                }
 680
 681                if (t) {
 682                        err = 0;
 683                        if (cmd == SIOCCHGTUNNEL) {
 684                                t->parms.iph.ttl = p.iph.ttl;
 685                                t->parms.iph.tos = p.iph.tos;
 686                        }
 687                        if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
 688                                err = -EFAULT;
 689                } else
 690                        err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
 691                break;
 692
 693        case SIOCDELTUNNEL:
 694                err = -EPERM;
 695                if (!capable(CAP_NET_ADMIN))
 696                        goto done;
 697
 698                if (dev == &ipip6_fb_tunnel_dev) {
 699                        err = -EFAULT;
 700                        if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
 701                                goto done;
 702                        err = -ENOENT;
 703                        if ((t = ipip6_tunnel_locate(&p, 0)) == NULL)
 704                                goto done;
 705                        err = -EPERM;
 706                        if (t == &ipip6_fb_tunnel)
 707                                goto done;
 708                        dev = t->dev;
 709                }
 710                err = unregister_netdevice(dev);
 711                break;
 712
 713        default:
 714                err = -EINVAL;
 715        }
 716
 717done:
 718        MOD_DEC_USE_COUNT;
 719        return err;
 720}
 721
 722static struct net_device_stats *ipip6_tunnel_get_stats(struct net_device *dev)
 723{
 724        return &(((struct ip_tunnel*)dev->priv)->stat);
 725}
 726
 727static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu)
 728{
 729        if (new_mtu < IPV6_MIN_MTU || new_mtu > 0xFFF8 - sizeof(struct iphdr))
 730                return -EINVAL;
 731        dev->mtu = new_mtu;
 732        return 0;
 733}
 734
 735static void ipip6_tunnel_init_gen(struct net_device *dev)
 736{
 737        struct ip_tunnel *t = (struct ip_tunnel*)dev->priv;
 738
 739        dev->destructor         = ipip6_tunnel_destructor;
 740        dev->uninit             = ipip6_tunnel_uninit;
 741        dev->hard_start_xmit    = ipip6_tunnel_xmit;
 742        dev->get_stats          = ipip6_tunnel_get_stats;
 743        dev->do_ioctl           = ipip6_tunnel_ioctl;
 744        dev->change_mtu         = ipip6_tunnel_change_mtu;
 745
 746        dev->type               = ARPHRD_SIT;
 747        dev->hard_header_len    = LL_MAX_HEADER + sizeof(struct iphdr);
 748        dev->mtu                = 1500 - sizeof(struct iphdr);
 749        dev->flags              = IFF_NOARP;
 750        dev->iflink             = 0;
 751        dev->addr_len           = 4;
 752        memcpy(dev->dev_addr, &t->parms.iph.saddr, 4);
 753        memcpy(dev->broadcast, &t->parms.iph.daddr, 4);
 754}
 755
 756static int ipip6_tunnel_init(struct net_device *dev)
 757{
 758        struct net_device *tdev = NULL;
 759        struct ip_tunnel *tunnel;
 760        struct iphdr *iph;
 761
 762        tunnel = (struct ip_tunnel*)dev->priv;
 763        iph = &tunnel->parms.iph;
 764
 765        ipip6_tunnel_init_gen(dev);
 766
 767        if (iph->daddr) {
 768                struct rtable *rt;
 769                if (!ip_route_output(&rt, iph->daddr, iph->saddr, RT_TOS(iph->tos), tunnel->parms.link)) {
 770                        tdev = rt->u.dst.dev;
 771                        ip_rt_put(rt);
 772                }
 773                dev->flags |= IFF_POINTOPOINT;
 774        }
 775
 776        if (!tdev && tunnel->parms.link)
 777                tdev = __dev_get_by_index(tunnel->parms.link);
 778
 779        if (tdev) {
 780                dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
 781                dev->mtu = tdev->mtu - sizeof(struct iphdr);
 782                if (dev->mtu < IPV6_MIN_MTU)
 783                        dev->mtu = IPV6_MIN_MTU;
 784        }
 785        dev->iflink = tunnel->parms.link;
 786
 787        return 0;
 788}
 789
 790#ifdef MODULE
 791static int ipip6_fb_tunnel_open(struct net_device *dev)
 792{
 793        MOD_INC_USE_COUNT;
 794        return 0;
 795}
 796
 797static int ipip6_fb_tunnel_close(struct net_device *dev)
 798{
 799        MOD_DEC_USE_COUNT;
 800        return 0;
 801}
 802#endif
 803
 804int __init ipip6_fb_tunnel_init(struct net_device *dev)
 805{
 806        struct iphdr *iph;
 807
 808        ipip6_tunnel_init_gen(dev);
 809#ifdef MODULE
 810        dev->open               = ipip6_fb_tunnel_open;
 811        dev->stop               = ipip6_fb_tunnel_close;
 812#endif
 813
 814        iph = &ipip6_fb_tunnel.parms.iph;
 815        iph->version            = 4;
 816        iph->protocol           = IPPROTO_IPV6;
 817        iph->ihl                = 5;
 818        iph->ttl                = 64;
 819
 820        dev_hold(dev);
 821        tunnels_wc[0]           = &ipip6_fb_tunnel;
 822        return 0;
 823}
 824
 825static struct inet_protocol sit_protocol = {
 826        ipip6_rcv,
 827        ipip6_err,
 828        0,
 829        IPPROTO_IPV6,
 830        0,
 831        NULL,
 832        "IPv6"
 833};
 834
 835#ifdef MODULE
 836void sit_cleanup(void)
 837{
 838        inet_del_protocol(&sit_protocol);
 839        unregister_netdev(&ipip6_fb_tunnel_dev);
 840}
 841#endif
 842
 843int __init sit_init(void)
 844{
 845        printk(KERN_INFO "IPv6 over IPv4 tunneling driver\n");
 846
 847        ipip6_fb_tunnel_dev.priv = (void*)&ipip6_fb_tunnel;
 848        strcpy(ipip6_fb_tunnel_dev.name, ipip6_fb_tunnel.parms.name);
 849        register_netdev(&ipip6_fb_tunnel_dev);
 850        inet_add_protocol(&sit_protocol);
 851        return 0;
 852}
 853
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.