aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKumar Sanghvi <kumar.sanghvi@stericsson.com>2010-10-12 16:14:43 -0400
committerDavid S. Miller <davem@davemloft.net>2010-10-13 17:40:34 -0400
commitb3d6255388de0680a14f0907deb7b7f4fa0d25d5 (patch)
tree8eaefeadef047a8bc6fcc269669ac4288e41ef64
parent7368ddf144afd79456fd853fa25f33e31da003a9 (diff)
Phonet: 'connect' socket implementation for Pipe controller
Based on suggestion by Rémi Denis-Courmont to implement 'connect' for Pipe controller logic, this patch implements 'connect' socket call for the Pipe controller logic. The patch does following:- - Removes setsockopts for PNPIPE_CREATE and PNPIPE_DESTROY - Adds setsockopt for setting the Pipe handle value - Implements connect socket call - Updates the Pipe controller logic User-space should now follow below sequence with Pipe controller:- -socket -bind -setsockopt for PNPIPE_PIPE_HANDLE -connect -setsockopt for PNPIPE_ENCAP_IP -setsockopt for PNPIPE_ENABLE GPRS/3G data has been tested working fine with this. Signed-off-by: Kumar Sanghvi <kumar.sanghvi@stericsson.com> Acked-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/phonet.h3
-rw-r--r--include/net/phonet/pep.h4
-rw-r--r--net/phonet/pep.c300
-rw-r--r--net/phonet/socket.c99
4 files changed, 215 insertions, 191 deletions
diff --git a/include/linux/phonet.h b/include/linux/phonet.h
index e27cbf931740..26c8df786918 100644
--- a/include/linux/phonet.h
+++ b/include/linux/phonet.h
@@ -36,10 +36,9 @@
36/* Socket options for SOL_PNPIPE level */ 36/* Socket options for SOL_PNPIPE level */
37#define PNPIPE_ENCAP 1 37#define PNPIPE_ENCAP 1
38#define PNPIPE_IFINDEX 2 38#define PNPIPE_IFINDEX 2
39#define PNPIPE_CREATE 3 39#define PNPIPE_PIPE_HANDLE 3
40#define PNPIPE_ENABLE 4 40#define PNPIPE_ENABLE 4
41/* unused slot */ 41/* unused slot */
42#define PNPIPE_DESTROY 6
43 42
44#define PNADDR_ANY 0 43#define PNADDR_ANY 0
45#define PNADDR_BROADCAST 0xFC 44#define PNADDR_BROADCAST 0xFC
diff --git a/include/net/phonet/pep.h b/include/net/phonet/pep.h
index def6cfa3f451..b60b28c99e87 100644
--- a/include/net/phonet/pep.h
+++ b/include/net/phonet/pep.h
@@ -46,8 +46,8 @@ struct pep_sock {
46 u8 init_enable; /* auto-enable at creation */ 46 u8 init_enable; /* auto-enable at creation */
47 u8 aligned; 47 u8 aligned;
48#ifdef CONFIG_PHONET_PIPECTRLR 48#ifdef CONFIG_PHONET_PIPECTRLR
49 u16 remote_pep; 49 u8 pipe_state;
50 u8 pipe_state; 50 struct sockaddr_pn remote_pep;
51#endif 51#endif
52}; 52};
53 53
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index f818f76d297d..9c903f9e5079 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -88,15 +88,6 @@ static int pep_reply(struct sock *sk, struct sk_buff *oskb,
88 const struct pnpipehdr *oph = pnp_hdr(oskb); 88 const struct pnpipehdr *oph = pnp_hdr(oskb);
89 struct pnpipehdr *ph; 89 struct pnpipehdr *ph;
90 struct sk_buff *skb; 90 struct sk_buff *skb;
91#ifdef CONFIG_PHONET_PIPECTRLR
92 const struct phonethdr *hdr = pn_hdr(oskb);
93 struct sockaddr_pn spn = {
94 .spn_family = AF_PHONET,
95 .spn_resource = 0xD9,
96 .spn_dev = hdr->pn_sdev,
97 .spn_obj = hdr->pn_sobj,
98 };
99#endif
100 91
101 skb = alloc_skb(MAX_PNPIPE_HEADER + len, priority); 92 skb = alloc_skb(MAX_PNPIPE_HEADER + len, priority);
102 if (!skb) 93 if (!skb)
@@ -114,11 +105,7 @@ static int pep_reply(struct sock *sk, struct sk_buff *oskb,
114 ph->pipe_handle = oph->pipe_handle; 105 ph->pipe_handle = oph->pipe_handle;
115 ph->error_code = code; 106 ph->error_code = code;
116 107
117#ifdef CONFIG_PHONET_PIPECTRLR
118 return pn_skb_send(sk, skb, &spn);
119#else
120 return pn_skb_send(sk, skb, &pipe_srv); 108 return pn_skb_send(sk, skb, &pipe_srv);
121#endif
122} 109}
123 110
124#define PAD 0x00 111#define PAD 0x00
@@ -188,18 +175,13 @@ static int pipe_get_flow_info(struct sock *sk, struct sk_buff *skb,
188 return 0; 175 return 0;
189} 176}
190 177
191static int pipe_handler_send_req(struct sock *sk, u16 dobj, u8 utid, 178static int pipe_handler_send_req(struct sock *sk, u8 utid,
192 u8 msg_id, u8 p_handle, gfp_t priority) 179 u8 msg_id, gfp_t priority)
193{ 180{
194 int len; 181 int len;
195 struct pnpipehdr *ph; 182 struct pnpipehdr *ph;
196 struct sk_buff *skb; 183 struct sk_buff *skb;
197 struct sockaddr_pn spn = { 184 struct pep_sock *pn = pep_sk(sk);
198 .spn_family = AF_PHONET,
199 .spn_resource = 0xD9,
200 .spn_dev = pn_dev(dobj),
201 .spn_obj = pn_obj(dobj),
202 };
203 185
204 static const u8 data[4] = { 186 static const u8 data[4] = {
205 PAD, PAD, PAD, PAD, 187 PAD, PAD, PAD, PAD,
@@ -235,30 +217,25 @@ static int pipe_handler_send_req(struct sock *sk, u16 dobj, u8 utid,
235 ph = pnp_hdr(skb); 217 ph = pnp_hdr(skb);
236 ph->utid = utid; 218 ph->utid = utid;
237 ph->message_id = msg_id; 219 ph->message_id = msg_id;
238 ph->pipe_handle = p_handle; 220 ph->pipe_handle = pn->pipe_handle;
239 ph->error_code = PN_PIPE_NO_ERROR; 221 ph->error_code = PN_PIPE_NO_ERROR;
240 222
241 return pn_skb_send(sk, skb, &spn); 223 return pn_skb_send(sk, skb, &pn->remote_pep);
242} 224}
243 225
244static int pipe_handler_send_created_ind(struct sock *sk, u16 dobj, 226static int pipe_handler_send_created_ind(struct sock *sk,
245 u8 utid, u8 p_handle, u8 msg_id, u8 tx_fc, u8 rx_fc) 227 u8 utid, u8 msg_id)
246{ 228{
247 int err_code; 229 int err_code;
248 struct pnpipehdr *ph; 230 struct pnpipehdr *ph;
249 struct sk_buff *skb; 231 struct sk_buff *skb;
250 struct sockaddr_pn spn = {
251 .spn_family = AF_PHONET,
252 .spn_resource = 0xD9,
253 .spn_dev = pn_dev(dobj),
254 .spn_obj = pn_obj(dobj),
255 };
256 232
233 struct pep_sock *pn = pep_sk(sk);
257 static u8 data[4] = { 234 static u8 data[4] = {
258 0x03, 0x04, 235 0x03, 0x04,
259 }; 236 };
260 data[2] = tx_fc; 237 data[2] = pn->tx_fc;
261 data[3] = rx_fc; 238 data[3] = pn->rx_fc;
262 239
263 /* 240 /*
264 * actually, below is number of sub-blocks and not error code. 241 * actually, below is number of sub-blocks and not error code.
@@ -282,24 +259,18 @@ static int pipe_handler_send_created_ind(struct sock *sk, u16 dobj,
282 ph = pnp_hdr(skb); 259 ph = pnp_hdr(skb);
283 ph->utid = utid; 260 ph->utid = utid;
284 ph->message_id = msg_id; 261 ph->message_id = msg_id;
285 ph->pipe_handle = p_handle; 262 ph->pipe_handle = pn->pipe_handle;
286 ph->error_code = err_code; 263 ph->error_code = err_code;
287 264
288 return pn_skb_send(sk, skb, &spn); 265 return pn_skb_send(sk, skb, &pn->remote_pep);
289} 266}
290 267
291static int pipe_handler_send_ind(struct sock *sk, u16 dobj, u8 utid, 268static int pipe_handler_send_ind(struct sock *sk, u8 utid, u8 msg_id)
292 u8 p_handle, u8 msg_id)
293{ 269{
294 int err_code; 270 int err_code;
295 struct pnpipehdr *ph; 271 struct pnpipehdr *ph;
296 struct sk_buff *skb; 272 struct sk_buff *skb;
297 struct sockaddr_pn spn = { 273 struct pep_sock *pn = pep_sk(sk);
298 .spn_family = AF_PHONET,
299 .spn_resource = 0xD9,
300 .spn_dev = pn_dev(dobj),
301 .spn_obj = pn_obj(dobj),
302 };
303 274
304 /* 275 /*
305 * actually, below is a filler. 276 * actually, below is a filler.
@@ -321,10 +292,10 @@ static int pipe_handler_send_ind(struct sock *sk, u16 dobj, u8 utid,
321 ph = pnp_hdr(skb); 292 ph = pnp_hdr(skb);
322 ph->utid = utid; 293 ph->utid = utid;
323 ph->message_id = msg_id; 294 ph->message_id = msg_id;
324 ph->pipe_handle = p_handle; 295 ph->pipe_handle = pn->pipe_handle;
325 ph->error_code = err_code; 296 ph->error_code = err_code;
326 297
327 return pn_skb_send(sk, skb, &spn); 298 return pn_skb_send(sk, skb, &pn->remote_pep);
328} 299}
329 300
330static int pipe_handler_enable_pipe(struct sock *sk, int enable) 301static int pipe_handler_enable_pipe(struct sock *sk, int enable)
@@ -339,34 +310,7 @@ static int pipe_handler_enable_pipe(struct sock *sk, int enable)
339 utid = PNS_PIPE_DISABLE_UTID; 310 utid = PNS_PIPE_DISABLE_UTID;
340 req = PNS_PEP_DISABLE_REQ; 311 req = PNS_PEP_DISABLE_REQ;
341 } 312 }
342 return pipe_handler_send_req(sk, pn->pn_sk.sobject, utid, req, 313 return pipe_handler_send_req(sk, utid, req, GFP_ATOMIC);
343 pn->pipe_handle, GFP_ATOMIC);
344}
345
346static int pipe_handler_create_pipe(struct sock *sk, int pipe_handle, int cmd)
347{
348 int ret;
349 struct pep_sock *pn = pep_sk(sk);
350
351 switch (cmd) {
352 case PNPIPE_CREATE:
353 ret = pipe_handler_send_req(sk, pn->pn_sk.sobject,
354 PNS_PEP_CONNECT_UTID, PNS_PEP_CONNECT_REQ,
355 pipe_handle, GFP_ATOMIC);
356 break;
357
358 case PNPIPE_DESTROY:
359 ret = pipe_handler_send_req(sk, pn->remote_pep,
360 PNS_PEP_DISCONNECT_UTID,
361 PNS_PEP_DISCONNECT_REQ,
362 pn->pipe_handle, GFP_ATOMIC);
363 break;
364
365 default:
366 ret = -EINVAL;
367 }
368
369 return ret;
370} 314}
371#endif 315#endif
372 316
@@ -434,14 +378,6 @@ static int pipe_snd_status(struct sock *sk, u8 type, u8 status, gfp_t priority)
434 struct pep_sock *pn = pep_sk(sk); 378 struct pep_sock *pn = pep_sk(sk);
435 struct pnpipehdr *ph; 379 struct pnpipehdr *ph;
436 struct sk_buff *skb; 380 struct sk_buff *skb;
437#ifdef CONFIG_PHONET_PIPECTRLR
438 struct sockaddr_pn spn = {
439 .spn_family = AF_PHONET,
440 .spn_resource = 0xD9,
441 .spn_dev = pn_dev(pn->remote_pep),
442 .spn_obj = pn_obj(pn->remote_pep),
443 };
444#endif
445 381
446 skb = alloc_skb(MAX_PNPIPE_HEADER + 4, priority); 382 skb = alloc_skb(MAX_PNPIPE_HEADER + 4, priority);
447 if (!skb) 383 if (!skb)
@@ -462,7 +398,7 @@ static int pipe_snd_status(struct sock *sk, u8 type, u8 status, gfp_t priority)
462 ph->data[4] = status; 398 ph->data[4] = status;
463 399
464#ifdef CONFIG_PHONET_PIPECTRLR 400#ifdef CONFIG_PHONET_PIPECTRLR
465 return pn_skb_send(sk, skb, &spn); 401 return pn_skb_send(sk, skb, &pn->remote_pep);
466#else 402#else
467 return pn_skb_send(sk, skb, &pipe_srv); 403 return pn_skb_send(sk, skb, &pipe_srv);
468#endif 404#endif
@@ -582,12 +518,6 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
582 struct pnpipehdr *hdr = pnp_hdr(skb); 518 struct pnpipehdr *hdr = pnp_hdr(skb);
583 struct sk_buff_head *queue; 519 struct sk_buff_head *queue;
584 int err = 0; 520 int err = 0;
585#ifdef CONFIG_PHONET_PIPECTRLR
586 struct phonethdr *ph = pn_hdr(skb);
587 static u8 host_pref_rx_fc[3], host_req_tx_fc[3];
588 u8 remote_pref_rx_fc[3], remote_req_tx_fc[3];
589 u8 negotiated_rx_fc, negotiated_tx_fc;
590#endif
591 521
592 BUG_ON(sk->sk_state == TCP_CLOSE_WAIT); 522 BUG_ON(sk->sk_state == TCP_CLOSE_WAIT);
593 523
@@ -596,40 +526,6 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
596 pep_reject_conn(sk, skb, PN_PIPE_ERR_PEP_IN_USE); 526 pep_reject_conn(sk, skb, PN_PIPE_ERR_PEP_IN_USE);
597 break; 527 break;
598 528
599#ifdef CONFIG_PHONET_PIPECTRLR
600 case PNS_PEP_CONNECT_RESP:
601 if ((ph->pn_sdev == pn_dev(pn->remote_pep)) &&
602 (ph->pn_sobj == pn_obj(pn->remote_pep))) {
603 pipe_get_flow_info(sk, skb, remote_pref_rx_fc,
604 remote_req_tx_fc);
605
606 negotiated_tx_fc = pipe_negotiate_fc(remote_req_tx_fc,
607 host_pref_rx_fc,
608 sizeof(host_pref_rx_fc));
609 negotiated_rx_fc = pipe_negotiate_fc(host_req_tx_fc,
610 remote_pref_rx_fc,
611 sizeof(host_pref_rx_fc));
612
613 pn->pipe_state = PIPE_DISABLED;
614 pipe_handler_send_created_ind(sk, pn->remote_pep,
615 PNS_PIPE_CREATED_IND_UTID,
616 pn->pipe_handle, PNS_PIPE_CREATED_IND,
617 negotiated_tx_fc, negotiated_rx_fc);
618 pipe_handler_send_created_ind(sk, pn->pn_sk.sobject,
619 PNS_PIPE_CREATED_IND_UTID,
620 pn->pipe_handle, PNS_PIPE_CREATED_IND,
621 negotiated_tx_fc, negotiated_rx_fc);
622 } else {
623 pipe_handler_send_req(sk, pn->remote_pep,
624 PNS_PEP_CONNECT_UTID,
625 PNS_PEP_CONNECT_REQ, pn->pipe_handle,
626 GFP_ATOMIC);
627 pipe_get_flow_info(sk, skb, host_pref_rx_fc,
628 host_req_tx_fc);
629 }
630 break;
631#endif
632
633 case PNS_PEP_DISCONNECT_REQ: 529 case PNS_PEP_DISCONNECT_REQ:
634 pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC); 530 pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
635 sk->sk_state = TCP_CLOSE_WAIT; 531 sk->sk_state = TCP_CLOSE_WAIT;
@@ -640,10 +536,7 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
640#ifdef CONFIG_PHONET_PIPECTRLR 536#ifdef CONFIG_PHONET_PIPECTRLR
641 case PNS_PEP_DISCONNECT_RESP: 537 case PNS_PEP_DISCONNECT_RESP:
642 pn->pipe_state = PIPE_IDLE; 538 pn->pipe_state = PIPE_IDLE;
643 pipe_handler_send_req(sk, pn->pn_sk.sobject, 539 sk->sk_state = TCP_CLOSE;
644 PNS_PEP_DISCONNECT_UTID,
645 PNS_PEP_DISCONNECT_REQ, pn->pipe_handle,
646 GFP_KERNEL);
647 break; 540 break;
648#endif 541#endif
649 542
@@ -654,21 +547,18 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
654 547
655#ifdef CONFIG_PHONET_PIPECTRLR 548#ifdef CONFIG_PHONET_PIPECTRLR
656 case PNS_PEP_ENABLE_RESP: 549 case PNS_PEP_ENABLE_RESP:
657 if ((ph->pn_sdev == pn_dev(pn->remote_pep)) && 550 pn->pipe_state = PIPE_ENABLED;
658 (ph->pn_sobj == pn_obj(pn->remote_pep))) { 551 pipe_handler_send_ind(sk, PNS_PIPE_ENABLED_IND_UTID,
659 pn->pipe_state = PIPE_ENABLED; 552 PNS_PIPE_ENABLED_IND);
660 pipe_handler_send_ind(sk, pn->remote_pep,
661 PNS_PIPE_ENABLED_IND_UTID,
662 pn->pipe_handle, PNS_PIPE_ENABLED_IND);
663 pipe_handler_send_ind(sk, pn->pn_sk.sobject,
664 PNS_PIPE_ENABLED_IND_UTID,
665 pn->pipe_handle, PNS_PIPE_ENABLED_IND);
666 } else
667 pipe_handler_send_req(sk, pn->remote_pep,
668 PNS_PIPE_ENABLE_UTID,
669 PNS_PEP_ENABLE_REQ, pn->pipe_handle,
670 GFP_KERNEL);
671 553
554 if (!pn_flow_safe(pn->tx_fc)) {
555 atomic_set(&pn->tx_credits, 1);
556 sk->sk_write_space(sk);
557 }
558 if (sk->sk_state == TCP_ESTABLISHED)
559 break; /* Nothing to do */
560 sk->sk_state = TCP_ESTABLISHED;
561 pipe_grant_credits(sk);
672 break; 562 break;
673#endif 563#endif
674 564
@@ -692,22 +582,12 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
692 582
693#ifdef CONFIG_PHONET_PIPECTRLR 583#ifdef CONFIG_PHONET_PIPECTRLR
694 case PNS_PEP_DISABLE_RESP: 584 case PNS_PEP_DISABLE_RESP:
695 if ((ph->pn_sdev == pn_dev(pn->remote_pep)) && 585 pn->pipe_state = PIPE_DISABLED;
696 (ph->pn_sobj == pn_obj(pn->remote_pep))) { 586 atomic_set(&pn->tx_credits, 0);
697 pn->pipe_state = PIPE_DISABLED; 587 pipe_handler_send_ind(sk, PNS_PIPE_DISABLED_IND_UTID,
698 pipe_handler_send_ind(sk, pn->remote_pep, 588 PNS_PIPE_DISABLED_IND);
699 PNS_PIPE_DISABLED_IND_UTID, 589 sk->sk_state = TCP_SYN_RECV;
700 pn->pipe_handle, 590 pn->rx_credits = 0;
701 PNS_PIPE_DISABLED_IND);
702 pipe_handler_send_ind(sk, pn->pn_sk.sobject,
703 PNS_PIPE_DISABLED_IND_UTID,
704 pn->pipe_handle,
705 PNS_PIPE_DISABLED_IND);
706 } else
707 pipe_handler_send_req(sk, pn->remote_pep,
708 PNS_PIPE_DISABLE_UTID,
709 PNS_PEP_DISABLE_REQ, pn->pipe_handle,
710 GFP_KERNEL);
711 break; 591 break;
712#endif 592#endif
713 593
@@ -802,6 +682,42 @@ static void pipe_destruct(struct sock *sk)
802 skb_queue_purge(&pn->ctrlreq_queue); 682 skb_queue_purge(&pn->ctrlreq_queue);
803} 683}
804 684
685#ifdef CONFIG_PHONET_PIPECTRLR
686static int pep_connresp_rcv(struct sock *sk, struct sk_buff *skb)
687{
688 struct pep_sock *pn = pep_sk(sk);
689 u8 host_pref_rx_fc[3] = {3, 2, 1}, host_req_tx_fc[3] = {3, 2, 1};
690 u8 remote_pref_rx_fc[3], remote_req_tx_fc[3];
691 u8 negotiated_rx_fc, negotiated_tx_fc;
692 int ret;
693
694 pipe_get_flow_info(sk, skb, remote_pref_rx_fc,
695 remote_req_tx_fc);
696 negotiated_tx_fc = pipe_negotiate_fc(remote_req_tx_fc,
697 host_pref_rx_fc,
698 sizeof(host_pref_rx_fc));
699 negotiated_rx_fc = pipe_negotiate_fc(host_req_tx_fc,
700 remote_pref_rx_fc,
701 sizeof(host_pref_rx_fc));
702
703 pn->pipe_state = PIPE_DISABLED;
704 sk->sk_state = TCP_SYN_RECV;
705 sk->sk_backlog_rcv = pipe_do_rcv;
706 sk->sk_destruct = pipe_destruct;
707 pn->rx_credits = 0;
708 pn->rx_fc = negotiated_rx_fc;
709 pn->tx_fc = negotiated_tx_fc;
710 sk->sk_state_change(sk);
711
712 ret = pipe_handler_send_created_ind(sk,
713 PNS_PIPE_CREATED_IND_UTID,
714 PNS_PIPE_CREATED_IND
715 );
716
717 return ret;
718}
719#endif
720
805static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb) 721static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb)
806{ 722{
807 struct sock *newsk; 723 struct sock *newsk;
@@ -884,9 +800,6 @@ static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb)
884 newpn->rx_fc = newpn->tx_fc = PN_LEGACY_FLOW_CONTROL; 800 newpn->rx_fc = newpn->tx_fc = PN_LEGACY_FLOW_CONTROL;
885 newpn->init_enable = enabled; 801 newpn->init_enable = enabled;
886 newpn->aligned = aligned; 802 newpn->aligned = aligned;
887#ifdef CONFIG_PHONET_PIPECTRLR
888 newpn->remote_pep = pn->remote_pep;
889#endif
890 803
891 BUG_ON(!skb_queue_empty(&newsk->sk_receive_queue)); 804 BUG_ON(!skb_queue_empty(&newsk->sk_receive_queue));
892 skb_queue_head(&newsk->sk_receive_queue, skb); 805 skb_queue_head(&newsk->sk_receive_queue, skb);
@@ -968,6 +881,12 @@ static int pep_do_rcv(struct sock *sk, struct sk_buff *skb)
968 err = pep_connreq_rcv(sk, skb); 881 err = pep_connreq_rcv(sk, skb);
969 break; 882 break;
970 883
884#ifdef CONFIG_PHONET_PIPECTRLR
885 case PNS_PEP_CONNECT_RESP:
886 err = pep_connresp_rcv(sk, skb);
887 break;
888#endif
889
971 case PNS_PEP_DISCONNECT_REQ: 890 case PNS_PEP_DISCONNECT_REQ:
972 pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC); 891 pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
973 break; 892 break;
@@ -1032,6 +951,18 @@ static void pep_sock_close(struct sock *sk, long timeout)
1032 /* Forcefully remove dangling Phonet pipe */ 951 /* Forcefully remove dangling Phonet pipe */
1033 pipe_do_remove(sk); 952 pipe_do_remove(sk);
1034 953
954#ifdef CONFIG_PHONET_PIPECTRLR
955 if (pn->pipe_state != PIPE_IDLE) {
956 /* send pep disconnect request */
957 pipe_handler_send_req(sk,
958 PNS_PEP_DISCONNECT_UTID, PNS_PEP_DISCONNECT_REQ,
959 GFP_KERNEL);
960
961 pn->pipe_state = PIPE_IDLE;
962 sk->sk_state = TCP_CLOSE;
963 }
964#endif
965
1035 ifindex = pn->ifindex; 966 ifindex = pn->ifindex;
1036 pn->ifindex = 0; 967 pn->ifindex = 0;
1037 release_sock(sk); 968 release_sock(sk);
@@ -1108,6 +1039,20 @@ out:
1108 return newsk; 1039 return newsk;
1109} 1040}
1110 1041
1042#ifdef CONFIG_PHONET_PIPECTRLR
1043static int pep_sock_connect(struct sock *sk, struct sockaddr *addr, int len)
1044{
1045 struct pep_sock *pn = pep_sk(sk);
1046 struct sockaddr_pn *spn = (struct sockaddr_pn *)addr;
1047
1048 memcpy(&pn->remote_pep, spn, sizeof(struct sockaddr_pn));
1049
1050 return pipe_handler_send_req(sk,
1051 PNS_PEP_CONNECT_UTID, PNS_PEP_CONNECT_REQ,
1052 GFP_ATOMIC);
1053}
1054#endif
1055
1111static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg) 1056static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg)
1112{ 1057{
1113 struct pep_sock *pn = pep_sk(sk); 1058 struct pep_sock *pn = pep_sk(sk);
@@ -1149,10 +1094,6 @@ static int pep_setsockopt(struct sock *sk, int level, int optname,
1149{ 1094{
1150 struct pep_sock *pn = pep_sk(sk); 1095 struct pep_sock *pn = pep_sk(sk);
1151 int val = 0, err = 0; 1096 int val = 0, err = 0;
1152#ifdef CONFIG_PHONET_PIPECTRLR
1153 int remote_pep;
1154 int pipe_handle;
1155#endif
1156 1097
1157 if (level != SOL_PNPIPE) 1098 if (level != SOL_PNPIPE)
1158 return -ENOPROTOOPT; 1099 return -ENOPROTOOPT;
@@ -1164,28 +1105,15 @@ static int pep_setsockopt(struct sock *sk, int level, int optname,
1164 lock_sock(sk); 1105 lock_sock(sk);
1165 switch (optname) { 1106 switch (optname) {
1166#ifdef CONFIG_PHONET_PIPECTRLR 1107#ifdef CONFIG_PHONET_PIPECTRLR
1167 case PNPIPE_CREATE: 1108 case PNPIPE_PIPE_HANDLE:
1168 if (val) { 1109 if (val) {
1169 if (pn->pipe_state > PIPE_IDLE) { 1110 if (pn->pipe_state > PIPE_IDLE) {
1170 err = -EFAULT; 1111 err = -EFAULT;
1171 break; 1112 break;
1172 } 1113 }
1173 remote_pep = val & 0xFFFF; 1114 pn->pipe_handle = val;
1174 pipe_handle = (val >> 16) & 0xFF;
1175 pn->remote_pep = remote_pep;
1176 err = pipe_handler_create_pipe(sk, pipe_handle,
1177 PNPIPE_CREATE);
1178 break;
1179 }
1180
1181 case PNPIPE_DESTROY:
1182 if (pn->pipe_state < PIPE_DISABLED) {
1183 err = -EFAULT;
1184 break; 1115 break;
1185 } 1116 }
1186
1187 err = pipe_handler_create_pipe(sk, 0x0, PNPIPE_DESTROY);
1188 break;
1189#endif 1117#endif
1190 1118
1191 case PNPIPE_ENCAP: 1119 case PNPIPE_ENCAP:
@@ -1278,14 +1206,6 @@ static int pipe_skb_send(struct sock *sk, struct sk_buff *skb)
1278 struct pep_sock *pn = pep_sk(sk); 1206 struct pep_sock *pn = pep_sk(sk);
1279 struct pnpipehdr *ph; 1207 struct pnpipehdr *ph;
1280 int err; 1208 int err;
1281#ifdef CONFIG_PHONET_PIPECTRLR
1282 struct sockaddr_pn spn = {
1283 .spn_family = AF_PHONET,
1284 .spn_resource = 0xD9,
1285 .spn_dev = pn_dev(pn->remote_pep),
1286 .spn_obj = pn_obj(pn->remote_pep),
1287 };
1288#endif
1289 1209
1290 if (pn_flow_safe(pn->tx_fc) && 1210 if (pn_flow_safe(pn->tx_fc) &&
1291 !atomic_add_unless(&pn->tx_credits, -1, 0)) { 1211 !atomic_add_unless(&pn->tx_credits, -1, 0)) {
@@ -1304,7 +1224,7 @@ static int pipe_skb_send(struct sock *sk, struct sk_buff *skb)
1304 ph->message_id = PNS_PIPE_DATA; 1224 ph->message_id = PNS_PIPE_DATA;
1305 ph->pipe_handle = pn->pipe_handle; 1225 ph->pipe_handle = pn->pipe_handle;
1306#ifdef CONFIG_PHONET_PIPECTRLR 1226#ifdef CONFIG_PHONET_PIPECTRLR
1307 err = pn_skb_send(sk, skb, &spn); 1227 err = pn_skb_send(sk, skb, &pn->remote_pep);
1308#else 1228#else
1309 err = pn_skb_send(sk, skb, &pipe_srv); 1229 err = pn_skb_send(sk, skb, &pipe_srv);
1310#endif 1230#endif
@@ -1504,6 +1424,8 @@ static void pep_sock_unhash(struct sock *sk)
1504 struct sock *skparent = NULL; 1424 struct sock *skparent = NULL;
1505 1425
1506 lock_sock(sk); 1426 lock_sock(sk);
1427
1428#ifndef CONFIG_PHONET_PIPECTRLR
1507 if ((1 << sk->sk_state) & ~(TCPF_CLOSE|TCPF_LISTEN)) { 1429 if ((1 << sk->sk_state) & ~(TCPF_CLOSE|TCPF_LISTEN)) {
1508 skparent = pn->listener; 1430 skparent = pn->listener;
1509 release_sock(sk); 1431 release_sock(sk);
@@ -1513,6 +1435,7 @@ static void pep_sock_unhash(struct sock *sk)
1513 sk_del_node_init(sk); 1435 sk_del_node_init(sk);
1514 sk = skparent; 1436 sk = skparent;
1515 } 1437 }
1438#endif
1516 /* Unhash a listening sock only when it is closed 1439 /* Unhash a listening sock only when it is closed
1517 * and all of its active connected pipes are closed. */ 1440 * and all of its active connected pipes are closed. */
1518 if (hlist_empty(&pn->hlist)) 1441 if (hlist_empty(&pn->hlist))
@@ -1526,6 +1449,9 @@ static void pep_sock_unhash(struct sock *sk)
1526static struct proto pep_proto = { 1449static struct proto pep_proto = {
1527 .close = pep_sock_close, 1450 .close = pep_sock_close,
1528 .accept = pep_sock_accept, 1451 .accept = pep_sock_accept,
1452#ifdef CONFIG_PHONET_PIPECTRLR
1453 .connect = pep_sock_connect,
1454#endif
1529 .ioctl = pep_ioctl, 1455 .ioctl = pep_ioctl,
1530 .init = pep_init, 1456 .init = pep_init,
1531 .setsockopt = pep_setsockopt, 1457 .setsockopt = pep_setsockopt,
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
index aca8fba099e9..25f746d20c1f 100644
--- a/net/phonet/socket.c
+++ b/net/phonet/socket.c
@@ -225,6 +225,101 @@ 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,
230 int len, int flags)
231{
232 struct sock *sk = sock->sk;
233 struct sockaddr_pn *spn = (struct sockaddr_pn *)addr;
234 long timeo;
235 int err;
236
237 if (len < sizeof(struct sockaddr_pn))
238 return -EINVAL;
239 if (spn->spn_family != AF_PHONET)
240 return -EAFNOSUPPORT;
241
242 lock_sock(sk);
243
244 switch (sock->state) {
245 case SS_UNCONNECTED:
246 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;
265 goto out;
266 case TCP_CLOSE:
267 sock->state = SS_UNCONNECTED;
268 break;
269 }
270 break;
271 case SS_DISCONNECTING:
272 case SS_FREE:
273 break;
274 }
275 sk->sk_state = TCP_CLOSE;
276 sk_stream_kill_queues(sk);
277
278 sock->state = SS_CONNECTING;
279 err = sk->sk_prot->connect(sk, addr, len);
280 if (err < 0) {
281 sock->state = SS_UNCONNECTED;
282 sk->sk_state = TCP_CLOSE;
283 goto out;
284 }
285
286 err = -EINPROGRESS;
287wait_connect:
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
303 err = -ETIMEDOUT;
304 if (timeo == 0 && sk->sk_state != TCP_SYN_RECV)
305 goto out;
306
307 if (sk->sk_state != TCP_SYN_RECV) {
308 sock->state = SS_UNCONNECTED;
309 err = sock_error(sk);
310 if (!err)
311 err = -ECONNREFUSED;
312 goto out;
313 }
314 sock->state = SS_CONNECTED;
315 err = 0;
316
317out:
318 release_sock(sk);
319 return err;
320}
321#endif
322
228static int pn_socket_accept(struct socket *sock, struct socket *newsock, 323static int pn_socket_accept(struct socket *sock, struct socket *newsock,
229 int flags) 324 int flags)
230{ 325{
@@ -393,7 +488,11 @@ const struct proto_ops phonet_stream_ops = {
393 .owner = THIS_MODULE, 488 .owner = THIS_MODULE,
394 .release = pn_socket_release, 489 .release = pn_socket_release,
395 .bind = pn_socket_bind, 490 .bind = pn_socket_bind,
491#ifdef CONFIG_PHONET_PIPECTRLR
492 .connect = pn_socket_connect,
493#else
396 .connect = sock_no_connect, 494 .connect = sock_no_connect,
495#endif
397 .socketpair = sock_no_socketpair, 496 .socketpair = sock_no_socketpair,
398 .accept = pn_socket_accept, 497 .accept = pn_socket_accept,
399 .getname = pn_socket_getname, 498 .getname = pn_socket_getname,