aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c27
-rw-r--r--net/ipv6/ip6_input.c12
-rw-r--r--net/ipv6/netfilter/ip6t_NPT.c2
-rw-r--r--net/ipv6/tcp_ipv6.c1
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)
2529static void init_loopback(struct net_device *dev) 2529static 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
2545static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr) 2572static 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) {