summaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c13
-rw-r--r--net/ipv6/datagram.c6
-rw-r--r--net/ipv6/esp6.c6
-rw-r--r--net/ipv6/ip6_output.c2
-rw-r--r--net/ipv6/ipv6_sockglue.c12
-rw-r--r--net/ipv6/ndisc.c2
-rw-r--r--net/ipv6/tcp_ipv6.c11
-rw-r--r--net/ipv6/xfrm6_policy.c2
8 files changed, 35 insertions, 19 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 1bd8d818f8e..e8c347579da 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -967,7 +967,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
if (unlikely(score.addr_type == IPV6_ADDR_ANY ||
score.addr_type & IPV6_ADDR_MULTICAST)) {
LIMIT_NETDEBUG(KERN_DEBUG
- "ADDRCONF: unspecified / multicast address"
+ "ADDRCONF: unspecified / multicast address "
"assigned as unicast address on %s",
dev->name);
continue;
@@ -2293,6 +2293,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
break;
}
+ if (!idev && dev->mtu >= IPV6_MIN_MTU)
+ idev = ipv6_add_dev(dev);
+
if (idev)
idev->if_flags |= IF_READY;
} else {
@@ -2357,12 +2360,18 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
break;
case NETDEV_CHANGEMTU:
- if ( idev && dev->mtu >= IPV6_MIN_MTU) {
+ if (idev && dev->mtu >= IPV6_MIN_MTU) {
rt6_mtu_change(dev, dev->mtu);
idev->cnf.mtu6 = dev->mtu;
break;
}
+ if (!idev && dev->mtu >= IPV6_MIN_MTU) {
+ idev = ipv6_add_dev(dev);
+ if (idev)
+ break;
+ }
+
/* MTU falled under IPV6_MIN_MTU. Stop IPv6 on this interface. */
case NETDEV_DOWN:
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 2ed689ac449..5d4245ab418 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -123,11 +123,11 @@ ipv4_connected:
goto out;
}
sk->sk_bound_dev_if = usin->sin6_scope_id;
- if (!sk->sk_bound_dev_if &&
- (addr_type & IPV6_ADDR_MULTICAST))
- fl.oif = np->mcast_oif;
}
+ if (!sk->sk_bound_dev_if && (addr_type & IPV6_ADDR_MULTICAST))
+ sk->sk_bound_dev_if = np->mcast_oif;
+
/* Connect to link-local address requires an interface */
if (!sk->sk_bound_dev_if) {
err = -EINVAL;
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 7db66f10e00..44405325467 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -230,6 +230,12 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
}
/* ... check padding bits here. Silly. :-) */
+ /* RFC4303: Drop dummy packets without any error */
+ if (nexthdr[1] == IPPROTO_NONE) {
+ ret = -EINVAL;
+ goto out;
+ }
+
pskb_trim(skb, skb->len - alen - padlen - 2);
ret = nexthdr[1];
}
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 86e1835ce4e..6338a9c1aa1 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -933,6 +933,8 @@ static int ip6_dst_lookup_tail(struct sock *sk,
return 0;
out_err_release:
+ if (err == -ENETUNREACH)
+ IP6_INC_STATS_BH(NULL, IPSTATS_MIB_OUTNOROUTES);
dst_release(*dst);
*dst = NULL;
return err;
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 1334fc174bc..8c5f80fd03a 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -1046,7 +1046,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
break;
default:
- return -EINVAL;
+ return -ENOPROTOOPT;
}
len = min_t(unsigned int, sizeof(int), len);
if(put_user(len, optlen))
@@ -1069,9 +1069,8 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
#ifdef CONFIG_NETFILTER
- /* we need to exclude all possible EINVALs except default case */
- if (err == -EINVAL && optname != IPV6_ADDRFORM &&
- optname != MCAST_MSFILTER) {
+ /* we need to exclude all possible ENOPROTOOPTs except default case */
+ if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) {
int len;
if (get_user(len, optlen))
@@ -1108,9 +1107,8 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
#ifdef CONFIG_NETFILTER
- /* we need to exclude all possible EINVALs except default case */
- if (err == -EINVAL && optname != IPV6_ADDRFORM &&
- optname != MCAST_MSFILTER) {
+ /* we need to exclude all possible ENOPROTOOPTs except default case */
+ if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) {
int len;
if (get_user(len, optlen))
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 67997a74ddc..777ed733b2d 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -612,7 +612,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
* optimistic addresses, but we may send the solicitation
* if we don't include the sllao. So here we check
* if our address is optimistic, and if so, we
- * supress the inclusion of the sllao.
+ * suppress the inclusion of the sllao.
*/
if (send_sllao) {
struct inet6_ifaddr *ifp = ipv6_get_ifaddr(saddr, dev, 1);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 3aad861975a..93980c3b83e 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -581,7 +581,10 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer,
}
sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
}
- tcp_alloc_md5sig_pool();
+ if (tcp_alloc_md5sig_pool() == NULL) {
+ kfree(newkey);
+ return -ENOMEM;
+ }
if (tp->md5sig_info->alloced6 == tp->md5sig_info->entries6) {
keys = kmalloc((sizeof (tp->md5sig_info->keys6[0]) *
(tp->md5sig_info->entries6 + 1)), GFP_ATOMIC);
@@ -634,10 +637,6 @@ static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer)
kfree(tp->md5sig_info->keys6);
tp->md5sig_info->keys6 = NULL;
tp->md5sig_info->alloced6 = 0;
-
- tcp_free_md5sig_pool();
-
- return 0;
} else {
/* shrink the database */
if (tp->md5sig_info->entries6 != i)
@@ -646,6 +645,8 @@ static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer)
(tp->md5sig_info->entries6 - i)
* sizeof (tp->md5sig_info->keys6[0]));
}
+ tcp_free_md5sig_pool();
+ return 0;
}
}
return -ENOENT;
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 82e27b80d07..b8e9eb445d7 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -233,7 +233,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
dst_prev->output = dst_prev->xfrm->outer_mode->afinfo->output;
/* Sheit... I remember I did this right. Apparently,
* it was magically lost, so this code needs audit */
- x->u.rt6.rt6i_flags = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);
+ x->u.rt6.rt6i_flags = rt0->rt6i_flags&(RTF_ANYCAST|RTF_LOCAL);
x->u.rt6.rt6i_metric = rt0->rt6i_metric;
x->u.rt6.rt6i_node = rt0->rt6i_node;
x->u.rt6.rt6i_gateway = rt0->rt6i_gateway;