aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/addrconf.h22
-rw-r--r--include/net/sctp/structs.h3
-rw-r--r--include/net/transp_v6.h3
-rw-r--r--include/net/udp.h1
-rw-r--r--net/ipv4/tunnel4.c2
-rw-r--r--net/ipv4/udp.c3
-rw-r--r--net/ipv6/addrconf.c107
-rw-r--r--net/ipv6/datagram.c45
-rw-r--r--net/ipv6/ip6_flowlabel.c2
-rw-r--r--net/ipv6/ipv6_sockglue.c21
-rw-r--r--net/ipv6/raw.c2
-rw-r--r--net/ipv6/route.c12
-rw-r--r--net/ipv6/tunnel6.c2
-rw-r--r--net/ipv6/udp.c8
-rw-r--r--net/sctp/ipv6.c5
-rw-r--r--net/sctp/protocol.c3
-rw-r--r--net/sctp/transport.c2
17 files changed, 146 insertions, 97 deletions
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 0a2f0372df31..bbd3d583c6e6 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -94,6 +94,28 @@ extern void addrconf_join_solict(struct net_device *dev,
94extern void addrconf_leave_solict(struct inet6_dev *idev, 94extern void addrconf_leave_solict(struct inet6_dev *idev,
95 struct in6_addr *addr); 95 struct in6_addr *addr);
96 96
97static inline unsigned long addrconf_timeout_fixup(u32 timeout,
98 unsigned unit)
99{
100 if (timeout == 0xffffffff)
101 return ~0UL;
102
103 /*
104 * Avoid arithmetic overflow.
105 * Assuming unit is constant and non-zero, this "if" statement
106 * will go away on 64bit archs.
107 */
108 if (0xfffffffe > LONG_MAX / unit && timeout > LONG_MAX / unit)
109 return LONG_MAX / unit;
110
111 return timeout;
112}
113
114static inline int addrconf_finite_timeout(unsigned long timeout)
115{
116 return ~timeout;
117}
118
97/* 119/*
98 * IPv6 Address Label subsystem (addrlabel.c) 120 * IPv6 Address Label subsystem (addrlabel.c)
99 */ 121 */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 0ce0443c5b79..917d425f0542 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -548,7 +548,8 @@ struct sctp_af {
548 struct dst_entry *(*get_dst) (struct sctp_association *asoc, 548 struct dst_entry *(*get_dst) (struct sctp_association *asoc,
549 union sctp_addr *daddr, 549 union sctp_addr *daddr,
550 union sctp_addr *saddr); 550 union sctp_addr *saddr);
551 void (*get_saddr) (struct sctp_association *asoc, 551 void (*get_saddr) (struct sctp_sock *sk,
552 struct sctp_association *asoc,
552 struct dst_entry *dst, 553 struct dst_entry *dst,
553 union sctp_addr *daddr, 554 union sctp_addr *daddr,
554 union sctp_addr *saddr); 555 union sctp_addr *saddr);
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h
index 27394e0447d8..112934a3288d 100644
--- a/include/net/transp_v6.h
+++ b/include/net/transp_v6.h
@@ -40,7 +40,8 @@ extern int datagram_recv_ctl(struct sock *sk,
40 struct msghdr *msg, 40 struct msghdr *msg,
41 struct sk_buff *skb); 41 struct sk_buff *skb);
42 42
43extern int datagram_send_ctl(struct msghdr *msg, 43extern int datagram_send_ctl(struct net *net,
44 struct msghdr *msg,
44 struct flowi *fl, 45 struct flowi *fl,
45 struct ipv6_txoptions *opt, 46 struct ipv6_txoptions *opt,
46 int *hlimit, int *tclass); 47 int *hlimit, int *tclass);
diff --git a/include/net/udp.h b/include/net/udp.h
index 3e55a99b0ba3..ccce83707046 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -135,6 +135,7 @@ extern void udp_err(struct sk_buff *, u32);
135 135
136extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk, 136extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk,
137 struct msghdr *msg, size_t len); 137 struct msghdr *msg, size_t len);
138extern void udp_flush_pending_frames(struct sock *sk);
138 139
139extern int udp_rcv(struct sk_buff *skb); 140extern int udp_rcv(struct sk_buff *skb);
140extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg); 141extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c
index d3b709a6f264..cb1f0e83830b 100644
--- a/net/ipv4/tunnel4.c
+++ b/net/ipv4/tunnel4.c
@@ -97,7 +97,7 @@ static int tunnel64_rcv(struct sk_buff *skb)
97{ 97{
98 struct xfrm_tunnel *handler; 98 struct xfrm_tunnel *handler;
99 99
100 if (!pskb_may_pull(skb, sizeof(struct iphdr))) 100 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
101 goto drop; 101 goto drop;
102 102
103 for (handler = tunnel64_handlers; handler; handler = handler->next) 103 for (handler = tunnel64_handlers; handler; handler = handler->next)
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index db1cb7c96d63..56fcda3694ba 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -420,7 +420,7 @@ void udp_err(struct sk_buff *skb, u32 info)
420/* 420/*
421 * Throw away all pending data and cancel the corking. Socket is locked. 421 * Throw away all pending data and cancel the corking. Socket is locked.
422 */ 422 */
423static void udp_flush_pending_frames(struct sock *sk) 423void udp_flush_pending_frames(struct sock *sk)
424{ 424{
425 struct udp_sock *up = udp_sk(sk); 425 struct udp_sock *up = udp_sk(sk);
426 426
@@ -430,6 +430,7 @@ static void udp_flush_pending_frames(struct sock *sk)
430 ip_flush_pending_frames(sk); 430 ip_flush_pending_frames(sk);
431 } 431 }
432} 432}
433EXPORT_SYMBOL(udp_flush_pending_frames);
433 434
434/** 435/**
435 * udp4_hwcsum_outgoing - handle outgoing HW checksumming 436 * udp4_hwcsum_outgoing - handle outgoing HW checksumming
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 */
2029static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, 2028static 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
2097static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, 2101static 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/datagram.c b/net/ipv6/datagram.c
index 94fa6ae77cfe..b9c2de84a8a2 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
499int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, 499int 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)) {
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/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 56d55fecf8ec..26b83e512a09 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -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) {
@@ -416,7 +424,7 @@ sticky_done:
416 msg.msg_controllen = optlen; 424 msg.msg_controllen = optlen;
417 msg.msg_control = (void*)(opt+1); 425 msg.msg_control = (void*)(opt+1);
418 426
419 retv = datagram_send_ctl(&msg, &fl, opt, &junk, &junk); 427 retv = datagram_send_ctl(net, &msg, &fl, opt, &junk, &junk);
420 if (retv) 428 if (retv)
421 goto done; 429 goto done;
422update: 430update:
@@ -832,7 +840,7 @@ static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt,
832 len = min_t(unsigned int, len, ipv6_optlen(hdr)); 840 len = min_t(unsigned int, len, ipv6_optlen(hdr));
833 if (copy_to_user(optval, hdr, len)) 841 if (copy_to_user(optval, hdr, len))
834 return -EFAULT; 842 return -EFAULT;
835 return ipv6_optlen(hdr); 843 return len;
836} 844}
837 845
838static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, 846static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
@@ -975,6 +983,9 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
975 len = ipv6_getsockopt_sticky(sk, np->opt, 983 len = ipv6_getsockopt_sticky(sk, np->opt,
976 optname, optval, len); 984 optname, optval, len);
977 release_sock(sk); 985 release_sock(sk);
986 /* check if ipv6_getsockopt_sticky() returns err code */
987 if (len < 0)
988 return len;
978 return put_user(len, optlen); 989 return put_user(len, optlen);
979 } 990 }
980 991
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 232e0dc45bf5..603df76e0522 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;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 48534c6c0735..220cffe9e63b 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -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;
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);
856out: 859out:
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;
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index e45e44c60635..e4aac3266fcd 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -299,7 +299,8 @@ static inline int sctp_v6_addr_match_len(union sctp_addr *s1,
299/* Fills in the source address(saddr) based on the destination address(daddr) 299/* Fills in the source address(saddr) based on the destination address(daddr)
300 * and asoc's bind address list. 300 * and asoc's bind address list.
301 */ 301 */
302static void sctp_v6_get_saddr(struct sctp_association *asoc, 302static void sctp_v6_get_saddr(struct sctp_sock *sk,
303 struct sctp_association *asoc,
303 struct dst_entry *dst, 304 struct dst_entry *dst,
304 union sctp_addr *daddr, 305 union sctp_addr *daddr,
305 union sctp_addr *saddr) 306 union sctp_addr *saddr)
@@ -318,7 +319,7 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc,
318 if (!asoc) { 319 if (!asoc) {
319 ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, 320 ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL,
320 &daddr->v6.sin6_addr, 321 &daddr->v6.sin6_addr,
321 inet6_sk(asoc->base.sk)->srcprefs, 322 inet6_sk(&sk->inet.sk)->srcprefs,
322 &saddr->v6.sin6_addr); 323 &saddr->v6.sin6_addr);
323 SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " NIP6_FMT "\n", 324 SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " NIP6_FMT "\n",
324 NIP6(saddr->v6.sin6_addr)); 325 NIP6(saddr->v6.sin6_addr));
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 0ec234b762c2..13ee7fa92e07 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -519,7 +519,8 @@ out:
519/* For v4, the source address is cached in the route entry(dst). So no need 519/* For v4, the source address is cached in the route entry(dst). So no need
520 * to cache it separately and hence this is an empty routine. 520 * to cache it separately and hence this is an empty routine.
521 */ 521 */
522static void sctp_v4_get_saddr(struct sctp_association *asoc, 522static void sctp_v4_get_saddr(struct sctp_sock *sk,
523 struct sctp_association *asoc,
523 struct dst_entry *dst, 524 struct dst_entry *dst,
524 union sctp_addr *daddr, 525 union sctp_addr *daddr,
525 union sctp_addr *saddr) 526 union sctp_addr *saddr)
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index f4938f6c5abe..62082e7b7972 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -291,7 +291,7 @@ void sctp_transport_route(struct sctp_transport *transport,
291 if (saddr) 291 if (saddr)
292 memcpy(&transport->saddr, saddr, sizeof(union sctp_addr)); 292 memcpy(&transport->saddr, saddr, sizeof(union sctp_addr));
293 else 293 else
294 af->get_saddr(asoc, dst, daddr, &transport->saddr); 294 af->get_saddr(opt, asoc, dst, daddr, &transport->saddr);
295 295
296 transport->dst = dst; 296 transport->dst = dst;
297 if ((transport->param_flags & SPP_PMTUD_DISABLE) && transport->pathmtu) { 297 if ((transport->param_flags & SPP_PMTUD_DISABLE) && transport->pathmtu) {