1
2
3
4
5
6
7
8
9
10
11
12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
14#include <linux/time.h>
15#include <linux/errno.h>
16#include <linux/socket.h>
17#include <linux/fcntl.h>
18#include <linux/stat.h>
19#include <linux/string.h>
20#include <linux/sched/signal.h>
21#include <linux/uaccess.h>
22#include <linux/in.h>
23#include <linux/net.h>
24#include <linux/mm.h>
25#include <linux/netdevice.h>
26#include <linux/signal.h>
27#include <linux/slab.h>
28#include <net/scm.h>
29#include <net/sock.h>
30#include <linux/ipx.h>
31#include <linux/poll.h>
32#include <linux/file.h>
33
34#include "ncp_fs.h"
35
36#include "ncpsign_kernel.h"
37
38static int _recv(struct socket *sock, void *buf, int size, unsigned flags)
39{
40 struct msghdr msg = {NULL, };
41 struct kvec iov = {buf, size};
42 iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &iov, 1, size);
43 return sock_recvmsg(sock, &msg, flags);
44}
45
46static int _send(struct socket *sock, const void *buff, int len)
47{
48 struct msghdr msg = { .msg_flags = 0 };
49 struct kvec vec = {.iov_base = (void *)buff, .iov_len = len};
50 iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &vec, 1, len);
51 return sock_sendmsg(sock, &msg);
52}
53
54struct ncp_request_reply {
55 struct list_head req;
56 wait_queue_head_t wq;
57 atomic_t refs;
58 unsigned char* reply_buf;
59 size_t datalen;
60 int result;
61 enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE, RQ_ABANDONED } status;
62 struct iov_iter from;
63 struct kvec tx_iov[3];
64 u_int16_t tx_type;
65 u_int32_t sign[6];
66};
67
68static inline struct ncp_request_reply* ncp_alloc_req(void)
69{
70 struct ncp_request_reply *req;
71
72 req = kmalloc(sizeof(struct ncp_request_reply), GFP_KERNEL);
73 if (!req)
74 return NULL;
75
76 init_waitqueue_head(&req->wq);
77 atomic_set(&req->refs, (1));
78 req->status = RQ_IDLE;
79
80 return req;
81}
82
83static void ncp_req_get(struct ncp_request_reply *req)
84{
85 atomic_inc(&req->refs);
86}
87
88static void ncp_req_put(struct ncp_request_reply *req)
89{
90 if (atomic_dec_and_test(&req->refs))
91 kfree(req);
92}
93
94void ncp_tcp_data_ready(struct sock *sk)
95{
96 struct ncp_server *server = sk->sk_user_data;
97
98 server->data_ready(sk);
99 schedule_work(&server->rcv.tq);
100}
101
102void ncp_tcp_error_report(struct sock *sk)
103{
104 struct ncp_server *server = sk->sk_user_data;
105
106 server->error_report(sk);
107 schedule_work(&server->rcv.tq);
108}
109
110void ncp_tcp_write_space(struct sock *sk)
111{
112 struct ncp_server *server = sk->sk_user_data;
113
114
115
116 server->write_space(sk);
117 if (server->tx.creq)
118 schedule_work(&server->tx.tq);
119}
120
121void ncpdgram_timeout_call(struct timer_list *t)
122{
123 struct ncp_server *server = from_timer(server, t, timeout_tm);
124
125 schedule_work(&server->timeout_tq);
126}
127
128static inline void ncp_finish_request(struct ncp_server *server, struct ncp_request_reply *req, int result)
129{
130 req->result = result;
131 if (req->status != RQ_ABANDONED)
132 memcpy(req->reply_buf, server->rxbuf, req->datalen);
133 req->status = RQ_DONE;
134 wake_up_all(&req->wq);
135 ncp_req_put(req);
136}
137
138static void __abort_ncp_connection(struct ncp_server *server)
139{
140 struct ncp_request_reply *req;
141
142 ncp_invalidate_conn(server);
143 del_timer(&server->timeout_tm);
144 while (!list_empty(&server->tx.requests)) {
145 req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
146
147 list_del_init(&req->req);
148 ncp_finish_request(server, req, -EIO);
149 }
150 req = server->rcv.creq;
151 if (req) {
152 server->rcv.creq = NULL;
153 ncp_finish_request(server, req, -EIO);
154 server->rcv.ptr = NULL;
155 server->rcv.state = 0;
156 }
157 req = server->tx.creq;
158 if (req) {
159 server->tx.creq = NULL;
160 ncp_finish_request(server, req, -EIO);
161 }
162}
163
164static inline int get_conn_number(struct ncp_reply_header *rp)
165{
166 return rp->conn_low | (rp->conn_high << 8);
167}
168
169static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err)
170{
171
172 switch (req->status) {
173 case RQ_IDLE:
174 case RQ_DONE:
175 break;
176 case RQ_QUEUED:
177 list_del_init(&req->req);
178 ncp_finish_request(server, req, err);
179 break;
180 case RQ_INPROGRESS:
181 req->status = RQ_ABANDONED;
182 break;
183 case RQ_ABANDONED:
184 break;
185 }
186}
187
188static inline void ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err)
189{
190 mutex_lock(&server->rcv.creq_mutex);
191 __ncp_abort_request(server, req, err);
192 mutex_unlock(&server->rcv.creq_mutex);
193}
194
195static inline void __ncptcp_abort(struct ncp_server *server)
196{
197 __abort_ncp_connection(server);
198}
199
200static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req)
201{
202 struct msghdr msg = { .msg_iter = req->from, .msg_flags = MSG_DONTWAIT };
203 return sock_sendmsg(sock, &msg);
204}
205
206static void __ncptcp_try_send(struct ncp_server *server)
207{
208 struct ncp_request_reply *rq;
209 struct msghdr msg = { .msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT };
210 int result;
211
212 rq = server->tx.creq;
213 if (!rq)
214 return;
215
216 msg.msg_iter = rq->from;
217 result = sock_sendmsg(server->ncp_sock, &msg);
218
219 if (result == -EAGAIN)
220 return;
221
222 if (result < 0) {
223 pr_err("tcp: Send failed: %d\n", result);
224 __ncp_abort_request(server, rq, result);
225 return;
226 }
227 if (!msg_data_left(&msg)) {
228 server->rcv.creq = rq;
229 server->tx.creq = NULL;
230 return;
231 }
232 rq->from = msg.msg_iter;
233}
234
235static inline void ncp_init_header(struct ncp_server *server, struct ncp_request_reply *req, struct ncp_request_header *h)
236{
237 req->status = RQ_INPROGRESS;
238 h->conn_low = server->connection;
239 h->conn_high = server->connection >> 8;
240 h->sequence = ++server->sequence;
241}
242
243static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request_reply *req)
244{
245 size_t signlen, len = req->tx_iov[1].iov_len;
246 struct ncp_request_header *h = req->tx_iov[1].iov_base;
247
248 ncp_init_header(server, req, h);
249 signlen = sign_packet(server,
250 req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1,
251 len - sizeof(struct ncp_request_header) + 1,
252 cpu_to_le32(len), req->sign);
253 if (signlen) {
254
255 req->tx_iov[2].iov_base = req->sign;
256 req->tx_iov[2].iov_len = signlen;
257 }
258 iov_iter_kvec(&req->from, WRITE | ITER_KVEC,
259 req->tx_iov + 1, signlen ? 2 : 1, len + signlen);
260 server->rcv.creq = req;
261 server->timeout_last = server->m.time_out;
262 server->timeout_retries = server->m.retry_count;
263 ncpdgram_send(server->ncp_sock, req);
264 mod_timer(&server->timeout_tm, jiffies + server->m.time_out);
265}
266
267#define NCP_TCP_XMIT_MAGIC (0x446D6454)
268#define NCP_TCP_XMIT_VERSION (1)
269#define NCP_TCP_RCVD_MAGIC (0x744E6350)
270
271static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_reply *req)
272{
273 size_t signlen, len = req->tx_iov[1].iov_len;
274 struct ncp_request_header *h = req->tx_iov[1].iov_base;
275
276 ncp_init_header(server, req, h);
277 signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1,
278 len - sizeof(struct ncp_request_header) + 1,
279 cpu_to_be32(len + 24), req->sign + 4) + 16;
280
281 req->sign[0] = htonl(NCP_TCP_XMIT_MAGIC);
282 req->sign[1] = htonl(len + signlen);
283 req->sign[2] = htonl(NCP_TCP_XMIT_VERSION);
284 req->sign[3] = htonl(req->datalen + 8);
285
286 req->tx_iov[0].iov_base = req->sign;
287 req->tx_iov[0].iov_len = signlen;
288 iov_iter_kvec(&req->from, WRITE | ITER_KVEC,
289 req->tx_iov, 2, len + signlen);
290
291 server->tx.creq = req;
292 __ncptcp_try_send(server);
293}
294
295static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req)
296{
297
298
299 memcpy(server->txbuf, req->tx_iov[1].iov_base, req->tx_iov[1].iov_len);
300 req->tx_iov[1].iov_base = server->txbuf;
301
302 if (server->ncp_sock->type == SOCK_STREAM)
303 ncptcp_start_request(server, req);
304 else
305 ncpdgram_start_request(server, req);
306}
307
308static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply *req)
309{
310 mutex_lock(&server->rcv.creq_mutex);
311 if (!ncp_conn_valid(server)) {
312 mutex_unlock(&server->rcv.creq_mutex);
313 pr_err("tcp: Server died\n");
314 return -EIO;
315 }
316 ncp_req_get(req);
317 if (server->tx.creq || server->rcv.creq) {
318 req->status = RQ_QUEUED;
319 list_add_tail(&req->req, &server->tx.requests);
320 mutex_unlock(&server->rcv.creq_mutex);
321 return 0;
322 }
323 __ncp_start_request(server, req);
324 mutex_unlock(&server->rcv.creq_mutex);
325 return 0;
326}
327
328static void __ncp_next_request(struct ncp_server *server)
329{
330 struct ncp_request_reply *req;
331
332 server->rcv.creq = NULL;
333 if (list_empty(&server->tx.requests)) {
334 return;
335 }
336 req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
337 list_del_init(&req->req);
338 __ncp_start_request(server, req);
339}
340
341static void info_server(struct ncp_server *server, unsigned int id, const void * data, size_t len)
342{
343 if (server->info_sock) {
344 struct msghdr msg = { .msg_flags = MSG_NOSIGNAL };
345 __be32 hdr[2] = {cpu_to_be32(len + 8), cpu_to_be32(id)};
346 struct kvec iov[2] = {
347 {.iov_base = hdr, .iov_len = 8},
348 {.iov_base = (void *)data, .iov_len = len},
349 };
350
351 iov_iter_kvec(&msg.msg_iter, ITER_KVEC | WRITE,
352 iov, 2, len + 8);
353
354 sock_sendmsg(server->info_sock, &msg);
355 }
356}
357
358void ncpdgram_rcv_proc(struct work_struct *work)
359{
360 struct ncp_server *server =
361 container_of(work, struct ncp_server, rcv.tq);
362 struct socket* sock;
363
364 sock = server->ncp_sock;
365
366 while (1) {
367 struct ncp_reply_header reply;
368 int result;
369
370 result = _recv(sock, &reply, sizeof(reply), MSG_PEEK | MSG_DONTWAIT);
371 if (result < 0) {
372 break;
373 }
374 if (result >= sizeof(reply)) {
375 struct ncp_request_reply *req;
376
377 if (reply.type == NCP_WATCHDOG) {
378 unsigned char buf[10];
379
380 if (server->connection != get_conn_number(&reply)) {
381 goto drop;
382 }
383 result = _recv(sock, buf, sizeof(buf), MSG_DONTWAIT);
384 if (result < 0) {
385 ncp_dbg(1, "recv failed with %d\n", result);
386 continue;
387 }
388 if (result < 10) {
389 ncp_dbg(1, "too short (%u) watchdog packet\n", result);
390 continue;
391 }
392 if (buf[9] != '?') {
393 ncp_dbg(1, "bad signature (%02X) in watchdog packet\n", buf[9]);
394 continue;
395 }
396 buf[9] = 'Y';
397 _send(sock, buf, sizeof(buf));
398 continue;
399 }
400 if (reply.type != NCP_POSITIVE_ACK && reply.type != NCP_REPLY) {
401 result = _recv(sock, server->unexpected_packet.data, sizeof(server->unexpected_packet.data), MSG_DONTWAIT);
402 if (result < 0) {
403 continue;
404 }
405 info_server(server, 0, server->unexpected_packet.data, result);
406 continue;
407 }
408 mutex_lock(&server->rcv.creq_mutex);
409 req = server->rcv.creq;
410 if (req && (req->tx_type == NCP_ALLOC_SLOT_REQUEST || (server->sequence == reply.sequence &&
411 server->connection == get_conn_number(&reply)))) {
412 if (reply.type == NCP_POSITIVE_ACK) {
413 server->timeout_retries = server->m.retry_count;
414 server->timeout_last = NCP_MAX_RPC_TIMEOUT;
415 mod_timer(&server->timeout_tm, jiffies + NCP_MAX_RPC_TIMEOUT);
416 } else if (reply.type == NCP_REPLY) {
417 result = _recv(sock, server->rxbuf, req->datalen, MSG_DONTWAIT);
418#ifdef CONFIG_NCPFS_PACKET_SIGNING
419 if (result >= 0 && server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
420 if (result < 8 + 8) {
421 result = -EIO;
422 } else {
423 unsigned int hdrl;
424
425 result -= 8;
426 hdrl = sock->sk->sk_family == AF_INET ? 8 : 6;
427 if (sign_verify_reply(server, server->rxbuf + hdrl, result - hdrl, cpu_to_le32(result), server->rxbuf + result)) {
428 pr_info("Signature violation\n");
429 result = -EIO;
430 }
431 }
432 }
433#endif
434 del_timer(&server->timeout_tm);
435 server->rcv.creq = NULL;
436 ncp_finish_request(server, req, result);
437 __ncp_next_request(server);
438 mutex_unlock(&server->rcv.creq_mutex);
439 continue;
440 }
441 }
442 mutex_unlock(&server->rcv.creq_mutex);
443 }
444drop:;
445 _recv(sock, &reply, sizeof(reply), MSG_DONTWAIT);
446 }
447}
448
449static void __ncpdgram_timeout_proc(struct ncp_server *server)
450{
451
452 if (!timer_pending(&server->timeout_tm)) {
453 struct ncp_request_reply* req;
454
455 req = server->rcv.creq;
456 if (req) {
457 int timeout;
458
459 if (server->m.flags & NCP_MOUNT_SOFT) {
460 if (server->timeout_retries-- == 0) {
461 __ncp_abort_request(server, req, -ETIMEDOUT);
462 return;
463 }
464 }
465
466 ncpdgram_send(server->ncp_sock, req);
467 timeout = server->timeout_last << 1;
468 if (timeout > NCP_MAX_RPC_TIMEOUT) {
469 timeout = NCP_MAX_RPC_TIMEOUT;
470 }
471 server->timeout_last = timeout;
472 mod_timer(&server->timeout_tm, jiffies + timeout);
473 }
474 }
475}
476
477void ncpdgram_timeout_proc(struct work_struct *work)
478{
479 struct ncp_server *server =
480 container_of(work, struct ncp_server, timeout_tq);
481 mutex_lock(&server->rcv.creq_mutex);
482 __ncpdgram_timeout_proc(server);
483 mutex_unlock(&server->rcv.creq_mutex);
484}
485
486static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len)
487{
488 int result;
489
490 if (buffer) {
491 result = _recv(server->ncp_sock, buffer, len, MSG_DONTWAIT);
492 } else {
493 static unsigned char dummy[1024];
494
495 if (len > sizeof(dummy)) {
496 len = sizeof(dummy);
497 }
498 result = _recv(server->ncp_sock, dummy, len, MSG_DONTWAIT);
499 }
500 if (result < 0) {
501 return result;
502 }
503 if (result > len) {
504 pr_err("tcp: bug in recvmsg (%u > %zu)\n", result, len);
505 return -EIO;
506 }
507 return result;
508}
509
510static int __ncptcp_rcv_proc(struct ncp_server *server)
511{
512
513 while (1) {
514 int result;
515 struct ncp_request_reply *req;
516 int datalen;
517 int type;
518
519 while (server->rcv.len) {
520 result = do_tcp_rcv(server, server->rcv.ptr, server->rcv.len);
521 if (result == -EAGAIN) {
522 return 0;
523 }
524 if (result <= 0) {
525 req = server->rcv.creq;
526 if (req) {
527 __ncp_abort_request(server, req, -EIO);
528 } else {
529 __ncptcp_abort(server);
530 }
531 if (result < 0) {
532 pr_err("tcp: error in recvmsg: %d\n", result);
533 } else {
534 ncp_dbg(1, "tcp: EOF\n");
535 }
536 return -EIO;
537 }
538 if (server->rcv.ptr) {
539 server->rcv.ptr += result;
540 }
541 server->rcv.len -= result;
542 }
543 switch (server->rcv.state) {
544 case 0:
545 if (server->rcv.buf.magic != htonl(NCP_TCP_RCVD_MAGIC)) {
546 pr_err("tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic));
547 __ncptcp_abort(server);
548 return -EIO;
549 }
550 datalen = ntohl(server->rcv.buf.len) & 0x0FFFFFFF;
551 if (datalen < 10) {
552 pr_err("tcp: Unexpected reply len %d\n", datalen);
553 __ncptcp_abort(server);
554 return -EIO;
555 }
556#ifdef CONFIG_NCPFS_PACKET_SIGNING
557 if (server->sign_active) {
558 if (datalen < 18) {
559 pr_err("tcp: Unexpected reply len %d\n", datalen);
560 __ncptcp_abort(server);
561 return -EIO;
562 }
563 server->rcv.buf.len = datalen - 8;
564 server->rcv.ptr = (unsigned char*)&server->rcv.buf.p1;
565 server->rcv.len = 8;
566 server->rcv.state = 4;
567 break;
568 }
569#endif
570 type = ntohs(server->rcv.buf.type);
571#ifdef CONFIG_NCPFS_PACKET_SIGNING
572cont:;
573#endif
574 if (type != NCP_REPLY) {
575 if (datalen - 8 <= sizeof(server->unexpected_packet.data)) {
576 *(__u16*)(server->unexpected_packet.data) = htons(type);
577 server->unexpected_packet.len = datalen - 8;
578
579 server->rcv.state = 5;
580 server->rcv.ptr = server->unexpected_packet.data + 2;
581 server->rcv.len = datalen - 10;
582 break;
583 }
584 ncp_dbg(1, "tcp: Unexpected NCP type %02X\n", type);
585skipdata2:;
586 server->rcv.state = 2;
587skipdata:;
588 server->rcv.ptr = NULL;
589 server->rcv.len = datalen - 10;
590 break;
591 }
592 req = server->rcv.creq;
593 if (!req) {
594 ncp_dbg(1, "Reply without appropriate request\n");
595 goto skipdata2;
596 }
597 if (datalen > req->datalen + 8) {
598 pr_err("tcp: Unexpected reply len %d (expected at most %zd)\n", datalen, req->datalen + 8);
599 server->rcv.state = 3;
600 goto skipdata;
601 }
602 req->datalen = datalen - 8;
603 ((struct ncp_reply_header*)server->rxbuf)->type = NCP_REPLY;
604 server->rcv.ptr = server->rxbuf + 2;
605 server->rcv.len = datalen - 10;
606 server->rcv.state = 1;
607 break;
608#ifdef CONFIG_NCPFS_PACKET_SIGNING
609 case 4:
610 datalen = server->rcv.buf.len;
611 type = ntohs(server->rcv.buf.type2);
612 goto cont;
613#endif
614 case 1:
615 req = server->rcv.creq;
616 if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) {
617 if (((struct ncp_reply_header*)server->rxbuf)->sequence != server->sequence) {
618 pr_err("tcp: Bad sequence number\n");
619 __ncp_abort_request(server, req, -EIO);
620 return -EIO;
621 }
622 if ((((struct ncp_reply_header*)server->rxbuf)->conn_low | (((struct ncp_reply_header*)server->rxbuf)->conn_high << 8)) != server->connection) {
623 pr_err("tcp: Connection number mismatch\n");
624 __ncp_abort_request(server, req, -EIO);
625 return -EIO;
626 }
627 }
628#ifdef CONFIG_NCPFS_PACKET_SIGNING
629 if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
630 if (sign_verify_reply(server, server->rxbuf + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) {
631 pr_err("tcp: Signature violation\n");
632 __ncp_abort_request(server, req, -EIO);
633 return -EIO;
634 }
635 }
636#endif
637 ncp_finish_request(server, req, req->datalen);
638 nextreq:;
639 __ncp_next_request(server);
640 case 2:
641 next:;
642 server->rcv.ptr = (unsigned char*)&server->rcv.buf;
643 server->rcv.len = 10;
644 server->rcv.state = 0;
645 break;
646 case 3:
647 ncp_finish_request(server, server->rcv.creq, -EIO);
648 goto nextreq;
649 case 5:
650 info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len);
651 goto next;
652 }
653 }
654}
655
656void ncp_tcp_rcv_proc(struct work_struct *work)
657{
658 struct ncp_server *server =
659 container_of(work, struct ncp_server, rcv.tq);
660
661 mutex_lock(&server->rcv.creq_mutex);
662 __ncptcp_rcv_proc(server);
663 mutex_unlock(&server->rcv.creq_mutex);
664}
665
666void ncp_tcp_tx_proc(struct work_struct *work)
667{
668 struct ncp_server *server =
669 container_of(work, struct ncp_server, tx.tq);
670
671 mutex_lock(&server->rcv.creq_mutex);
672 __ncptcp_try_send(server);
673 mutex_unlock(&server->rcv.creq_mutex);
674}
675
676static int do_ncp_rpc_call(struct ncp_server *server, int size,
677 unsigned char* reply_buf, int max_reply_size)
678{
679 int result;
680 struct ncp_request_reply *req;
681
682 req = ncp_alloc_req();
683 if (!req)
684 return -ENOMEM;
685
686 req->reply_buf = reply_buf;
687 req->datalen = max_reply_size;
688 req->tx_iov[1].iov_base = server->packet;
689 req->tx_iov[1].iov_len = size;
690 req->tx_type = *(u_int16_t*)server->packet;
691
692 result = ncp_add_request(server, req);
693 if (result < 0)
694 goto out;
695
696 if (wait_event_interruptible(req->wq, req->status == RQ_DONE)) {
697 ncp_abort_request(server, req, -EINTR);
698 result = -EINTR;
699 goto out;
700 }
701
702 result = req->result;
703
704out:
705 ncp_req_put(req);
706
707 return result;
708}
709
710
711
712
713
714static int ncp_do_request(struct ncp_server *server, int size,
715 void* reply, int max_reply_size)
716{
717 int result;
718
719 if (server->lock == 0) {
720 pr_err("Server not locked!\n");
721 return -EIO;
722 }
723 if (!ncp_conn_valid(server)) {
724 return -EIO;
725 }
726 {
727 sigset_t old_set;
728 unsigned long mask, flags;
729
730 spin_lock_irqsave(¤t->sighand->siglock, flags);
731 old_set = current->blocked;
732 if (current->flags & PF_EXITING)
733 mask = 0;
734 else
735 mask = sigmask(SIGKILL);
736 if (server->m.flags & NCP_MOUNT_INTR) {
737
738
739
740
741
742 if (current->sighand->action[SIGINT - 1].sa.sa_handler == SIG_DFL)
743 mask |= sigmask(SIGINT);
744 if (current->sighand->action[SIGQUIT - 1].sa.sa_handler == SIG_DFL)
745 mask |= sigmask(SIGQUIT);
746 }
747 siginitsetinv(¤t->blocked, mask);
748 recalc_sigpending();
749 spin_unlock_irqrestore(¤t->sighand->siglock, flags);
750
751 result = do_ncp_rpc_call(server, size, reply, max_reply_size);
752
753 spin_lock_irqsave(¤t->sighand->siglock, flags);
754 current->blocked = old_set;
755 recalc_sigpending();
756 spin_unlock_irqrestore(¤t->sighand->siglock, flags);
757 }
758
759 ncp_dbg(2, "do_ncp_rpc_call returned %d\n", result);
760
761 return result;
762}
763
764
765
766
767
768int ncp_request2(struct ncp_server *server, int function,
769 void* rpl, int size)
770{
771 struct ncp_request_header *h;
772 struct ncp_reply_header* reply = rpl;
773 int result;
774
775 h = (struct ncp_request_header *) (server->packet);
776 if (server->has_subfunction != 0) {
777 *(__u16 *) & (h->data[0]) = htons(server->current_size - sizeof(*h) - 2);
778 }
779 h->type = NCP_REQUEST;
780
781
782
783
784 h->task = 2;
785 h->function = function;
786
787 result = ncp_do_request(server, server->current_size, reply, size);
788 if (result < 0) {
789 ncp_dbg(1, "ncp_request_error: %d\n", result);
790 goto out;
791 }
792 server->completion = reply->completion_code;
793 server->conn_status = reply->connection_state;
794 server->reply_size = result;
795 server->ncp_reply_size = result - sizeof(struct ncp_reply_header);
796
797 result = reply->completion_code;
798
799 if (result != 0)
800 ncp_vdbg("completion code=%x\n", result);
801out:
802 return result;
803}
804
805int ncp_connect(struct ncp_server *server)
806{
807 struct ncp_request_header *h;
808 int result;
809
810 server->connection = 0xFFFF;
811 server->sequence = 255;
812
813 h = (struct ncp_request_header *) (server->packet);
814 h->type = NCP_ALLOC_SLOT_REQUEST;
815 h->task = 2;
816 h->function = 0;
817
818 result = ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
819 if (result < 0)
820 goto out;
821 server->connection = h->conn_low + (h->conn_high * 256);
822 result = 0;
823out:
824 return result;
825}
826
827int ncp_disconnect(struct ncp_server *server)
828{
829 struct ncp_request_header *h;
830
831 h = (struct ncp_request_header *) (server->packet);
832 h->type = NCP_DEALLOC_SLOT_REQUEST;
833 h->task = 2;
834 h->function = 0;
835
836 return ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
837}
838
839void ncp_lock_server(struct ncp_server *server)
840{
841 mutex_lock(&server->mutex);
842 if (server->lock)
843 pr_warn("%s: was locked!\n", __func__);
844 server->lock = 1;
845}
846
847void ncp_unlock_server(struct ncp_server *server)
848{
849 if (!server->lock) {
850 pr_warn("%s: was not locked!\n", __func__);
851 return;
852 }
853 server->lock = 0;
854 mutex_unlock(&server->mutex);
855}
856