aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c2
-rw-r--r--net/ipv6/af_inet6.c47
-rw-r--r--net/ipv6/icmp.c2
-rw-r--r--net/ipv6/ip6_output.c3
-rw-r--r--net/ipv6/ipv6_sockglue.c4
-rw-r--r--net/ipv6/mcast.c5
-rw-r--r--net/ipv6/netfilter/ip6_tables.c2
7 files changed, 46 insertions, 19 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index a16064b..76ff9f4 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -985,6 +985,8 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
}
/* Rule 4: Prefer home address -- not implemented yet */
+ if (hiscore.rule < 4)
+ hiscore.rule++;
/* Rule 5: Prefer outgoing interface */
if (hiscore.rule < 5) {
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index c63b8ce..d954638 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -92,10 +92,13 @@ static int inet6_create(struct socket *sock, int protocol)
struct proto *answer_prot;
unsigned char answer_flags;
char answer_no_check;
- int rc;
+ int try_loading_module = 0;
+ int err;
/* Look for the requested type/protocol pair. */
answer = NULL;
+lookup_protocol:
+ err = -ESOCKTNOSUPPORT;
rcu_read_lock();
list_for_each_rcu(p, &inetsw6[sock->type]) {
answer = list_entry(p, struct inet_protosw, list);
@@ -113,21 +116,37 @@ static int inet6_create(struct socket *sock, int protocol)
if (IPPROTO_IP == answer->protocol)
break;
}
+ err = -EPROTONOSUPPORT;
answer = NULL;
}
- rc = -ESOCKTNOSUPPORT;
- if (!answer)
- goto out_rcu_unlock;
- rc = -EPERM;
+ if (!answer) {
+ if (try_loading_module < 2) {
+ rcu_read_unlock();
+ /*
+ * Be more specific, e.g. net-pf-10-proto-132-type-1
+ * (net-pf-PF_INET6-proto-IPPROTO_SCTP-type-SOCK_STREAM)
+ */
+ if (++try_loading_module == 1)
+ request_module("net-pf-%d-proto-%d-type-%d",
+ PF_INET6, protocol, sock->type);
+ /*
+ * Fall back to generic, e.g. net-pf-10-proto-132
+ * (net-pf-PF_INET6-proto-IPPROTO_SCTP)
+ */
+ else
+ request_module("net-pf-%d-proto-%d",
+ PF_INET6, protocol);
+ goto lookup_protocol;
+ } else
+ goto out_rcu_unlock;
+ }
+
+ err = -EPERM;
if (answer->capability > 0 && !capable(answer->capability))
goto out_rcu_unlock;
- rc = -EPROTONOSUPPORT;
- if (!protocol)
- goto out_rcu_unlock;
sock->ops = answer->ops;
-
answer_prot = answer->prot;
answer_no_check = answer->no_check;
answer_flags = answer->flags;
@@ -135,14 +154,14 @@ static int inet6_create(struct socket *sock, int protocol)
BUG_TRAP(answer_prot->slab != NULL);
- rc = -ENOBUFS;
+ err = -ENOBUFS;
sk = sk_alloc(PF_INET6, GFP_KERNEL, answer_prot, 1);
if (sk == NULL)
goto out;
sock_init_data(sock, sk);
- rc = 0;
+ err = 0;
sk->sk_no_check = answer_no_check;
if (INET_PROTOSW_REUSE & answer_flags)
sk->sk_reuse = 1;
@@ -202,14 +221,14 @@ static int inet6_create(struct socket *sock, int protocol)
sk->sk_prot->hash(sk);
}
if (sk->sk_prot->init) {
- rc = sk->sk_prot->init(sk);
- if (rc) {
+ err = sk->sk_prot->init(sk);
+ if (err) {
sk_common_release(sk);
goto out;
}
}
out:
- return rc;
+ return err;
out_rcu_unlock:
rcu_read_unlock();
goto out;
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 1bdf0fb..34a3322 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -751,7 +751,7 @@ void icmpv6_cleanup(void)
inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);
}
-static struct icmp6_err {
+static const struct icmp6_err {
int err;
int fatal;
} tab_unreach[] = {
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index c1fa693..8523c76 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -774,7 +774,8 @@ out_err_release:
*dst = NULL;
return err;
}
-inline int ip6_ufo_append_data(struct sock *sk,
+
+static inline int ip6_ufo_append_data(struct sock *sk,
int getfrag(void *from, char *to, int offset, int len,
int odd, struct sk_buff *skb),
void *from, int length, int hh_len, int fragheaderlen,
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 25757ad..3620718 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -628,8 +628,8 @@ e_inval:
return -EINVAL;
}
-int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr,
- char __user *optval, int len)
+static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr,
+ char __user *optval, int len)
{
if (!hdr)
return 0;
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index f15e04a..fd939da 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1231,6 +1231,11 @@ int igmp6_event_report(struct sk_buff *skb)
if (skb->pkt_type == PACKET_LOOPBACK)
return 0;
+ /* send our report if the MC router may not have heard this report */
+ if (skb->pkt_type != PACKET_MULTICAST &&
+ skb->pkt_type != PACKET_BROADCAST)
+ return 0;
+
if (!pskb_may_pull(skb, sizeof(struct in6_addr)))
return -EINVAL;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 7d49222..95d4692 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1972,7 +1972,7 @@ static int ip6t_get_matches(char *buffer, char **start, off_t offset, int length
return pos;
}
-static struct { char *name; get_info_t *get_info; } ip6t_proc_entry[] =
+static const struct { char *name; get_info_t *get_info; } ip6t_proc_entry[] =
{ { "ip6_tables_names", ip6t_get_tables },
{ "ip6_tables_targets", ip6t_get_targets },
{ "ip6_tables_matches", ip6t_get_matches },