aboutsummaryrefslogtreecommitdiffstats
path: root/net/phonet/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/phonet/socket.c')
-rw-r--r--net/phonet/socket.c126
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
229static int pn_socket_connect(struct socket *sock, struct sockaddr *addr, 228static 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) {
287wait_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;
317out: 300out:
318 release_sock(sk); 301 release_sock(sk);
319 return err; 302 return err;
320} 303}
321#endif
322 304
323static int pn_socket_accept(struct socket *sock, struct socket *newsock, 305static 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;
445out: 425out:
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,