diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r-- | net/ipv6/addrconf.c | 233 |
1 files changed, 140 insertions, 93 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 21c2c818df3b..53e3a9d756b0 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -195,6 +195,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = { | |||
195 | .max_addresses = IPV6_MAX_ADDRESSES, | 195 | .max_addresses = IPV6_MAX_ADDRESSES, |
196 | .accept_ra_defrtr = 1, | 196 | .accept_ra_defrtr = 1, |
197 | .accept_ra_from_local = 0, | 197 | .accept_ra_from_local = 0, |
198 | .accept_ra_min_hop_limit= 1, | ||
198 | .accept_ra_pinfo = 1, | 199 | .accept_ra_pinfo = 1, |
199 | #ifdef CONFIG_IPV6_ROUTER_PREF | 200 | #ifdef CONFIG_IPV6_ROUTER_PREF |
200 | .accept_ra_rtr_pref = 1, | 201 | .accept_ra_rtr_pref = 1, |
@@ -211,7 +212,8 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = { | |||
211 | .accept_ra_mtu = 1, | 212 | .accept_ra_mtu = 1, |
212 | .stable_secret = { | 213 | .stable_secret = { |
213 | .initialized = false, | 214 | .initialized = false, |
214 | } | 215 | }, |
216 | .use_oif_addrs_only = 0, | ||
215 | }; | 217 | }; |
216 | 218 | ||
217 | static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { | 219 | static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { |
@@ -236,6 +238,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { | |||
236 | .max_addresses = IPV6_MAX_ADDRESSES, | 238 | .max_addresses = IPV6_MAX_ADDRESSES, |
237 | .accept_ra_defrtr = 1, | 239 | .accept_ra_defrtr = 1, |
238 | .accept_ra_from_local = 0, | 240 | .accept_ra_from_local = 0, |
241 | .accept_ra_min_hop_limit= 1, | ||
239 | .accept_ra_pinfo = 1, | 242 | .accept_ra_pinfo = 1, |
240 | #ifdef CONFIG_IPV6_ROUTER_PREF | 243 | #ifdef CONFIG_IPV6_ROUTER_PREF |
241 | .accept_ra_rtr_pref = 1, | 244 | .accept_ra_rtr_pref = 1, |
@@ -253,6 +256,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { | |||
253 | .stable_secret = { | 256 | .stable_secret = { |
254 | .initialized = false, | 257 | .initialized = false, |
255 | }, | 258 | }, |
259 | .use_oif_addrs_only = 0, | ||
256 | }; | 260 | }; |
257 | 261 | ||
258 | /* Check if a valid qdisc is available */ | 262 | /* Check if a valid qdisc is available */ |
@@ -1358,15 +1362,96 @@ out: | |||
1358 | return ret; | 1362 | return ret; |
1359 | } | 1363 | } |
1360 | 1364 | ||
1365 | static int __ipv6_dev_get_saddr(struct net *net, | ||
1366 | struct ipv6_saddr_dst *dst, | ||
1367 | struct inet6_dev *idev, | ||
1368 | struct ipv6_saddr_score *scores, | ||
1369 | int hiscore_idx) | ||
1370 | { | ||
1371 | struct ipv6_saddr_score *score = &scores[1 - hiscore_idx], *hiscore = &scores[hiscore_idx]; | ||
1372 | |||
1373 | read_lock_bh(&idev->lock); | ||
1374 | list_for_each_entry(score->ifa, &idev->addr_list, if_list) { | ||
1375 | int i; | ||
1376 | |||
1377 | /* | ||
1378 | * - Tentative Address (RFC2462 section 5.4) | ||
1379 | * - A tentative address is not considered | ||
1380 | * "assigned to an interface" in the traditional | ||
1381 | * sense, unless it is also flagged as optimistic. | ||
1382 | * - Candidate Source Address (section 4) | ||
1383 | * - In any case, anycast addresses, multicast | ||
1384 | * addresses, and the unspecified address MUST | ||
1385 | * NOT be included in a candidate set. | ||
1386 | */ | ||
1387 | if ((score->ifa->flags & IFA_F_TENTATIVE) && | ||
1388 | (!(score->ifa->flags & IFA_F_OPTIMISTIC))) | ||
1389 | continue; | ||
1390 | |||
1391 | score->addr_type = __ipv6_addr_type(&score->ifa->addr); | ||
1392 | |||
1393 | if (unlikely(score->addr_type == IPV6_ADDR_ANY || | ||
1394 | score->addr_type & IPV6_ADDR_MULTICAST)) { | ||
1395 | net_dbg_ratelimited("ADDRCONF: unspecified / multicast address assigned as unicast address on %s", | ||
1396 | idev->dev->name); | ||
1397 | continue; | ||
1398 | } | ||
1399 | |||
1400 | score->rule = -1; | ||
1401 | bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX); | ||
1402 | |||
1403 | for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) { | ||
1404 | int minihiscore, miniscore; | ||
1405 | |||
1406 | minihiscore = ipv6_get_saddr_eval(net, hiscore, dst, i); | ||
1407 | miniscore = ipv6_get_saddr_eval(net, score, dst, i); | ||
1408 | |||
1409 | if (minihiscore > miniscore) { | ||
1410 | if (i == IPV6_SADDR_RULE_SCOPE && | ||
1411 | score->scopedist > 0) { | ||
1412 | /* | ||
1413 | * special case: | ||
1414 | * each remaining entry | ||
1415 | * has too small (not enough) | ||
1416 | * scope, because ifa entries | ||
1417 | * are sorted by their scope | ||
1418 | * values. | ||
1419 | */ | ||
1420 | goto out; | ||
1421 | } | ||
1422 | break; | ||
1423 | } else if (minihiscore < miniscore) { | ||
1424 | if (hiscore->ifa) | ||
1425 | in6_ifa_put(hiscore->ifa); | ||
1426 | |||
1427 | in6_ifa_hold(score->ifa); | ||
1428 | |||
1429 | swap(hiscore, score); | ||
1430 | hiscore_idx = 1 - hiscore_idx; | ||
1431 | |||
1432 | /* restore our iterator */ | ||
1433 | score->ifa = hiscore->ifa; | ||
1434 | |||
1435 | break; | ||
1436 | } | ||
1437 | } | ||
1438 | } | ||
1439 | out: | ||
1440 | read_unlock_bh(&idev->lock); | ||
1441 | return hiscore_idx; | ||
1442 | } | ||
1443 | |||
1361 | int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev, | 1444 | int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev, |
1362 | const struct in6_addr *daddr, unsigned int prefs, | 1445 | const struct in6_addr *daddr, unsigned int prefs, |
1363 | struct in6_addr *saddr) | 1446 | struct in6_addr *saddr) |
1364 | { | 1447 | { |
1365 | struct ipv6_saddr_score scores[2], | 1448 | struct ipv6_saddr_score scores[2], *hiscore; |
1366 | *score = &scores[0], *hiscore = &scores[1]; | ||
1367 | struct ipv6_saddr_dst dst; | 1449 | struct ipv6_saddr_dst dst; |
1450 | struct inet6_dev *idev; | ||
1368 | struct net_device *dev; | 1451 | struct net_device *dev; |
1369 | int dst_type; | 1452 | int dst_type; |
1453 | bool use_oif_addr = false; | ||
1454 | int hiscore_idx = 0; | ||
1370 | 1455 | ||
1371 | dst_type = __ipv6_addr_type(daddr); | 1456 | dst_type = __ipv6_addr_type(daddr); |
1372 | dst.addr = daddr; | 1457 | dst.addr = daddr; |
@@ -1375,105 +1460,50 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev, | |||
1375 | dst.label = ipv6_addr_label(net, daddr, dst_type, dst.ifindex); | 1460 | dst.label = ipv6_addr_label(net, daddr, dst_type, dst.ifindex); |
1376 | dst.prefs = prefs; | 1461 | dst.prefs = prefs; |
1377 | 1462 | ||
1378 | hiscore->rule = -1; | 1463 | scores[hiscore_idx].rule = -1; |
1379 | hiscore->ifa = NULL; | 1464 | scores[hiscore_idx].ifa = NULL; |
1380 | 1465 | ||
1381 | rcu_read_lock(); | 1466 | rcu_read_lock(); |
1382 | 1467 | ||
1383 | for_each_netdev_rcu(net, dev) { | 1468 | /* Candidate Source Address (section 4) |
1384 | struct inet6_dev *idev; | 1469 | * - multicast and link-local destination address, |
1385 | 1470 | * the set of candidate source address MUST only | |
1386 | /* Candidate Source Address (section 4) | 1471 | * include addresses assigned to interfaces |
1387 | * - multicast and link-local destination address, | 1472 | * belonging to the same link as the outgoing |
1388 | * the set of candidate source address MUST only | 1473 | * interface. |
1389 | * include addresses assigned to interfaces | 1474 | * (- For site-local destination addresses, the |
1390 | * belonging to the same link as the outgoing | 1475 | * set of candidate source addresses MUST only |
1391 | * interface. | 1476 | * include addresses assigned to interfaces |
1392 | * (- For site-local destination addresses, the | 1477 | * belonging to the same site as the outgoing |
1393 | * set of candidate source addresses MUST only | 1478 | * interface.) |
1394 | * include addresses assigned to interfaces | 1479 | * - "It is RECOMMENDED that the candidate source addresses |
1395 | * belonging to the same site as the outgoing | 1480 | * be the set of unicast addresses assigned to the |
1396 | * interface.) | 1481 | * interface that will be used to send to the destination |
1397 | */ | 1482 | * (the 'outgoing' interface)." (RFC 6724) |
1398 | if (((dst_type & IPV6_ADDR_MULTICAST) || | 1483 | */ |
1399 | dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL) && | 1484 | if (dst_dev) { |
1400 | dst.ifindex && dev->ifindex != dst.ifindex) | 1485 | idev = __in6_dev_get(dst_dev); |
1401 | continue; | 1486 | if ((dst_type & IPV6_ADDR_MULTICAST) || |
1402 | 1487 | dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL || | |
1403 | idev = __in6_dev_get(dev); | 1488 | (idev && idev->cnf.use_oif_addrs_only)) { |
1404 | if (!idev) | 1489 | use_oif_addr = true; |
1405 | continue; | 1490 | } |
1406 | 1491 | } | |
1407 | read_lock_bh(&idev->lock); | ||
1408 | list_for_each_entry(score->ifa, &idev->addr_list, if_list) { | ||
1409 | int i; | ||
1410 | |||
1411 | /* | ||
1412 | * - Tentative Address (RFC2462 section 5.4) | ||
1413 | * - A tentative address is not considered | ||
1414 | * "assigned to an interface" in the traditional | ||
1415 | * sense, unless it is also flagged as optimistic. | ||
1416 | * - Candidate Source Address (section 4) | ||
1417 | * - In any case, anycast addresses, multicast | ||
1418 | * addresses, and the unspecified address MUST | ||
1419 | * NOT be included in a candidate set. | ||
1420 | */ | ||
1421 | if ((score->ifa->flags & IFA_F_TENTATIVE) && | ||
1422 | (!(score->ifa->flags & IFA_F_OPTIMISTIC))) | ||
1423 | continue; | ||
1424 | |||
1425 | score->addr_type = __ipv6_addr_type(&score->ifa->addr); | ||
1426 | 1492 | ||
1427 | if (unlikely(score->addr_type == IPV6_ADDR_ANY || | 1493 | if (use_oif_addr) { |
1428 | score->addr_type & IPV6_ADDR_MULTICAST)) { | 1494 | if (idev) |
1429 | net_dbg_ratelimited("ADDRCONF: unspecified / multicast address assigned as unicast address on %s", | 1495 | hiscore_idx = __ipv6_dev_get_saddr(net, &dst, idev, scores, hiscore_idx); |
1430 | dev->name); | 1496 | } else { |
1497 | for_each_netdev_rcu(net, dev) { | ||
1498 | idev = __in6_dev_get(dev); | ||
1499 | if (!idev) | ||
1431 | continue; | 1500 | continue; |
1432 | } | 1501 | hiscore_idx = __ipv6_dev_get_saddr(net, &dst, idev, scores, hiscore_idx); |
1433 | |||
1434 | score->rule = -1; | ||
1435 | bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX); | ||
1436 | |||
1437 | for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) { | ||
1438 | int minihiscore, miniscore; | ||
1439 | |||
1440 | minihiscore = ipv6_get_saddr_eval(net, hiscore, &dst, i); | ||
1441 | miniscore = ipv6_get_saddr_eval(net, score, &dst, i); | ||
1442 | |||
1443 | if (minihiscore > miniscore) { | ||
1444 | if (i == IPV6_SADDR_RULE_SCOPE && | ||
1445 | score->scopedist > 0) { | ||
1446 | /* | ||
1447 | * special case: | ||
1448 | * each remaining entry | ||
1449 | * has too small (not enough) | ||
1450 | * scope, because ifa entries | ||
1451 | * are sorted by their scope | ||
1452 | * values. | ||
1453 | */ | ||
1454 | goto try_nextdev; | ||
1455 | } | ||
1456 | break; | ||
1457 | } else if (minihiscore < miniscore) { | ||
1458 | if (hiscore->ifa) | ||
1459 | in6_ifa_put(hiscore->ifa); | ||
1460 | |||
1461 | in6_ifa_hold(score->ifa); | ||
1462 | |||
1463 | swap(hiscore, score); | ||
1464 | |||
1465 | /* restore our iterator */ | ||
1466 | score->ifa = hiscore->ifa; | ||
1467 | |||
1468 | break; | ||
1469 | } | ||
1470 | } | ||
1471 | } | 1502 | } |
1472 | try_nextdev: | ||
1473 | read_unlock_bh(&idev->lock); | ||
1474 | } | 1503 | } |
1475 | rcu_read_unlock(); | 1504 | rcu_read_unlock(); |
1476 | 1505 | ||
1506 | hiscore = &scores[hiscore_idx]; | ||
1477 | if (!hiscore->ifa) | 1507 | if (!hiscore->ifa) |
1478 | return -EADDRNOTAVAIL; | 1508 | return -EADDRNOTAVAIL; |
1479 | 1509 | ||
@@ -4560,6 +4590,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, | |||
4560 | array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor; | 4590 | array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor; |
4561 | array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses; | 4591 | array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses; |
4562 | array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr; | 4592 | array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr; |
4593 | array[DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT] = cnf->accept_ra_min_hop_limit; | ||
4563 | array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo; | 4594 | array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo; |
4564 | #ifdef CONFIG_IPV6_ROUTER_PREF | 4595 | #ifdef CONFIG_IPV6_ROUTER_PREF |
4565 | array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref; | 4596 | array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref; |
@@ -4586,6 +4617,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, | |||
4586 | array[DEVCONF_ACCEPT_RA_FROM_LOCAL] = cnf->accept_ra_from_local; | 4617 | array[DEVCONF_ACCEPT_RA_FROM_LOCAL] = cnf->accept_ra_from_local; |
4587 | array[DEVCONF_ACCEPT_RA_MTU] = cnf->accept_ra_mtu; | 4618 | array[DEVCONF_ACCEPT_RA_MTU] = cnf->accept_ra_mtu; |
4588 | /* we omit DEVCONF_STABLE_SECRET for now */ | 4619 | /* we omit DEVCONF_STABLE_SECRET for now */ |
4620 | array[DEVCONF_USE_OIF_ADDRS_ONLY] = cnf->use_oif_addrs_only; | ||
4589 | } | 4621 | } |
4590 | 4622 | ||
4591 | static inline size_t inet6_ifla6_size(void) | 4623 | static inline size_t inet6_ifla6_size(void) |
@@ -5456,6 +5488,13 @@ static struct addrconf_sysctl_table | |||
5456 | .proc_handler = proc_dointvec, | 5488 | .proc_handler = proc_dointvec, |
5457 | }, | 5489 | }, |
5458 | { | 5490 | { |
5491 | .procname = "accept_ra_min_hop_limit", | ||
5492 | .data = &ipv6_devconf.accept_ra_min_hop_limit, | ||
5493 | .maxlen = sizeof(int), | ||
5494 | .mode = 0644, | ||
5495 | .proc_handler = proc_dointvec, | ||
5496 | }, | ||
5497 | { | ||
5459 | .procname = "accept_ra_pinfo", | 5498 | .procname = "accept_ra_pinfo", |
5460 | .data = &ipv6_devconf.accept_ra_pinfo, | 5499 | .data = &ipv6_devconf.accept_ra_pinfo, |
5461 | .maxlen = sizeof(int), | 5500 | .maxlen = sizeof(int), |
@@ -5585,6 +5624,14 @@ static struct addrconf_sysctl_table | |||
5585 | .proc_handler = addrconf_sysctl_stable_secret, | 5624 | .proc_handler = addrconf_sysctl_stable_secret, |
5586 | }, | 5625 | }, |
5587 | { | 5626 | { |
5627 | .procname = "use_oif_addrs_only", | ||
5628 | .data = &ipv6_devconf.use_oif_addrs_only, | ||
5629 | .maxlen = sizeof(int), | ||
5630 | .mode = 0644, | ||
5631 | .proc_handler = proc_dointvec, | ||
5632 | |||
5633 | }, | ||
5634 | { | ||
5588 | /* sentinel */ | 5635 | /* sentinel */ |
5589 | } | 5636 | } |
5590 | }, | 5637 | }, |