X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv6%2Fexthdrs.c;h=e0839eafc3a90e36e085ef50f895382d5d441f9a;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=464a3f4d63e3d34fd241f2dc9e7a9d3e4317f036;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 464a3f4d6..e0839eafc 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -314,9 +314,11 @@ looped_back: dst_release(xchg(&skb->dst, NULL)); ip6_route_input(skb); if (skb->dst->error) { + skb_push(skb, skb->data - skb->nh.raw); dst_input(skb); return -1; } + if (skb->dst->dev->flags&IFF_LOOPBACK) { if (skb->nh.ipv6h->hop_limit <= 1) { IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); @@ -329,6 +331,7 @@ looped_back: goto looped_back; } + skb_push(skb, skb->data - skb->nh.raw); dst_input(skb); return -1; } @@ -498,83 +501,6 @@ int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff) * for headers. */ -static u8 *ipv6_build_rthdr(struct sk_buff *skb, u8 *prev_hdr, - struct ipv6_rt_hdr *opt, struct in6_addr *addr) -{ - struct rt0_hdr *phdr, *ihdr; - int hops; - - ihdr = (struct rt0_hdr *) opt; - - phdr = (struct rt0_hdr *) skb_put(skb, (ihdr->rt_hdr.hdrlen + 1) << 3); - memcpy(phdr, ihdr, sizeof(struct rt0_hdr)); - - hops = ihdr->rt_hdr.hdrlen >> 1; - - if (hops > 1) - memcpy(phdr->addr, ihdr->addr + 1, - (hops - 1) * sizeof(struct in6_addr)); - - ipv6_addr_copy(phdr->addr + (hops - 1), addr); - - phdr->rt_hdr.nexthdr = *prev_hdr; - *prev_hdr = NEXTHDR_ROUTING; - return &phdr->rt_hdr.nexthdr; -} - -static u8 *ipv6_build_exthdr(struct sk_buff *skb, u8 *prev_hdr, u8 type, struct ipv6_opt_hdr *opt) -{ - struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_put(skb, ipv6_optlen(opt)); - - memcpy(h, opt, ipv6_optlen(opt)); - h->nexthdr = *prev_hdr; - *prev_hdr = type; - return &h->nexthdr; -} - -u8 *ipv6_build_nfrag_opts(struct sk_buff *skb, u8 *prev_hdr, struct ipv6_txoptions *opt, - struct in6_addr *daddr, u32 jumbolen) -{ - struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb->data; - - if (opt && opt->hopopt) - prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_HOP, opt->hopopt); - - if (jumbolen) { - u8 *jumboopt = (u8 *)skb_put(skb, 8); - - if (opt && opt->hopopt) { - *jumboopt++ = IPV6_TLV_PADN; - *jumboopt++ = 0; - h->hdrlen++; - } else { - h = (struct ipv6_opt_hdr *)jumboopt; - h->nexthdr = *prev_hdr; - h->hdrlen = 0; - jumboopt += 2; - *prev_hdr = NEXTHDR_HOP; - prev_hdr = &h->nexthdr; - } - jumboopt[0] = IPV6_TLV_JUMBO; - jumboopt[1] = 4; - *(u32*)(jumboopt+2) = htonl(jumbolen); - } - if (opt) { - if (opt->dst0opt) - prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_DEST, opt->dst0opt); - if (opt->srcrt) - prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt, daddr); - } - return prev_hdr; -} - -u8 *ipv6_build_frag_opts(struct sk_buff *skb, u8 *prev_hdr, struct ipv6_txoptions *opt) -{ - if (opt->dst1opt) - prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_DEST, opt->dst1opt); - return prev_hdr; -} - static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto, struct ipv6_rt_hdr *opt, struct in6_addr **addr_p)