aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv4/af_inet.c7
-rw-r--r--net/ipv4/igmp.c5
-rw-r--r--net/ipv6/af_inet6.c47
-rw-r--r--net/ipv6/mcast.c5
-rw-r--r--net/sctp/socket.c10
-rw-r--r--net/sctp/transport.c3
6 files changed, 52 insertions, 25 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index eaa150c33b04..d368cf249000 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -228,13 +228,14 @@ static int inet_create(struct socket *sock, int protocol)
228 unsigned char answer_flags; 228 unsigned char answer_flags;
229 char answer_no_check; 229 char answer_no_check;
230 int try_loading_module = 0; 230 int try_loading_module = 0;
231 int err = -ESOCKTNOSUPPORT; 231 int err;
232 232
233 sock->state = SS_UNCONNECTED; 233 sock->state = SS_UNCONNECTED;
234 234
235 /* Look for the requested type/protocol pair. */ 235 /* Look for the requested type/protocol pair. */
236 answer = NULL; 236 answer = NULL;
237lookup_protocol: 237lookup_protocol:
238 err = -ESOCKTNOSUPPORT;
238 rcu_read_lock(); 239 rcu_read_lock();
239 list_for_each_rcu(p, &inetsw[sock->type]) { 240 list_for_each_rcu(p, &inetsw[sock->type]) {
240 answer = list_entry(p, struct inet_protosw, list); 241 answer = list_entry(p, struct inet_protosw, list);
@@ -252,6 +253,7 @@ lookup_protocol:
252 if (IPPROTO_IP == answer->protocol) 253 if (IPPROTO_IP == answer->protocol)
253 break; 254 break;
254 } 255 }
256 err = -EPROTONOSUPPORT;
255 answer = NULL; 257 answer = NULL;
256 } 258 }
257 259
@@ -280,9 +282,6 @@ lookup_protocol:
280 err = -EPERM; 282 err = -EPERM;
281 if (answer->capability > 0 && !capable(answer->capability)) 283 if (answer->capability > 0 && !capable(answer->capability))
282 goto out_rcu_unlock; 284 goto out_rcu_unlock;
283 err = -EPROTONOSUPPORT;
284 if (!protocol)
285 goto out_rcu_unlock;
286 285
287 sock->ops = answer->ops; 286 sock->ops = answer->ops;
288 answer_prot = answer->prot; 287 answer_prot = answer->prot;
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index c04607b49212..4a195c724f01 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -897,7 +897,10 @@ int igmp_rcv(struct sk_buff *skb)
897 /* Is it our report looped back? */ 897 /* Is it our report looped back? */
898 if (((struct rtable*)skb->dst)->fl.iif == 0) 898 if (((struct rtable*)skb->dst)->fl.iif == 0)
899 break; 899 break;
900 igmp_heard_report(in_dev, ih->group); 900 /* don't rely on MC router hearing unicast reports */
901 if (skb->pkt_type == PACKET_MULTICAST ||
902 skb->pkt_type == PACKET_BROADCAST)
903 igmp_heard_report(in_dev, ih->group);
901 break; 904 break;
902 case IGMP_PIM: 905 case IGMP_PIM:
903#ifdef CONFIG_IP_PIMSM_V1 906#ifdef CONFIG_IP_PIMSM_V1
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index c63b8ce0e1b5..d9546380fa04 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)
92 struct proto *answer_prot; 92 struct proto *answer_prot;
93 unsigned char answer_flags; 93 unsigned char answer_flags;
94 char answer_no_check; 94 char answer_no_check;
95 int rc; 95 int try_loading_module = 0;
96 int err;
96 97
97 /* Look for the requested type/protocol pair. */ 98 /* Look for the requested type/protocol pair. */
98 answer = NULL; 99 answer = NULL;
100lookup_protocol:
101 err = -ESOCKTNOSUPPORT;
99 rcu_read_lock(); 102 rcu_read_lock();
100 list_for_each_rcu(p, &inetsw6[sock->type]) { 103 list_for_each_rcu(p, &inetsw6[sock->type]) {
101 answer = list_entry(p, struct inet_protosw, list); 104 answer = list_entry(p, struct inet_protosw, list);
@@ -113,21 +116,37 @@ static int inet6_create(struct socket *sock, int protocol)
113 if (IPPROTO_IP == answer->protocol) 116 if (IPPROTO_IP == answer->protocol)
114 break; 117 break;
115 } 118 }
119 err = -EPROTONOSUPPORT;
116 answer = NULL; 120 answer = NULL;
117 } 121 }
118 122
119 rc = -ESOCKTNOSUPPORT; 123 if (!answer) {
120 if (!answer) 124 if (try_loading_module < 2) {
121 goto out_rcu_unlock; 125 rcu_read_unlock();
122 rc = -EPERM; 126 /*
127 * Be more specific, e.g. net-pf-10-proto-132-type-1
128 * (net-pf-PF_INET6-proto-IPPROTO_SCTP-type-SOCK_STREAM)
129 */
130 if (++try_loading_module == 1)
131 request_module("net-pf-%d-proto-%d-type-%d",
132 PF_INET6, protocol, sock->type);
133 /*
134 * Fall back to generic, e.g. net-pf-10-proto-132
135 * (net-pf-PF_INET6-proto-IPPROTO_SCTP)
136 */
137 else
138 request_module("net-pf-%d-proto-%d",
139 PF_INET6, protocol);
140 goto lookup_protocol;
141 } else
142 goto out_rcu_unlock;
143 }
144
145 err = -EPERM;
123 if (answer->capability > 0 && !capable(answer->capability)) 146 if (answer->capability > 0 && !capable(answer->capability))
124 goto out_rcu_unlock; 147 goto out_rcu_unlock;
125 rc = -EPROTONOSUPPORT;
126 if (!protocol)
127 goto out_rcu_unlock;
128 148
129 sock->ops = answer->ops; 149 sock->ops = answer->ops;
130
131 answer_prot = answer->prot; 150 answer_prot = answer->prot;
132 answer_no_check = answer->no_check; 151 answer_no_check = answer->no_check;
133 answer_flags = answer->flags; 152 answer_flags = answer->flags;
@@ -135,14 +154,14 @@ static int inet6_create(struct socket *sock, int protocol)
135 154
136 BUG_TRAP(answer_prot->slab != NULL); 155 BUG_TRAP(answer_prot->slab != NULL);
137 156
138 rc = -ENOBUFS; 157 err = -ENOBUFS;
139 sk = sk_alloc(PF_INET6, GFP_KERNEL, answer_prot, 1); 158 sk = sk_alloc(PF_INET6, GFP_KERNEL, answer_prot, 1);
140 if (sk == NULL) 159 if (sk == NULL)
141 goto out; 160 goto out;
142 161
143 sock_init_data(sock, sk); 162 sock_init_data(sock, sk);
144 163
145 rc = 0; 164 err = 0;
146 sk->sk_no_check = answer_no_check; 165 sk->sk_no_check = answer_no_check;
147 if (INET_PROTOSW_REUSE & answer_flags) 166 if (INET_PROTOSW_REUSE & answer_flags)
148 sk->sk_reuse = 1; 167 sk->sk_reuse = 1;
@@ -202,14 +221,14 @@ static int inet6_create(struct socket *sock, int protocol)
202 sk->sk_prot->hash(sk); 221 sk->sk_prot->hash(sk);
203 } 222 }
204 if (sk->sk_prot->init) { 223 if (sk->sk_prot->init) {
205 rc = sk->sk_prot->init(sk); 224 err = sk->sk_prot->init(sk);
206 if (rc) { 225 if (err) {
207 sk_common_release(sk); 226 sk_common_release(sk);
208 goto out; 227 goto out;
209 } 228 }
210 } 229 }
211out: 230out:
212 return rc; 231 return err;
213out_rcu_unlock: 232out_rcu_unlock:
214 rcu_read_unlock(); 233 rcu_read_unlock();
215 goto out; 234 goto out;
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index f15e04ad026e..fd939da090c4 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1231,6 +1231,11 @@ int igmp6_event_report(struct sk_buff *skb)
1231 if (skb->pkt_type == PACKET_LOOPBACK) 1231 if (skb->pkt_type == PACKET_LOOPBACK)
1232 return 0; 1232 return 0;
1233 1233
1234 /* send our report if the MC router may not have heard this report */
1235 if (skb->pkt_type != PACKET_MULTICAST &&
1236 skb->pkt_type != PACKET_BROADCAST)
1237 return 0;
1238
1234 if (!pskb_may_pull(skb, sizeof(struct in6_addr))) 1239 if (!pskb_may_pull(skb, sizeof(struct in6_addr)))
1235 return -EINVAL; 1240 return -EINVAL;
1236 1241
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index abab81f3818f..d890dfa8818f 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4743,11 +4743,6 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags,
4743 struct sk_buff *skb; 4743 struct sk_buff *skb;
4744 long timeo; 4744 long timeo;
4745 4745
4746 /* Caller is allowed not to check sk->sk_err before calling. */
4747 error = sock_error(sk);
4748 if (error)
4749 goto no_packet;
4750
4751 timeo = sock_rcvtimeo(sk, noblock); 4746 timeo = sock_rcvtimeo(sk, noblock);
4752 4747
4753 SCTP_DEBUG_PRINTK("Timeout: timeo: %ld, MAX: %ld.\n", 4748 SCTP_DEBUG_PRINTK("Timeout: timeo: %ld, MAX: %ld.\n",
@@ -4774,6 +4769,11 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags,
4774 if (skb) 4769 if (skb)
4775 return skb; 4770 return skb;
4776 4771
4772 /* Caller is allowed not to check sk->sk_err before calling. */
4773 error = sock_error(sk);
4774 if (error)
4775 goto no_packet;
4776
4777 if (sk->sk_shutdown & RCV_SHUTDOWN) 4777 if (sk->sk_shutdown & RCV_SHUTDOWN)
4778 break; 4778 break;
4779 4779
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 6bc27200e6ca..268ddaf2dc0f 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -261,7 +261,8 @@ void sctp_transport_route(struct sctp_transport *transport,
261 * association's active path for getsockname(). 261 * association's active path for getsockname().
262 */ 262 */
263 if (asoc && (transport == asoc->peer.active_path)) 263 if (asoc && (transport == asoc->peer.active_path))
264 af->to_sk_saddr(&transport->saddr, asoc->base.sk); 264 opt->pf->af->to_sk_saddr(&transport->saddr,
265 asoc->base.sk);
265 } else 266 } else
266 transport->pmtu = SCTP_DEFAULT_MAXSEGMENT; 267 transport->pmtu = SCTP_DEFAULT_MAXSEGMENT;
267} 268}