linux/net/ipv6/exthdrs.c
<<
>>
Prefs
   1/*
   2 *      Extension Header handling for IPv6
   3 *      Linux INET6 implementation
   4 *
   5 *      Authors:
   6 *      Pedro Roque             <roque@di.fc.ul.pt>
   7 *      Andi Kleen              <ak@muc.de>
   8 *      Alexey Kuznetsov        <kuznet@ms2.inr.ac.ru>
   9 *
  10 *      This program is free software; you can redistribute it and/or
  11 *      modify it under the terms of the GNU General Public License
  12 *      as published by the Free Software Foundation; either version
  13 *      2 of the License, or (at your option) any later version.
  14 */
  15
  16/* Changes:
  17 *      yoshfuji                : ensure not to overrun while parsing
  18 *                                tlv options.
  19 *      Mitsuru KANDA @USAGI and: Remove ipv6_parse_exthdrs().
  20 *      YOSHIFUJI Hideaki @USAGI  Register inbound extension header
  21 *                                handlers as inet6_protocol{}.
  22 */
  23
  24#include <linux/errno.h>
  25#include <linux/types.h>
  26#include <linux/socket.h>
  27#include <linux/sockios.h>
  28#include <linux/net.h>
  29#include <linux/netdevice.h>
  30#include <linux/in6.h>
  31#include <linux/icmpv6.h>
  32#include <linux/slab.h>
  33#include <linux/export.h>
  34
  35#include <net/dst.h>
  36#include <net/sock.h>
  37#include <net/snmp.h>
  38
  39#include <net/ipv6.h>
  40#include <net/protocol.h>
  41#include <net/transp_v6.h>
  42#include <net/rawv6.h>
  43#include <net/ndisc.h>
  44#include <net/ip6_route.h>
  45#include <net/addrconf.h>
  46#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
  47#include <net/xfrm.h>
  48#endif
  49
  50#include <asm/uaccess.h>
  51
  52int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
  53{
  54        const unsigned char *nh = skb_network_header(skb);
  55        int packet_len = skb->tail - skb->network_header;
  56        struct ipv6_opt_hdr *hdr;
  57        int len;
  58
  59        if (offset + 2 > packet_len)
  60                goto bad;
  61        hdr = (struct ipv6_opt_hdr *)(nh + offset);
  62        len = ((hdr->hdrlen + 1) << 3);
  63
  64        if (offset + len > packet_len)
  65                goto bad;
  66
  67        offset += 2;
  68        len -= 2;
  69
  70        while (len > 0) {
  71                int opttype = nh[offset];
  72                int optlen;
  73
  74                if (opttype == type)
  75                        return offset;
  76
  77                switch (opttype) {
  78                case IPV6_TLV_PAD1:
  79                        optlen = 1;
  80                        break;
  81                default:
  82                        optlen = nh[offset + 1] + 2;
  83                        if (optlen > len)
  84                                goto bad;
  85                        break;
  86                }
  87                offset += optlen;
  88                len -= optlen;
  89        }
  90        /* not_found */
  91 bad:
  92        return -1;
  93}
  94EXPORT_SYMBOL_GPL(ipv6_find_tlv);
  95
  96/*
  97 *      Parsing tlv encoded headers.
  98 *
  99 *      Parsing function "func" returns true, if parsing succeed
 100 *      and false, if it failed.
 101 *      It MUST NOT touch skb->h.
 102 */
 103
 104struct tlvtype_proc {
 105        int     type;
 106        bool    (*func)(struct sk_buff *skb, int offset);
 107};
 108
 109/*********************
 110  Generic functions
 111 *********************/
 112
 113/* An unknown option is detected, decide what to do */
 114
 115static bool ip6_tlvopt_unknown(struct sk_buff *skb, int optoff)
 116{
 117        switch ((skb_network_header(skb)[optoff] & 0xC0) >> 6) {
 118        case 0: /* ignore */
 119                return true;
 120
 121        case 1: /* drop packet */
 122                break;
 123
 124        case 3: /* Send ICMP if not a multicast address and drop packet */
 125                /* Actually, it is redundant check. icmp_send
 126                   will recheck in any case.
 127                 */
 128                if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr))
 129                        break;
 130        case 2: /* send ICMP PARM PROB regardless and drop packet */
 131                icmpv6_param_prob(skb, ICMPV6_UNK_OPTION, optoff);
 132                return false;
 133        }
 134
 135        kfree_skb(skb);
 136        return false;
 137}
 138
 139/* Parse tlv encoded option header (hop-by-hop or destination) */
 140
 141static bool ip6_parse_tlv(const struct tlvtype_proc *procs, struct sk_buff *skb)
 142{
 143        const struct tlvtype_proc *curr;
 144        const unsigned char *nh = skb_network_header(skb);
 145        int off = skb_network_header_len(skb);
 146        int len = (skb_transport_header(skb)[1] + 1) << 3;
 147        int padlen = 0;
 148
 149        if (skb_transport_offset(skb) + len > skb_headlen(skb))
 150                goto bad;
 151
 152        off += 2;
 153        len -= 2;
 154
 155        while (len > 0) {
 156                int optlen = nh[off + 1] + 2;
 157                int i;
 158
 159                switch (nh[off]) {
 160                case IPV6_TLV_PAD1:
 161                        optlen = 1;
 162                        padlen++;
 163                        if (padlen > 7)
 164                                goto bad;
 165                        break;
 166
 167                case IPV6_TLV_PADN:
 168                        /* RFC 2460 states that the purpose of PadN is
 169                         * to align the containing header to multiples
 170                         * of 8. 7 is therefore the highest valid value.
 171                         * See also RFC 4942, Section 2.1.9.5.
 172                         */
 173                        padlen += optlen;
 174                        if (padlen > 7)
 175                                goto bad;
 176                        /* RFC 4942 recommends receiving hosts to
 177                         * actively check PadN payload to contain
 178                         * only zeroes.
 179                         */
 180                        for (i = 2; i < optlen; i++) {
 181                                if (nh[off + i] != 0)
 182                                        goto bad;
 183                        }
 184                        break;
 185
 186                default: /* Other TLV code so scan list */
 187                        if (optlen > len)
 188                                goto bad;
 189                        for (curr=procs; curr->type >= 0; curr++) {
 190                                if (curr->type == nh[off]) {
 191                                        /* type specific length/alignment
 192                                           checks will be performed in the
 193                                           func(). */
 194                                        if (curr->func(skb, off) == false)
 195                                                return false;
 196                                        break;
 197                                }
 198                        }
 199                        if (curr->type < 0) {
 200                                if (ip6_tlvopt_unknown(skb, off) == 0)
 201                                        return false;
 202                        }
 203                        padlen = 0;
 204                        break;
 205                }
 206                off += optlen;
 207                len -= optlen;
 208        }
 209        /* This case will not be caught by above check since its padding
 210         * length is smaller than 7:
 211         * 1 byte NH + 1 byte Length + 6 bytes Padding
 212         */
 213        if ((padlen == 6) && ((off - skb_network_header_len(skb)) == 8))
 214                goto bad;
 215
 216        if (len == 0)
 217                return true;
 218bad:
 219        kfree_skb(skb);
 220        return false;
 221}
 222
 223/*****************************
 224  Destination options header.
 225 *****************************/
 226
 227#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 228static bool ipv6_dest_hao(struct sk_buff *skb, int optoff)
 229{
 230        struct ipv6_destopt_hao *hao;
 231        struct inet6_skb_parm *opt = IP6CB(skb);
 232        struct ipv6hdr *ipv6h = ipv6_hdr(skb);
 233        struct in6_addr tmp_addr;
 234        int ret;
 235
 236        if (opt->dsthao) {
 237                LIMIT_NETDEBUG(KERN_DEBUG "hao duplicated\n");
 238                goto discard;
 239        }
 240        opt->dsthao = opt->dst1;
 241        opt->dst1 = 0;
 242
 243        hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + optoff);
 244
 245        if (hao->length != 16) {
 246                LIMIT_NETDEBUG(
 247                        KERN_DEBUG "hao invalid option length = %d\n", hao->length);
 248                goto discard;
 249        }
 250
 251        if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) {
 252                LIMIT_NETDEBUG(
 253                        KERN_DEBUG "hao is not an unicast addr: %pI6\n", &hao->addr);
 254                goto discard;
 255        }
 256
 257        ret = xfrm6_input_addr(skb, (xfrm_address_t *)&ipv6h->daddr,
 258                               (xfrm_address_t *)&hao->addr, IPPROTO_DSTOPTS);
 259        if (unlikely(ret < 0))
 260                goto discard;
 261
 262        if (skb_cloned(skb)) {
 263                if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
 264                        goto discard;
 265
 266                /* update all variable using below by copied skbuff */
 267                hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) +
 268                                                  optoff);
 269                ipv6h = ipv6_hdr(skb);
 270        }
 271
 272        if (skb->ip_summed == CHECKSUM_COMPLETE)
 273                skb->ip_summed = CHECKSUM_NONE;
 274
 275        tmp_addr = ipv6h->saddr;
 276        ipv6h->saddr = hao->addr;
 277        hao->addr = tmp_addr;
 278
 279        if (skb->tstamp.tv64 == 0)
 280                __net_timestamp(skb);
 281
 282        return true;
 283
 284 discard:
 285        kfree_skb(skb);
 286        return false;
 287}
 288#endif
 289
 290static const struct tlvtype_proc tlvprocdestopt_lst[] = {
 291#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 292        {
 293                .type   = IPV6_TLV_HAO,
 294                .func   = ipv6_dest_hao,
 295        },
 296#endif
 297        {-1,                    NULL}
 298};
 299
 300static int ipv6_destopt_rcv(struct sk_buff *skb)
 301{
 302        struct inet6_skb_parm *opt = IP6CB(skb);
 303#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 304        __u16 dstbuf;
 305#endif
 306        struct dst_entry *dst = skb_dst(skb);
 307
 308        if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
 309            !pskb_may_pull(skb, (skb_transport_offset(skb) +
 310                                 ((skb_transport_header(skb)[1] + 1) << 3)))) {
 311                IP6_INC_STATS_BH(dev_net(dst->dev), ip6_dst_idev(dst),
 312                                 IPSTATS_MIB_INHDRERRORS);
 313                kfree_skb(skb);
 314                return -1;
 315        }
 316
 317        opt->lastopt = opt->dst1 = skb_network_header_len(skb);
 318#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 319        dstbuf = opt->dst1;
 320#endif
 321
 322        if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
 323                skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
 324                opt = IP6CB(skb);
 325#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 326                opt->nhoff = dstbuf;
 327#else
 328                opt->nhoff = opt->dst1;
 329#endif
 330                return 1;
 331        }
 332
 333        IP6_INC_STATS_BH(dev_net(dst->dev),
 334                         ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
 335        return -1;
 336}
 337
 338/********************************
 339  Routing header.
 340 ********************************/
 341
 342/* called with rcu_read_lock() */
 343static int ipv6_rthdr_rcv(struct sk_buff *skb)
 344{
 345        struct inet6_skb_parm *opt = IP6CB(skb);
 346        struct in6_addr *addr = NULL;
 347        struct in6_addr daddr;
 348        struct inet6_dev *idev;
 349        int n, i;
 350        struct ipv6_rt_hdr *hdr;
 351        struct rt0_hdr *rthdr;
 352        struct net *net = dev_net(skb->dev);
 353        int accept_source_route = net->ipv6.devconf_all->accept_source_route;
 354
 355        idev = __in6_dev_get(skb->dev);
 356        if (idev && accept_source_route > idev->cnf.accept_source_route)
 357                accept_source_route = idev->cnf.accept_source_route;
 358
 359        if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
 360            !pskb_may_pull(skb, (skb_transport_offset(skb) +
 361                                 ((skb_transport_header(skb)[1] + 1) << 3)))) {
 362                IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 363                                 IPSTATS_MIB_INHDRERRORS);
 364                kfree_skb(skb);
 365                return -1;
 366        }
 367
 368        hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb);
 369
 370        if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
 371            skb->pkt_type != PACKET_HOST) {
 372                IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 373                                 IPSTATS_MIB_INADDRERRORS);
 374                kfree_skb(skb);
 375                return -1;
 376        }
 377
 378looped_back:
 379        if (hdr->segments_left == 0) {
 380                switch (hdr->type) {
 381#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 382                case IPV6_SRCRT_TYPE_2:
 383                        /* Silently discard type 2 header unless it was
 384                         * processed by own
 385                         */
 386                        if (!addr) {
 387                                IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 388                                                 IPSTATS_MIB_INADDRERRORS);
 389                                kfree_skb(skb);
 390                                return -1;
 391                        }
 392                        break;
 393#endif
 394                default:
 395                        break;
 396                }
 397
 398                opt->lastopt = opt->srcrt = skb_network_header_len(skb);
 399                skb->transport_header += (hdr->hdrlen + 1) << 3;
 400                opt->dst0 = opt->dst1;
 401                opt->dst1 = 0;
 402                opt->nhoff = (&hdr->nexthdr) - skb_network_header(skb);
 403                return 1;
 404        }
 405
 406        switch (hdr->type) {
 407#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 408        case IPV6_SRCRT_TYPE_2:
 409                if (accept_source_route < 0)
 410                        goto unknown_rh;
 411                /* Silently discard invalid RTH type 2 */
 412                if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
 413                        IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 414                                         IPSTATS_MIB_INHDRERRORS);
 415                        kfree_skb(skb);
 416                        return -1;
 417                }
 418                break;
 419#endif
 420        default:
 421                goto unknown_rh;
 422        }
 423
 424        /*
 425         *      This is the routing header forwarding algorithm from
 426         *      RFC 2460, page 16.
 427         */
 428
 429        n = hdr->hdrlen >> 1;
 430
 431        if (hdr->segments_left > n) {
 432                IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 433                                 IPSTATS_MIB_INHDRERRORS);
 434                icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
 435                                  ((&hdr->segments_left) -
 436                                   skb_network_header(skb)));
 437                return -1;
 438        }
 439
 440        /* We are about to mangle packet header. Be careful!
 441           Do not damage packets queued somewhere.
 442         */
 443        if (skb_cloned(skb)) {
 444                /* the copy is a forwarded packet */
 445                if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
 446                        IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 447                                         IPSTATS_MIB_OUTDISCARDS);
 448                        kfree_skb(skb);
 449                        return -1;
 450                }
 451                hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb);
 452        }
 453
 454        if (skb->ip_summed == CHECKSUM_COMPLETE)
 455                skb->ip_summed = CHECKSUM_NONE;
 456
 457        i = n - --hdr->segments_left;
 458
 459        rthdr = (struct rt0_hdr *) hdr;
 460        addr = rthdr->addr;
 461        addr += i - 1;
 462
 463        switch (hdr->type) {
 464#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 465        case IPV6_SRCRT_TYPE_2:
 466                if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
 467                                     (xfrm_address_t *)&ipv6_hdr(skb)->saddr,
 468                                     IPPROTO_ROUTING) < 0) {
 469                        IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 470                                         IPSTATS_MIB_INADDRERRORS);
 471                        kfree_skb(skb);
 472                        return -1;
 473                }
 474                if (!ipv6_chk_home_addr(dev_net(skb_dst(skb)->dev), addr)) {
 475                        IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 476                                         IPSTATS_MIB_INADDRERRORS);
 477                        kfree_skb(skb);
 478                        return -1;
 479                }
 480                break;
 481#endif
 482        default:
 483                break;
 484        }
 485
 486        if (ipv6_addr_is_multicast(addr)) {
 487                IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 488                                 IPSTATS_MIB_INADDRERRORS);
 489                kfree_skb(skb);
 490                return -1;
 491        }
 492
 493        daddr = *addr;
 494        *addr = ipv6_hdr(skb)->daddr;
 495        ipv6_hdr(skb)->daddr = daddr;
 496
 497        skb_dst_drop(skb);
 498        ip6_route_input(skb);
 499        if (skb_dst(skb)->error) {
 500                skb_push(skb, skb->data - skb_network_header(skb));
 501                dst_input(skb);
 502                return -1;
 503        }
 504
 505        if (skb_dst(skb)->dev->flags&IFF_LOOPBACK) {
 506                if (ipv6_hdr(skb)->hop_limit <= 1) {
 507                        IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 508                                         IPSTATS_MIB_INHDRERRORS);
 509                        icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
 510                                    0);
 511                        kfree_skb(skb);
 512                        return -1;
 513                }
 514                ipv6_hdr(skb)->hop_limit--;
 515                goto looped_back;
 516        }
 517
 518        skb_push(skb, skb->data - skb_network_header(skb));
 519        dst_input(skb);
 520        return -1;
 521
 522unknown_rh:
 523        IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INHDRERRORS);
 524        icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
 525                          (&hdr->type) - skb_network_header(skb));
 526        return -1;
 527}
 528
 529static const struct inet6_protocol rthdr_protocol = {
 530        .handler        =       ipv6_rthdr_rcv,
 531        .flags          =       INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
 532};
 533
 534static const struct inet6_protocol destopt_protocol = {
 535        .handler        =       ipv6_destopt_rcv,
 536        .flags          =       INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
 537};
 538
 539static const struct inet6_protocol nodata_protocol = {
 540        .handler        =       dst_discard,
 541        .flags          =       INET6_PROTO_NOPOLICY,
 542};
 543
 544int __init ipv6_exthdrs_init(void)
 545{
 546        int ret;
 547
 548        ret = inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING);
 549        if (ret)
 550                goto out;
 551
 552        ret = inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
 553        if (ret)
 554                goto out_rthdr;
 555
 556        ret = inet6_add_protocol(&nodata_protocol, IPPROTO_NONE);
 557        if (ret)
 558                goto out_destopt;
 559
 560out:
 561        return ret;
 562out_rthdr:
 563        inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
 564out_destopt:
 565        inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
 566        goto out;
 567};
 568
 569void ipv6_exthdrs_exit(void)
 570{
 571        inet6_del_protocol(&nodata_protocol, IPPROTO_NONE);
 572        inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
 573        inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
 574}
 575
 576/**********************************
 577  Hop-by-hop options.
 578 **********************************/
 579
 580/*
 581 * Note: we cannot rely on skb_dst(skb) before we assign it in ip6_route_input().
 582 */
 583static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb)
 584{
 585        return skb_dst(skb) ? ip6_dst_idev(skb_dst(skb)) : __in6_dev_get(skb->dev);
 586}
 587
 588static inline struct net *ipv6_skb_net(struct sk_buff *skb)
 589{
 590        return skb_dst(skb) ? dev_net(skb_dst(skb)->dev) : dev_net(skb->dev);
 591}
 592
 593/* Router Alert as of RFC 2711 */
 594
 595static bool ipv6_hop_ra(struct sk_buff *skb, int optoff)
 596{
 597        const unsigned char *nh = skb_network_header(skb);
 598
 599        if (nh[optoff + 1] == 2) {
 600                IP6CB(skb)->ra = optoff;
 601                return true;
 602        }
 603        LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n",
 604                       nh[optoff + 1]);
 605        kfree_skb(skb);
 606        return false;
 607}
 608
 609/* Jumbo payload */
 610
 611static bool ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
 612{
 613        const unsigned char *nh = skb_network_header(skb);
 614        struct net *net = ipv6_skb_net(skb);
 615        u32 pkt_len;
 616
 617        if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
 618                LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
 619                               nh[optoff+1]);
 620                IP6_INC_STATS_BH(net, ipv6_skb_idev(skb),
 621                                 IPSTATS_MIB_INHDRERRORS);
 622                goto drop;
 623        }
 624
 625        pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
 626        if (pkt_len <= IPV6_MAXPLEN) {
 627                IP6_INC_STATS_BH(net, ipv6_skb_idev(skb),
 628                                 IPSTATS_MIB_INHDRERRORS);
 629                icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
 630                return false;
 631        }
 632        if (ipv6_hdr(skb)->payload_len) {
 633                IP6_INC_STATS_BH(net, ipv6_skb_idev(skb),
 634                                 IPSTATS_MIB_INHDRERRORS);
 635                icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
 636                return false;
 637        }
 638
 639        if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
 640                IP6_INC_STATS_BH(net, ipv6_skb_idev(skb),
 641                                 IPSTATS_MIB_INTRUNCATEDPKTS);
 642                goto drop;
 643        }
 644
 645        if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
 646                goto drop;
 647
 648        return true;
 649
 650drop:
 651        kfree_skb(skb);
 652        return false;
 653}
 654
 655static const struct tlvtype_proc tlvprochopopt_lst[] = {
 656        {
 657                .type   = IPV6_TLV_ROUTERALERT,
 658                .func   = ipv6_hop_ra,
 659        },
 660        {
 661                .type   = IPV6_TLV_JUMBO,
 662                .func   = ipv6_hop_jumbo,
 663        },
 664        { -1, }
 665};
 666
 667int ipv6_parse_hopopts(struct sk_buff *skb)
 668{
 669        struct inet6_skb_parm *opt = IP6CB(skb);
 670
 671        /*
 672         * skb_network_header(skb) is equal to skb->data, and
 673         * skb_network_header_len(skb) is always equal to
 674         * sizeof(struct ipv6hdr) by definition of
 675         * hop-by-hop options.
 676         */
 677        if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
 678            !pskb_may_pull(skb, (sizeof(struct ipv6hdr) +
 679                                 ((skb_transport_header(skb)[1] + 1) << 3)))) {
 680                kfree_skb(skb);
 681                return -1;
 682        }
 683
 684        opt->hop = sizeof(struct ipv6hdr);
 685        if (ip6_parse_tlv(tlvprochopopt_lst, skb)) {
 686                skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
 687                opt = IP6CB(skb);
 688                opt->nhoff = sizeof(struct ipv6hdr);
 689                return 1;
 690        }
 691        return -1;
 692}
 693
 694/*
 695 *      Creating outbound headers.
 696 *
 697 *      "build" functions work when skb is filled from head to tail (datagram)
 698 *      "push"  functions work when headers are added from tail to head (tcp)
 699 *
 700 *      In both cases we assume, that caller reserved enough room
 701 *      for headers.
 702 */
 703
 704static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
 705                            struct ipv6_rt_hdr *opt,
 706                            struct in6_addr **addr_p)
 707{
 708        struct rt0_hdr *phdr, *ihdr;
 709        int hops;
 710
 711        ihdr = (struct rt0_hdr *) opt;
 712
 713        phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
 714        memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
 715
 716        hops = ihdr->rt_hdr.hdrlen >> 1;
 717
 718        if (hops > 1)
 719                memcpy(phdr->addr, ihdr->addr + 1,
 720                       (hops - 1) * sizeof(struct in6_addr));
 721
 722        phdr->addr[hops - 1] = **addr_p;
 723        *addr_p = ihdr->addr;
 724
 725        phdr->rt_hdr.nexthdr = *proto;
 726        *proto = NEXTHDR_ROUTING;
 727}
 728
 729static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
 730{
 731        struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
 732
 733        memcpy(h, opt, ipv6_optlen(opt));
 734        h->nexthdr = *proto;
 735        *proto = type;
 736}
 737
 738void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
 739                          u8 *proto,
 740                          struct in6_addr **daddr)
 741{
 742        if (opt->srcrt) {
 743                ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
 744                /*
 745                 * IPV6_RTHDRDSTOPTS is ignored
 746                 * unless IPV6_RTHDR is set (RFC3542).
 747                 */
 748                if (opt->dst0opt)
 749                        ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
 750        }
 751        if (opt->hopopt)
 752                ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
 753}
 754EXPORT_SYMBOL(ipv6_push_nfrag_opts);
 755
 756void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
 757{
 758        if (opt->dst1opt)
 759                ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
 760}
 761
 762struct ipv6_txoptions *
 763ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
 764{
 765        struct ipv6_txoptions *opt2;
 766
 767        opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC);
 768        if (opt2) {
 769                long dif = (char *)opt2 - (char *)opt;
 770                memcpy(opt2, opt, opt->tot_len);
 771                if (opt2->hopopt)
 772                        *((char **)&opt2->hopopt) += dif;
 773                if (opt2->dst0opt)
 774                        *((char **)&opt2->dst0opt) += dif;
 775                if (opt2->dst1opt)
 776                        *((char **)&opt2->dst1opt) += dif;
 777                if (opt2->srcrt)
 778                        *((char **)&opt2->srcrt) += dif;
 779        }
 780        return opt2;
 781}
 782EXPORT_SYMBOL_GPL(ipv6_dup_options);
 783
 784static int ipv6_renew_option(void *ohdr,
 785                             struct ipv6_opt_hdr __user *newopt, int newoptlen,
 786                             int inherit,
 787                             struct ipv6_opt_hdr **hdr,
 788                             char **p)
 789{
 790        if (inherit) {
 791                if (ohdr) {
 792                        memcpy(*p, ohdr, ipv6_optlen((struct ipv6_opt_hdr *)ohdr));
 793                        *hdr = (struct ipv6_opt_hdr *)*p;
 794                        *p += CMSG_ALIGN(ipv6_optlen(*hdr));
 795                }
 796        } else {
 797                if (newopt) {
 798                        if (copy_from_user(*p, newopt, newoptlen))
 799                                return -EFAULT;
 800                        *hdr = (struct ipv6_opt_hdr *)*p;
 801                        if (ipv6_optlen(*hdr) > newoptlen)
 802                                return -EINVAL;
 803                        *p += CMSG_ALIGN(newoptlen);
 804                }
 805        }
 806        return 0;
 807}
 808
 809struct ipv6_txoptions *
 810ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
 811                   int newtype,
 812                   struct ipv6_opt_hdr __user *newopt, int newoptlen)
 813{
 814        int tot_len = 0;
 815        char *p;
 816        struct ipv6_txoptions *opt2;
 817        int err;
 818
 819        if (opt) {
 820                if (newtype != IPV6_HOPOPTS && opt->hopopt)
 821                        tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
 822                if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
 823                        tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
 824                if (newtype != IPV6_RTHDR && opt->srcrt)
 825                        tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
 826                if (newtype != IPV6_DSTOPTS && opt->dst1opt)
 827                        tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
 828        }
 829
 830        if (newopt && newoptlen)
 831                tot_len += CMSG_ALIGN(newoptlen);
 832
 833        if (!tot_len)
 834                return NULL;
 835
 836        tot_len += sizeof(*opt2);
 837        opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
 838        if (!opt2)
 839                return ERR_PTR(-ENOBUFS);
 840
 841        memset(opt2, 0, tot_len);
 842
 843        opt2->tot_len = tot_len;
 844        p = (char *)(opt2 + 1);
 845
 846        err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen,
 847                                newtype != IPV6_HOPOPTS,
 848                                &opt2->hopopt, &p);
 849        if (err)
 850                goto out;
 851
 852        err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen,
 853                                newtype != IPV6_RTHDRDSTOPTS,
 854                                &opt2->dst0opt, &p);
 855        if (err)
 856                goto out;
 857
 858        err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen,
 859                                newtype != IPV6_RTHDR,
 860                                (struct ipv6_opt_hdr **)&opt2->srcrt, &p);
 861        if (err)
 862                goto out;
 863
 864        err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen,
 865                                newtype != IPV6_DSTOPTS,
 866                                &opt2->dst1opt, &p);
 867        if (err)
 868                goto out;
 869
 870        opt2->opt_nflen = (opt2->hopopt ? ipv6_optlen(opt2->hopopt) : 0) +
 871                          (opt2->dst0opt ? ipv6_optlen(opt2->dst0opt) : 0) +
 872                          (opt2->srcrt ? ipv6_optlen(opt2->srcrt) : 0);
 873        opt2->opt_flen = (opt2->dst1opt ? ipv6_optlen(opt2->dst1opt) : 0);
 874
 875        return opt2;
 876out:
 877        sock_kfree_s(sk, opt2, opt2->tot_len);
 878        return ERR_PTR(err);
 879}
 880
 881struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
 882                                          struct ipv6_txoptions *opt)
 883{
 884        /*
 885         * ignore the dest before srcrt unless srcrt is being included.
 886         * --yoshfuji
 887         */
 888        if (opt && opt->dst0opt && !opt->srcrt) {
 889                if (opt_space != opt) {
 890                        memcpy(opt_space, opt, sizeof(*opt_space));
 891                        opt = opt_space;
 892                }
 893                opt->opt_nflen -= ipv6_optlen(opt->dst0opt);
 894                opt->dst0opt = NULL;
 895        }
 896
 897        return opt;
 898}
 899EXPORT_SYMBOL_GPL(ipv6_fixup_options);
 900
 901/**
 902 * fl6_update_dst - update flowi destination address with info given
 903 *                  by srcrt option, if any.
 904 *
 905 * @fl6: flowi6 for which daddr is to be updated
 906 * @opt: struct ipv6_txoptions in which to look for srcrt opt
 907 * @orig: copy of original daddr address if modified
 908 *
 909 * Returns NULL if no txoptions or no srcrt, otherwise returns orig
 910 * and initial value of fl6->daddr set in orig
 911 */
 912struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
 913                                const struct ipv6_txoptions *opt,
 914                                struct in6_addr *orig)
 915{
 916        if (!opt || !opt->srcrt)
 917                return NULL;
 918
 919        *orig = fl6->daddr;
 920        fl6->daddr = *((struct rt0_hdr *)opt->srcrt)->addr;
 921        return orig;
 922}
 923EXPORT_SYMBOL_GPL(fl6_update_dst);
 924
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.