~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise-security

« back to all changes in this revision

Viewing changes to net/ipv6/ndisc.c

  • Committer: Package Import Robot
  • Author(s): Paolo Pisati, Paolo Pisati
  • Date: 2011-12-06 15:56:07 UTC
  • Revision ID: package-import@ubuntu.com-20111206155607-pcf44kv5fmhk564f
Tags: 3.2.0-1401.1
[ Paolo Pisati ]

* Rebased on top of Ubuntu-3.2.0-3.8
* Tilt-tracking @ ef2487af4bb15bdd0689631774b5a5e3a59f74e2
* Delete debian.ti-omap4/control, it shoudln't be tracked
* Fix architecture spelling (s/armel/armhf/)
* [Config] Update configs following 3.2 import
* [Config] Fix compilation: disable CODA and ARCH_OMAP3
* [Config] Fix compilation: disable Ethernet Faraday
* Update series to precise

Show diffs side-by-side

added added

removed removed

Lines of Context:
107
107
        .error_report =         ndisc_error_report,
108
108
        .output =               neigh_resolve_output,
109
109
        .connected_output =     neigh_connected_output,
110
 
        .hh_output =            dev_queue_xmit,
111
 
        .queue_xmit =           dev_queue_xmit,
112
110
};
113
111
 
114
112
static const struct neigh_ops ndisc_hh_ops = {
117
115
        .error_report =         ndisc_error_report,
118
116
        .output =               neigh_resolve_output,
119
117
        .connected_output =     neigh_resolve_output,
120
 
        .hh_output =            dev_queue_xmit,
121
 
        .queue_xmit =           dev_queue_xmit,
122
118
};
123
119
 
124
120
 
125
121
static const struct neigh_ops ndisc_direct_ops = {
126
122
        .family =               AF_INET6,
127
 
        .output =               dev_queue_xmit,
128
 
        .connected_output =     dev_queue_xmit,
129
 
        .hh_output =            dev_queue_xmit,
130
 
        .queue_xmit =           dev_queue_xmit,
 
123
        .output =               neigh_direct_output,
 
124
        .connected_output =     neigh_direct_output,
131
125
};
132
126
 
133
127
struct neigh_table nd_tbl = {
376
370
        struct neigh_parms *parms;
377
371
        int is_multicast = ipv6_addr_is_multicast(addr);
378
372
 
379
 
        rcu_read_lock();
380
373
        in6_dev = in6_dev_get(dev);
381
374
        if (in6_dev == NULL) {
382
 
                rcu_read_unlock();
383
375
                return -EINVAL;
384
376
        }
385
377
 
386
378
        parms = in6_dev->nd_parms;
387
379
        __neigh_parms_put(neigh->parms);
388
380
        neigh->parms = neigh_parms_clone(parms);
389
 
        rcu_read_unlock();
390
381
 
391
382
        neigh->type = is_multicast ? RTN_MULTICAST : RTN_UNICAST;
392
383
        if (!dev->header_ops) {
393
384
                neigh->nud_state = NUD_NOARP;
394
385
                neigh->ops = &ndisc_direct_ops;
395
 
                neigh->output = neigh->ops->queue_xmit;
 
386
                neigh->output = neigh_direct_output;
396
387
        } else {
397
388
                if (is_multicast) {
398
389
                        neigh->nud_state = NUD_NOARP;
539
530
 
540
531
        skb_dst_set(skb, dst);
541
532
 
542
 
        idev = in6_dev_get(dst->dev);
 
533
        rcu_read_lock();
 
534
        idev = __in6_dev_get(dst->dev);
543
535
        IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
544
536
 
545
537
        err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
549
541
                ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
550
542
        }
551
543
 
552
 
        if (likely(idev != NULL))
553
 
                in6_dev_put(idev);
 
544
        rcu_read_unlock();
554
545
}
555
546
 
556
547
EXPORT_SYMBOL(ndisc_send_skb);
1045
1036
        if (skb->len < sizeof(*rs_msg))
1046
1037
                return;
1047
1038
 
1048
 
        idev = in6_dev_get(skb->dev);
 
1039
        idev = __in6_dev_get(skb->dev);
1049
1040
        if (!idev) {
1050
1041
                if (net_ratelimit())
1051
1042
                        ND_PRINTK1("ICMP6 RS: can't find in6 device\n");
1086
1077
                neigh_release(neigh);
1087
1078
        }
1088
1079
out:
1089
 
        in6_dev_put(idev);
 
1080
        return;
1090
1081
}
1091
1082
 
1092
1083
static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt)
1185
1176
         *      set the RA_RECV flag in the interface
1186
1177
         */
1187
1178
 
1188
 
        in6_dev = in6_dev_get(skb->dev);
 
1179
        in6_dev = __in6_dev_get(skb->dev);
1189
1180
        if (in6_dev == NULL) {
1190
1181
                ND_PRINTK0(KERN_ERR
1191
1182
                           "ICMPv6 RA: can't find inet6 device for %s.\n",
1194
1185
        }
1195
1186
 
1196
1187
        if (!ndisc_parse_options(opt, optlen, &ndopts)) {
1197
 
                in6_dev_put(in6_dev);
1198
1188
                ND_PRINTK2(KERN_WARNING
1199
1189
                           "ICMP6 RA: invalid ND options\n");
1200
1190
                return;
1231
1221
        if (!in6_dev->cnf.accept_ra_defrtr)
1232
1222
                goto skip_defrtr;
1233
1223
 
 
1224
        if (ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, NULL, 0))
 
1225
                goto skip_defrtr;
 
1226
 
1234
1227
        lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);
