diff options
Diffstat (limited to 'net/phonet/socket.c')
-rw-r--r-- | net/phonet/socket.c | 126 |
1 files changed, 51 insertions, 75 deletions
diff --git a/net/phonet/socket.c b/net/phonet/socket.c index 25f746d20c1f..b1adafab377c 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c | |||
@@ -225,15 +225,18 @@ static int pn_socket_autobind(struct socket *sock) | |||
225 | return 0; /* socket was already bound */ | 225 | return 0; /* socket was already bound */ |
226 | } | 226 | } |
227 | 227 | ||
228 | #ifdef CONFIG_PHONET_PIPECTRLR | ||
229 | static int pn_socket_connect(struct socket *sock, struct sockaddr *addr, | 228 | static int pn_socket_connect(struct socket *sock, struct sockaddr *addr, |
230 | int len, int flags) | 229 | int len, int flags) |
231 | { | 230 | { |
232 | struct sock *sk = sock->sk; | 231 | struct sock *sk = sock->sk; |
232 | struct pn_sock *pn = pn_sk(sk); | ||
233 | struct sockaddr_pn *spn = (struct sockaddr_pn *)addr; | 233 | struct sockaddr_pn *spn = (struct sockaddr_pn *)addr; |
234 | long timeo; | 234 | struct task_struct *tsk = current; |
235 | long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); | ||
235 | int err; | 236 | int err; |
236 | 237 | ||
238 | if (pn_socket_autobind(sock)) | ||
239 | return -ENOBUFS; | ||
237 | if (len < sizeof(struct sockaddr_pn)) | 240 | if (len < sizeof(struct sockaddr_pn)) |
238 | return -EINVAL; | 241 | return -EINVAL; |
239 | if (spn->spn_family != AF_PHONET) | 242 | if (spn->spn_family != AF_PHONET) |
@@ -243,82 +246,61 @@ static int pn_socket_connect(struct socket *sock, struct sockaddr *addr, | |||
243 | 246 | ||
244 | switch (sock->state) { | 247 | switch (sock->state) { |
245 | case SS_UNCONNECTED: | 248 | case SS_UNCONNECTED: |
246 | sk->sk_state = TCP_CLOSE; | 249 | if (sk->sk_state != TCP_CLOSE) { |
247 | break; | ||
248 | case SS_CONNECTING: | ||
249 | switch (sk->sk_state) { | ||
250 | case TCP_SYN_RECV: | ||
251 | sock->state = SS_CONNECTED; | ||
252 | err = -EISCONN; | 250 | err = -EISCONN; |
253 | goto out; | 251 | goto out; |
254 | case TCP_CLOSE: | ||
255 | err = -EALREADY; | ||
256 | if (flags & O_NONBLOCK) | ||
257 | goto out; | ||
258 | goto wait_connect; | ||
259 | } | 252 | } |
260 | break; | 253 | break; |
261 | case SS_CONNECTED: | 254 | case SS_CONNECTING: |
262 | switch (sk->sk_state) { | 255 | err = -EALREADY; |
263 | case TCP_SYN_RECV: | 256 | goto out; |
264 | err = -EISCONN; | 257 | default: |
265 | goto out; | 258 | err = -EISCONN; |
266 | case TCP_CLOSE: | 259 | goto out; |
267 | sock->state = SS_UNCONNECTED; | ||
268 | break; | ||
269 | } | ||
270 | break; | ||
271 | case SS_DISCONNECTING: | ||
272 | case SS_FREE: | ||
273 | break; | ||
274 | } | 260 | } |
275 | sk->sk_state = TCP_CLOSE; | ||
276 | sk_stream_kill_queues(sk); | ||
277 | 261 | ||
262 | pn->dobject = pn_sockaddr_get_object(spn); | ||
263 | pn->resource = pn_sockaddr_get_resource(spn); | ||
278 | sock->state = SS_CONNECTING; | 264 | sock->state = SS_CONNECTING; |
265 | |||
279 | err = sk->sk_prot->connect(sk, addr, len); | 266 | err = sk->sk_prot->connect(sk, addr, len); |
280 | if (err < 0) { | 267 | if (err) { |
281 | sock->state = SS_UNCONNECTED; | 268 | sock->state = SS_UNCONNECTED; |
282 | sk->sk_state = TCP_CLOSE; | 269 | pn->dobject = 0; |
283 | goto out; | 270 | goto out; |
284 | } | 271 | } |
285 | 272 | ||
286 | err = -EINPROGRESS; | 273 | while (sk->sk_state == TCP_SYN_SENT) { |
287 | wait_connect: | 274 | DEFINE_WAIT(wait); |
288 | if (sk->sk_state != TCP_SYN_RECV && (flags & O_NONBLOCK)) | ||
289 | goto out; | ||
290 | |||
291 | timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); | ||
292 | release_sock(sk); | ||
293 | |||
294 | err = -ERESTARTSYS; | ||
295 | timeo = wait_event_interruptible_timeout(*sk_sleep(sk), | ||
296 | sk->sk_state != TCP_CLOSE, | ||
297 | timeo); | ||
298 | |||
299 | lock_sock(sk); | ||
300 | if (timeo < 0) | ||
301 | goto out; /* -ERESTARTSYS */ | ||
302 | 275 | ||
303 | err = -ETIMEDOUT; | 276 | if (!timeo) { |
304 | if (timeo == 0 && sk->sk_state != TCP_SYN_RECV) | 277 | err = -EINPROGRESS; |
305 | goto out; | 278 | goto out; |
279 | } | ||
280 | if (signal_pending(tsk)) { | ||
281 | err = sock_intr_errno(timeo); | ||
282 | goto out; | ||
283 | } | ||
306 | 284 | ||
307 | if (sk->sk_state != TCP_SYN_RECV) { | 285 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, |
308 | sock->state = SS_UNCONNECTED; | 286 | TASK_INTERRUPTIBLE); |
309 | err = sock_error(sk); | 287 | release_sock(sk); |
310 | if (!err) | 288 | timeo = schedule_timeout(timeo); |
311 | err = -ECONNREFUSED; | 289 | lock_sock(sk); |
312 | goto out; | 290 | finish_wait(sk_sleep(sk), &wait); |
313 | } | 291 | } |
314 | sock->state = SS_CONNECTED; | ||
315 | err = 0; | ||
316 | 292 | ||
293 | if ((1 << sk->sk_state) & (TCPF_SYN_RECV|TCPF_ESTABLISHED)) | ||
294 | err = 0; | ||
295 | else if (sk->sk_state == TCP_CLOSE_WAIT) | ||
296 | err = -ECONNRESET; | ||
297 | else | ||
298 | err = -ECONNREFUSED; | ||
299 | sock->state = err ? SS_UNCONNECTED : SS_CONNECTED; | ||
317 | out: | 300 | out: |
318 | release_sock(sk); | 301 | release_sock(sk); |
319 | return err; | 302 | return err; |
320 | } | 303 | } |
321 | #endif | ||
322 | 304 | ||
323 | static int pn_socket_accept(struct socket *sock, struct socket *newsock, | 305 | static int pn_socket_accept(struct socket *sock, struct socket *newsock, |
324 | int flags) | 306 | int flags) |
@@ -327,6 +309,9 @@ static int pn_socket_accept(struct socket *sock, struct socket *newsock, | |||
327 | struct sock *newsk; | 309 | struct sock *newsk; |
328 | int err; | 310 | int err; |
329 | 311 | ||
312 | if (unlikely(sk->sk_state != TCP_LISTEN)) | ||
313 | return -EINVAL; | ||
314 | |||
330 | newsk = sk->sk_prot->accept(sk, flags, &err); | 315 | newsk = sk->sk_prot->accept(sk, flags, &err); |
331 | if (!newsk) | 316 | if (!newsk) |
332 | return err; | 317 | return err; |
@@ -363,13 +348,8 @@ static unsigned int pn_socket_poll(struct file *file, struct socket *sock, | |||
363 | 348 | ||
364 | poll_wait(file, sk_sleep(sk), wait); | 349 | poll_wait(file, sk_sleep(sk), wait); |
365 | 350 | ||
366 | switch (sk->sk_state) { | 351 | if (sk->sk_state == TCP_CLOSE) |
367 | case TCP_LISTEN: | ||
368 | return hlist_empty(&pn->ackq) ? 0 : POLLIN; | ||
369 | case TCP_CLOSE: | ||
370 | return POLLERR; | 352 | return POLLERR; |
371 | } | ||
372 | |||
373 | if (!skb_queue_empty(&sk->sk_receive_queue)) | 353 | if (!skb_queue_empty(&sk->sk_receive_queue)) |
374 | mask |= POLLIN | POLLRDNORM; | 354 | mask |= POLLIN | POLLRDNORM; |
375 | if (!skb_queue_empty(&pn->ctrlreq_queue)) | 355 | if (!skb_queue_empty(&pn->ctrlreq_queue)) |
@@ -428,19 +408,19 @@ static int pn_socket_listen(struct socket *sock, int backlog) | |||
428 | struct sock *sk = sock->sk; | 408 | struct sock *sk = sock->sk; |
429 | int err = 0; | 409 | int err = 0; |
430 | 410 | ||
431 | if (sock->state != SS_UNCONNECTED) | ||
432 | return -EINVAL; | ||
433 | if (pn_socket_autobind(sock)) | 411 | if (pn_socket_autobind(sock)) |
434 | return -ENOBUFS; | 412 | return -ENOBUFS; |
435 | 413 | ||
436 | lock_sock(sk); | 414 | lock_sock(sk); |
437 | if (sk->sk_state != TCP_CLOSE) { | 415 | if (sock->state != SS_UNCONNECTED) { |
438 | err = -EINVAL; | 416 | err = -EINVAL; |
439 | goto out; | 417 | goto out; |
440 | } | 418 | } |
441 | 419 | ||
442 | sk->sk_state = TCP_LISTEN; | 420 | if (sk->sk_state != TCP_LISTEN) { |
443 | sk->sk_ack_backlog = 0; | 421 | sk->sk_state = TCP_LISTEN; |
422 | sk->sk_ack_backlog = 0; | ||
423 | } | ||
444 | sk->sk_max_ack_backlog = backlog; | 424 | sk->sk_max_ack_backlog = backlog; |
445 | out: | 425 | out: |
446 | release_sock(sk); | 426 | release_sock(sk); |
@@ -488,11 +468,7 @@ const struct proto_ops phonet_stream_ops = { | |||
488 | .owner = THIS_MODULE, | 468 | .owner = THIS_MODULE, |
489 | .release = pn_socket_release, | 469 | .release = pn_socket_release, |
490 | .bind = pn_socket_bind, | 470 | .bind = pn_socket_bind, |
491 | #ifdef CONFIG_PHONET_PIPECTRLR | ||
492 | .connect = pn_socket_connect, | 471 | .connect = pn_socket_connect, |
493 | #else | ||
494 | .connect = sock_no_connect, | ||
495 | #endif | ||
496 | .socketpair = sock_no_socketpair, | 472 | .socketpair = sock_no_socketpair, |
497 | .accept = pn_socket_accept, | 473 | .accept = pn_socket_accept, |
498 | .getname = pn_socket_getname, | 474 | .getname = pn_socket_getname, |
@@ -633,8 +609,8 @@ static int pn_sock_seq_show(struct seq_file *seq, void *v) | |||
633 | 609 | ||
634 | seq_printf(seq, "%2d %04X:%04X:%02X %02X %08X:%08X %5d %lu " | 610 | seq_printf(seq, "%2d %04X:%04X:%02X %02X %08X:%08X %5d %lu " |
635 | "%d %p %d%n", | 611 | "%d %p %d%n", |
636 | sk->sk_protocol, pn->sobject, 0, pn->resource, | 612 | sk->sk_protocol, pn->sobject, pn->dobject, |
637 | sk->sk_state, | 613 | pn->resource, sk->sk_state, |
638 | sk_wmem_alloc_get(sk), sk_rmem_alloc_get(sk), | 614 | sk_wmem_alloc_get(sk), sk_rmem_alloc_get(sk), |
639 | sock_i_uid(sk), sock_i_ino(sk), | 615 | sock_i_uid(sk), sock_i_ino(sk), |
640 | atomic_read(&sk->sk_refcnt), sk, | 616 | atomic_read(&sk->sk_refcnt), sk, |