diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 107 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 2 | ||||
-rw-r--r-- | net/ipv6/datagram.c | 50 | ||||
-rw-r--r-- | net/ipv6/ip6_flowlabel.c | 2 | ||||
-rw-r--r-- | net/ipv6/ip6_input.c | 9 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 2 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 44 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6table_mangle.c | 2 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_reasm.c | 9 | ||||
-rw-r--r-- | net/ipv6/raw.c | 13 | ||||
-rw-r--r-- | net/ipv6/reassembly.c | 2 | ||||
-rw-r--r-- | net/ipv6/route.c | 26 | ||||
-rw-r--r-- | net/ipv6/sit.c | 44 | ||||
-rw-r--r-- | net/ipv6/syncookies.c | 1 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 7 | ||||
-rw-r--r-- | net/ipv6/tunnel6.c | 2 | ||||
-rw-r--r-- | net/ipv6/udp.c | 8 |
17 files changed, 196 insertions, 134 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 3a835578fd1c..147588f4c7c0 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -731,8 +731,13 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
731 | onlink = -1; | 731 | onlink = -1; |
732 | 732 | ||
733 | spin_lock(&ifa->lock); | 733 | spin_lock(&ifa->lock); |
734 | lifetime = min_t(unsigned long, | 734 | |
735 | ifa->valid_lft, 0x7fffffffUL/HZ); | 735 | lifetime = addrconf_timeout_fixup(ifa->valid_lft, HZ); |
736 | /* | ||
737 | * Note: Because this address is | ||
738 | * not permanent, lifetime < | ||
739 | * LONG_MAX / HZ here. | ||
740 | */ | ||
736 | if (time_before(expires, | 741 | if (time_before(expires, |
737 | ifa->tstamp + lifetime * HZ)) | 742 | ifa->tstamp + lifetime * HZ)) |
738 | expires = ifa->tstamp + lifetime * HZ; | 743 | expires = ifa->tstamp + lifetime * HZ; |
@@ -1722,7 +1727,6 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1722 | __u32 valid_lft; | 1727 | __u32 valid_lft; |
1723 | __u32 prefered_lft; | 1728 | __u32 prefered_lft; |
1724 | int addr_type; | 1729 | int addr_type; |
1725 | unsigned long rt_expires; | ||
1726 | struct inet6_dev *in6_dev; | 1730 | struct inet6_dev *in6_dev; |
1727 | 1731 | ||
1728 | pinfo = (struct prefix_info *) opt; | 1732 | pinfo = (struct prefix_info *) opt; |
@@ -1764,28 +1768,23 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1764 | * 2) Configure prefixes with the auto flag set | 1768 | * 2) Configure prefixes with the auto flag set |
1765 | */ | 1769 | */ |
1766 | 1770 | ||
1767 | if (valid_lft == INFINITY_LIFE_TIME) | 1771 | if (pinfo->onlink) { |
1768 | rt_expires = ~0UL; | 1772 | struct rt6_info *rt; |
1769 | else if (valid_lft >= 0x7FFFFFFF/HZ) { | 1773 | unsigned long rt_expires; |
1774 | |||
1770 | /* Avoid arithmetic overflow. Really, we could | 1775 | /* Avoid arithmetic overflow. Really, we could |
1771 | * save rt_expires in seconds, likely valid_lft, | 1776 | * save rt_expires in seconds, likely valid_lft, |
1772 | * but it would require division in fib gc, that it | 1777 | * but it would require division in fib gc, that it |
1773 | * not good. | 1778 | * not good. |
1774 | */ | 1779 | */ |
1775 | rt_expires = 0x7FFFFFFF - (0x7FFFFFFF % HZ); | 1780 | if (HZ > USER_HZ) |
1776 | } else | 1781 | rt_expires = addrconf_timeout_fixup(valid_lft, HZ); |
1777 | rt_expires = valid_lft * HZ; | 1782 | else |
1783 | rt_expires = addrconf_timeout_fixup(valid_lft, USER_HZ); | ||
1778 | 1784 | ||
1779 | /* | 1785 | if (addrconf_finite_timeout(rt_expires)) |
1780 | * We convert this (in jiffies) to clock_t later. | 1786 | rt_expires *= HZ; |
1781 | * Avoid arithmetic overflow there as well. | ||
1782 | * Overflow can happen only if HZ < USER_HZ. | ||
1783 | */ | ||
1784 | if (HZ < USER_HZ && ~rt_expires && rt_expires > 0x7FFFFFFF / USER_HZ) | ||
1785 | rt_expires = 0x7FFFFFFF / USER_HZ; | ||
1786 | 1787 | ||
1787 | if (pinfo->onlink) { | ||
1788 | struct rt6_info *rt; | ||
1789 | rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL, | 1788 | rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL, |
1790 | dev->ifindex, 1); | 1789 | dev->ifindex, 1); |
1791 | 1790 | ||
@@ -1794,7 +1793,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1794 | if (valid_lft == 0) { | 1793 | if (valid_lft == 0) { |
1795 | ip6_del_rt(rt); | 1794 | ip6_del_rt(rt); |
1796 | rt = NULL; | 1795 | rt = NULL; |
1797 | } else if (~rt_expires) { | 1796 | } else if (addrconf_finite_timeout(rt_expires)) { |
1798 | /* not infinity */ | 1797 | /* not infinity */ |
1799 | rt->rt6i_expires = jiffies + rt_expires; | 1798 | rt->rt6i_expires = jiffies + rt_expires; |
1800 | rt->rt6i_flags |= RTF_EXPIRES; | 1799 | rt->rt6i_flags |= RTF_EXPIRES; |
@@ -1803,9 +1802,9 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1803 | rt->rt6i_expires = 0; | 1802 | rt->rt6i_expires = 0; |
1804 | } | 1803 | } |
1805 | } else if (valid_lft) { | 1804 | } else if (valid_lft) { |
1806 | int flags = RTF_ADDRCONF | RTF_PREFIX_RT; | ||
1807 | clock_t expires = 0; | 1805 | clock_t expires = 0; |
1808 | if (~rt_expires) { | 1806 | int flags = RTF_ADDRCONF | RTF_PREFIX_RT; |
1807 | if (addrconf_finite_timeout(rt_expires)) { | ||
1809 | /* not infinity */ | 1808 | /* not infinity */ |
1810 | flags |= RTF_EXPIRES; | 1809 | flags |= RTF_EXPIRES; |
1811 | expires = jiffies_to_clock_t(rt_expires); | 1810 | expires = jiffies_to_clock_t(rt_expires); |
@@ -2027,7 +2026,7 @@ err_exit: | |||
2027 | * Manual configuration of address on an interface | 2026 | * Manual configuration of address on an interface |
2028 | */ | 2027 | */ |
2029 | static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, | 2028 | static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, |
2030 | int plen, __u8 ifa_flags, __u32 prefered_lft, | 2029 | unsigned int plen, __u8 ifa_flags, __u32 prefered_lft, |
2031 | __u32 valid_lft) | 2030 | __u32 valid_lft) |
2032 | { | 2031 | { |
2033 | struct inet6_ifaddr *ifp; | 2032 | struct inet6_ifaddr *ifp; |
@@ -2036,9 +2035,13 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, | |||
2036 | int scope; | 2035 | int scope; |
2037 | u32 flags; | 2036 | u32 flags; |
2038 | clock_t expires; | 2037 | clock_t expires; |
2038 | unsigned long timeout; | ||
2039 | 2039 | ||
2040 | ASSERT_RTNL(); | 2040 | ASSERT_RTNL(); |
2041 | 2041 | ||
2042 | if (plen > 128) | ||
2043 | return -EINVAL; | ||
2044 | |||
2042 | /* check the lifetime */ | 2045 | /* check the lifetime */ |
2043 | if (!valid_lft || prefered_lft > valid_lft) | 2046 | if (!valid_lft || prefered_lft > valid_lft) |
2044 | return -EINVAL; | 2047 | return -EINVAL; |
@@ -2052,22 +2055,23 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, | |||
2052 | 2055 | ||
2053 | scope = ipv6_addr_scope(pfx); | 2056 | scope = ipv6_addr_scope(pfx); |
2054 | 2057 | ||
2055 | if (valid_lft == INFINITY_LIFE_TIME) { | 2058 | timeout = addrconf_timeout_fixup(valid_lft, HZ); |
2056 | ifa_flags |= IFA_F_PERMANENT; | 2059 | if (addrconf_finite_timeout(timeout)) { |
2057 | flags = 0; | 2060 | expires = jiffies_to_clock_t(timeout * HZ); |
2058 | expires = 0; | 2061 | valid_lft = timeout; |
2059 | } else { | ||
2060 | if (valid_lft >= 0x7FFFFFFF/HZ) | ||
2061 | valid_lft = 0x7FFFFFFF/HZ; | ||
2062 | flags = RTF_EXPIRES; | 2062 | flags = RTF_EXPIRES; |
2063 | expires = jiffies_to_clock_t(valid_lft * HZ); | 2063 | } else { |
2064 | expires = 0; | ||
2065 | flags = 0; | ||
2066 | ifa_flags |= IFA_F_PERMANENT; | ||
2064 | } | 2067 | } |
2065 | 2068 | ||
2066 | if (prefered_lft == 0) | 2069 | timeout = addrconf_timeout_fixup(prefered_lft, HZ); |
2067 | ifa_flags |= IFA_F_DEPRECATED; | 2070 | if (addrconf_finite_timeout(timeout)) { |
2068 | else if ((prefered_lft >= 0x7FFFFFFF/HZ) && | 2071 | if (timeout == 0) |
2069 | (prefered_lft != INFINITY_LIFE_TIME)) | 2072 | ifa_flags |= IFA_F_DEPRECATED; |
2070 | prefered_lft = 0x7FFFFFFF/HZ; | 2073 | prefered_lft = timeout; |
2074 | } | ||
2071 | 2075 | ||
2072 | ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags); | 2076 | ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags); |
2073 | 2077 | ||
@@ -2095,12 +2099,15 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, | |||
2095 | } | 2099 | } |
2096 | 2100 | ||
2097 | static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, | 2101 | static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, |
2098 | int plen) | 2102 | unsigned int plen) |
2099 | { | 2103 | { |
2100 | struct inet6_ifaddr *ifp; | 2104 | struct inet6_ifaddr *ifp; |
2101 | struct inet6_dev *idev; | 2105 | struct inet6_dev *idev; |
2102 | struct net_device *dev; | 2106 | struct net_device *dev; |
2103 | 2107 | ||
2108 | if (plen > 128) | ||
2109 | return -EINVAL; | ||
2110 | |||
2104 | dev = __dev_get_by_index(net, ifindex); | 2111 | dev = __dev_get_by_index(net, ifindex); |
2105 | if (!dev) | 2112 | if (!dev) |
2106 | return -ENODEV; | 2113 | return -ENODEV; |
@@ -3169,26 +3176,28 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, | |||
3169 | { | 3176 | { |
3170 | u32 flags; | 3177 | u32 flags; |
3171 | clock_t expires; | 3178 | clock_t expires; |
3179 | unsigned long timeout; | ||
3172 | 3180 | ||
3173 | if (!valid_lft || (prefered_lft > valid_lft)) | 3181 | if (!valid_lft || (prefered_lft > valid_lft)) |
3174 | return -EINVAL; | 3182 | return -EINVAL; |
3175 | 3183 | ||
3176 | if (valid_lft == INFINITY_LIFE_TIME) { | 3184 | timeout = addrconf_timeout_fixup(valid_lft, HZ); |
3177 | ifa_flags |= IFA_F_PERMANENT; | 3185 | if (addrconf_finite_timeout(timeout)) { |
3178 | flags = 0; | 3186 | expires = jiffies_to_clock_t(timeout * HZ); |
3179 | expires = 0; | 3187 | valid_lft = timeout; |
3180 | } else { | ||
3181 | if (valid_lft >= 0x7FFFFFFF/HZ) | ||
3182 | valid_lft = 0x7FFFFFFF/HZ; | ||
3183 | flags = RTF_EXPIRES; | 3188 | flags = RTF_EXPIRES; |
3184 | expires = jiffies_to_clock_t(valid_lft * HZ); | 3189 | } else { |
3190 | expires = 0; | ||
3191 | flags = 0; | ||
3192 | ifa_flags |= IFA_F_PERMANENT; | ||
3185 | } | 3193 | } |
3186 | 3194 | ||
3187 | if (prefered_lft == 0) | 3195 | timeout = addrconf_timeout_fixup(prefered_lft, HZ); |
3188 | ifa_flags |= IFA_F_DEPRECATED; | 3196 | if (addrconf_finite_timeout(timeout)) { |
3189 | else if ((prefered_lft >= 0x7FFFFFFF/HZ) && | 3197 | if (timeout == 0) |
3190 | (prefered_lft != INFINITY_LIFE_TIME)) | 3198 | ifa_flags |= IFA_F_DEPRECATED; |
3191 | prefered_lft = 0x7FFFFFFF/HZ; | 3199 | prefered_lft = timeout; |
3200 | } | ||
3192 | 3201 | ||
3193 | spin_lock_bh(&ifp->lock); | 3202 | spin_lock_bh(&ifp->lock); |
3194 | ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD | IFA_F_HOMEADDRESS)) | ifa_flags; | 3203 | ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD | IFA_F_HOMEADDRESS)) | ifa_flags; |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 3c6aafb02183..e84b3fd17fb4 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -191,7 +191,7 @@ lookup_protocol: | |||
191 | np->mcast_hops = -1; | 191 | np->mcast_hops = -1; |
192 | np->mc_loop = 1; | 192 | np->mc_loop = 1; |
193 | np->pmtudisc = IPV6_PMTUDISC_WANT; | 193 | np->pmtudisc = IPV6_PMTUDISC_WANT; |
194 | np->ipv6only = init_net.ipv6.sysctl.bindv6only; | 194 | np->ipv6only = net->ipv6.sysctl.bindv6only; |
195 | 195 | ||
196 | /* Init the ipv4 part of the socket since we can have sockets | 196 | /* Init the ipv4 part of the socket since we can have sockets |
197 | * using v6 API for ipv4. | 197 | * using v6 API for ipv4. |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 94fa6ae77cfe..0f0f94a40335 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -496,7 +496,8 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | |||
496 | return 0; | 496 | return 0; |
497 | } | 497 | } |
498 | 498 | ||
499 | int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, | 499 | int datagram_send_ctl(struct net *net, |
500 | struct msghdr *msg, struct flowi *fl, | ||
500 | struct ipv6_txoptions *opt, | 501 | struct ipv6_txoptions *opt, |
501 | int *hlimit, int *tclass) | 502 | int *hlimit, int *tclass) |
502 | { | 503 | { |
@@ -509,7 +510,6 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, | |||
509 | 510 | ||
510 | for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { | 511 | for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { |
511 | int addr_type; | 512 | int addr_type; |
512 | struct net_device *dev = NULL; | ||
513 | 513 | ||
514 | if (!CMSG_OK(msg, cmsg)) { | 514 | if (!CMSG_OK(msg, cmsg)) { |
515 | err = -EINVAL; | 515 | err = -EINVAL; |
@@ -522,6 +522,9 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, | |||
522 | switch (cmsg->cmsg_type) { | 522 | switch (cmsg->cmsg_type) { |
523 | case IPV6_PKTINFO: | 523 | case IPV6_PKTINFO: |
524 | case IPV6_2292PKTINFO: | 524 | case IPV6_2292PKTINFO: |
525 | { | ||
526 | struct net_device *dev = NULL; | ||
527 | |||
525 | if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct in6_pktinfo))) { | 528 | if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct in6_pktinfo))) { |
526 | err = -EINVAL; | 529 | err = -EINVAL; |
527 | goto exit_f; | 530 | goto exit_f; |
@@ -535,32 +538,32 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, | |||
535 | fl->oif = src_info->ipi6_ifindex; | 538 | fl->oif = src_info->ipi6_ifindex; |
536 | } | 539 | } |
537 | 540 | ||
538 | addr_type = ipv6_addr_type(&src_info->ipi6_addr); | 541 | addr_type = __ipv6_addr_type(&src_info->ipi6_addr); |
539 | 542 | ||
540 | if (addr_type == IPV6_ADDR_ANY) | 543 | if (fl->oif) { |
541 | break; | 544 | dev = dev_get_by_index(net, fl->oif); |
545 | if (!dev) | ||
546 | return -ENODEV; | ||
547 | } else if (addr_type & IPV6_ADDR_LINKLOCAL) | ||
548 | return -EINVAL; | ||
542 | 549 | ||
543 | if (addr_type & IPV6_ADDR_LINKLOCAL) { | 550 | if (addr_type != IPV6_ADDR_ANY) { |
544 | if (!src_info->ipi6_ifindex) | 551 | int strict = __ipv6_addr_src_scope(addr_type) <= IPV6_ADDR_SCOPE_LINKLOCAL; |
545 | return -EINVAL; | 552 | if (!ipv6_chk_addr(net, &src_info->ipi6_addr, |
546 | else { | 553 | strict ? dev : NULL, 0)) |
547 | dev = dev_get_by_index(&init_net, src_info->ipi6_ifindex); | 554 | err = -EINVAL; |
548 | if (!dev) | 555 | else |
549 | return -ENODEV; | 556 | ipv6_addr_copy(&fl->fl6_src, &src_info->ipi6_addr); |
550 | } | ||
551 | } | ||
552 | if (!ipv6_chk_addr(&init_net, &src_info->ipi6_addr, | ||
553 | dev, 0)) { | ||
554 | if (dev) | ||
555 | dev_put(dev); | ||
556 | err = -EINVAL; | ||
557 | goto exit_f; | ||
558 | } | 557 | } |
558 | |||
559 | if (dev) | 559 | if (dev) |
560 | dev_put(dev); | 560 | dev_put(dev); |
561 | 561 | ||
562 | ipv6_addr_copy(&fl->fl6_src, &src_info->ipi6_addr); | 562 | if (err) |
563 | goto exit_f; | ||
564 | |||
563 | break; | 565 | break; |
566 | } | ||
564 | 567 | ||
565 | case IPV6_FLOWINFO: | 568 | case IPV6_FLOWINFO: |
566 | if (cmsg->cmsg_len < CMSG_LEN(4)) { | 569 | if (cmsg->cmsg_len < CMSG_LEN(4)) { |
@@ -702,6 +705,11 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, | |||
702 | } | 705 | } |
703 | 706 | ||
704 | *hlimit = *(int *)CMSG_DATA(cmsg); | 707 | *hlimit = *(int *)CMSG_DATA(cmsg); |
708 | if (*hlimit < -1 || *hlimit > 0xff) { | ||
709 | err = -EINVAL; | ||
710 | goto exit_f; | ||
711 | } | ||
712 | |||
705 | break; | 713 | break; |
706 | 714 | ||
707 | case IPV6_TCLASS: | 715 | case IPV6_TCLASS: |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index eb7a940310f4..37a4e777e347 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -354,7 +354,7 @@ fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval, | |||
354 | msg.msg_control = (void*)(fl->opt+1); | 354 | msg.msg_control = (void*)(fl->opt+1); |
355 | flowi.oif = 0; | 355 | flowi.oif = 0; |
356 | 356 | ||
357 | err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk, &junk); | 357 | err = datagram_send_ctl(net, &msg, &flowi, fl->opt, &junk, &junk); |
358 | if (err) | 358 | if (err) |
359 | goto done; | 359 | goto done; |
360 | err = -EINVAL; | 360 | err = -EINVAL; |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 4e5c8615832c..17eb48b8e329 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -102,6 +102,15 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
102 | if (hdr->version != 6) | 102 | if (hdr->version != 6) |
103 | goto err; | 103 | goto err; |
104 | 104 | ||
105 | /* | ||
106 | * RFC4291 2.5.3 | ||
107 | * A packet received on an interface with a destination address | ||
108 | * of loopback must be dropped. | ||
109 | */ | ||
110 | if (!(dev->flags & IFF_LOOPBACK) && | ||
111 | ipv6_addr_loopback(&hdr->daddr)) | ||
112 | goto err; | ||
113 | |||
105 | skb->transport_header = skb->network_header + sizeof(*hdr); | 114 | skb->transport_header = skb->network_header + sizeof(*hdr); |
106 | IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); | 115 | IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); |
107 | 116 | ||
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 2de3c464fe75..14796181e8b5 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -197,7 +197,7 @@ static int ip6mr_vif_seq_show(struct seq_file *seq, void *v) | |||
197 | const char *name = vif->dev ? vif->dev->name : "none"; | 197 | const char *name = vif->dev ? vif->dev->name : "none"; |
198 | 198 | ||
199 | seq_printf(seq, | 199 | seq_printf(seq, |
200 | "%2Zd %-10s %8ld %7ld %8ld %7ld %05X\n", | 200 | "%2td %-10s %8ld %7ld %8ld %7ld %05X\n", |
201 | vif - vif6_table, | 201 | vif - vif6_table, |
202 | name, vif->bytes_in, vif->pkt_in, | 202 | name, vif->bytes_in, vif->pkt_in, |
203 | vif->bytes_out, vif->pkt_out, | 203 | vif->bytes_out, vif->pkt_out, |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 56d55fecf8ec..86e28a75267f 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -67,7 +67,7 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *)) | |||
67 | 67 | ||
68 | /* RA packet may be delivered ONLY to IPPROTO_RAW socket */ | 68 | /* RA packet may be delivered ONLY to IPPROTO_RAW socket */ |
69 | if (sk->sk_type != SOCK_RAW || inet_sk(sk)->num != IPPROTO_RAW) | 69 | if (sk->sk_type != SOCK_RAW || inet_sk(sk)->num != IPPROTO_RAW) |
70 | return -EINVAL; | 70 | return -ENOPROTOOPT; |
71 | 71 | ||
72 | new_ra = (sel>=0) ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL; | 72 | new_ra = (sel>=0) ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL; |
73 | 73 | ||
@@ -161,9 +161,17 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
161 | struct ipv6_txoptions *opt; | 161 | struct ipv6_txoptions *opt; |
162 | struct sk_buff *pktopt; | 162 | struct sk_buff *pktopt; |
163 | 163 | ||
164 | if (sk->sk_protocol != IPPROTO_UDP && | 164 | if (sk->sk_type == SOCK_RAW) |
165 | sk->sk_protocol != IPPROTO_UDPLITE && | 165 | break; |
166 | sk->sk_protocol != IPPROTO_TCP) | 166 | |
167 | if (sk->sk_protocol == IPPROTO_UDP || | ||
168 | sk->sk_protocol == IPPROTO_UDPLITE) { | ||
169 | struct udp_sock *up = udp_sk(sk); | ||
170 | if (up->pending == AF_INET6) { | ||
171 | retv = -EBUSY; | ||
172 | break; | ||
173 | } | ||
174 | } else if (sk->sk_protocol != IPPROTO_TCP) | ||
167 | break; | 175 | break; |
168 | 176 | ||
169 | if (sk->sk_state != TCP_ESTABLISHED) { | 177 | if (sk->sk_state != TCP_ESTABLISHED) { |
@@ -337,18 +345,21 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
337 | case IPV6_DSTOPTS: | 345 | case IPV6_DSTOPTS: |
338 | { | 346 | { |
339 | struct ipv6_txoptions *opt; | 347 | struct ipv6_txoptions *opt; |
348 | |||
349 | /* remove any sticky options header with a zero option | ||
350 | * length, per RFC3542. | ||
351 | */ | ||
340 | if (optlen == 0) | 352 | if (optlen == 0) |
341 | optval = NULL; | 353 | optval = NULL; |
354 | else if (optlen < sizeof(struct ipv6_opt_hdr) || | ||
355 | optlen & 0x7 || optlen > 8 * 255) | ||
356 | goto e_inval; | ||
342 | 357 | ||
343 | /* hop-by-hop / destination options are privileged option */ | 358 | /* hop-by-hop / destination options are privileged option */ |
344 | retv = -EPERM; | 359 | retv = -EPERM; |
345 | if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) | 360 | if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) |
346 | break; | 361 | break; |
347 | 362 | ||
348 | if (optlen < sizeof(struct ipv6_opt_hdr) || | ||
349 | optlen & 0x7 || optlen > 8 * 255) | ||
350 | goto e_inval; | ||
351 | |||
352 | opt = ipv6_renew_options(sk, np->opt, optname, | 363 | opt = ipv6_renew_options(sk, np->opt, optname, |
353 | (struct ipv6_opt_hdr __user *)optval, | 364 | (struct ipv6_opt_hdr __user *)optval, |
354 | optlen); | 365 | optlen); |
@@ -416,7 +427,7 @@ sticky_done: | |||
416 | msg.msg_controllen = optlen; | 427 | msg.msg_controllen = optlen; |
417 | msg.msg_control = (void*)(opt+1); | 428 | msg.msg_control = (void*)(opt+1); |
418 | 429 | ||
419 | retv = datagram_send_ctl(&msg, &fl, opt, &junk, &junk); | 430 | retv = datagram_send_ctl(net, &msg, &fl, opt, &junk, &junk); |
420 | if (retv) | 431 | if (retv) |
421 | goto done; | 432 | goto done; |
422 | update: | 433 | update: |
@@ -438,7 +449,7 @@ done: | |||
438 | 449 | ||
439 | case IPV6_MULTICAST_HOPS: | 450 | case IPV6_MULTICAST_HOPS: |
440 | if (sk->sk_type == SOCK_STREAM) | 451 | if (sk->sk_type == SOCK_STREAM) |
441 | goto e_inval; | 452 | break; |
442 | if (optlen < sizeof(int)) | 453 | if (optlen < sizeof(int)) |
443 | goto e_inval; | 454 | goto e_inval; |
444 | if (val > 255 || val < -1) | 455 | if (val > 255 || val < -1) |
@@ -450,13 +461,15 @@ done: | |||
450 | case IPV6_MULTICAST_LOOP: | 461 | case IPV6_MULTICAST_LOOP: |
451 | if (optlen < sizeof(int)) | 462 | if (optlen < sizeof(int)) |
452 | goto e_inval; | 463 | goto e_inval; |
464 | if (val != valbool) | ||
465 | goto e_inval; | ||
453 | np->mc_loop = valbool; | 466 | np->mc_loop = valbool; |
454 | retv = 0; | 467 | retv = 0; |
455 | break; | 468 | break; |
456 | 469 | ||
457 | case IPV6_MULTICAST_IF: | 470 | case IPV6_MULTICAST_IF: |
458 | if (sk->sk_type == SOCK_STREAM) | 471 | if (sk->sk_type == SOCK_STREAM) |
459 | goto e_inval; | 472 | break; |
460 | if (optlen < sizeof(int)) | 473 | if (optlen < sizeof(int)) |
461 | goto e_inval; | 474 | goto e_inval; |
462 | 475 | ||
@@ -832,7 +845,7 @@ static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt, | |||
832 | len = min_t(unsigned int, len, ipv6_optlen(hdr)); | 845 | len = min_t(unsigned int, len, ipv6_optlen(hdr)); |
833 | if (copy_to_user(optval, hdr, len)) | 846 | if (copy_to_user(optval, hdr, len)) |
834 | return -EFAULT; | 847 | return -EFAULT; |
835 | return ipv6_optlen(hdr); | 848 | return len; |
836 | } | 849 | } |
837 | 850 | ||
838 | static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | 851 | static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, |
@@ -852,7 +865,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
852 | if (sk->sk_protocol != IPPROTO_UDP && | 865 | if (sk->sk_protocol != IPPROTO_UDP && |
853 | sk->sk_protocol != IPPROTO_UDPLITE && | 866 | sk->sk_protocol != IPPROTO_UDPLITE && |
854 | sk->sk_protocol != IPPROTO_TCP) | 867 | sk->sk_protocol != IPPROTO_TCP) |
855 | return -EINVAL; | 868 | return -ENOPROTOOPT; |
856 | if (sk->sk_state != TCP_ESTABLISHED) | 869 | if (sk->sk_state != TCP_ESTABLISHED) |
857 | return -ENOTCONN; | 870 | return -ENOTCONN; |
858 | val = sk->sk_family; | 871 | val = sk->sk_family; |
@@ -866,6 +879,8 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
866 | return -EINVAL; | 879 | return -EINVAL; |
867 | if (copy_from_user(&gsf, optval, GROUP_FILTER_SIZE(0))) | 880 | if (copy_from_user(&gsf, optval, GROUP_FILTER_SIZE(0))) |
868 | return -EFAULT; | 881 | return -EFAULT; |
882 | if (gsf.gf_group.ss_family != AF_INET6) | ||
883 | return -EADDRNOTAVAIL; | ||
869 | lock_sock(sk); | 884 | lock_sock(sk); |
870 | err = ip6_mc_msfget(sk, &gsf, | 885 | err = ip6_mc_msfget(sk, &gsf, |
871 | (struct group_filter __user *)optval, optlen); | 886 | (struct group_filter __user *)optval, optlen); |
@@ -975,6 +990,9 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
975 | len = ipv6_getsockopt_sticky(sk, np->opt, | 990 | len = ipv6_getsockopt_sticky(sk, np->opt, |
976 | optname, optval, len); | 991 | optname, optval, len); |
977 | release_sock(sk); | 992 | release_sock(sk); |
993 | /* check if ipv6_getsockopt_sticky() returns err code */ | ||
994 | if (len < 0) | ||
995 | return len; | ||
978 | return put_user(len, optlen); | 996 | return put_user(len, optlen); |
979 | } | 997 | } |
980 | 998 | ||
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 27a5e8b48d93..f405cea21a8b 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -129,7 +129,7 @@ static struct nf_hook_ops ip6t_ops[] __read_mostly = { | |||
129 | .priority = NF_IP6_PRI_MANGLE, | 129 | .priority = NF_IP6_PRI_MANGLE, |
130 | }, | 130 | }, |
131 | { | 131 | { |
132 | .hook = ip6t_local_hook, | 132 | .hook = ip6t_route_hook, |
133 | .owner = THIS_MODULE, | 133 | .owner = THIS_MODULE, |
134 | .pf = PF_INET6, | 134 | .pf = PF_INET6, |
135 | .hooknum = NF_INET_LOCAL_IN, | 135 | .hooknum = NF_INET_LOCAL_IN, |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 2dccad48058c..cf20bc4fd60d 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -207,9 +207,12 @@ fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst) | |||
207 | arg.id = id; | 207 | arg.id = id; |
208 | arg.src = src; | 208 | arg.src = src; |
209 | arg.dst = dst; | 209 | arg.dst = dst; |
210 | |||
211 | read_lock_bh(&nf_frags.lock); | ||
210 | hash = ip6qhashfn(id, src, dst); | 212 | hash = ip6qhashfn(id, src, dst); |
211 | 213 | ||
212 | q = inet_frag_find(&nf_init_frags, &nf_frags, &arg, hash); | 214 | q = inet_frag_find(&nf_init_frags, &nf_frags, &arg, hash); |
215 | local_bh_enable(); | ||
213 | if (q == NULL) | 216 | if (q == NULL) |
214 | goto oom; | 217 | goto oom; |
215 | 218 | ||
@@ -638,10 +641,10 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) | |||
638 | goto ret_orig; | 641 | goto ret_orig; |
639 | } | 642 | } |
640 | 643 | ||
641 | spin_lock(&fq->q.lock); | 644 | spin_lock_bh(&fq->q.lock); |
642 | 645 | ||
643 | if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) { | 646 | if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) { |
644 | spin_unlock(&fq->q.lock); | 647 | spin_unlock_bh(&fq->q.lock); |
645 | pr_debug("Can't insert skb to queue\n"); | 648 | pr_debug("Can't insert skb to queue\n"); |
646 | fq_put(fq); | 649 | fq_put(fq); |
647 | goto ret_orig; | 650 | goto ret_orig; |
@@ -653,7 +656,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb) | |||
653 | if (ret_skb == NULL) | 656 | if (ret_skb == NULL) |
654 | pr_debug("Can't reassemble fragmented packets\n"); | 657 | pr_debug("Can't reassemble fragmented packets\n"); |
655 | } | 658 | } |
656 | spin_unlock(&fq->q.lock); | 659 | spin_unlock_bh(&fq->q.lock); |
657 | 660 | ||
658 | fq_put(fq); | 661 | fq_put(fq); |
659 | return ret_skb; | 662 | return ret_skb; |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 232e0dc45bf5..3aee12310d94 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -813,7 +813,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
813 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 813 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
814 | opt->tot_len = sizeof(struct ipv6_txoptions); | 814 | opt->tot_len = sizeof(struct ipv6_txoptions); |
815 | 815 | ||
816 | err = datagram_send_ctl(msg, &fl, opt, &hlimit, &tclass); | 816 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, &tclass); |
817 | if (err < 0) { | 817 | if (err < 0) { |
818 | fl6_sock_release(flowlabel); | 818 | fl6_sock_release(flowlabel); |
819 | return err; | 819 | return err; |
@@ -1164,6 +1164,15 @@ static void rawv6_close(struct sock *sk, long timeout) | |||
1164 | sk_common_release(sk); | 1164 | sk_common_release(sk); |
1165 | } | 1165 | } |
1166 | 1166 | ||
1167 | static int raw6_destroy(struct sock *sk) | ||
1168 | { | ||
1169 | lock_sock(sk); | ||
1170 | ip6_flush_pending_frames(sk); | ||
1171 | release_sock(sk); | ||
1172 | |||
1173 | return inet6_destroy_sock(sk); | ||
1174 | } | ||
1175 | |||
1167 | static int rawv6_init_sk(struct sock *sk) | 1176 | static int rawv6_init_sk(struct sock *sk) |
1168 | { | 1177 | { |
1169 | struct raw6_sock *rp = raw6_sk(sk); | 1178 | struct raw6_sock *rp = raw6_sk(sk); |
@@ -1187,11 +1196,11 @@ struct proto rawv6_prot = { | |||
1187 | .name = "RAWv6", | 1196 | .name = "RAWv6", |
1188 | .owner = THIS_MODULE, | 1197 | .owner = THIS_MODULE, |
1189 | .close = rawv6_close, | 1198 | .close = rawv6_close, |
1199 | .destroy = raw6_destroy, | ||
1190 | .connect = ip6_datagram_connect, | 1200 | .connect = ip6_datagram_connect, |
1191 | .disconnect = udp_disconnect, | 1201 | .disconnect = udp_disconnect, |
1192 | .ioctl = rawv6_ioctl, | 1202 | .ioctl = rawv6_ioctl, |
1193 | .init = rawv6_init_sk, | 1203 | .init = rawv6_init_sk, |
1194 | .destroy = inet6_destroy_sock, | ||
1195 | .setsockopt = rawv6_setsockopt, | 1204 | .setsockopt = rawv6_setsockopt, |
1196 | .getsockopt = rawv6_getsockopt, | 1205 | .getsockopt = rawv6_getsockopt, |
1197 | .sendmsg = rawv6_sendmsg, | 1206 | .sendmsg = rawv6_sendmsg, |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 798cabc7535b..a60d7d129713 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -247,6 +247,8 @@ fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst, | |||
247 | arg.id = id; | 247 | arg.id = id; |
248 | arg.src = src; | 248 | arg.src = src; |
249 | arg.dst = dst; | 249 | arg.dst = dst; |
250 | |||
251 | read_lock(&ip6_frags.lock); | ||
250 | hash = ip6qhashfn(id, src, dst); | 252 | hash = ip6qhashfn(id, src, dst); |
251 | 253 | ||
252 | q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); | 254 | q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 48534c6c0735..7ff687020fa9 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -240,7 +240,7 @@ static inline int rt6_need_strict(struct in6_addr *daddr) | |||
240 | static inline struct rt6_info *rt6_device_match(struct net *net, | 240 | static inline struct rt6_info *rt6_device_match(struct net *net, |
241 | struct rt6_info *rt, | 241 | struct rt6_info *rt, |
242 | int oif, | 242 | int oif, |
243 | int strict) | 243 | int flags) |
244 | { | 244 | { |
245 | struct rt6_info *local = NULL; | 245 | struct rt6_info *local = NULL; |
246 | struct rt6_info *sprt; | 246 | struct rt6_info *sprt; |
@@ -253,7 +253,7 @@ static inline struct rt6_info *rt6_device_match(struct net *net, | |||
253 | if (dev->flags & IFF_LOOPBACK) { | 253 | if (dev->flags & IFF_LOOPBACK) { |
254 | if (sprt->rt6i_idev == NULL || | 254 | if (sprt->rt6i_idev == NULL || |
255 | sprt->rt6i_idev->dev->ifindex != oif) { | 255 | sprt->rt6i_idev->dev->ifindex != oif) { |
256 | if (strict && oif) | 256 | if (flags & RT6_LOOKUP_F_IFACE && oif) |
257 | continue; | 257 | continue; |
258 | if (local && (!oif || | 258 | if (local && (!oif || |
259 | local->rt6i_idev->dev->ifindex == oif)) | 259 | local->rt6i_idev->dev->ifindex == oif)) |
@@ -266,7 +266,7 @@ static inline struct rt6_info *rt6_device_match(struct net *net, | |||
266 | if (local) | 266 | if (local) |
267 | return local; | 267 | return local; |
268 | 268 | ||
269 | if (strict) | 269 | if (flags & RT6_LOOKUP_F_IFACE) |
270 | return net->ipv6.ip6_null_entry; | 270 | return net->ipv6.ip6_null_entry; |
271 | } | 271 | } |
272 | return rt; | 272 | return rt; |
@@ -446,7 +446,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | |||
446 | struct route_info *rinfo = (struct route_info *) opt; | 446 | struct route_info *rinfo = (struct route_info *) opt; |
447 | struct in6_addr prefix_buf, *prefix; | 447 | struct in6_addr prefix_buf, *prefix; |
448 | unsigned int pref; | 448 | unsigned int pref; |
449 | u32 lifetime; | 449 | unsigned long lifetime; |
450 | struct rt6_info *rt; | 450 | struct rt6_info *rt; |
451 | 451 | ||
452 | if (len < sizeof(struct route_info)) { | 452 | if (len < sizeof(struct route_info)) { |
@@ -472,13 +472,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | |||
472 | if (pref == ICMPV6_ROUTER_PREF_INVALID) | 472 | if (pref == ICMPV6_ROUTER_PREF_INVALID) |
473 | pref = ICMPV6_ROUTER_PREF_MEDIUM; | 473 | pref = ICMPV6_ROUTER_PREF_MEDIUM; |
474 | 474 | ||
475 | lifetime = ntohl(rinfo->lifetime); | 475 | lifetime = addrconf_timeout_fixup(ntohl(rinfo->lifetime), HZ); |
476 | if (lifetime == 0xffffffff) { | ||
477 | /* infinity */ | ||
478 | } else if (lifetime > 0x7fffffff/HZ - 1) { | ||
479 | /* Avoid arithmetic overflow */ | ||
480 | lifetime = 0x7fffffff/HZ - 1; | ||
481 | } | ||
482 | 476 | ||
483 | if (rinfo->length == 3) | 477 | if (rinfo->length == 3) |
484 | prefix = (struct in6_addr *)rinfo->prefix; | 478 | prefix = (struct in6_addr *)rinfo->prefix; |
@@ -506,7 +500,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | |||
506 | (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref); | 500 | (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref); |
507 | 501 | ||
508 | if (rt) { | 502 | if (rt) { |
509 | if (lifetime == 0xffffffff) { | 503 | if (!addrconf_finite_timeout(lifetime)) { |
510 | rt->rt6i_flags &= ~RTF_EXPIRES; | 504 | rt->rt6i_flags &= ~RTF_EXPIRES; |
511 | } else { | 505 | } else { |
512 | rt->rt6i_expires = jiffies + HZ * lifetime; | 506 | rt->rt6i_expires = jiffies + HZ * lifetime; |
@@ -2202,8 +2196,12 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | |||
2202 | 2196 | ||
2203 | NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); | 2197 | NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); |
2204 | 2198 | ||
2205 | expires = (rt->rt6i_flags & RTF_EXPIRES) ? | 2199 | if (!(rt->rt6i_flags & RTF_EXPIRES)) |
2206 | rt->rt6i_expires - jiffies : 0; | 2200 | expires = 0; |
2201 | else if (rt->rt6i_expires - jiffies < INT_MAX) | ||
2202 | expires = rt->rt6i_expires - jiffies; | ||
2203 | else | ||
2204 | expires = INT_MAX; | ||
2207 | 2205 | ||
2208 | if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0, | 2206 | if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0, |
2209 | expires, rt->u.dst.error) < 0) | 2207 | expires, rt->u.dst.error) < 0) |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 3de6ffdaedf2..32e871a6c25a 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -222,15 +222,18 @@ __ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr) | |||
222 | 222 | ||
223 | } | 223 | } |
224 | 224 | ||
225 | static int ipip6_tunnel_get_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | 225 | static int ipip6_tunnel_get_prl(struct ip_tunnel *t, |
226 | struct ip_tunnel_prl __user *a) | ||
226 | { | 227 | { |
227 | struct ip_tunnel_prl *kp; | 228 | struct ip_tunnel_prl kprl, *kp; |
228 | struct ip_tunnel_prl_entry *prl; | 229 | struct ip_tunnel_prl_entry *prl; |
229 | unsigned int cmax, c = 0, ca, len; | 230 | unsigned int cmax, c = 0, ca, len; |
230 | int ret = 0; | 231 | int ret = 0; |
231 | 232 | ||
232 | cmax = a->datalen / sizeof(*a); | 233 | if (copy_from_user(&kprl, a, sizeof(kprl))) |
233 | if (cmax > 1 && a->addr != htonl(INADDR_ANY)) | 234 | return -EFAULT; |
235 | cmax = kprl.datalen / sizeof(kprl); | ||
236 | if (cmax > 1 && kprl.addr != htonl(INADDR_ANY)) | ||
234 | cmax = 1; | 237 | cmax = 1; |
235 | 238 | ||
236 | /* For simple GET or for root users, | 239 | /* For simple GET or for root users, |
@@ -261,26 +264,25 @@ static int ipip6_tunnel_get_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | |||
261 | for (prl = t->prl; prl; prl = prl->next) { | 264 | for (prl = t->prl; prl; prl = prl->next) { |
262 | if (c > cmax) | 265 | if (c > cmax) |
263 | break; | 266 | break; |
264 | if (a->addr != htonl(INADDR_ANY) && prl->addr != a->addr) | 267 | if (kprl.addr != htonl(INADDR_ANY) && prl->addr != kprl.addr) |
265 | continue; | 268 | continue; |
266 | kp[c].addr = prl->addr; | 269 | kp[c].addr = prl->addr; |
267 | kp[c].flags = prl->flags; | 270 | kp[c].flags = prl->flags; |
268 | c++; | 271 | c++; |
269 | if (a->addr != htonl(INADDR_ANY)) | 272 | if (kprl.addr != htonl(INADDR_ANY)) |
270 | break; | 273 | break; |
271 | } | 274 | } |
272 | out: | 275 | out: |
273 | read_unlock(&ipip6_lock); | 276 | read_unlock(&ipip6_lock); |
274 | 277 | ||
275 | len = sizeof(*kp) * c; | 278 | len = sizeof(*kp) * c; |
276 | ret = len ? copy_to_user(a->data, kp, len) : 0; | 279 | ret = 0; |
280 | if ((len && copy_to_user(a + 1, kp, len)) || put_user(len, &a->datalen)) | ||
281 | ret = -EFAULT; | ||
277 | 282 | ||
278 | kfree(kp); | 283 | kfree(kp); |
279 | if (ret) | ||
280 | return -EFAULT; | ||
281 | 284 | ||
282 | a->datalen = len; | 285 | return ret; |
283 | return 0; | ||
284 | } | 286 | } |
285 | 287 | ||
286 | static int | 288 | static int |
@@ -873,11 +875,20 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
873 | break; | 875 | break; |
874 | 876 | ||
875 | case SIOCGETPRL: | 877 | case SIOCGETPRL: |
878 | err = -EINVAL; | ||
879 | if (dev == sitn->fb_tunnel_dev) | ||
880 | goto done; | ||
881 | err = -ENOENT; | ||
882 | if (!(t = netdev_priv(dev))) | ||
883 | goto done; | ||
884 | err = ipip6_tunnel_get_prl(t, ifr->ifr_ifru.ifru_data); | ||
885 | break; | ||
886 | |||
876 | case SIOCADDPRL: | 887 | case SIOCADDPRL: |
877 | case SIOCDELPRL: | 888 | case SIOCDELPRL: |
878 | case SIOCCHGPRL: | 889 | case SIOCCHGPRL: |
879 | err = -EPERM; | 890 | err = -EPERM; |
880 | if (cmd != SIOCGETPRL && !capable(CAP_NET_ADMIN)) | 891 | if (!capable(CAP_NET_ADMIN)) |
881 | goto done; | 892 | goto done; |
882 | err = -EINVAL; | 893 | err = -EINVAL; |
883 | if (dev == sitn->fb_tunnel_dev) | 894 | if (dev == sitn->fb_tunnel_dev) |
@@ -890,12 +901,6 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
890 | goto done; | 901 | goto done; |
891 | 902 | ||
892 | switch (cmd) { | 903 | switch (cmd) { |
893 | case SIOCGETPRL: | ||
894 | err = ipip6_tunnel_get_prl(t, &prl); | ||
895 | if (!err && copy_to_user(ifr->ifr_ifru.ifru_data, | ||
896 | &prl, sizeof(prl))) | ||
897 | err = -EFAULT; | ||
898 | break; | ||
899 | case SIOCDELPRL: | 904 | case SIOCDELPRL: |
900 | err = ipip6_tunnel_del_prl(t, &prl); | 905 | err = ipip6_tunnel_del_prl(t, &prl); |
901 | break; | 906 | break; |
@@ -904,8 +909,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
904 | err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); | 909 | err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); |
905 | break; | 910 | break; |
906 | } | 911 | } |
907 | if (cmd != SIOCGETPRL) | 912 | netdev_state_change(dev); |
908 | netdev_state_change(dev); | ||
909 | break; | 913 | break; |
910 | 914 | ||
911 | default: | 915 | default: |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 938ce4ecde55..3ecc1157994e 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -198,7 +198,6 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
198 | ireq = inet_rsk(req); | 198 | ireq = inet_rsk(req); |
199 | ireq6 = inet6_rsk(req); | 199 | ireq6 = inet6_rsk(req); |
200 | treq = tcp_rsk(req); | 200 | treq = tcp_rsk(req); |
201 | ireq6->pktopts = NULL; | ||
202 | 201 | ||
203 | if (security_inet_conn_request(sk, skb, req)) { | 202 | if (security_inet_conn_request(sk, skb, req)) { |
204 | reqsk_free(req); | 203 | reqsk_free(req); |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 715965f0fac0..40ea9c36d24b 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1299,7 +1299,6 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1299 | treq = inet6_rsk(req); | 1299 | treq = inet6_rsk(req); |
1300 | ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr); | 1300 | ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr); |
1301 | ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr); | 1301 | ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr); |
1302 | treq->pktopts = NULL; | ||
1303 | if (!want_cookie) | 1302 | if (!want_cookie) |
1304 | TCP_ECN_create_request(req, tcp_hdr(skb)); | 1303 | TCP_ECN_create_request(req, tcp_hdr(skb)); |
1305 | 1304 | ||
@@ -2037,7 +2036,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) | |||
2037 | 2036 | ||
2038 | seq_printf(seq, | 2037 | seq_printf(seq, |
2039 | "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " | 2038 | "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " |
2040 | "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %u %u %u %u %d\n", | 2039 | "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %lu %lu %u %u %d\n", |
2041 | i, | 2040 | i, |
2042 | src->s6_addr32[0], src->s6_addr32[1], | 2041 | src->s6_addr32[0], src->s6_addr32[1], |
2043 | src->s6_addr32[2], src->s6_addr32[3], srcp, | 2042 | src->s6_addr32[2], src->s6_addr32[3], srcp, |
@@ -2053,8 +2052,8 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) | |||
2053 | icsk->icsk_probes_out, | 2052 | icsk->icsk_probes_out, |
2054 | sock_i_ino(sp), | 2053 | sock_i_ino(sp), |
2055 | atomic_read(&sp->sk_refcnt), sp, | 2054 | atomic_read(&sp->sk_refcnt), sp, |
2056 | icsk->icsk_rto, | 2055 | jiffies_to_clock_t(icsk->icsk_rto), |
2057 | icsk->icsk_ack.ato, | 2056 | jiffies_to_clock_t(icsk->icsk_ack.ato), |
2058 | (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong, | 2057 | (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong, |
2059 | tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh | 2058 | tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh |
2060 | ); | 2059 | ); |
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c index 6323921b40be..669f280989c3 100644 --- a/net/ipv6/tunnel6.c +++ b/net/ipv6/tunnel6.c | |||
@@ -109,7 +109,7 @@ static int tunnel46_rcv(struct sk_buff *skb) | |||
109 | { | 109 | { |
110 | struct xfrm6_tunnel *handler; | 110 | struct xfrm6_tunnel *handler; |
111 | 111 | ||
112 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 112 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) |
113 | goto drop; | 113 | goto drop; |
114 | 114 | ||
115 | for (handler = tunnel46_handlers; handler; handler = handler->next) | 115 | for (handler = tunnel46_handlers; handler; handler = handler->next) |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 1fd784f3e2ec..dd309626ae9a 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -534,7 +534,9 @@ static void udp_v6_flush_pending_frames(struct sock *sk) | |||
534 | { | 534 | { |
535 | struct udp_sock *up = udp_sk(sk); | 535 | struct udp_sock *up = udp_sk(sk); |
536 | 536 | ||
537 | if (up->pending) { | 537 | if (up->pending == AF_INET) |
538 | udp_flush_pending_frames(sk); | ||
539 | else if (up->pending) { | ||
538 | up->len = 0; | 540 | up->len = 0; |
539 | up->pending = 0; | 541 | up->pending = 0; |
540 | ip6_flush_pending_frames(sk); | 542 | ip6_flush_pending_frames(sk); |
@@ -731,7 +733,7 @@ do_udp_sendmsg: | |||
731 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 733 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
732 | opt->tot_len = sizeof(*opt); | 734 | opt->tot_len = sizeof(*opt); |
733 | 735 | ||
734 | err = datagram_send_ctl(msg, &fl, opt, &hlimit, &tclass); | 736 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, &tclass); |
735 | if (err < 0) { | 737 | if (err < 0) { |
736 | fl6_sock_release(flowlabel); | 738 | fl6_sock_release(flowlabel); |
737 | return err; | 739 | return err; |
@@ -848,12 +850,14 @@ do_append_data: | |||
848 | } else { | 850 | } else { |
849 | dst_release(dst); | 851 | dst_release(dst); |
850 | } | 852 | } |
853 | dst = NULL; | ||
851 | } | 854 | } |
852 | 855 | ||
853 | if (err > 0) | 856 | if (err > 0) |
854 | err = np->recverr ? net_xmit_errno(err) : 0; | 857 | err = np->recverr ? net_xmit_errno(err) : 0; |
855 | release_sock(sk); | 858 | release_sock(sk); |
856 | out: | 859 | out: |
860 | dst_release(dst); | ||
857 | fl6_sock_release(flowlabel); | 861 | fl6_sock_release(flowlabel); |
858 | if (!err) | 862 | if (!err) |
859 | return len; | 863 | return len; |