Phonet: advise against enabling the pipe controller
[deliverable/linux.git] / net / phonet / pep.c
CommitLineData
9641458d
RDC
1/*
2 * File: pep.c
3 *
4 * Phonet pipe protocol end point socket
5 *
6 * Copyright (C) 2008 Nokia Corporation.
7 *
8 * Author: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * version 2 as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 * 02110-1301 USA
23 */
24
25#include <linux/kernel.h>
5a0e3ad6 26#include <linux/slab.h>
9641458d
RDC
27#include <linux/socket.h>
28#include <net/sock.h>
29#include <net/tcp_states.h>
30#include <asm/ioctls.h>
31
32#include <linux/phonet.h>
33#include <net/phonet/phonet.h>
34#include <net/phonet/pep.h>
02a47617 35#include <net/phonet/gprs.h>
9641458d
RDC
36
37/* sk_state values:
38 * TCP_CLOSE sock not in use yet
39 * TCP_CLOSE_WAIT disconnected pipe
40 * TCP_LISTEN listening pipe endpoint
41 * TCP_SYN_RECV connected pipe in disabled state
42 * TCP_ESTABLISHED connected pipe in enabled state
43 *
44 * pep_sock locking:
45 * - sk_state, ackq, hlist: sock lock needed
46 * - listener: read only
47 * - pipe_handle: read only
48 */
49
50#define CREDITS_MAX 10
51#define CREDITS_THR 7
52
53static const struct sockaddr_pn pipe_srv = {
54 .spn_family = AF_PHONET,
55 .spn_resource = 0xD9, /* pipe service */
56};
57
58#define pep_sb_size(s) (((s) + 5) & ~3) /* 2-bytes head, 32-bits aligned */
59
60/* Get the next TLV sub-block. */
61static unsigned char *pep_get_sb(struct sk_buff *skb, u8 *ptype, u8 *plen,
62 void *buf)
63{
64 void *data = NULL;
65 struct {
66 u8 sb_type;
67 u8 sb_len;
68 } *ph, h;
69 int buflen = *plen;
70
71 ph = skb_header_pointer(skb, 0, 2, &h);
72 if (ph == NULL || ph->sb_len < 2 || !pskb_may_pull(skb, ph->sb_len))
73 return NULL;
74 ph->sb_len -= 2;
75 *ptype = ph->sb_type;
76 *plen = ph->sb_len;
77
78 if (buflen > ph->sb_len)
79 buflen = ph->sb_len;
80 data = skb_header_pointer(skb, 2, buflen, buf);
81 __skb_pull(skb, 2 + ph->sb_len);
82 return data;
83}
84
85static int pep_reply(struct sock *sk, struct sk_buff *oskb,
86 u8 code, const void *data, int len, gfp_t priority)
87{
88 const struct pnpipehdr *oph = pnp_hdr(oskb);
89 struct pnpipehdr *ph;
90 struct sk_buff *skb;
8d98efa8
KS
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
9641458d
RDC
100
101 skb = alloc_skb(MAX_PNPIPE_HEADER + len, priority);
102 if (!skb)
103 return -ENOMEM;
104 skb_set_owner_w(skb, sk);
105
106 skb_reserve(skb, MAX_PNPIPE_HEADER);
107 __skb_put(skb, len);
108 skb_copy_to_linear_data(skb, data, len);
109 __skb_push(skb, sizeof(*ph));
110 skb_reset_transport_header(skb);
111 ph = pnp_hdr(skb);
112 ph->utid = oph->utid;
113 ph->message_id = oph->message_id + 1; /* REQ -> RESP */
114 ph->pipe_handle = oph->pipe_handle;
115 ph->error_code = code;
116
8d98efa8
KS
117#ifdef CONFIG_PHONET_PIPECTRLR
118 return pn_skb_send(sk, skb, &spn);
119#else
9641458d 120 return pn_skb_send(sk, skb, &pipe_srv);
8d98efa8 121#endif
9641458d
RDC
122}
123
124#define PAD 0x00
8d98efa8
KS
125
126#ifdef CONFIG_PHONET_PIPECTRLR
127static u8 pipe_negotiate_fc(u8 *host_fc, u8 *remote_fc, int len)
128{
129 int i, j;
130 u8 base_fc, final_fc;
131
132 for (i = 0; i < len; i++) {
133 base_fc = host_fc[i];
134 for (j = 0; j < len; j++) {
135 if (remote_fc[j] == base_fc) {
136 final_fc = base_fc;
137 goto done;
138 }
139 }
140 }
141 return -EINVAL;
142
143done:
144 return final_fc;
145
146}
147
148static int pipe_get_flow_info(struct sock *sk, struct sk_buff *skb,
149 u8 *pref_rx_fc, u8 *req_tx_fc)
150{
151 struct pnpipehdr *hdr;
152 u8 n_sb;
153
154 if (!pskb_may_pull(skb, sizeof(*hdr) + 4))
155 return -EINVAL;
156
157 hdr = pnp_hdr(skb);
158 n_sb = hdr->data[4];
159
160 __skb_pull(skb, sizeof(*hdr) + 4);
161 while (n_sb > 0) {
162 u8 type, buf[3], len = sizeof(buf);
163 u8 *data = pep_get_sb(skb, &type, &len, buf);
164
165 if (data == NULL)
166 return -EINVAL;
167
168 switch (type) {
169 case PN_PIPE_SB_REQUIRED_FC_TX:
170 if (len < 3 || (data[2] | data[3] | data[4]) > 3)
171 break;
172 req_tx_fc[0] = data[2];
173 req_tx_fc[1] = data[3];
174 req_tx_fc[2] = data[4];
175 break;
176
177 case PN_PIPE_SB_PREFERRED_FC_RX:
178 if (len < 3 || (data[2] | data[3] | data[4]) > 3)
179 break;
180 pref_rx_fc[0] = data[2];
181 pref_rx_fc[1] = data[3];
182 pref_rx_fc[2] = data[4];
183 break;
184
185 }
186 n_sb--;
187 }
188 return 0;
189}
190
191static int pipe_handler_send_req(struct sock *sk, u16 dobj, u8 utid,
192 u8 msg_id, u8 p_handle, gfp_t priority)
193{
194 int len;
195 struct pnpipehdr *ph;
196 struct sk_buff *skb;
197 struct sockaddr_pn spn = {
198 .spn_family = AF_PHONET,
199 .spn_resource = 0xD9,
200 .spn_dev = pn_dev(dobj),
201 .spn_obj = pn_obj(dobj),
202 };
203
204 static const u8 data[4] = {
205 PAD, PAD, PAD, PAD,
206 };
207
208 switch (msg_id) {
209 case PNS_PEP_CONNECT_REQ:
210 len = sizeof(data);
211 break;
212
213 case PNS_PEP_DISCONNECT_REQ:
214 case PNS_PEP_ENABLE_REQ:
215 case PNS_PEP_DISABLE_REQ:
216 len = 0;
217 break;
218
219 default:
220 return -EINVAL;
221 }
222
223 skb = alloc_skb(MAX_PNPIPE_HEADER + len, priority);
224 if (!skb)
225 return -ENOMEM;
226 skb_set_owner_w(skb, sk);
227
228 skb_reserve(skb, MAX_PNPIPE_HEADER);
229 if (len) {
230 __skb_put(skb, len);
231 skb_copy_to_linear_data(skb, data, len);
232 }
233 __skb_push(skb, sizeof(*ph));
234 skb_reset_transport_header(skb);
235 ph = pnp_hdr(skb);
236 ph->utid = utid;
237 ph->message_id = msg_id;
238 ph->pipe_handle = p_handle;
239 ph->error_code = PN_PIPE_NO_ERROR;
240
241 return pn_skb_send(sk, skb, &spn);
242}
243
244static int pipe_handler_send_created_ind(struct sock *sk, u16 dobj,
245 u8 utid, u8 p_handle, u8 msg_id, u8 tx_fc, u8 rx_fc)
246{
247 int err_code;
248 struct pnpipehdr *ph;
249 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
257 static u8 data[4] = {
258 0x03, 0x04,
259 };
260 data[2] = tx_fc;
261 data[3] = rx_fc;
262
263 /*
264 * actually, below is number of sub-blocks and not error code.
265 * Pipe_created_ind message format does not have any
266 * error code field. However, the Phonet stack will always send
267 * an error code as part of pnpipehdr. So, use that err_code to
268 * specify the number of sub-blocks.
269 */
270 err_code = 0x01;
271
272 skb = alloc_skb(MAX_PNPIPE_HEADER + sizeof(data), GFP_ATOMIC);
273 if (!skb)
274 return -ENOMEM;
275 skb_set_owner_w(skb, sk);
276
277 skb_reserve(skb, MAX_PNPIPE_HEADER);
278 __skb_put(skb, sizeof(data));
279 skb_copy_to_linear_data(skb, data, sizeof(data));
280 __skb_push(skb, sizeof(*ph));
281 skb_reset_transport_header(skb);
282 ph = pnp_hdr(skb);
283 ph->utid = utid;
284 ph->message_id = msg_id;
285 ph->pipe_handle = p_handle;
286 ph->error_code = err_code;
287
288 return pn_skb_send(sk, skb, &spn);
289}
290
291static int pipe_handler_send_ind(struct sock *sk, u16 dobj, u8 utid,
292 u8 p_handle, u8 msg_id)
293{
294 int err_code;
295 struct pnpipehdr *ph;
296 struct sk_buff *skb;
297 struct sockaddr_pn spn = {
298 .spn_family = AF_PHONET,
299 .spn_resource = 0xD9,
300 .spn_dev = pn_dev(dobj),
301 .spn_obj = pn_obj(dobj),
302 };
303
304 /*
305 * actually, below is a filler.
306 * Pipe_enabled/disabled_ind message format does not have any
307 * error code field. However, the Phonet stack will always send
308 * an error code as part of pnpipehdr. So, use that err_code to
309 * specify the filler value.
310 */
311 err_code = 0x0;
312
313 skb = alloc_skb(MAX_PNPIPE_HEADER, GFP_ATOMIC);
314 if (!skb)
315 return -ENOMEM;
316 skb_set_owner_w(skb, sk);
317
318 skb_reserve(skb, MAX_PNPIPE_HEADER);
319 __skb_push(skb, sizeof(*ph));
320 skb_reset_transport_header(skb);
321 ph = pnp_hdr(skb);
322 ph->utid = utid;
323 ph->message_id = msg_id;
324 ph->pipe_handle = p_handle;
325 ph->error_code = err_code;
326
327 return pn_skb_send(sk, skb, &spn);
328}
329
330static int pipe_handler_enable_pipe(struct sock *sk, int cmd)
331{
332 int ret;
333 struct pep_sock *pn = pep_sk(sk);
334
335 switch (cmd) {
336 case PNPIPE_ENABLE:
337 ret = pipe_handler_send_req(sk, pn->pn_sk.sobject,
338 PNS_PIPE_ENABLE_UTID, PNS_PEP_ENABLE_REQ,
339 pn->pipe_handle, GFP_ATOMIC);
340 break;
341
342 case PNPIPE_DISABLE:
343 ret = pipe_handler_send_req(sk, pn->pn_sk.sobject,
344 PNS_PIPE_DISABLE_UTID, PNS_PEP_DISABLE_REQ,
345 pn->pipe_handle, GFP_ATOMIC);
346 break;
347
348 default:
349 ret = -EINVAL;
350 }
351
352 return ret;
353}
354
355static int pipe_handler_create_pipe(struct sock *sk, int pipe_handle, int cmd)
356{
357 int ret;
358 struct pep_sock *pn = pep_sk(sk);
359
360 switch (cmd) {
361 case PNPIPE_CREATE:
362 ret = pipe_handler_send_req(sk, pn->pn_sk.sobject,
363 PNS_PEP_CONNECT_UTID, PNS_PEP_CONNECT_REQ,
364 pipe_handle, GFP_ATOMIC);
365 break;
366
367 case PNPIPE_DESTROY:
368 ret = pipe_handler_send_req(sk, pn->remote_pep,
369 PNS_PEP_DISCONNECT_UTID,
370 PNS_PEP_DISCONNECT_REQ,
371 pn->pipe_handle, GFP_ATOMIC);
372 break;
373
374 default:
375 ret = -EINVAL;
376 }
377
378 return ret;
379}
380#endif
381
9641458d
RDC
382static int pep_accept_conn(struct sock *sk, struct sk_buff *skb)
383{
384 static const u8 data[20] = {
385 PAD, PAD, PAD, 2 /* sub-blocks */,
386 PN_PIPE_SB_REQUIRED_FC_TX, pep_sb_size(5), 3, PAD,
387 PN_MULTI_CREDIT_FLOW_CONTROL,
388 PN_ONE_CREDIT_FLOW_CONTROL,
389 PN_LEGACY_FLOW_CONTROL,
390 PAD,
391 PN_PIPE_SB_PREFERRED_FC_RX, pep_sb_size(5), 3, PAD,
392 PN_MULTI_CREDIT_FLOW_CONTROL,
393 PN_ONE_CREDIT_FLOW_CONTROL,
394 PN_LEGACY_FLOW_CONTROL,
395 PAD,
396 };
397
398 might_sleep();
399 return pep_reply(sk, skb, PN_PIPE_NO_ERROR, data, sizeof(data),
400 GFP_KERNEL);
401}
402
403static int pep_reject_conn(struct sock *sk, struct sk_buff *skb, u8 code)
404{
405 static const u8 data[4] = { PAD, PAD, PAD, 0 /* sub-blocks */ };
406 WARN_ON(code == PN_PIPE_NO_ERROR);
407 return pep_reply(sk, skb, code, data, sizeof(data), GFP_ATOMIC);
408}
409
410/* Control requests are not sent by the pipe service and have a specific
411 * message format. */
c41bd97f
RDC
412static int pep_ctrlreq_error(struct sock *sk, struct sk_buff *oskb, u8 code,
413 gfp_t priority)
9641458d
RDC
414{
415 const struct pnpipehdr *oph = pnp_hdr(oskb);
416 struct sk_buff *skb;
417 struct pnpipehdr *ph;
418 struct sockaddr_pn dst;
419
c41bd97f 420 skb = alloc_skb(MAX_PNPIPE_HEADER + 4, priority);
9641458d
RDC
421 if (!skb)
422 return -ENOMEM;
423 skb_set_owner_w(skb, sk);
424
425 skb_reserve(skb, MAX_PHONET_HEADER);
426 ph = (struct pnpipehdr *)skb_put(skb, sizeof(*ph) + 4);
427
428 ph->utid = oph->utid;
429 ph->message_id = PNS_PEP_CTRL_RESP;
430 ph->pipe_handle = oph->pipe_handle;
431 ph->data[0] = oph->data[1]; /* CTRL id */
432 ph->data[1] = oph->data[0]; /* PEP type */
433 ph->data[2] = code; /* error code, at an usual offset */
434 ph->data[3] = PAD;
435 ph->data[4] = PAD;
436
437 pn_skb_get_src_sockaddr(oskb, &dst);
438 return pn_skb_send(sk, skb, &dst);
439}
440
441static int pipe_snd_status(struct sock *sk, u8 type, u8 status, gfp_t priority)
442{
443 struct pep_sock *pn = pep_sk(sk);
444 struct pnpipehdr *ph;
445 struct sk_buff *skb;
8d98efa8
KS
446#ifdef CONFIG_PHONET_PIPECTRLR
447 struct sockaddr_pn spn = {
448 .spn_family = AF_PHONET,
449 .spn_resource = 0xD9,
450 .spn_dev = pn_dev(pn->remote_pep),
451 .spn_obj = pn_obj(pn->remote_pep),
452 };
453#endif
9641458d
RDC
454
455 skb = alloc_skb(MAX_PNPIPE_HEADER + 4, priority);
456 if (!skb)
457 return -ENOMEM;
458 skb_set_owner_w(skb, sk);
459
460 skb_reserve(skb, MAX_PNPIPE_HEADER + 4);
461 __skb_push(skb, sizeof(*ph) + 4);
462 skb_reset_transport_header(skb);
463 ph = pnp_hdr(skb);
464 ph->utid = 0;
465 ph->message_id = PNS_PEP_STATUS_IND;
466 ph->pipe_handle = pn->pipe_handle;
467 ph->pep_type = PN_PEP_TYPE_COMMON;
468 ph->data[1] = type;
469 ph->data[2] = PAD;
470 ph->data[3] = PAD;
471 ph->data[4] = status;
472
8d98efa8
KS
473#ifdef CONFIG_PHONET_PIPECTRLR
474 return pn_skb_send(sk, skb, &spn);
475#else
9641458d 476 return pn_skb_send(sk, skb, &pipe_srv);
8d98efa8 477#endif
9641458d
RDC
478}
479
480/* Send our RX flow control information to the sender.
481 * Socket must be locked. */
482static void pipe_grant_credits(struct sock *sk)
483{
484 struct pep_sock *pn = pep_sk(sk);
485
486 BUG_ON(sk->sk_state != TCP_ESTABLISHED);
487
488 switch (pn->rx_fc) {
489 case PN_LEGACY_FLOW_CONTROL: /* TODO */
490 break;
491 case PN_ONE_CREDIT_FLOW_CONTROL:
492 pipe_snd_status(sk, PN_PEP_IND_FLOW_CONTROL,
493 PEP_IND_READY, GFP_ATOMIC);
494 pn->rx_credits = 1;
495 break;
496 case PN_MULTI_CREDIT_FLOW_CONTROL:
497 if ((pn->rx_credits + CREDITS_THR) > CREDITS_MAX)
498 break;
499 if (pipe_snd_status(sk, PN_PEP_IND_ID_MCFC_GRANT_CREDITS,
500 CREDITS_MAX - pn->rx_credits,
501 GFP_ATOMIC) == 0)
502 pn->rx_credits = CREDITS_MAX;
503 break;
504 }
505}
506
507static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
508{
509 struct pep_sock *pn = pep_sk(sk);
a91e7d47 510 struct pnpipehdr *hdr;
be677730 511 int wake = 0;
9641458d
RDC
512
513 if (!pskb_may_pull(skb, sizeof(*hdr) + 4))
514 return -EINVAL;
515
a91e7d47 516 hdr = pnp_hdr(skb);
9641458d
RDC
517 if (hdr->data[0] != PN_PEP_TYPE_COMMON) {
518 LIMIT_NETDEBUG(KERN_DEBUG"Phonet unknown PEP type: %u\n",
519 (unsigned)hdr->data[0]);
520 return -EOPNOTSUPP;
521 }
522
523 switch (hdr->data[1]) {
524 case PN_PEP_IND_FLOW_CONTROL:
525 switch (pn->tx_fc) {
526 case PN_LEGACY_FLOW_CONTROL:
527 switch (hdr->data[4]) {
528 case PEP_IND_BUSY:
be677730 529 atomic_set(&pn->tx_credits, 0);
9641458d
RDC
530 break;
531 case PEP_IND_READY:
be677730 532 atomic_set(&pn->tx_credits, wake = 1);
9641458d
RDC
533 break;
534 }
535 break;
536 case PN_ONE_CREDIT_FLOW_CONTROL:
537 if (hdr->data[4] == PEP_IND_READY)
be677730 538 atomic_set(&pn->tx_credits, wake = 1);
9641458d
RDC
539 break;
540 }
541 break;
542
543 case PN_PEP_IND_ID_MCFC_GRANT_CREDITS:
544 if (pn->tx_fc != PN_MULTI_CREDIT_FLOW_CONTROL)
545 break;
be677730 546 atomic_add(wake = hdr->data[4], &pn->tx_credits);
9641458d
RDC
547 break;
548
549 default:
550 LIMIT_NETDEBUG(KERN_DEBUG"Phonet unknown PEP indication: %u\n",
551 (unsigned)hdr->data[1]);
552 return -EOPNOTSUPP;
553 }
be677730 554 if (wake)
9641458d
RDC
555 sk->sk_write_space(sk);
556 return 0;
557}
558
559static int pipe_rcv_created(struct sock *sk, struct sk_buff *skb)
560{
561 struct pep_sock *pn = pep_sk(sk);
562 struct pnpipehdr *hdr = pnp_hdr(skb);
563 u8 n_sb = hdr->data[0];
564
565 pn->rx_fc = pn->tx_fc = PN_LEGACY_FLOW_CONTROL;
566 __skb_pull(skb, sizeof(*hdr));
567 while (n_sb > 0) {
568 u8 type, buf[2], len = sizeof(buf);
569 u8 *data = pep_get_sb(skb, &type, &len, buf);
570
571 if (data == NULL)
572 return -EINVAL;
573 switch (type) {
574 case PN_PIPE_SB_NEGOTIATED_FC:
575 if (len < 2 || (data[0] | data[1]) > 3)
576 break;
577 pn->tx_fc = data[0] & 3;
578 pn->rx_fc = data[1] & 3;
579 break;
580 }
581 n_sb--;
582 }
583 return 0;
584}
585
586/* Queue an skb to a connected sock.
587 * Socket lock must be held. */
588static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
589{
590 struct pep_sock *pn = pep_sk(sk);
591 struct pnpipehdr *hdr = pnp_hdr(skb);
c41bd97f 592 struct sk_buff_head *queue;
9641458d 593 int err = 0;
8d98efa8
KS
594#ifdef CONFIG_PHONET_PIPECTRLR
595 struct phonethdr *ph = pn_hdr(skb);
596 static u8 host_pref_rx_fc[3], host_req_tx_fc[3];
597 u8 remote_pref_rx_fc[3], remote_req_tx_fc[3];
598 u8 negotiated_rx_fc, negotiated_tx_fc;
599#endif
9641458d
RDC
600
601 BUG_ON(sk->sk_state == TCP_CLOSE_WAIT);
602
603 switch (hdr->message_id) {
604 case PNS_PEP_CONNECT_REQ:
605 pep_reject_conn(sk, skb, PN_PIPE_ERR_PEP_IN_USE);
606 break;
607
8d98efa8
KS
608#ifdef CONFIG_PHONET_PIPECTRLR
609 case PNS_PEP_CONNECT_RESP:
610 if ((ph->pn_sdev == pn_dev(pn->remote_pep)) &&
611 (ph->pn_sobj == pn_obj(pn->remote_pep))) {
612 pipe_get_flow_info(sk, skb, remote_pref_rx_fc,
613 remote_req_tx_fc);
614
615 negotiated_tx_fc = pipe_negotiate_fc(remote_req_tx_fc,
616 host_pref_rx_fc,
617 sizeof(host_pref_rx_fc));
618 negotiated_rx_fc = pipe_negotiate_fc(host_req_tx_fc,
619 remote_pref_rx_fc,
620 sizeof(host_pref_rx_fc));
621
622 pn->pipe_state = PIPE_DISABLED;
623 pipe_handler_send_created_ind(sk, pn->remote_pep,
624 PNS_PIPE_CREATED_IND_UTID,
625 pn->pipe_handle, PNS_PIPE_CREATED_IND,
626 negotiated_tx_fc, negotiated_rx_fc);
627 pipe_handler_send_created_ind(sk, pn->pn_sk.sobject,
628 PNS_PIPE_CREATED_IND_UTID,
629 pn->pipe_handle, PNS_PIPE_CREATED_IND,
630 negotiated_tx_fc, negotiated_rx_fc);
631 } else {
632 pipe_handler_send_req(sk, pn->remote_pep,
633 PNS_PEP_CONNECT_UTID,
634 PNS_PEP_CONNECT_REQ, pn->pipe_handle,
635 GFP_ATOMIC);
636 pipe_get_flow_info(sk, skb, host_pref_rx_fc,
637 host_req_tx_fc);
638 }
639 break;
640#endif
641
9641458d
RDC
642 case PNS_PEP_DISCONNECT_REQ:
643 pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
644 sk->sk_state = TCP_CLOSE_WAIT;
645 if (!sock_flag(sk, SOCK_DEAD))
646 sk->sk_state_change(sk);
647 break;
648
8d98efa8
KS
649#ifdef CONFIG_PHONET_PIPECTRLR
650 case PNS_PEP_DISCONNECT_RESP:
651 pn->pipe_state = PIPE_IDLE;
652 pipe_handler_send_req(sk, pn->pn_sk.sobject,
653 PNS_PEP_DISCONNECT_UTID,
654 PNS_PEP_DISCONNECT_REQ, pn->pipe_handle,
655 GFP_KERNEL);
656 break;
657#endif
658
9641458d
RDC
659 case PNS_PEP_ENABLE_REQ:
660 /* Wait for PNS_PIPE_(ENABLED|REDIRECTED)_IND */
661 pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
662 break;
663
8d98efa8
KS
664#ifdef CONFIG_PHONET_PIPECTRLR
665 case PNS_PEP_ENABLE_RESP:
666 if ((ph->pn_sdev == pn_dev(pn->remote_pep)) &&
667 (ph->pn_sobj == pn_obj(pn->remote_pep))) {
668 pn->pipe_state = PIPE_ENABLED;
669 pipe_handler_send_ind(sk, pn->remote_pep,
670 PNS_PIPE_ENABLED_IND_UTID,
671 pn->pipe_handle, PNS_PIPE_ENABLED_IND);
672 pipe_handler_send_ind(sk, pn->pn_sk.sobject,
673 PNS_PIPE_ENABLED_IND_UTID,
674 pn->pipe_handle, PNS_PIPE_ENABLED_IND);
675 } else
676 pipe_handler_send_req(sk, pn->remote_pep,
677 PNS_PIPE_ENABLE_UTID,
678 PNS_PEP_ENABLE_REQ, pn->pipe_handle,
679 GFP_KERNEL);
680
681 break;
682#endif
683
9641458d
RDC
684 case PNS_PEP_RESET_REQ:
685 switch (hdr->state_after_reset) {
686 case PN_PIPE_DISABLE:
687 pn->init_enable = 0;
688 break;
689 case PN_PIPE_ENABLE:
690 pn->init_enable = 1;
691 break;
692 default: /* not allowed to send an error here!? */
693 err = -EINVAL;
694 goto out;
695 }
696 /* fall through */
697 case PNS_PEP_DISABLE_REQ:
be677730 698 atomic_set(&pn->tx_credits, 0);
9641458d
RDC
699 pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
700 break;
701
8d98efa8
KS
702#ifdef CONFIG_PHONET_PIPECTRLR
703 case PNS_PEP_DISABLE_RESP:
704 if ((ph->pn_sdev == pn_dev(pn->remote_pep)) &&
705 (ph->pn_sobj == pn_obj(pn->remote_pep))) {
706 pn->pipe_state = PIPE_DISABLED;
707 pipe_handler_send_ind(sk, pn->remote_pep,
708 PNS_PIPE_DISABLED_IND_UTID,
709 pn->pipe_handle,
710 PNS_PIPE_DISABLED_IND);
711 pipe_handler_send_ind(sk, pn->pn_sk.sobject,
712 PNS_PIPE_DISABLED_IND_UTID,
713 pn->pipe_handle,
714 PNS_PIPE_DISABLED_IND);
715 } else
716 pipe_handler_send_req(sk, pn->remote_pep,
717 PNS_PIPE_DISABLE_UTID,
718 PNS_PEP_DISABLE_REQ, pn->pipe_handle,
719 GFP_KERNEL);
720 break;
721#endif
722
9641458d 723 case PNS_PEP_CTRL_REQ:
2e2fb4b3
RDC
724 if (skb_queue_len(&pn->ctrlreq_queue) >= PNPIPE_CTRLREQ_MAX) {
725 atomic_inc(&sk->sk_drops);
c41bd97f 726 break;
2e2fb4b3 727 }
c41bd97f
RDC
728 __skb_pull(skb, 4);
729 queue = &pn->ctrlreq_queue;
730 goto queue;
9641458d 731
fc6a1107
RDC
732 case PNS_PIPE_ALIGNED_DATA:
733 __skb_pull(skb, 1);
734 /* fall through */
9641458d
RDC
735 case PNS_PIPE_DATA:
736 __skb_pull(skb, 3); /* Pipe data header */
737 if (!pn_flow_safe(pn->rx_fc)) {
738 err = sock_queue_rcv_skb(sk, skb);
739 if (!err)
740 return 0;
741 break;
742 }
743
744 if (pn->rx_credits == 0) {
2e2fb4b3 745 atomic_inc(&sk->sk_drops);
9641458d
RDC
746 err = -ENOBUFS;
747 break;
748 }
749 pn->rx_credits--;
c41bd97f
RDC
750 queue = &sk->sk_receive_queue;
751 goto queue;
9641458d
RDC
752
753 case PNS_PEP_STATUS_IND:
754 pipe_rcv_status(sk, skb);
755 break;
756
757 case PNS_PIPE_REDIRECTED_IND:
758 err = pipe_rcv_created(sk, skb);
759 break;
760
761 case PNS_PIPE_CREATED_IND:
762 err = pipe_rcv_created(sk, skb);
763 if (err)
764 break;
765 /* fall through */
766 case PNS_PIPE_RESET_IND:
767 if (!pn->init_enable)
768 break;
769 /* fall through */
770 case PNS_PIPE_ENABLED_IND:
771 if (!pn_flow_safe(pn->tx_fc)) {
be677730 772 atomic_set(&pn->tx_credits, 1);
9641458d
RDC
773 sk->sk_write_space(sk);
774 }
775 if (sk->sk_state == TCP_ESTABLISHED)
776 break; /* Nothing to do */
777 sk->sk_state = TCP_ESTABLISHED;
778 pipe_grant_credits(sk);
779 break;
780
781 case PNS_PIPE_DISABLED_IND:
782 sk->sk_state = TCP_SYN_RECV;
783 pn->rx_credits = 0;
784 break;
785
786 default:
787 LIMIT_NETDEBUG(KERN_DEBUG"Phonet unknown PEP message: %u\n",
788 hdr->message_id);
789 err = -EINVAL;
790 }
791out:
792 kfree_skb(skb);
793 return err;
c41bd97f
RDC
794
795queue:
796 skb->dev = NULL;
797 skb_set_owner_r(skb, sk);
798 err = skb->len;
799 skb_queue_tail(queue, skb);
800 if (!sock_flag(sk, SOCK_DEAD))
801 sk->sk_data_ready(sk, err);
802 return 0;
9641458d
RDC
803}
804
805/* Destroy connected sock. */
806static void pipe_destruct(struct sock *sk)
807{
c41bd97f
RDC
808 struct pep_sock *pn = pep_sk(sk);
809
9641458d 810 skb_queue_purge(&sk->sk_receive_queue);
c41bd97f 811 skb_queue_purge(&pn->ctrlreq_queue);
9641458d
RDC
812}
813
814static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb)
815{
816 struct sock *newsk;
817 struct pep_sock *newpn, *pn = pep_sk(sk);
818 struct pnpipehdr *hdr;
819 struct sockaddr_pn dst;
820 u16 peer_type;
821 u8 pipe_handle, enabled, n_sb;
fea93ece 822 u8 aligned = 0;
9641458d
RDC
823
824 if (!pskb_pull(skb, sizeof(*hdr) + 4))
825 return -EINVAL;
826
827 hdr = pnp_hdr(skb);
828 pipe_handle = hdr->pipe_handle;
829 switch (hdr->state_after_connect) {
830 case PN_PIPE_DISABLE:
831 enabled = 0;
832 break;
833 case PN_PIPE_ENABLE:
834 enabled = 1;
835 break;
836 default:
837 pep_reject_conn(sk, skb, PN_PIPE_ERR_INVALID_PARAM);
838 return -EINVAL;
839 }
840 peer_type = hdr->other_pep_type << 8;
841
842 if (unlikely(sk->sk_state != TCP_LISTEN) || sk_acceptq_is_full(sk)) {
843 pep_reject_conn(sk, skb, PN_PIPE_ERR_PEP_IN_USE);
844 return -ENOBUFS;
845 }
846
847 /* Parse sub-blocks (options) */
848 n_sb = hdr->data[4];
849 while (n_sb > 0) {
850 u8 type, buf[1], len = sizeof(buf);
851 const u8 *data = pep_get_sb(skb, &type, &len, buf);
852
853 if (data == NULL)
854 return -EINVAL;
855 switch (type) {
856 case PN_PIPE_SB_CONNECT_REQ_PEP_SUB_TYPE:
857 if (len < 1)
858 return -EINVAL;
859 peer_type = (peer_type & 0xff00) | data[0];
860 break;
fea93ece
RDC
861 case PN_PIPE_SB_ALIGNED_DATA:
862 aligned = data[0] != 0;
863 break;
9641458d
RDC
864 }
865 n_sb--;
866 }
867
868 skb = skb_clone(skb, GFP_ATOMIC);
869 if (!skb)
870 return -ENOMEM;
871
872 /* Create a new to-be-accepted sock */
873 newsk = sk_alloc(sock_net(sk), PF_PHONET, GFP_ATOMIC, sk->sk_prot);
874 if (!newsk) {
875 kfree_skb(skb);
876 return -ENOMEM;
877 }
878 sock_init_data(NULL, newsk);
879 newsk->sk_state = TCP_SYN_RECV;
880 newsk->sk_backlog_rcv = pipe_do_rcv;
881 newsk->sk_protocol = sk->sk_protocol;
882 newsk->sk_destruct = pipe_destruct;
883
884 newpn = pep_sk(newsk);
885 pn_skb_get_dst_sockaddr(skb, &dst);
886 newpn->pn_sk.sobject = pn_sockaddr_get_object(&dst);
887 newpn->pn_sk.resource = pn->pn_sk.resource;
c41bd97f 888 skb_queue_head_init(&newpn->ctrlreq_queue);
9641458d 889 newpn->pipe_handle = pipe_handle;
be677730 890 atomic_set(&newpn->tx_credits, 0);
9641458d 891 newpn->peer_type = peer_type;
be677730 892 newpn->rx_credits = 0;
9641458d
RDC
893 newpn->rx_fc = newpn->tx_fc = PN_LEGACY_FLOW_CONTROL;
894 newpn->init_enable = enabled;
fea93ece 895 newpn->aligned = aligned;
8d98efa8
KS
896#ifdef CONFIG_PHONET_PIPECTRLR
897 newpn->remote_pep = pn->remote_pep;
898#endif
9641458d
RDC
899
900 BUG_ON(!skb_queue_empty(&newsk->sk_receive_queue));
901 skb_queue_head(&newsk->sk_receive_queue, skb);
902 if (!sock_flag(sk, SOCK_DEAD))
903 sk->sk_data_ready(sk, 0);
904
905 sk_acceptq_added(sk);
906 sk_add_node(newsk, &pn->ackq);
907 return 0;
908}
909
910/* Listening sock must be locked */
911static struct sock *pep_find_pipe(const struct hlist_head *hlist,
912 const struct sockaddr_pn *dst,
913 u8 pipe_handle)
914{
915 struct hlist_node *node;
916 struct sock *sknode;
917 u16 dobj = pn_sockaddr_get_object(dst);
918
919 sk_for_each(sknode, node, hlist) {
920 struct pep_sock *pnnode = pep_sk(sknode);
921
922 /* Ports match, but addresses might not: */
923 if (pnnode->pn_sk.sobject != dobj)
924 continue;
925 if (pnnode->pipe_handle != pipe_handle)
926 continue;
927 if (sknode->sk_state == TCP_CLOSE_WAIT)
928 continue;
929
930 sock_hold(sknode);
931 return sknode;
932 }
933 return NULL;
934}
935
936/*
937 * Deliver an skb to a listening sock.
938 * Socket lock must be held.
939 * We then queue the skb to the right connected sock (if any).
940 */
941static int pep_do_rcv(struct sock *sk, struct sk_buff *skb)
942{
943 struct pep_sock *pn = pep_sk(sk);
944 struct sock *sknode;
2ddc1ac1 945 struct pnpipehdr *hdr;
9641458d
RDC
946 struct sockaddr_pn dst;
947 int err = NET_RX_SUCCESS;
948 u8 pipe_handle;
949
950 if (!pskb_may_pull(skb, sizeof(*hdr)))
951 goto drop;
952
953 hdr = pnp_hdr(skb);
954 pipe_handle = hdr->pipe_handle;
955 if (pipe_handle == PN_PIPE_INVALID_HANDLE)
956 goto drop;
957
958 pn_skb_get_dst_sockaddr(skb, &dst);
959
960 /* Look for an existing pipe handle */
961 sknode = pep_find_pipe(&pn->hlist, &dst, pipe_handle);
962 if (sknode)
963 return sk_receive_skb(sknode, skb, 1);
964
965 /* Look for a pipe handle pending accept */
966 sknode = pep_find_pipe(&pn->ackq, &dst, pipe_handle);
967 if (sknode) {
968 sock_put(sknode);
969 if (net_ratelimit())
970 printk(KERN_WARNING"Phonet unconnected PEP ignored");
971 err = NET_RX_DROP;
972 goto drop;
973 }
974
975 switch (hdr->message_id) {
976 case PNS_PEP_CONNECT_REQ:
977 err = pep_connreq_rcv(sk, skb);
978 break;
979
980 case PNS_PEP_DISCONNECT_REQ:
981 pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
982 break;
983
984 case PNS_PEP_CTRL_REQ:
c41bd97f 985 pep_ctrlreq_error(sk, skb, PN_PIPE_INVALID_HANDLE, GFP_ATOMIC);
9641458d
RDC
986 break;
987
988 case PNS_PEP_RESET_REQ:
989 case PNS_PEP_ENABLE_REQ:
990 case PNS_PEP_DISABLE_REQ:
991 /* invalid handle is not even allowed here! */
992 default:
993 err = NET_RX_DROP;
994 }
995drop:
996 kfree_skb(skb);
997 return err;
998}
999
6482f554
RDC
1000static int pipe_do_remove(struct sock *sk)
1001{
1002 struct pep_sock *pn = pep_sk(sk);
1003 struct pnpipehdr *ph;
1004 struct sk_buff *skb;
1005
1006 skb = alloc_skb(MAX_PNPIPE_HEADER, GFP_KERNEL);
1007 if (!skb)
1008 return -ENOMEM;
1009
1010 skb_reserve(skb, MAX_PNPIPE_HEADER);
1011 __skb_push(skb, sizeof(*ph));
1012 skb_reset_transport_header(skb);
1013 ph = pnp_hdr(skb);
1014 ph->utid = 0;
1015 ph->message_id = PNS_PIPE_REMOVE_REQ;
1016 ph->pipe_handle = pn->pipe_handle;
1017 ph->data[0] = PAD;
1018
1019 return pn_skb_send(sk, skb, &pipe_srv);
1020}
1021
9641458d
RDC
1022/* associated socket ceases to exist */
1023static void pep_sock_close(struct sock *sk, long timeout)
1024{
1025 struct pep_sock *pn = pep_sk(sk);
02a47617 1026 int ifindex = 0;
9641458d 1027
e513480e 1028 sock_hold(sk); /* keep a reference after sk_common_release() */
9641458d
RDC
1029 sk_common_release(sk);
1030
1031 lock_sock(sk);
1032 if (sk->sk_state == TCP_LISTEN) {
1033 /* Destroy the listen queue */
1034 struct sock *sknode;
1035 struct hlist_node *p, *n;
1036
1037 sk_for_each_safe(sknode, p, n, &pn->ackq)
1038 sk_del_node_init(sknode);
1039 sk->sk_state = TCP_CLOSE;
6482f554
RDC
1040 } else if ((1 << sk->sk_state) & (TCPF_SYN_RECV|TCPF_ESTABLISHED))
1041 /* Forcefully remove dangling Phonet pipe */
1042 pipe_do_remove(sk);
1043
02a47617
RDC
1044 ifindex = pn->ifindex;
1045 pn->ifindex = 0;
9641458d 1046 release_sock(sk);
02a47617
RDC
1047
1048 if (ifindex)
1049 gprs_detach(sk);
e513480e 1050 sock_put(sk);
9641458d
RDC
1051}
1052
1053static int pep_wait_connreq(struct sock *sk, int noblock)
1054{
1055 struct task_struct *tsk = current;
1056 struct pep_sock *pn = pep_sk(sk);
1057 long timeo = sock_rcvtimeo(sk, noblock);
1058
1059 for (;;) {
1060 DEFINE_WAIT(wait);
1061
1062 if (sk->sk_state != TCP_LISTEN)
1063 return -EINVAL;
1064 if (!hlist_empty(&pn->ackq))
1065 break;
1066 if (!timeo)
1067 return -EWOULDBLOCK;
1068 if (signal_pending(tsk))
1069 return sock_intr_errno(timeo);
1070
43815482 1071 prepare_to_wait_exclusive(sk_sleep(sk), &wait,
9641458d
RDC
1072 TASK_INTERRUPTIBLE);
1073 release_sock(sk);
1074 timeo = schedule_timeout(timeo);
1075 lock_sock(sk);
43815482 1076 finish_wait(sk_sleep(sk), &wait);
9641458d
RDC
1077 }
1078
1079 return 0;
1080}
1081
1082static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp)
1083{
1084 struct pep_sock *pn = pep_sk(sk);
1085 struct sock *newsk = NULL;
1086 struct sk_buff *oskb;
1087 int err;
1088
1089 lock_sock(sk);
1090 err = pep_wait_connreq(sk, flags & O_NONBLOCK);
1091 if (err)
1092 goto out;
1093
1094 newsk = __sk_head(&pn->ackq);
1095
1096 oskb = skb_dequeue(&newsk->sk_receive_queue);
1097 err = pep_accept_conn(newsk, oskb);
1098 if (err) {
1099 skb_queue_head(&newsk->sk_receive_queue, oskb);
1100 newsk = NULL;
1101 goto out;
1102 }
635f0815 1103 kfree_skb(oskb);
9641458d
RDC
1104
1105 sock_hold(sk);
1106 pep_sk(newsk)->listener = sk;
1107
1108 sock_hold(newsk);
1109 sk_del_node_init(newsk);
1110 sk_acceptq_removed(sk);
1111 sk_add_node(newsk, &pn->hlist);
1112 __sock_put(newsk);
1113
1114out:
1115 release_sock(sk);
1116 *errp = err;
1117 return newsk;
1118}
1119
1120static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg)
1121{
c41bd97f 1122 struct pep_sock *pn = pep_sk(sk);
9641458d
RDC
1123 int answ;
1124
1125 switch (cmd) {
1126 case SIOCINQ:
1127 if (sk->sk_state == TCP_LISTEN)
1128 return -EINVAL;
1129
1130 lock_sock(sk);
f64f9e71
JP
1131 if (sock_flag(sk, SOCK_URGINLINE) &&
1132 !skb_queue_empty(&pn->ctrlreq_queue))
c41bd97f
RDC
1133 answ = skb_peek(&pn->ctrlreq_queue)->len;
1134 else if (!skb_queue_empty(&sk->sk_receive_queue))
9641458d
RDC
1135 answ = skb_peek(&sk->sk_receive_queue)->len;
1136 else
1137 answ = 0;
1138 release_sock(sk);
1139 return put_user(answ, (int __user *)arg);
1140 }
1141
1142 return -ENOIOCTLCMD;
1143}
1144
1145static int pep_init(struct sock *sk)
1146{
1147 struct pep_sock *pn = pep_sk(sk);
1148
1149 INIT_HLIST_HEAD(&pn->ackq);
1150 INIT_HLIST_HEAD(&pn->hlist);
c41bd97f 1151 skb_queue_head_init(&pn->ctrlreq_queue);
9641458d
RDC
1152 pn->pipe_handle = PN_PIPE_INVALID_HANDLE;
1153 return 0;
1154}
1155
02a47617 1156static int pep_setsockopt(struct sock *sk, int level, int optname,
b7058842 1157 char __user *optval, unsigned int optlen)
02a47617
RDC
1158{
1159 struct pep_sock *pn = pep_sk(sk);
1160 int val = 0, err = 0;
8d98efa8
KS
1161#ifdef CONFIG_PHONET_PIPECTRLR
1162 int remote_pep;
1163 int pipe_handle;
1164#endif
02a47617
RDC
1165
1166 if (level != SOL_PNPIPE)
1167 return -ENOPROTOOPT;
1168 if (optlen >= sizeof(int)) {
1169 if (get_user(val, (int __user *) optval))
1170 return -EFAULT;
1171 }
1172
1173 lock_sock(sk);
1174 switch (optname) {
8d98efa8
KS
1175#ifdef CONFIG_PHONET_PIPECTRLR
1176 case PNPIPE_CREATE:
1177 if (val) {
1178 if (pn->pipe_state > PIPE_IDLE) {
1179 err = -EFAULT;
1180 break;
1181 }
1182 remote_pep = val & 0xFFFF;
1183 pipe_handle = (val >> 16) & 0xFF;
1184 pn->remote_pep = remote_pep;
1185 err = pipe_handler_create_pipe(sk, pipe_handle,
1186 PNPIPE_CREATE);
1187 break;
1188 }
1189
1190 case PNPIPE_ENABLE:
1191 if (pn->pipe_state != PIPE_DISABLED) {
1192 err = -EFAULT;
1193 break;
1194 }
1195 err = pipe_handler_enable_pipe(sk, PNPIPE_ENABLE);
1196 break;
1197
1198 case PNPIPE_DISABLE:
1199 if (pn->pipe_state != PIPE_ENABLED) {
1200 err = -EFAULT;
1201 break;
1202 }
1203
1204 err = pipe_handler_enable_pipe(sk, PNPIPE_DISABLE);
1205 break;
1206
1207 case PNPIPE_DESTROY:
1208 if (pn->pipe_state < PIPE_DISABLED) {
1209 err = -EFAULT;
1210 break;
1211 }
1212
1213 err = pipe_handler_create_pipe(sk, 0x0, PNPIPE_DESTROY);
1214 break;
1215#endif
1216
02a47617
RDC
1217 case PNPIPE_ENCAP:
1218 if (val && val != PNPIPE_ENCAP_IP) {
1219 err = -EINVAL;
1220 break;
1221 }
1222 if (!pn->ifindex == !val)
1223 break; /* Nothing to do! */
1224 if (!capable(CAP_NET_ADMIN)) {
1225 err = -EPERM;
1226 break;
1227 }
1228 if (val) {
1229 release_sock(sk);
1230 err = gprs_attach(sk);
1231 if (err > 0) {
1232 pn->ifindex = err;
1233 err = 0;
1234 }
1235 } else {
1236 pn->ifindex = 0;
1237 release_sock(sk);
1238 gprs_detach(sk);
1239 err = 0;
1240 }
1241 goto out_norel;
1242 default:
1243 err = -ENOPROTOOPT;
1244 }
1245 release_sock(sk);
1246
1247out_norel:
1248 return err;
1249}
1250
1251static int pep_getsockopt(struct sock *sk, int level, int optname,
1252 char __user *optval, int __user *optlen)
1253{
1254 struct pep_sock *pn = pep_sk(sk);
1255 int len, val;
1256
1257 if (level != SOL_PNPIPE)
1258 return -ENOPROTOOPT;
1259 if (get_user(len, optlen))
1260 return -EFAULT;
1261
1262 switch (optname) {
1263 case PNPIPE_ENCAP:
1264 val = pn->ifindex ? PNPIPE_ENCAP_IP : PNPIPE_ENCAP_NONE;
1265 break;
8d98efa8
KS
1266
1267#ifdef CONFIG_PHONET_PIPECTRLR
1268 case PNPIPE_INQ:
1269 val = pn->pipe_state;
1270 break;
1271#endif
1272
02a47617
RDC
1273 case PNPIPE_IFINDEX:
1274 val = pn->ifindex;
1275 break;
1276 default:
1277 return -ENOPROTOOPT;
1278 }
1279
1280 len = min_t(unsigned int, sizeof(int), len);
1281 if (put_user(len, optlen))
1282 return -EFAULT;
1283 if (put_user(val, (int __user *) optval))
1284 return -EFAULT;
1285 return 0;
1286}
1287
1288static int pipe_skb_send(struct sock *sk, struct sk_buff *skb)
1289{
1290 struct pep_sock *pn = pep_sk(sk);
1291 struct pnpipehdr *ph;
e1a5964f 1292 int err;
8d98efa8
KS
1293#ifdef CONFIG_PHONET_PIPECTRLR
1294 struct sockaddr_pn spn = {
1295 .spn_family = AF_PHONET,
1296 .spn_resource = 0xD9,
1297 .spn_dev = pn_dev(pn->remote_pep),
1298 .spn_obj = pn_obj(pn->remote_pep),
1299 };
1300#endif
02a47617 1301
be677730
RDC
1302 if (pn_flow_safe(pn->tx_fc) &&
1303 !atomic_add_unless(&pn->tx_credits, -1, 0)) {
1304 kfree_skb(skb);
1305 return -ENOBUFS;
1306 }
1307
fea93ece 1308 skb_push(skb, 3 + pn->aligned);
02a47617
RDC
1309 skb_reset_transport_header(skb);
1310 ph = pnp_hdr(skb);
1311 ph->utid = 0;
fea93ece
RDC
1312 if (pn->aligned) {
1313 ph->message_id = PNS_PIPE_ALIGNED_DATA;
1314 ph->data[0] = 0; /* padding */
1315 } else
1316 ph->message_id = PNS_PIPE_DATA;
02a47617 1317 ph->pipe_handle = pn->pipe_handle;
8d98efa8 1318#ifdef CONFIG_PHONET_PIPECTRLR
e1a5964f 1319 err = pn_skb_send(sk, skb, &spn);
8d98efa8 1320#else
e1a5964f 1321 err = pn_skb_send(sk, skb, &pipe_srv);
8d98efa8 1322#endif
e1a5964f
RDC
1323
1324 if (err && pn_flow_safe(pn->tx_fc))
1325 atomic_inc(&pn->tx_credits);
1326 return err;
1327
02a47617
RDC
1328}
1329
9641458d
RDC
1330static int pep_sendmsg(struct kiocb *iocb, struct sock *sk,
1331 struct msghdr *msg, size_t len)
1332{
1333 struct pep_sock *pn = pep_sk(sk);
b1704374 1334 struct sk_buff *skb;
9641458d
RDC
1335 long timeo;
1336 int flags = msg->msg_flags;
1337 int err, done;
1338
82ecbcb9
RDC
1339 if ((msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL|
1340 MSG_CMSG_COMPAT)) ||
1341 !(msg->msg_flags & MSG_EOR))
9641458d
RDC
1342 return -EOPNOTSUPP;
1343
b1704374
RDC
1344 skb = sock_alloc_send_skb(sk, MAX_PNPIPE_HEADER + len,
1345 flags & MSG_DONTWAIT, &err);
1346 if (!skb)
02ac3268 1347 return err;
b1704374
RDC
1348
1349 skb_reserve(skb, MAX_PHONET_HEADER + 3);
1350 err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
1351 if (err < 0)
1352 goto outfree;
1353
9641458d
RDC
1354 lock_sock(sk);
1355 timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
1356 if ((1 << sk->sk_state) & (TCPF_LISTEN|TCPF_CLOSE)) {
1357 err = -ENOTCONN;
1358 goto out;
1359 }
1360 if (sk->sk_state != TCP_ESTABLISHED) {
1361 /* Wait until the pipe gets to enabled state */
1362disabled:
1363 err = sk_stream_wait_connect(sk, &timeo);
1364 if (err)
1365 goto out;
1366
1367 if (sk->sk_state == TCP_CLOSE_WAIT) {
1368 err = -ECONNRESET;
1369 goto out;
1370 }
1371 }
1372 BUG_ON(sk->sk_state != TCP_ESTABLISHED);
1373
1374 /* Wait until flow control allows TX */
be677730 1375 done = atomic_read(&pn->tx_credits);
9641458d
RDC
1376 while (!done) {
1377 DEFINE_WAIT(wait);
1378
1379 if (!timeo) {
1380 err = -EAGAIN;
1381 goto out;
1382 }
1383 if (signal_pending(current)) {
1384 err = sock_intr_errno(timeo);
1385 goto out;
1386 }
1387
43815482 1388 prepare_to_wait(sk_sleep(sk), &wait,
9641458d 1389 TASK_INTERRUPTIBLE);
be677730 1390 done = sk_wait_event(sk, &timeo, atomic_read(&pn->tx_credits));
43815482 1391 finish_wait(sk_sleep(sk), &wait);
9641458d
RDC
1392
1393 if (sk->sk_state != TCP_ESTABLISHED)
1394 goto disabled;
1395 }
1396
02a47617 1397 err = pipe_skb_send(sk, skb);
9641458d
RDC
1398 if (err >= 0)
1399 err = len; /* success! */
1400 skb = NULL;
1401out:
1402 release_sock(sk);
b1704374 1403outfree:
9641458d
RDC
1404 kfree_skb(skb);
1405 return err;
1406}
1407
02a47617
RDC
1408int pep_writeable(struct sock *sk)
1409{
1410 struct pep_sock *pn = pep_sk(sk);
1411
be677730 1412 return atomic_read(&pn->tx_credits);
02a47617
RDC
1413}
1414
1415int pep_write(struct sock *sk, struct sk_buff *skb)
1416{
1417 struct sk_buff *rskb, *fs;
1418 int flen = 0;
1419
fea93ece
RDC
1420 if (pep_sk(sk)->aligned)
1421 return pipe_skb_send(sk, skb);
1422
02a47617
RDC
1423 rskb = alloc_skb(MAX_PNPIPE_HEADER, GFP_ATOMIC);
1424 if (!rskb) {
1425 kfree_skb(skb);
1426 return -ENOMEM;
1427 }
1428 skb_shinfo(rskb)->frag_list = skb;
1429 rskb->len += skb->len;
1430 rskb->data_len += rskb->len;
1431 rskb->truesize += rskb->len;
1432
1433 /* Avoid nested fragments */
5c313e9a 1434 skb_walk_frags(skb, fs)
02a47617
RDC
1435 flen += fs->len;
1436 skb->next = skb_shinfo(skb)->frag_list;
5c313e9a 1437 skb_frag_list_init(skb);
02a47617
RDC
1438 skb->len -= flen;
1439 skb->data_len -= flen;
1440 skb->truesize -= flen;
1441
1442 skb_reserve(rskb, MAX_PHONET_HEADER + 3);
1443 return pipe_skb_send(sk, rskb);
1444}
1445
1446struct sk_buff *pep_read(struct sock *sk)
1447{
1448 struct sk_buff *skb = skb_dequeue(&sk->sk_receive_queue);
1449
1450 if (sk->sk_state == TCP_ESTABLISHED)
1451 pipe_grant_credits(sk);
1452 return skb;
1453}
1454
9641458d
RDC
1455static int pep_recvmsg(struct kiocb *iocb, struct sock *sk,
1456 struct msghdr *msg, size_t len, int noblock,
1457 int flags, int *addr_len)
1458{
1459 struct sk_buff *skb;
1460 int err;
1461
82ecbcb9
RDC
1462 if (flags & ~(MSG_OOB|MSG_PEEK|MSG_TRUNC|MSG_DONTWAIT|MSG_WAITALL|
1463 MSG_NOSIGNAL|MSG_CMSG_COMPAT))
1464 return -EOPNOTSUPP;
1465
9641458d
RDC
1466 if (unlikely(1 << sk->sk_state & (TCPF_LISTEN | TCPF_CLOSE)))
1467 return -ENOTCONN;
1468
c41bd97f
RDC
1469 if ((flags & MSG_OOB) || sock_flag(sk, SOCK_URGINLINE)) {
1470 /* Dequeue and acknowledge control request */
1471 struct pep_sock *pn = pep_sk(sk);
1472
82ecbcb9
RDC
1473 if (flags & MSG_PEEK)
1474 return -EOPNOTSUPP;
c41bd97f
RDC
1475 skb = skb_dequeue(&pn->ctrlreq_queue);
1476 if (skb) {
1477 pep_ctrlreq_error(sk, skb, PN_PIPE_NO_ERROR,
1478 GFP_KERNEL);
1479 msg->msg_flags |= MSG_OOB;
1480 goto copy;
1481 }
1482 if (flags & MSG_OOB)
1483 return -EINVAL;
1484 }
1485
9641458d
RDC
1486 skb = skb_recv_datagram(sk, flags, noblock, &err);
1487 lock_sock(sk);
1488 if (skb == NULL) {
1489 if (err == -ENOTCONN && sk->sk_state == TCP_CLOSE_WAIT)
1490 err = -ECONNRESET;
1491 release_sock(sk);
1492 return err;
1493 }
1494
1495 if (sk->sk_state == TCP_ESTABLISHED)
1496 pipe_grant_credits(sk);
1497 release_sock(sk);
c41bd97f 1498copy:
9641458d 1499 msg->msg_flags |= MSG_EOR;
9641458d
RDC
1500 if (skb->len > len)
1501 msg->msg_flags |= MSG_TRUNC;
1502 else
1503 len = skb->len;
1504
1505 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, len);
1506 if (!err)
1507 err = (flags & MSG_TRUNC) ? skb->len : len;
1508
1509 skb_free_datagram(sk, skb);
1510 return err;
1511}
1512
1513static void pep_sock_unhash(struct sock *sk)
1514{
1515 struct pep_sock *pn = pep_sk(sk);
1516 struct sock *skparent = NULL;
1517
1518 lock_sock(sk);
1519 if ((1 << sk->sk_state) & ~(TCPF_CLOSE|TCPF_LISTEN)) {
1520 skparent = pn->listener;
9641458d
RDC
1521 release_sock(sk);
1522
9641458d 1523 pn = pep_sk(skparent);
7dfde179
RDC
1524 lock_sock(skparent);
1525 sk_del_node_init(sk);
1526 sk = skparent;
9641458d
RDC
1527 }
1528 /* Unhash a listening sock only when it is closed
1529 * and all of its active connected pipes are closed. */
1530 if (hlist_empty(&pn->hlist))
1531 pn_sock_unhash(&pn->pn_sk.sk);
1532 release_sock(sk);
1533
1534 if (skparent)
1535 sock_put(skparent);
1536}
1537
1538static struct proto pep_proto = {
1539 .close = pep_sock_close,
1540 .accept = pep_sock_accept,
1541 .ioctl = pep_ioctl,
1542 .init = pep_init,
02a47617
RDC
1543 .setsockopt = pep_setsockopt,
1544 .getsockopt = pep_getsockopt,
9641458d
RDC
1545 .sendmsg = pep_sendmsg,
1546 .recvmsg = pep_recvmsg,
1547 .backlog_rcv = pep_do_rcv,
1548 .hash = pn_sock_hash,
1549 .unhash = pep_sock_unhash,
1550 .get_port = pn_sock_get_port,
1551 .obj_size = sizeof(struct pep_sock),
1552 .owner = THIS_MODULE,
1553 .name = "PNPIPE",
1554};
1555
1556static struct phonet_protocol pep_pn_proto = {
1557 .ops = &phonet_stream_ops,
1558 .prot = &pep_proto,
1559 .sock_type = SOCK_SEQPACKET,
1560};
1561
1562static int __init pep_register(void)
1563{
1564 return phonet_proto_register(PN_PROTO_PIPE, &pep_pn_proto);
1565}
1566
1567static void __exit pep_unregister(void)
1568{
1569 phonet_proto_unregister(PN_PROTO_PIPE, &pep_pn_proto);
1570}
1571
1572module_init(pep_register);
1573module_exit(pep_unregister);
1574MODULE_AUTHOR("Remi Denis-Courmont, Nokia");
1575MODULE_DESCRIPTION("Phonet pipe protocol");
1576MODULE_LICENSE("GPL");
1577MODULE_ALIAS_NET_PF_PROTO(PF_PHONET, PN_PROTO_PIPE);
This page took 0.28063 seconds and 5 git commands to generate.