diff options
Diffstat (limited to 'net/ipv6')
| -rw-r--r-- | net/ipv6/addrconf.c | 27 | ||||
| -rw-r--r-- | net/ipv6/ip6_input.c | 12 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6t_NPT.c | 2 | ||||
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 1 |
4 files changed, 41 insertions, 1 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 26512250e095..a459c4f5b769 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -2529,6 +2529,9 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) | |||
| 2529 | static void init_loopback(struct net_device *dev) | 2529 | static void init_loopback(struct net_device *dev) |
| 2530 | { | 2530 | { |
| 2531 | struct inet6_dev *idev; | 2531 | struct inet6_dev *idev; |
| 2532 | struct net_device *sp_dev; | ||
| 2533 | struct inet6_ifaddr *sp_ifa; | ||
| 2534 | struct rt6_info *sp_rt; | ||
| 2532 | 2535 | ||
| 2533 | /* ::1 */ | 2536 | /* ::1 */ |
| 2534 | 2537 | ||
| @@ -2540,6 +2543,30 @@ static void init_loopback(struct net_device *dev) | |||
| 2540 | } | 2543 | } |
| 2541 | 2544 | ||
| 2542 | add_addr(idev, &in6addr_loopback, 128, IFA_HOST); | 2545 | add_addr(idev, &in6addr_loopback, 128, IFA_HOST); |
| 2546 | |||
| 2547 | /* Add routes to other interface's IPv6 addresses */ | ||
| 2548 | for_each_netdev(dev_net(dev), sp_dev) { | ||
| 2549 | if (!strcmp(sp_dev->name, dev->name)) | ||
| 2550 | continue; | ||
| 2551 | |||
| 2552 | idev = __in6_dev_get(sp_dev); | ||
| 2553 | if (!idev) | ||
| 2554 | continue; | ||
| 2555 | |||
| 2556 | read_lock_bh(&idev->lock); | ||
| 2557 | list_for_each_entry(sp_ifa, &idev->addr_list, if_list) { | ||
| 2558 | |||
| 2559 | if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE)) | ||
| 2560 | continue; | ||
| 2561 | |||
| 2562 | sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0); | ||
| 2563 | |||
| 2564 | /* Failure cases are ignored */ | ||
| 2565 | if (!IS_ERR(sp_rt)) | ||
| 2566 | ip6_ins_rt(sp_rt); | ||
| 2567 | } | ||
| 2568 | read_unlock_bh(&idev->lock); | ||
| 2569 | } | ||
| 2543 | } | 2570 | } |
| 2544 | 2571 | ||
| 2545 | static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr) | 2572 | static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr) |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index e33fe0ab2568..2bab2aa59745 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
| @@ -118,6 +118,18 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
| 118 | ipv6_addr_loopback(&hdr->daddr)) | 118 | ipv6_addr_loopback(&hdr->daddr)) |
| 119 | goto err; | 119 | goto err; |
| 120 | 120 | ||
| 121 | /* RFC4291 Errata ID: 3480 | ||
| 122 | * Interface-Local scope spans only a single interface on a | ||
| 123 | * node and is useful only for loopback transmission of | ||
| 124 | * multicast. Packets with interface-local scope received | ||
| 125 | * from another node must be discarded. | ||
| 126 | */ | ||
| 127 | if (!(skb->pkt_type == PACKET_LOOPBACK || | ||
| 128 | dev->flags & IFF_LOOPBACK) && | ||
| 129 | ipv6_addr_is_multicast(&hdr->daddr) && | ||
| 130 | IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1) | ||
| 131 | goto err; | ||
| 132 | |||
| 121 | /* RFC4291 2.7 | 133 | /* RFC4291 2.7 |
| 122 | * Nodes must not originate a packet to a multicast address whose scope | 134 | * Nodes must not originate a packet to a multicast address whose scope |
| 123 | * field contains the reserved value 0; if such a packet is received, it | 135 | * field contains the reserved value 0; if such a packet is received, it |
diff --git a/net/ipv6/netfilter/ip6t_NPT.c b/net/ipv6/netfilter/ip6t_NPT.c index 33608c610276..cb631143721c 100644 --- a/net/ipv6/netfilter/ip6t_NPT.c +++ b/net/ipv6/netfilter/ip6t_NPT.c | |||
| @@ -57,7 +57,7 @@ static bool ip6t_npt_map_pfx(const struct ip6t_npt_tginfo *npt, | |||
| 57 | if (pfx_len - i >= 32) | 57 | if (pfx_len - i >= 32) |
| 58 | mask = 0; | 58 | mask = 0; |
| 59 | else | 59 | else |
| 60 | mask = htonl(~((1 << (pfx_len - i)) - 1)); | 60 | mask = htonl((1 << (i - pfx_len + 32)) - 1); |
| 61 | 61 | ||
| 62 | idx = i / 32; | 62 | idx = i / 32; |
| 63 | addr->s6_addr32[idx] &= mask; | 63 | addr->s6_addr32[idx] &= mask; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index f6d629fd6aee..46a5be85be87 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -386,6 +386,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
| 386 | 386 | ||
| 387 | if (dst) | 387 | if (dst) |
| 388 | dst->ops->redirect(dst, sk, skb); | 388 | dst->ops->redirect(dst, sk, skb); |
| 389 | goto out; | ||
| 389 | } | 390 | } |
| 390 | 391 | ||
| 391 | if (type == ICMPV6_PKT_TOOBIG) { | 392 | if (type == ICMPV6_PKT_TOOBIG) { |
