diff options
author | Kumar Sanghvi <kumar.sanghvi@stericsson.com> | 2010-10-12 16:14:43 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-10-13 17:40:34 -0400 |
commit | b3d6255388de0680a14f0907deb7b7f4fa0d25d5 (patch) | |
tree | 8eaefeadef047a8bc6fcc269669ac4288e41ef64 | |
parent | 7368ddf144afd79456fd853fa25f33e31da003a9 (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.h | 3 | ||||
-rw-r--r-- | include/net/phonet/pep.h | 4 | ||||
-rw-r--r-- | net/phonet/pep.c | 300 | ||||
-rw-r--r-- | net/phonet/socket.c | 99 |
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 | ||
191 | static int pipe_handler_send_req(struct sock *sk, u16 dobj, u8 utid, | 178 | static 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 | ||
244 | static int pipe_handler_send_created_ind(struct sock *sk, u16 dobj, | 226 | static 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 | ||
291 | static int pipe_handler_send_ind(struct sock *sk, u16 dobj, u8 utid, | 268 | static 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 | ||
330 | static int pipe_handler_enable_pipe(struct sock *sk, int enable) | 301 | static 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 | |||
346 | static 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 | ||
686 | static 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 | |||
805 | static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb) | 721 | static 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 | ||
1043 | static 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 | |||
1111 | static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg) | 1056 | static 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) | |||
1526 | static struct proto pep_proto = { | 1449 | static 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 | ||
229 | static 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; | ||
287 | wait_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 | |||
317 | out: | ||
318 | release_sock(sk); | ||
319 | return err; | ||
320 | } | ||
321 | #endif | ||
322 | |||
228 | static int pn_socket_accept(struct socket *sock, struct socket *newsock, | 323 | static 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, |