1235
1228
 
1236
1229
#ifdef CONFIG_IPV6_ROUTER_PREF
1244
1237
        rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev);
1245
1238
 
1246
1239
        if (rt)
1247
 
                neigh = rt->rt6i_nexthop;
 
1240
                neigh = dst_get_neighbour(&rt->dst);
1248
1241
 
1249
1242
        if (rt && lifetime == 0) {
1250
1243
                neigh_clone(neigh);
1261
1254
                        ND_PRINTK0(KERN_ERR
1262
1255
                                   "ICMPv6 RA: %s() failed to add default route.\n",
1263
1256
                                   __func__);
1264
 
                        in6_dev_put(in6_dev);
1265
1257
                        return;
1266
1258
                }
1267
1259
 
1268
 
                neigh = rt->rt6i_nexthop;
 
1260
                neigh = dst_get_neighbour(&rt->dst);
1269
1261
                if (neigh == NULL) {
1270
1262
                        ND_PRINTK0(KERN_ERR
1271
1263
                                   "ICMPv6 RA: %s() got default router without neighbour.\n",
1272
1264
                                   __func__);
1273
1265
                        dst_release(&rt->dst);
1274
 
                        in6_dev_put(in6_dev);
1275
1266
                        return;
1276
1267
                }
1277
1268
                neigh->flags |= NTF_ROUTER;
1355
1346
                goto out;
1356
1347
 
1357
1348
#ifdef CONFIG_IPV6_ROUTE_INFO
 
1349
        if (ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, NULL, 0))
 
1350
                goto skip_routeinfo;
 
1351
 
1358
1352
        if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) {
1359
1353
                struct nd_opt_hdr *p;
1360
1354
                for (p = ndopts.nd_opts_ri;
1372
1366
                                      &ipv6_hdr(skb)->saddr);
1373
1367
                }
1374
1368
        }
 
1369
 
 
1370
skip_routeinfo:
1375
1371
#endif
1376
1372
 
1377
1373
#ifdef CONFIG_IPV6_NDISC_NODETYPE
1428
1424
                dst_release(&rt->dst);
1429
1425
        else if (neigh)
1430
1426
                neigh_release(neigh);
1431
 
        in6_dev_put(in6_dev);
1432
1427
}
1433
1428
 
1434
1429
static void ndisc_redirect_rcv(struct sk_buff *skb)
1487
1482
                return;
1488
1483
        }
1489
1484
 
1490
 
        in6_dev = in6_dev_get(skb->dev);
 
1485
        in6_dev = __in6_dev_get(skb->dev);
1491
1486
        if (!in6_dev)
1492
1487
                return;
1493
 
        if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects) {
1494
 
                in6_dev_put(in6_dev);
 
1488
        if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects)
1495
1489
                return;
1496
 
        }
1497
1490
 
1498
1491
        /* RFC2461 8.1:
1499
1492
         *      The IP source address of the Redirect MUST be the same as the current
1503
1496
        if (!ndisc_parse_options((u8*)(dest + 1), optlen, &ndopts)) {
1504
1497
                ND_PRINTK2(KERN_WARNING
1505
1498
                           "ICMPv6 Redirect: invalid ND options\n");
1506
 
                in6_dev_put(in6_dev);
1507
1499
                return;
1508
1500
        }
1509
1501
        if (ndopts.nd_opts_tgt_lladdr) {
1512
1504
                if (!lladdr) {
1513
1505
                        ND_PRINTK2(KERN_WARNING
1514
1506
                                   "ICMPv6 Redirect: invalid link-layer address length\n");
1515
 
                        in6_dev_put(in6_dev);
1516
1507
                        return;
1517
1508
                }
1518
1509
        }
1524
1515
                             on_link);
1525
1516
                neigh_release(neigh);
1526
1517
        }
1527
 
        in6_dev_put(in6_dev);
1528
1518
}
1529
1519
 
1530
1520
void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
1581
1571
        }
1582
1572
        if (!rt->rt6i_peer)
1583
1573
                rt6_bind_peer(rt, 1);
1584
 
        if (inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ))
 
1574
        if (!inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ))
1585
1575
                goto release;
1586
1576
 
1587
1577
        if (dev->addr_len) {
1657
1647
                                             csum_partial(icmph, len, 0));
1658
1648
 
1659
1649
        skb_dst_set(buff, dst);
1660
 
        idev = in6_dev_get(dst->dev);
 
1650
        rcu_read_lock();
 
1651
        idev = __in6_dev_get(dst->dev);
1661
1652
        IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
1662
1653
        err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev,
1663
1654
                      dst_output);
1666
1657
                ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
1667
1658
        }
1668
1659
 
1669
 
        if (likely(idev != NULL))
1670
 
                in6_dev_put(idev);
 
1660
        rcu_read_unlock();
1671
1661
        return;
1672
1662
 
1673
1663
release: