Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

ip6_output.c

Go to the documentation of this file.
00001 /*
00002  *      IPv6 output functions
00003  *      Linux INET6 implementation 
00004  *
00005  *      Authors:
00006  *      Pedro Roque             <roque@di.fc.ul.pt>     
00007  *
00008  *      $Id: ip6_output.c,v 1.17.2.1 2000/09/13 01:27:53 davem Exp $
00009  *
00010  *      Based on linux/net/ipv4/ip_output.c
00011  *
00012  *      This program is free software; you can redistribute it and/or
00013  *      modify it under the terms of the GNU General Public License
00014  *      as published by the Free Software Foundation; either version
00015  *      2 of the License, or (at your option) any later version.
00016  *
00017  *      Changes:
00018  *      A.N.Kuznetsov   :       airthmetics in fragmentation.
00019  *                              extension headers are implemented.
00020  *                              route changes now work.
00021  *                              ip6_forward does not confuse sniffers.
00022  *                              etc.
00023  *                              
00024  */
00025 
00026 #include <linux/errno.h>
00027 #include <linux/types.h>
00028 #include <linux/socket.h>
00029 #include <linux/net.h>
00030 #include <linux/netdevice.h>
00031 #include <linux/if_arp.h>
00032 #include <linux/in6.h>
00033 #include <linux/route.h>
00034 
00035 #include <net/sock.h>
00036 #include <net/snmp.h>
00037 
00038 #include <net/ipv6.h>
00039 #include <net/ndisc.h>
00040 #include <net/protocol.h>
00041 #include <net/ip6_route.h>
00042 #include <net/addrconf.h>
00043 #include <net/rawv6.h>
00044 #include <net/icmp.h>
00045 
00046 static u32      ipv6_fragmentation_id = 1;
00047 
00048 int ip6_output(struct sk_buff *skb)
00049 {
00050         struct dst_entry *dst = skb->dst;
00051         struct device *dev = dst->dev;
00052         struct hh_cache *hh = dst->hh;
00053 
00054         skb->protocol = __constant_htons(ETH_P_IPV6);
00055         skb->dev = dev;
00056 
00057         if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr)) {
00058                 if (!(dev->flags&IFF_LOOPBACK) &&
00059                     (skb->sk == NULL || skb->sk->net_pinfo.af_inet6.mc_loop) &&
00060                     ipv6_chk_mcast_addr(dev, &skb->nh.ipv6h->daddr)) {
00061                         /* Do not check for IFF_ALLMULTI; multicast routing
00062                            is not supported in any case.
00063                          */
00064                         dev_loopback_xmit(skb);
00065 
00066                         if (skb->nh.ipv6h->hop_limit == 0) {
00067                                 kfree_skb(skb);
00068                                 return 0;
00069                         }
00070                 }
00071 
00072                 ipv6_statistics.Ip6OutMcastPkts++;
00073         }
00074 
00075         if (hh) {
00076 #ifdef __alpha__
00077                 /* Alpha has disguisting memcpy. Help it. */
00078                 u64 *aligned_hdr = (u64*)(skb->data - 16);
00079                 u64 *aligned_hdr0 = hh->hh_data;
00080                 read_lock_irq(&hh->hh_lock);
00081                 aligned_hdr[0] = aligned_hdr0[0];
00082                 aligned_hdr[1] = aligned_hdr0[1];
00083 #else
00084                 read_lock_irq(&hh->hh_lock);
00085                 memcpy(skb->data - 16, hh->hh_data, 16);
00086 #endif
00087                 read_unlock_irq(&hh->hh_lock);
00088                 skb_push(skb, dev->hard_header_len);
00089                 return hh->hh_output(skb);
00090         } else if (dst->neighbour)
00091                 return dst->neighbour->output(skb);
00092 
00093         kfree_skb(skb);
00094         return -EINVAL;
00095 }
00096 
00097 /*
00098  *      xmit an sk_buff (used by TCP)
00099  */
00100 
00101 int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
00102              struct ipv6_txoptions *opt)
00103 {
00104         struct ipv6_pinfo * np = sk ? &sk->net_pinfo.af_inet6 : NULL;
00105         struct in6_addr *first_hop = fl->nl_u.ip6_u.daddr;
00106         struct dst_entry *dst = skb->dst;
00107         struct ipv6hdr *hdr;
00108         u8  proto = fl->proto;
00109         int seg_len = skb->len;
00110         int hlimit;
00111 
00112         if (opt) {
00113                 int head_room;
00114 
00115                 /* First: exthdrs may take lots of space (~8K for now)
00116                    MAX_HEADER is not enough.
00117                  */
00118                 head_room = opt->opt_nflen + opt->opt_flen;
00119                 seg_len += head_room;
00120                 head_room += sizeof(struct ipv6hdr) + ((dst->dev->hard_header_len + 15)&~15);
00121 
00122                 if (skb_headroom(skb) < head_room) {
00123                         struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room);
00124                         kfree_skb(skb);
00125                         skb = skb2;
00126                         if (skb == NULL)
00127                                 return -ENOBUFS;
00128                         if (sk)
00129                                 skb_set_owner_w(skb, sk);
00130                 }
00131                 if (opt->opt_flen)
00132                         ipv6_push_frag_opts(skb, opt, &proto);
00133                 if (opt->opt_nflen)
00134                         ipv6_push_nfrag_opts(skb, opt, &proto, &first_hop);
00135         }
00136 
00137         hdr = skb->nh.ipv6h = (struct ipv6hdr*)skb_push(skb, sizeof(struct ipv6hdr));
00138 
00139         /*
00140          *      Fill in the IPv6 header
00141          */
00142 
00143         *(u32*)hdr = __constant_htonl(0x60000000) | fl->fl6_flowlabel;
00144         hlimit = -1;
00145         if (np)
00146                 hlimit = np->hop_limit;
00147         if (hlimit < 0)
00148                 hlimit = ((struct rt6_info*)dst)->rt6i_hoplimit;
00149 
00150         hdr->payload_len = htons(seg_len);
00151         hdr->nexthdr = proto;
00152         hdr->hop_limit = hlimit;
00153 
00154         ipv6_addr_copy(&hdr->saddr, fl->nl_u.ip6_u.saddr);
00155         ipv6_addr_copy(&hdr->daddr, first_hop);
00156 
00157         if (skb->len <= dst->pmtu) {
00158                 ipv6_statistics.Ip6OutRequests++;
00159                 dst->output(skb);
00160                 return 0;
00161         }
00162 
00163         printk(KERN_DEBUG "IPv6: sending pkt_too_big to self\n");
00164         start_bh_atomic();
00165         icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst->pmtu, skb->dev);
00166         end_bh_atomic();
00167         kfree_skb(skb);
00168         return -EMSGSIZE;
00169 }
00170 
00171 /*
00172  *      To avoid extra problems ND packets are send through this
00173  *      routine. It's code duplication but I really want to avoid
00174  *      extra checks since ipv6_build_header is used by TCP (which
00175  *      is for us performace critical)
00176  */
00177 
00178 int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct device *dev,
00179                struct in6_addr *saddr, struct in6_addr *daddr,
00180                int proto, int len)
00181 {
00182         struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
00183         struct ipv6hdr *hdr;
00184         int totlen;
00185 
00186         skb->protocol = __constant_htons(ETH_P_IPV6);
00187         skb->dev = dev;
00188 
00189         totlen = len + sizeof(struct ipv6hdr);
00190 
00191         hdr = (struct ipv6hdr *) skb_put(skb, sizeof(struct ipv6hdr));
00192         skb->nh.ipv6h = hdr;
00193 
00194         *(u32*)hdr = htonl(0x60000000);
00195 
00196         hdr->payload_len = htons(len);
00197         hdr->nexthdr = proto;
00198         hdr->hop_limit = np->hop_limit;
00199 
00200         ipv6_addr_copy(&hdr->saddr, saddr);
00201         ipv6_addr_copy(&hdr->daddr, daddr);
00202 
00203         return 0;
00204 }
00205 
00206 static struct ipv6hdr * ip6_bld_1(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
00207                                   int hlimit, unsigned pktlength)
00208 {
00209         struct ipv6hdr *hdr;
00210         
00211         skb->nh.raw = skb_put(skb, sizeof(struct ipv6hdr));
00212         hdr = skb->nh.ipv6h;
00213         
00214         *(u32*)hdr = fl->fl6_flowlabel | htonl(0x60000000);
00215 
00216         hdr->payload_len = htons(pktlength - sizeof(struct ipv6hdr));
00217         hdr->hop_limit = hlimit;
00218         hdr->nexthdr = fl->proto;
00219 
00220         ipv6_addr_copy(&hdr->saddr, fl->nl_u.ip6_u.saddr);
00221         ipv6_addr_copy(&hdr->daddr, fl->nl_u.ip6_u.daddr);
00222         return hdr;
00223 }
00224 
00225 static __inline__ u8 * ipv6_build_fraghdr(struct sk_buff *skb, u8* prev_hdr, unsigned offset)
00226 {
00227         struct frag_hdr *fhdr;
00228 
00229         fhdr = (struct frag_hdr *) skb_put(skb, sizeof(struct frag_hdr));
00230 
00231         fhdr->nexthdr  = *prev_hdr;
00232         *prev_hdr = NEXTHDR_FRAGMENT;
00233         prev_hdr = &fhdr->nexthdr;
00234 
00235         fhdr->reserved = 0;
00236         fhdr->frag_off = htons(offset);
00237         fhdr->identification = ipv6_fragmentation_id++;
00238         return &fhdr->nexthdr;
00239 }
00240 
00241 static int ip6_frag_xmit(struct sock *sk, inet_getfrag_t getfrag,
00242                          const void *data, struct dst_entry *dst,
00243                          struct flowi *fl, struct ipv6_txoptions *opt,
00244                          struct in6_addr *final_dst,
00245                          int hlimit, int flags, unsigned length, int mtu)
00246 {
00247         struct ipv6hdr *hdr;
00248         struct sk_buff *last_skb;
00249         u8 *prev_hdr;
00250         int unfrag_len;
00251         int frag_len;
00252         int last_len;
00253         int nfrags;
00254         int fhdr_dist;
00255         int frag_off;
00256         int data_off;
00257         int err;
00258 
00259         /*
00260          *      Fragmentation
00261          *
00262          *      Extension header order:
00263          *      Hop-by-hop -> Dest0 -> Routing -> Fragment -> Auth -> Dest1 -> rest (...)
00264          *      
00265          *      We must build the non-fragmented part that
00266          *      will be in every packet... this also means
00267          *      that other extension headers (Dest, Auth, etc)
00268          *      must be considered in the data to be fragmented
00269          */
00270 
00271         unfrag_len = sizeof(struct ipv6hdr) + sizeof(struct frag_hdr);
00272         last_len = length;
00273 
00274         if (opt) {
00275                 unfrag_len += opt->opt_nflen;
00276                 last_len += opt->opt_flen;
00277         }
00278 
00279         /*
00280          *      Length of fragmented part on every packet but 
00281          *      the last must be an:
00282          *      "integer multiple of 8 octects".
00283          */
00284 
00285         frag_len = (mtu - unfrag_len) & ~0x7;
00286 
00287         /* Unfragmentable part exceeds mtu. */
00288         if (frag_len <= 0) {
00289                 ipv6_local_error(sk, EMSGSIZE, fl, mtu);
00290                 return -EMSGSIZE;
00291         }
00292 
00293         nfrags = last_len / frag_len;
00294 
00295         /*
00296          *      We must send from end to start because of 
00297          *      UDP/ICMP checksums. We do a funny trick:
00298          *      fill the last skb first with the fixed
00299          *      header (and its data) and then use it
00300          *      to create the following segments and send it
00301          *      in the end. If the peer is checking the M_flag
00302          *      to trigger the reassembly code then this 
00303          *      might be a good idea.
00304          */
00305 
00306         frag_off = nfrags * frag_len;
00307         last_len -= frag_off;
00308 
00309         if (last_len == 0) {
00310                 last_len = frag_len;
00311                 frag_off -= frag_len;
00312                 nfrags--;
00313         }
00314         data_off = frag_off;
00315 
00316         /* And it is implementation problem: for now we assume, that
00317            all the exthdrs will fit to the first fragment.
00318          */
00319         if (opt) {
00320                 if (frag_len < opt->opt_flen) {
00321                         ipv6_local_error(sk, EMSGSIZE, fl, mtu);
00322                         return -EMSGSIZE;
00323                 }
00324                 data_off = frag_off - opt->opt_flen;
00325         }
00326 
00327         last_skb = sock_alloc_send_skb(sk, unfrag_len + frag_len +
00328                                        dst->dev->hard_header_len + 15,
00329                                        0, flags & MSG_DONTWAIT, &err);
00330 
00331         if (last_skb == NULL)
00332                 return err;
00333 
00334         last_skb->dst = dst_clone(dst);
00335 
00336         skb_reserve(last_skb, (dst->dev->hard_header_len + 15) & ~15);
00337 
00338         hdr = ip6_bld_1(sk, last_skb, fl, hlimit, frag_len+unfrag_len);
00339         prev_hdr = &hdr->nexthdr;
00340 
00341         if (opt && opt->opt_nflen)
00342                 prev_hdr = ipv6_build_nfrag_opts(last_skb, prev_hdr, opt, final_dst, 0);
00343 
00344         prev_hdr = ipv6_build_fraghdr(last_skb, prev_hdr, frag_off);
00345         fhdr_dist = prev_hdr - last_skb->data;
00346 
00347         err = getfrag(data, &hdr->saddr, last_skb->tail, data_off, last_len);
00348 
00349         if (!err) {
00350                 while (nfrags--) {
00351                         struct sk_buff *skb;
00352                         
00353                         struct frag_hdr *fhdr2;
00354                                 
00355                         skb = skb_copy(last_skb, sk->allocation);
00356 
00357                         if (skb == NULL) {
00358                                 ipv6_statistics.Ip6FragFails++;
00359                                 kfree_skb(last_skb);
00360                                 return -ENOMEM;
00361                         }
00362                         
00363                         frag_off -= frag_len;
00364                         data_off -= frag_len;
00365 
00366                         fhdr2 = (struct frag_hdr *) (skb->data + fhdr_dist);
00367 
00368                         /* more flag on */
00369                         fhdr2->frag_off = htons(frag_off | 1);
00370 
00371                         /* Write fragmentable exthdrs to the first chunk */
00372                         if (nfrags == 0 && opt && opt->opt_flen) {
00373                                 ipv6_build_frag_opts(skb, &fhdr2->nexthdr, opt);
00374                                 frag_len -= opt->opt_flen;
00375                                 data_off = 0;
00376                         }
00377 
00378                         err = getfrag(data, &hdr->saddr,skb_put(skb, frag_len),
00379                                       data_off, frag_len);
00380 
00381                         if (err) {
00382                                 kfree_skb(skb);
00383                                 break;
00384                         }
00385 
00386                         ipv6_statistics.Ip6FragCreates++;
00387                         ipv6_statistics.Ip6OutRequests++;
00388                         dst->output(skb);
00389                 }
00390         }
00391 
00392         if (err) {
00393                 ipv6_statistics.Ip6FragFails++;
00394                 kfree_skb(last_skb);
00395                 return -EFAULT;
00396         }
00397 
00398         hdr->payload_len = htons(unfrag_len + last_len - sizeof(struct ipv6hdr));
00399 
00400         /*
00401          *      update last_skb to reflect the getfrag we did
00402          *      on start.
00403          */
00404 
00405         skb_put(last_skb, last_len);
00406 
00407         ipv6_statistics.Ip6FragCreates++;
00408         ipv6_statistics.Ip6FragOKs++;
00409         ipv6_statistics.Ip6OutRequests++;
00410         dst->output(last_skb);
00411 
00412         return 0;
00413 }
00414 
00415 int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
00416                    struct flowi *fl, unsigned length,
00417                    struct ipv6_txoptions *opt, int hlimit, int flags)
00418 {
00419         struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
00420         struct in6_addr *final_dst = NULL;
00421         struct dst_entry *dst;
00422         int err = 0;
00423         unsigned int pktlength, jumbolen, mtu;
00424         struct in6_addr saddr;
00425 
00426         if (opt && opt->srcrt) {
00427                 struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
00428                 final_dst = fl->fl6_dst;
00429                 fl->fl6_dst = rt0->addr;
00430         }
00431 
00432         if (!fl->oif && ipv6_addr_is_multicast(fl->nl_u.ip6_u.daddr))
00433                 fl->oif = np->mcast_oif;
00434 
00435         dst = NULL;
00436         if (sk->dst_cache) {
00437                 dst = dst_check(&sk->dst_cache, np->dst_cookie);
00438                 if (dst) {
00439                         struct rt6_info *rt = (struct rt6_info*)dst_clone(dst);
00440 
00441                         /* Yes, checking route validity in not connected
00442                            case is not very simple. Take into account,
00443                            that we do not support routing by source, TOS,
00444                            and MSG_DONTROUTE            --ANK (980726)
00445 
00446                            1. If route was host route, check that
00447                               cached destination is current.
00448                               If it is network route, we still may
00449                               check its validity using saved pointer
00450                               to the last used address: daddr_cache.
00451                               We do not want to save whole address now,
00452                               (because main consumer of this service
00453                                is tcp, which has not this problem),
00454                               so that the last trick works only on connected
00455                               sockets.
00456                            2. oif also should be the same.
00457                          */
00458                         if (((rt->rt6i_dst.plen != 128 ||
00459                               ipv6_addr_cmp(fl->fl6_dst, &rt->rt6i_dst.addr))
00460                              && (np->daddr_cache == NULL ||
00461                                  ipv6_addr_cmp(fl->fl6_dst, np->daddr_cache)))
00462                             || (fl->oif && fl->oif != dst->dev->ifindex)) {
00463                                 dst_release(dst);
00464                                 dst = NULL;
00465                         }
00466                 }
00467         }
00468 
00469         if (dst == NULL)
00470                 dst = ip6_route_output(sk, fl);
00471 
00472         if (dst->error) {
00473                 ipv6_statistics.Ip6OutNoRoutes++;
00474                 dst_release(dst);
00475                 return -ENETUNREACH;
00476         }
00477 
00478         if (fl->fl6_src == NULL) {
00479                 err = ipv6_get_saddr(dst, fl->fl6_dst, &saddr);
00480 
00481                 if (err) {
00482 #if IP6_DEBUG >= 2
00483                         printk(KERN_DEBUG "ip6_build_xmit: "
00484                                "no availiable source address\n");
00485 #endif
00486                         goto out;
00487                 }
00488                 fl->fl6_src = &saddr;
00489         }
00490         pktlength = length;
00491 
00492         if (hlimit < 0) {
00493                 if (ipv6_addr_is_multicast(fl->fl6_dst))
00494                         hlimit = np->mcast_hops;
00495                 else
00496                         hlimit = np->hop_limit;
00497                 if (hlimit < 0)
00498                         hlimit = ((struct rt6_info*)dst)->rt6i_hoplimit;
00499         }
00500 
00501         jumbolen = 0;
00502 
00503         if (!sk->ip_hdrincl) {
00504                 pktlength += sizeof(struct ipv6hdr);
00505                 if (opt)
00506                         pktlength += opt->opt_flen + opt->opt_nflen;
00507 
00508                 if (pktlength > 0xFFFF + sizeof(struct ipv6hdr)) {
00509                         /* Jumbo datagram.
00510                            It is assumed, that in the case of sk->ip_hdrincl
00511                            jumbo option is supplied by user.
00512                          */
00513                         pktlength += 8;
00514                         jumbolen = pktlength - sizeof(struct ipv6hdr);
00515                 }
00516         }
00517 
00518         mtu = dst->pmtu;
00519         if (np->frag_size < mtu) {
00520                 if (np->frag_size)
00521                         mtu = np->frag_size;
00522                 else if (np->pmtudisc == IPV6_PMTUDISC_DONT)
00523                         mtu = IPV6_MIN_MTU;
00524         }
00525 
00526         /* Critical arithmetic overflow check.
00527            FIXME: may gcc optimize it out? --ANK (980726)
00528          */
00529         if (pktlength < length) {
00530                 ipv6_local_error(sk, EMSGSIZE, fl, mtu);
00531                 err = -EMSGSIZE;
00532                 goto out;
00533         }
00534 
00535         if (pktlength <= mtu) {
00536                 struct sk_buff *skb;
00537                 struct ipv6hdr *hdr;
00538                 struct device *dev = dst->dev;
00539 
00540                 skb = sock_alloc_send_skb(sk, pktlength + 15 +
00541                                           dev->hard_header_len, 0,
00542                                           flags & MSG_DONTWAIT, &err);
00543 
00544                 if (skb == NULL) {
00545                         ipv6_statistics.Ip6OutDiscards++;
00546                         goto out;
00547                 }
00548 
00549                 skb->dst = dst_clone(dst);
00550 
00551                 skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
00552 
00553                 hdr = (struct ipv6hdr *) skb->tail;
00554                 skb->nh.ipv6h = hdr;
00555 
00556                 if (!sk->ip_hdrincl) {
00557                         ip6_bld_1(sk, skb, fl, hlimit,
00558                                   jumbolen ? sizeof(struct ipv6hdr) : pktlength);
00559 
00560                         if (opt || jumbolen) {
00561                                 u8 *prev_hdr = &hdr->nexthdr;
00562                                 prev_hdr = ipv6_build_nfrag_opts(skb, prev_hdr, opt, final_dst, jumbolen);
00563                                 if (opt && opt->opt_flen)
00564                                         ipv6_build_frag_opts(skb, prev_hdr, opt);
00565                         }
00566                 }
00567 
00568                 skb_put(skb, length);
00569                 err = getfrag(data, &hdr->saddr,
00570                               ((char *) hdr) + (pktlength - length),
00571                               0, length);
00572 
00573                 if (!err) {
00574                         ipv6_statistics.Ip6OutRequests++;
00575                         dst->output(skb);
00576                 } else {
00577                         err = -EFAULT;
00578                         kfree_skb(skb);
00579                 }
00580         } else {
00581                 if (sk->ip_hdrincl || jumbolen ||
00582                     np->pmtudisc == IPV6_PMTUDISC_DO) {
00583                         ipv6_local_error(sk, EMSGSIZE, fl, mtu);
00584                         err = -EMSGSIZE;
00585                         goto out;
00586                 }
00587 
00588                 err = ip6_frag_xmit(sk, getfrag, data, dst, fl, opt, final_dst, hlimit,
00589                                     flags, length, mtu);
00590         }
00591 
00592         /*
00593          *      cleanup
00594          */
00595 out:
00596         ip6_dst_store(sk, dst, fl->nl_u.ip6_u.daddr == &np->daddr ? &np->daddr : NULL);
00597         return err;
00598 }
00599 
00600 int ip6_call_ra_chain(struct sk_buff *skb, int sel)
00601 {
00602         struct ip6_ra_chain *ra;
00603         struct sock *last = NULL;
00604 
00605         for (ra = ip6_ra_chain; ra; ra = ra->next) {
00606                 struct sock *sk = ra->sk;
00607                 if (sk && ra->sel == sel) {
00608                         if (last) {
00609                                 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
00610                                 if (skb2)
00611                                         rawv6_rcv(last, skb2, skb2->len);
00612                         }
00613                         last = sk;
00614                 }
00615         }
00616 
00617         if (last) {
00618                 rawv6_rcv(last, skb, skb->len);
00619                 return 1;
00620         }
00621         return 0;
00622 }
00623 
00624 int ip6_forward(struct sk_buff *skb)
00625 {
00626         struct dst_entry *dst = skb->dst;
00627         struct ipv6hdr *hdr = skb->nh.ipv6h;
00628         struct inet6_skb_parm *opt =(struct inet6_skb_parm*)skb->cb;
00629         
00630         if (ipv6_devconf.forwarding == 0 && opt->srcrt == 0)
00631                 goto drop;
00632 
00633         /*
00634          *      We DO NOT make any processing on
00635          *      RA packets, pushing them to user level AS IS
00636          *      without ane WARRANTY that application will be able
00637          *      to interpret them. The reason is that we
00638          *      cannot make anything clever here.
00639          *
00640          *      We are not end-node, so that if packet contains
00641          *      AH/ESP, we cannot make anything.
00642          *      Defragmentation also would be mistake, RA packets
00643          *      cannot be fragmented, because there is no warranty
00644          *      that different fragments will go along one path. --ANK
00645          */
00646         if (opt->ra) {
00647                 u8 *ptr = skb->nh.raw + opt->ra;
00648                 if (ip6_call_ra_chain(skb, (ptr[2]<<8) + ptr[3]))
00649                         return 0;
00650         }
00651 
00652         /*
00653          *      check and decrement ttl
00654          */
00655         if (hdr->hop_limit <= 1) {
00656                 /* Force OUTPUT device used as source address */
00657                 skb->dev = dst->dev;
00658                 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
00659                             0, skb->dev);
00660 
00661                 kfree_skb(skb);
00662                 return -ETIMEDOUT;
00663         }
00664 
00665         /* IPv6 specs say nothing about it, but it is clear that we cannot
00666            send redirects to source routed frames.
00667          */
00668         if (skb->dev == dst->dev && dst->neighbour && opt->srcrt == 0) {
00669                 struct in6_addr *target = NULL;
00670                 struct rt6_info *rt;
00671                 struct neighbour *n = dst->neighbour;
00672 
00673                 /*
00674                  *      incoming and outgoing devices are the same
00675                  *      send a redirect.
00676                  */
00677 
00678                 rt = (struct rt6_info *) dst;
00679                 if ((rt->rt6i_flags & RTF_GATEWAY))
00680                         target = (struct in6_addr*)&n->primary_key;
00681                 else
00682                         target = &hdr->daddr;
00683 
00684                 /* Limit redirects both by destination (here)
00685                    and by source (inside ndisc_send_redirect)
00686                  */
00687                 if (xrlim_allow(dst, 1*HZ))
00688                         ndisc_send_redirect(skb, n, target);
00689         } else if (ipv6_addr_type(&hdr->saddr)&(IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK
00690                                                 |IPV6_ADDR_LINKLOCAL)) {
00691                 /* This check is security critical. */
00692                 goto drop;
00693         }
00694 
00695         if (skb->len > dst->pmtu) {
00696                 /* Again, force OUTPUT device used as source address */
00697                 skb->dev = dst->dev;
00698                 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst->pmtu, skb->dev);
00699                 ipv6_statistics.Ip6InTooBigErrors++;
00700                 kfree_skb(skb);
00701                 return -EMSGSIZE;
00702         }
00703 
00704         if ((skb = skb_cow(skb, dst->dev->hard_header_len)) == NULL)
00705                 return 0;
00706 
00707         hdr = skb->nh.ipv6h;
00708 
00709         /* Mangling hops number delayed to point after skb COW */
00710  
00711         hdr->hop_limit--;
00712 
00713         ipv6_statistics.Ip6OutForwDatagrams++;
00714         return dst->output(skb);
00715 
00716 drop:
00717         ipv6_statistics.Ip6InAddrErrors++;
00718         kfree_skb(skb);
00719         return -EINVAL;
00720 }