aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/phonet/pep.c172
-rw-r--r--net/phonet/socket.c102
2 files changed, 141 insertions, 133 deletions
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index abfb795af142..671effb4ea15 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -136,7 +136,6 @@ static int pep_indicate(struct sock *sk, u8 id, u8 code,
136 136
137#define PAD 0x00 137#define PAD 0x00
138 138
139#ifdef CONFIG_PHONET_PIPECTRLR
140static int pipe_handler_request(struct sock *sk, u8 id, u8 code, 139static int pipe_handler_request(struct sock *sk, u8 id, u8 code,
141 const void *data, int len) 140 const void *data, int len)
142{ 141{
@@ -168,11 +167,7 @@ static int pipe_handler_send_created_ind(struct sock *sk)
168 data, 4, GFP_ATOMIC); 167 data, 4, GFP_ATOMIC);
169} 168}
170 169
171static int pipe_handler_send_ind(struct sock *sk, u8 id) 170#ifdef CONFIG_PHONET_PIPECTRLR
172{
173 return pep_indicate(sk, id, PAD, NULL, 0, GFP_ATOMIC);
174}
175
176static int pipe_handler_enable_pipe(struct sock *sk, int enable) 171static int pipe_handler_enable_pipe(struct sock *sk, int enable)
177{ 172{
178 u8 id = enable ? PNS_PEP_ENABLE_REQ : PNS_PEP_DISABLE_REQ; 173 u8 id = enable ? PNS_PEP_ENABLE_REQ : PNS_PEP_DISABLE_REQ;
@@ -376,32 +371,11 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
376 sk->sk_state_change(sk); 371 sk->sk_state_change(sk);
377 break; 372 break;
378 373
379#ifdef CONFIG_PHONET_PIPECTRLR
380 case PNS_PEP_DISCONNECT_RESP:
381 sk->sk_state = TCP_CLOSE;
382 break;
383#endif
384
385 case PNS_PEP_ENABLE_REQ: 374 case PNS_PEP_ENABLE_REQ:
386 /* Wait for PNS_PIPE_(ENABLED|REDIRECTED)_IND */ 375 /* Wait for PNS_PIPE_(ENABLED|REDIRECTED)_IND */
387 pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC); 376 pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
388 break; 377 break;
389 378
390#ifdef CONFIG_PHONET_PIPECTRLR
391 case PNS_PEP_ENABLE_RESP:
392 pipe_handler_send_ind(sk, PNS_PIPE_ENABLED_IND);
393
394 if (!pn_flow_safe(pn->tx_fc)) {
395 atomic_set(&pn->tx_credits, 1);
396 sk->sk_write_space(sk);
397 }
398 if (sk->sk_state == TCP_ESTABLISHED)
399 break; /* Nothing to do */
400 sk->sk_state = TCP_ESTABLISHED;
401 pipe_grant_credits(sk, GFP_ATOMIC);
402 break;
403#endif
404
405 case PNS_PEP_RESET_REQ: 379 case PNS_PEP_RESET_REQ:
406 switch (hdr->state_after_reset) { 380 switch (hdr->state_after_reset) {
407 case PN_PIPE_DISABLE: 381 case PN_PIPE_DISABLE:
@@ -420,15 +394,6 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
420 pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC); 394 pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
421 break; 395 break;
422 396
423#ifdef CONFIG_PHONET_PIPECTRLR
424 case PNS_PEP_DISABLE_RESP:
425 atomic_set(&pn->tx_credits, 0);
426 pipe_handler_send_ind(sk, PNS_PIPE_DISABLED_IND);
427 sk->sk_state = TCP_SYN_RECV;
428 pn->rx_credits = 0;
429 break;
430#endif
431
432 case PNS_PEP_CTRL_REQ: 397 case PNS_PEP_CTRL_REQ:
433 if (skb_queue_len(&pn->ctrlreq_queue) >= PNPIPE_CTRLREQ_MAX) { 398 if (skb_queue_len(&pn->ctrlreq_queue) >= PNPIPE_CTRLREQ_MAX) {
434 atomic_inc(&sk->sk_drops); 399 atomic_inc(&sk->sk_drops);
@@ -521,7 +486,6 @@ static void pipe_destruct(struct sock *sk)
521 skb_queue_purge(&pn->ctrlreq_queue); 486 skb_queue_purge(&pn->ctrlreq_queue);
522} 487}
523 488
524#ifdef CONFIG_PHONET_PIPECTRLR
525static u8 pipe_negotiate_fc(const u8 *fcs, unsigned n) 489static u8 pipe_negotiate_fc(const u8 *fcs, unsigned n)
526{ 490{
527 unsigned i; 491 unsigned i;
@@ -546,6 +510,8 @@ static int pep_connresp_rcv(struct sock *sk, struct sk_buff *skb)
546 return -EINVAL; 510 return -EINVAL;
547 511
548 hdr = pnp_hdr(skb); 512 hdr = pnp_hdr(skb);
513 if (hdr->error_code != PN_PIPE_NO_ERROR)
514 return -ECONNREFUSED;
549 515
550 /* Parse sub-blocks */ 516 /* Parse sub-blocks */
551 n_sb = hdr->data[4]; 517 n_sb = hdr->data[4];
@@ -573,14 +539,74 @@ static int pep_connresp_rcv(struct sock *sk, struct sk_buff *skb)
573 n_sb--; 539 n_sb--;
574 } 540 }
575 541
576 sk->sk_state = TCP_SYN_RECV;
577 sk->sk_backlog_rcv = pipe_do_rcv;
578 pn->rx_credits = 0;
579 sk->sk_state_change(sk);
580
581 return pipe_handler_send_created_ind(sk); 542 return pipe_handler_send_created_ind(sk);
582} 543}
583#endif 544
545/* Queue an skb to an actively connected sock.
546 * Socket lock must be held. */
547static int pipe_handler_do_rcv(struct sock *sk, struct sk_buff *skb)
548{
549 struct pep_sock *pn = pep_sk(sk);
550 struct pnpipehdr *hdr = pnp_hdr(skb);
551 int err = NET_RX_SUCCESS;
552
553 switch (hdr->message_id) {
554 case PNS_PIPE_ALIGNED_DATA:
555 __skb_pull(skb, 1);
556 /* fall through */
557 case PNS_PIPE_DATA:
558 __skb_pull(skb, 3); /* Pipe data header */
559 if (!pn_flow_safe(pn->rx_fc)) {
560 err = sock_queue_rcv_skb(sk, skb);
561 if (!err)
562 return NET_RX_SUCCESS;
563 err = NET_RX_DROP;
564 break;
565 }
566
567 if (pn->rx_credits == 0) {
568 atomic_inc(&sk->sk_drops);
569 err = NET_RX_DROP;
570 break;
571 }
572 pn->rx_credits--;
573 skb->dev = NULL;
574 skb_set_owner_r(skb, sk);
575 err = skb->len;
576 skb_queue_tail(&sk->sk_receive_queue, skb);
577 if (!sock_flag(sk, SOCK_DEAD))
578 sk->sk_data_ready(sk, err);
579 return NET_RX_SUCCESS;
580
581 case PNS_PEP_CONNECT_RESP:
582 if (sk->sk_state != TCP_SYN_SENT)
583 break;
584 if (!sock_flag(sk, SOCK_DEAD))
585 sk->sk_state_change(sk);
586 if (pep_connresp_rcv(sk, skb)) {
587 sk->sk_state = TCP_CLOSE_WAIT;
588 break;
589 }
590
591 sk->sk_state = TCP_ESTABLISHED;
592 if (!pn_flow_safe(pn->tx_fc)) {
593 atomic_set(&pn->tx_credits, 1);
594 sk->sk_write_space(sk);
595 }
596 pipe_grant_credits(sk, GFP_ATOMIC);
597 break;
598
599 case PNS_PEP_DISCONNECT_RESP:
600 /* sock should already be dead, nothing to do */
601 break;
602
603 case PNS_PEP_STATUS_IND:
604 pipe_rcv_status(sk, skb);
605 break;
606 }
607 kfree_skb(skb);
608 return err;
609}
584 610
585/* Listening sock must be locked */ 611/* Listening sock must be locked */
586static struct sock *pep_find_pipe(const struct hlist_head *hlist, 612static struct sock *pep_find_pipe(const struct hlist_head *hlist,
@@ -649,12 +675,6 @@ static int pep_do_rcv(struct sock *sk, struct sk_buff *skb)
649 sk->sk_data_ready(sk, 0); 675 sk->sk_data_ready(sk, 0);
650 return NET_RX_SUCCESS; 676 return NET_RX_SUCCESS;
651 677
652#ifdef CONFIG_PHONET_PIPECTRLR
653 case PNS_PEP_CONNECT_RESP:
654 pep_connresp_rcv(sk, skb);
655 break;
656#endif
657
658 case PNS_PEP_DISCONNECT_REQ: 678 case PNS_PEP_DISCONNECT_REQ:
659 pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC); 679 pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
660 break; 680 break;
@@ -667,15 +687,19 @@ static int pep_do_rcv(struct sock *sk, struct sk_buff *skb)
667 case PNS_PEP_ENABLE_REQ: 687 case PNS_PEP_ENABLE_REQ:
668 case PNS_PEP_DISABLE_REQ: 688 case PNS_PEP_DISABLE_REQ:
669 /* invalid handle is not even allowed here! */ 689 /* invalid handle is not even allowed here! */
670 default:
671 break; 690 break;
691
692 default:
693 if ((1 << sk->sk_state)
694 & ~(TCPF_CLOSE|TCPF_LISTEN|TCPF_CLOSE_WAIT))
695 /* actively connected socket */
696 return pipe_handler_do_rcv(sk, skb);
672 } 697 }
673drop: 698drop:
674 kfree_skb(skb); 699 kfree_skb(skb);
675 return NET_RX_SUCCESS; 700 return NET_RX_SUCCESS;
676} 701}
677 702
678#ifndef CONFIG_PHONET_PIPECTRLR
679static int pipe_do_remove(struct sock *sk) 703static int pipe_do_remove(struct sock *sk)
680{ 704{
681 struct pep_sock *pn = pep_sk(sk); 705 struct pep_sock *pn = pep_sk(sk);
@@ -693,7 +717,6 @@ static int pipe_do_remove(struct sock *sk)
693 ph->data[0] = PAD; 717 ph->data[0] = PAD;
694 return pn_skb_send(sk, skb, NULL); 718 return pn_skb_send(sk, skb, NULL);
695} 719}
696#endif
697 720
698/* associated socket ceases to exist */ 721/* associated socket ceases to exist */
699static void pep_sock_close(struct sock *sk, long timeout) 722static void pep_sock_close(struct sock *sk, long timeout)
@@ -706,13 +729,12 @@ static void pep_sock_close(struct sock *sk, long timeout)
706 729
707 lock_sock(sk); 730 lock_sock(sk);
708 if ((1 << sk->sk_state) & (TCPF_SYN_RECV|TCPF_ESTABLISHED)) { 731 if ((1 << sk->sk_state) & (TCPF_SYN_RECV|TCPF_ESTABLISHED)) {
709#ifndef CONFIG_PHONET_PIPECTRLR 732 if (sk->sk_backlog_rcv == pipe_do_rcv)
710 /* Forcefully remove dangling Phonet pipe */ 733 /* Forcefully remove dangling Phonet pipe */
711 pipe_do_remove(sk); 734 pipe_do_remove(sk);
712#else 735 else
713 /* send pep disconnect request */ 736 pipe_handler_request(sk, PNS_PEP_DISCONNECT_REQ, PAD,
714 pipe_handler_request(sk, PNS_PEP_DISCONNECT_REQ, PAD, NULL, 0); 737 NULL, 0);
715#endif
716 } 738 }
717 sk->sk_state = TCP_CLOSE; 739 sk->sk_state = TCP_CLOSE;
718 740
@@ -844,20 +866,22 @@ drop:
844 return newsk; 866 return newsk;
845} 867}
846 868
847#ifdef CONFIG_PHONET_PIPECTRLR
848static int pep_sock_connect(struct sock *sk, struct sockaddr *addr, int len) 869static int pep_sock_connect(struct sock *sk, struct sockaddr *addr, int len)
849{ 870{
850 struct pep_sock *pn = pep_sk(sk); 871 struct pep_sock *pn = pep_sk(sk);
851 const struct sockaddr_pn *spn = (struct sockaddr_pn *)addr; 872 int err;
852 u8 data[4] = { 0 /* sub-blocks */, PAD, PAD, PAD }; 873 u8 data[4] = { 0 /* sub-blocks */, PAD, PAD, PAD };
853 874
854 pn->pn_sk.dobject = pn_sockaddr_get_object(spn);
855 pn->pn_sk.resource = pn_sockaddr_get_resource(spn);
856 pn->pipe_handle = 1; /* anything but INVALID_HANDLE */ 875 pn->pipe_handle = 1; /* anything but INVALID_HANDLE */
857 return pipe_handler_request(sk, PNS_PEP_CONNECT_REQ, 876 err = pipe_handler_request(sk, PNS_PEP_CONNECT_REQ,
858 PN_PIPE_DISABLE, data, 4); 877 PN_PIPE_ENABLE, data, 4);
878 if (err) {
879 pn->pipe_handle = PN_PIPE_INVALID_HANDLE;
880 return err;
881 }
882 sk->sk_state = TCP_SYN_SENT;
883 return 0;
859} 884}
860#endif
861 885
862static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg) 886static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg)
863{ 887{
@@ -890,8 +914,16 @@ static int pep_init(struct sock *sk)
890 914
891 sk->sk_destruct = pipe_destruct; 915 sk->sk_destruct = pipe_destruct;
892 INIT_HLIST_HEAD(&pn->hlist); 916 INIT_HLIST_HEAD(&pn->hlist);
917 pn->listener = NULL;
893 skb_queue_head_init(&pn->ctrlreq_queue); 918 skb_queue_head_init(&pn->ctrlreq_queue);
919 atomic_set(&pn->tx_credits, 0);
920 pn->ifindex = 0;
921 pn->peer_type = 0;
894 pn->pipe_handle = PN_PIPE_INVALID_HANDLE; 922 pn->pipe_handle = PN_PIPE_INVALID_HANDLE;
923 pn->rx_credits = 0;
924 pn->rx_fc = pn->tx_fc = PN_LEGACY_FLOW_CONTROL;
925 pn->init_enable = 1;
926 pn->aligned = 0;
895 return 0; 927 return 0;
896} 928}
897 929
@@ -1219,9 +1251,9 @@ static void pep_sock_unhash(struct sock *sk)
1219 1251
1220 lock_sock(sk); 1252 lock_sock(sk);
1221 1253
1222#ifndef CONFIG_PHONET_PIPECTRLR 1254 if (pn->listener != NULL) {
1223 if ((1 << sk->sk_state) & ~(TCPF_CLOSE|TCPF_LISTEN)) {
1224 skparent = pn->listener; 1255 skparent = pn->listener;
1256 pn->listener = NULL;
1225 release_sock(sk); 1257 release_sock(sk);
1226 1258
1227 pn = pep_sk(skparent); 1259 pn = pep_sk(skparent);
@@ -1229,7 +1261,7 @@ static void pep_sock_unhash(struct sock *sk)
1229 sk_del_node_init(sk); 1261 sk_del_node_init(sk);
1230 sk = skparent; 1262 sk = skparent;
1231 } 1263 }
1232#endif 1264
1233 /* Unhash a listening sock only when it is closed 1265 /* Unhash a listening sock only when it is closed
1234 * and all of its active connected pipes are closed. */ 1266 * and all of its active connected pipes are closed. */
1235 if (hlist_empty(&pn->hlist)) 1267 if (hlist_empty(&pn->hlist))
@@ -1243,9 +1275,7 @@ static void pep_sock_unhash(struct sock *sk)
1243static struct proto pep_proto = { 1275static struct proto pep_proto = {
1244 .close = pep_sock_close, 1276 .close = pep_sock_close,
1245 .accept = pep_sock_accept, 1277 .accept = pep_sock_accept,
1246#ifdef CONFIG_PHONET_PIPECTRLR
1247 .connect = pep_sock_connect, 1278 .connect = pep_sock_connect,
1248#endif
1249 .ioctl = pep_ioctl, 1279 .ioctl = pep_ioctl,
1250 .init = pep_init, 1280 .init = pep_init,
1251 .setsockopt = pep_setsockopt, 1281 .setsockopt = pep_setsockopt,
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
index 1eccfc35bcc0..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;
253 goto out;
254 case TCP_CLOSE:
255 err = -EALREADY;
256 if (flags & O_NONBLOCK)
257 goto out;
258 goto wait_connect;
259 }
260 break;
261 case SS_CONNECTED:
262 switch (sk->sk_state) {
263 case TCP_SYN_RECV:
264 err = -EISCONN; 250 err = -EISCONN;
265 goto out; 251 goto out;
266 case TCP_CLOSE:
267 sock->state = SS_UNCONNECTED;
268 break;
269 } 252 }
270 break; 253 break;
271 case SS_DISCONNECTING: 254 case SS_CONNECTING:
272 case SS_FREE: 255 err = -EALREADY;
273 break; 256 goto out;
257 default:
258 err = -EISCONN;
259 goto out;
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 275
294 err = -ERESTARTSYS; 276 if (!timeo) {
295 timeo = wait_event_interruptible_timeout(*sk_sleep(sk), 277 err = -EINPROGRESS;
296 sk->sk_state != TCP_CLOSE, 278 goto out;
297 timeo); 279 }
298 280 if (signal_pending(tsk)) {
299 lock_sock(sk); 281 err = sock_intr_errno(timeo);
300 if (timeo < 0) 282 goto out;
301 goto out; /* -ERESTARTSYS */ 283 }
302
303 err = -ETIMEDOUT;
304 if (timeo == 0 && sk->sk_state != TCP_SYN_RECV)
305 goto out;
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)
@@ -486,11 +468,7 @@ const struct proto_ops phonet_stream_ops = {
486 .owner = THIS_MODULE, 468 .owner = THIS_MODULE,
487 .release = pn_socket_release, 469 .release = pn_socket_release,
488 .bind = pn_socket_bind, 470 .bind = pn_socket_bind,
489#ifdef CONFIG_PHONET_PIPECTRLR
490 .connect = pn_socket_connect, 471 .connect = pn_socket_connect,
491#else
492 .connect = sock_no_connect,
493#endif
494 .socketpair = sock_no_socketpair, 472 .socketpair = sock_no_socketpair,
495 .accept = pn_socket_accept, 473 .accept = pn_socket_accept,
496 .getname = pn_socket_getname, 474 .getname = pn_socket_getname,