[PATCH] core-dumping unreadable binaries via PT_INTERP
[linux-2.6/verdex.git] / fs / ncpfs / sock.c
blobe496d8b65e92d50141139cec9519353e0a953793
1 /*
2 * linux/fs/ncpfs/sock.c
4 * Copyright (C) 1992, 1993 Rick Sladkey
6 * Modified 1995, 1996 by Volker Lendecke to be usable for ncp
7 * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
9 */
12 #include <linux/time.h>
13 #include <linux/errno.h>
14 #include <linux/socket.h>
15 #include <linux/fcntl.h>
16 #include <linux/stat.h>
17 #include <asm/uaccess.h>
18 #include <linux/in.h>
19 #include <linux/net.h>
20 #include <linux/mm.h>
21 #include <linux/netdevice.h>
22 #include <linux/signal.h>
23 #include <net/scm.h>
24 #include <net/sock.h>
25 #include <linux/ipx.h>
26 #include <linux/poll.h>
27 #include <linux/file.h>
29 #include <linux/ncp_fs.h>
31 #include "ncpsign_kernel.h"
33 static int _recv(struct socket *sock, void *buf, int size, unsigned flags)
35 struct msghdr msg = {NULL, };
36 struct kvec iov = {buf, size};
37 return kernel_recvmsg(sock, &msg, &iov, 1, size, flags);
40 static inline int do_send(struct socket *sock, struct kvec *vec, int count,
41 int len, unsigned flags)
43 struct msghdr msg = { .msg_flags = flags };
44 return kernel_sendmsg(sock, &msg, vec, count, len);
47 static int _send(struct socket *sock, const void *buff, int len)
49 struct kvec vec;
50 vec.iov_base = (void *) buff;
51 vec.iov_len = len;
52 return do_send(sock, &vec, 1, len, 0);
55 struct ncp_request_reply {
56 struct list_head req;
57 wait_queue_head_t wq;
58 struct ncp_reply_header* reply_buf;
59 size_t datalen;
60 int result;
61 enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE } status;
62 struct kvec* tx_ciov;
63 size_t tx_totallen;
64 size_t tx_iovlen;
65 struct kvec tx_iov[3];
66 u_int16_t tx_type;
67 u_int32_t sign[6];
70 void ncp_tcp_data_ready(struct sock *sk, int len)
72 struct ncp_server *server = sk->sk_user_data;
74 server->data_ready(sk, len);
75 schedule_work(&server->rcv.tq);
78 void ncp_tcp_error_report(struct sock *sk)
80 struct ncp_server *server = sk->sk_user_data;
82 server->error_report(sk);
83 schedule_work(&server->rcv.tq);
86 void ncp_tcp_write_space(struct sock *sk)
88 struct ncp_server *server = sk->sk_user_data;
90 /* We do not need any locking: we first set tx.creq, and then we do sendmsg,
91 not vice versa... */
92 server->write_space(sk);
93 if (server->tx.creq)
94 schedule_work(&server->tx.tq);
97 void ncpdgram_timeout_call(unsigned long v)
99 struct ncp_server *server = (void*)v;
101 schedule_work(&server->timeout_tq);
104 static inline void ncp_finish_request(struct ncp_request_reply *req, int result)
106 req->result = result;
107 req->status = RQ_DONE;
108 wake_up_all(&req->wq);
111 static void __abort_ncp_connection(struct ncp_server *server, struct ncp_request_reply *aborted, int err)
113 struct ncp_request_reply *req;
115 ncp_invalidate_conn(server);
116 del_timer(&server->timeout_tm);
117 while (!list_empty(&server->tx.requests)) {
118 req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
120 list_del_init(&req->req);
121 if (req == aborted) {
122 ncp_finish_request(req, err);
123 } else {
124 ncp_finish_request(req, -EIO);
127 req = server->rcv.creq;
128 if (req) {
129 server->rcv.creq = NULL;
130 if (req == aborted) {
131 ncp_finish_request(req, err);
132 } else {
133 ncp_finish_request(req, -EIO);
135 server->rcv.ptr = NULL;
136 server->rcv.state = 0;
138 req = server->tx.creq;
139 if (req) {
140 server->tx.creq = NULL;
141 if (req == aborted) {
142 ncp_finish_request(req, err);
143 } else {
144 ncp_finish_request(req, -EIO);
149 static inline int get_conn_number(struct ncp_reply_header *rp)
151 return rp->conn_low | (rp->conn_high << 8);
154 static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err)
156 /* If req is done, we got signal, but we also received answer... */
157 switch (req->status) {
158 case RQ_IDLE:
159 case RQ_DONE:
160 break;
161 case RQ_QUEUED:
162 list_del_init(&req->req);
163 ncp_finish_request(req, err);
164 break;
165 case RQ_INPROGRESS:
166 __abort_ncp_connection(server, req, err);
167 break;
171 static inline void ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err)
173 mutex_lock(&server->rcv.creq_mutex);
174 __ncp_abort_request(server, req, err);
175 mutex_unlock(&server->rcv.creq_mutex);
178 static inline void __ncptcp_abort(struct ncp_server *server)
180 __abort_ncp_connection(server, NULL, 0);
183 static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req)
185 struct kvec vec[3];
186 /* sock_sendmsg updates iov pointers for us :-( */
187 memcpy(vec, req->tx_ciov, req->tx_iovlen * sizeof(vec[0]));
188 return do_send(sock, vec, req->tx_iovlen,
189 req->tx_totallen, MSG_DONTWAIT);
192 static void __ncptcp_try_send(struct ncp_server *server)
194 struct ncp_request_reply *rq;
195 struct kvec *iov;
196 struct kvec iovc[3];
197 int result;
199 rq = server->tx.creq;
200 if (!rq)
201 return;
203 /* sock_sendmsg updates iov pointers for us :-( */
204 memcpy(iovc, rq->tx_ciov, rq->tx_iovlen * sizeof(iov[0]));
205 result = do_send(server->ncp_sock, iovc, rq->tx_iovlen,
206 rq->tx_totallen, MSG_NOSIGNAL | MSG_DONTWAIT);
208 if (result == -EAGAIN)
209 return;
211 if (result < 0) {
212 printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result);
213 __ncp_abort_request(server, rq, result);
214 return;
216 if (result >= rq->tx_totallen) {
217 server->rcv.creq = rq;
218 server->tx.creq = NULL;
219 return;
221 rq->tx_totallen -= result;
222 iov = rq->tx_ciov;
223 while (iov->iov_len <= result) {
224 result -= iov->iov_len;
225 iov++;
226 rq->tx_iovlen--;
228 iov->iov_base += result;
229 iov->iov_len -= result;
230 rq->tx_ciov = iov;
233 static inline void ncp_init_header(struct ncp_server *server, struct ncp_request_reply *req, struct ncp_request_header *h)
235 req->status = RQ_INPROGRESS;
236 h->conn_low = server->connection;
237 h->conn_high = server->connection >> 8;
238 h->sequence = ++server->sequence;
241 static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request_reply *req)
243 size_t signlen;
244 struct ncp_request_header* h;
246 req->tx_ciov = req->tx_iov + 1;
248 h = req->tx_iov[1].iov_base;
249 ncp_init_header(server, req, h);
250 signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1,
251 req->tx_iov[1].iov_len - sizeof(struct ncp_request_header) + 1,
252 cpu_to_le32(req->tx_totallen), req->sign);
253 if (signlen) {
254 req->tx_ciov[1].iov_base = req->sign;
255 req->tx_ciov[1].iov_len = signlen;
256 req->tx_iovlen += 1;
257 req->tx_totallen += signlen;
259 server->rcv.creq = req;
260 server->timeout_last = server->m.time_out;
261 server->timeout_retries = server->m.retry_count;
262 ncpdgram_send(server->ncp_sock, req);
263 mod_timer(&server->timeout_tm, jiffies + server->m.time_out);
266 #define NCP_TCP_XMIT_MAGIC (0x446D6454)
267 #define NCP_TCP_XMIT_VERSION (1)
268 #define NCP_TCP_RCVD_MAGIC (0x744E6350)
270 static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_reply *req)
272 size_t signlen;
273 struct ncp_request_header* h;
275 req->tx_ciov = req->tx_iov;
276 h = req->tx_iov[1].iov_base;
277 ncp_init_header(server, req, h);
278 signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1,
279 req->tx_iov[1].iov_len - sizeof(struct ncp_request_header) + 1,
280 cpu_to_be32(req->tx_totallen + 24), req->sign + 4) + 16;
282 req->sign[0] = htonl(NCP_TCP_XMIT_MAGIC);
283 req->sign[1] = htonl(req->tx_totallen + signlen);
284 req->sign[2] = htonl(NCP_TCP_XMIT_VERSION);
285 req->sign[3] = htonl(req->datalen + 8);
286 req->tx_iov[0].iov_base = req->sign;
287 req->tx_iov[0].iov_len = signlen;
288 req->tx_iovlen += 1;
289 req->tx_totallen += signlen;
291 server->tx.creq = req;
292 __ncptcp_try_send(server);
295 static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req)
297 if (server->ncp_sock->type == SOCK_STREAM)
298 ncptcp_start_request(server, req);
299 else
300 ncpdgram_start_request(server, req);
303 static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply *req)
305 mutex_lock(&server->rcv.creq_mutex);
306 if (!ncp_conn_valid(server)) {
307 mutex_unlock(&server->rcv.creq_mutex);
308 printk(KERN_ERR "ncpfs: tcp: Server died\n");
309 return -EIO;
311 if (server->tx.creq || server->rcv.creq) {
312 req->status = RQ_QUEUED;
313 list_add_tail(&req->req, &server->tx.requests);
314 mutex_unlock(&server->rcv.creq_mutex);
315 return 0;
317 __ncp_start_request(server, req);
318 mutex_unlock(&server->rcv.creq_mutex);
319 return 0;
322 static void __ncp_next_request(struct ncp_server *server)
324 struct ncp_request_reply *req;
326 server->rcv.creq = NULL;
327 if (list_empty(&server->tx.requests)) {
328 return;
330 req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
331 list_del_init(&req->req);
332 __ncp_start_request(server, req);
335 static void info_server(struct ncp_server *server, unsigned int id, const void * data, size_t len)
337 if (server->info_sock) {
338 struct kvec iov[2];
339 __be32 hdr[2];
341 hdr[0] = cpu_to_be32(len + 8);
342 hdr[1] = cpu_to_be32(id);
344 iov[0].iov_base = hdr;
345 iov[0].iov_len = 8;
346 iov[1].iov_base = (void *) data;
347 iov[1].iov_len = len;
349 do_send(server->info_sock, iov, 2, len + 8, MSG_NOSIGNAL);
353 void ncpdgram_rcv_proc(struct work_struct *work)
355 struct ncp_server *server =
356 container_of(work, struct ncp_server, rcv.tq);
357 struct socket* sock;
359 sock = server->ncp_sock;
361 while (1) {
362 struct ncp_reply_header reply;
363 int result;
365 result = _recv(sock, &reply, sizeof(reply), MSG_PEEK | MSG_DONTWAIT);
366 if (result < 0) {
367 break;
369 if (result >= sizeof(reply)) {
370 struct ncp_request_reply *req;
372 if (reply.type == NCP_WATCHDOG) {
373 unsigned char buf[10];
375 if (server->connection != get_conn_number(&reply)) {
376 goto drop;
378 result = _recv(sock, buf, sizeof(buf), MSG_DONTWAIT);
379 if (result < 0) {
380 DPRINTK("recv failed with %d\n", result);
381 continue;
383 if (result < 10) {
384 DPRINTK("too short (%u) watchdog packet\n", result);
385 continue;
387 if (buf[9] != '?') {
388 DPRINTK("bad signature (%02X) in watchdog packet\n", buf[9]);
389 continue;
391 buf[9] = 'Y';
392 _send(sock, buf, sizeof(buf));
393 continue;
395 if (reply.type != NCP_POSITIVE_ACK && reply.type != NCP_REPLY) {
396 result = _recv(sock, server->unexpected_packet.data, sizeof(server->unexpected_packet.data), MSG_DONTWAIT);
397 if (result < 0) {
398 continue;
400 info_server(server, 0, server->unexpected_packet.data, result);
401 continue;
403 mutex_lock(&server->rcv.creq_mutex);
404 req = server->rcv.creq;
405 if (req && (req->tx_type == NCP_ALLOC_SLOT_REQUEST || (server->sequence == reply.sequence &&
406 server->connection == get_conn_number(&reply)))) {
407 if (reply.type == NCP_POSITIVE_ACK) {
408 server->timeout_retries = server->m.retry_count;
409 server->timeout_last = NCP_MAX_RPC_TIMEOUT;
410 mod_timer(&server->timeout_tm, jiffies + NCP_MAX_RPC_TIMEOUT);
411 } else if (reply.type == NCP_REPLY) {
412 result = _recv(sock, (void*)req->reply_buf, req->datalen, MSG_DONTWAIT);
413 #ifdef CONFIG_NCPFS_PACKET_SIGNING
414 if (result >= 0 && server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
415 if (result < 8 + 8) {
416 result = -EIO;
417 } else {
418 unsigned int hdrl;
420 result -= 8;
421 hdrl = sock->sk->sk_family == AF_INET ? 8 : 6;
422 if (sign_verify_reply(server, ((char*)req->reply_buf) + hdrl, result - hdrl, cpu_to_le32(result), ((char*)req->reply_buf) + result)) {
423 printk(KERN_INFO "ncpfs: Signature violation\n");
424 result = -EIO;
428 #endif
429 del_timer(&server->timeout_tm);
430 server->rcv.creq = NULL;
431 ncp_finish_request(req, result);
432 __ncp_next_request(server);
433 mutex_unlock(&server->rcv.creq_mutex);
434 continue;
437 mutex_unlock(&server->rcv.creq_mutex);
439 drop:;
440 _recv(sock, &reply, sizeof(reply), MSG_DONTWAIT);
444 static void __ncpdgram_timeout_proc(struct ncp_server *server)
446 /* If timer is pending, we are processing another request... */
447 if (!timer_pending(&server->timeout_tm)) {
448 struct ncp_request_reply* req;
450 req = server->rcv.creq;
451 if (req) {
452 int timeout;
454 if (server->m.flags & NCP_MOUNT_SOFT) {
455 if (server->timeout_retries-- == 0) {
456 __ncp_abort_request(server, req, -ETIMEDOUT);
457 return;
460 /* Ignore errors */
461 ncpdgram_send(server->ncp_sock, req);
462 timeout = server->timeout_last << 1;
463 if (timeout > NCP_MAX_RPC_TIMEOUT) {
464 timeout = NCP_MAX_RPC_TIMEOUT;
466 server->timeout_last = timeout;
467 mod_timer(&server->timeout_tm, jiffies + timeout);
472 void ncpdgram_timeout_proc(struct work_struct *work)
474 struct ncp_server *server =
475 container_of(work, struct ncp_server, timeout_tq);
476 mutex_lock(&server->rcv.creq_mutex);
477 __ncpdgram_timeout_proc(server);
478 mutex_unlock(&server->rcv.creq_mutex);
481 static inline void ncp_init_req(struct ncp_request_reply* req)
483 init_waitqueue_head(&req->wq);
484 req->status = RQ_IDLE;
487 static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len)
489 int result;
491 if (buffer) {
492 result = _recv(server->ncp_sock, buffer, len, MSG_DONTWAIT);
493 } else {
494 static unsigned char dummy[1024];
496 if (len > sizeof(dummy)) {
497 len = sizeof(dummy);
499 result = _recv(server->ncp_sock, dummy, len, MSG_DONTWAIT);
501 if (result < 0) {
502 return result;
504 if (result > len) {
505 printk(KERN_ERR "ncpfs: tcp: bug in recvmsg (%u > %Zu)\n", result, len);
506 return -EIO;
508 return result;
511 static int __ncptcp_rcv_proc(struct ncp_server *server)
513 /* We have to check the result, so store the complete header */
514 while (1) {
515 int result;
516 struct ncp_request_reply *req;
517 int datalen;
518 int type;
520 while (server->rcv.len) {
521 result = do_tcp_rcv(server, server->rcv.ptr, server->rcv.len);
522 if (result == -EAGAIN) {
523 return 0;
525 if (result <= 0) {
526 req = server->rcv.creq;
527 if (req) {
528 __ncp_abort_request(server, req, -EIO);
529 } else {
530 __ncptcp_abort(server);
532 if (result < 0) {
533 printk(KERN_ERR "ncpfs: tcp: error in recvmsg: %d\n", result);
534 } else {
535 DPRINTK(KERN_ERR "ncpfs: tcp: EOF\n");
537 return -EIO;
539 if (server->rcv.ptr) {
540 server->rcv.ptr += result;
542 server->rcv.len -= result;
544 switch (server->rcv.state) {
545 case 0:
546 if (server->rcv.buf.magic != htonl(NCP_TCP_RCVD_MAGIC)) {
547 printk(KERN_ERR "ncpfs: tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic));
548 __ncptcp_abort(server);
549 return -EIO;
551 datalen = ntohl(server->rcv.buf.len) & 0x0FFFFFFF;
552 if (datalen < 10) {
553 printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
554 __ncptcp_abort(server);
555 return -EIO;
557 #ifdef CONFIG_NCPFS_PACKET_SIGNING
558 if (server->sign_active) {
559 if (datalen < 18) {
560 printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
561 __ncptcp_abort(server);
562 return -EIO;
564 server->rcv.buf.len = datalen - 8;
565 server->rcv.ptr = (unsigned char*)&server->rcv.buf.p1;
566 server->rcv.len = 8;
567 server->rcv.state = 4;
568 break;
570 #endif
571 type = ntohs(server->rcv.buf.type);
572 #ifdef CONFIG_NCPFS_PACKET_SIGNING
573 cont:;
574 #endif
575 if (type != NCP_REPLY) {
576 if (datalen - 8 <= sizeof(server->unexpected_packet.data)) {
577 *(__u16*)(server->unexpected_packet.data) = htons(type);
578 server->unexpected_packet.len = datalen - 8;
580 server->rcv.state = 5;
581 server->rcv.ptr = server->unexpected_packet.data + 2;
582 server->rcv.len = datalen - 10;
583 break;
585 DPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", type);
586 skipdata2:;
587 server->rcv.state = 2;
588 skipdata:;
589 server->rcv.ptr = NULL;
590 server->rcv.len = datalen - 10;
591 break;
593 req = server->rcv.creq;
594 if (!req) {
595 DPRINTK(KERN_ERR "ncpfs: Reply without appropriate request\n");
596 goto skipdata2;
598 if (datalen > req->datalen + 8) {
599 printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d (expected at most %Zd)\n", datalen, req->datalen + 8);
600 server->rcv.state = 3;
601 goto skipdata;
603 req->datalen = datalen - 8;
604 req->reply_buf->type = NCP_REPLY;
605 server->rcv.ptr = (unsigned char*)(req->reply_buf) + 2;
606 server->rcv.len = datalen - 10;
607 server->rcv.state = 1;
608 break;
609 #ifdef CONFIG_NCPFS_PACKET_SIGNING
610 case 4:
611 datalen = server->rcv.buf.len;
612 type = ntohs(server->rcv.buf.type2);
613 goto cont;
614 #endif
615 case 1:
616 req = server->rcv.creq;
617 if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) {
618 if (req->reply_buf->sequence != server->sequence) {
619 printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n");
620 __ncp_abort_request(server, req, -EIO);
621 return -EIO;
623 if ((req->reply_buf->conn_low | (req->reply_buf->conn_high << 8)) != server->connection) {
624 printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n");
625 __ncp_abort_request(server, req, -EIO);
626 return -EIO;
629 #ifdef CONFIG_NCPFS_PACKET_SIGNING
630 if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
631 if (sign_verify_reply(server, (unsigned char*)(req->reply_buf) + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) {
632 printk(KERN_ERR "ncpfs: tcp: Signature violation\n");
633 __ncp_abort_request(server, req, -EIO);
634 return -EIO;
637 #endif
638 ncp_finish_request(req, req->datalen);
639 nextreq:;
640 __ncp_next_request(server);
641 case 2:
642 next:;
643 server->rcv.ptr = (unsigned char*)&server->rcv.buf;
644 server->rcv.len = 10;
645 server->rcv.state = 0;
646 break;
647 case 3:
648 ncp_finish_request(server->rcv.creq, -EIO);
649 goto nextreq;
650 case 5:
651 info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len);
652 goto next;
657 void ncp_tcp_rcv_proc(struct work_struct *work)
659 struct ncp_server *server =
660 container_of(work, struct ncp_server, rcv.tq);
662 mutex_lock(&server->rcv.creq_mutex);
663 __ncptcp_rcv_proc(server);
664 mutex_unlock(&server->rcv.creq_mutex);
667 void ncp_tcp_tx_proc(struct work_struct *work)
669 struct ncp_server *server =
670 container_of(work, struct ncp_server, tx.tq);
672 mutex_lock(&server->rcv.creq_mutex);
673 __ncptcp_try_send(server);
674 mutex_unlock(&server->rcv.creq_mutex);
677 static int do_ncp_rpc_call(struct ncp_server *server, int size,
678 struct ncp_reply_header* reply_buf, int max_reply_size)
680 int result;
681 struct ncp_request_reply req;
683 ncp_init_req(&req);
684 req.reply_buf = reply_buf;
685 req.datalen = max_reply_size;
686 req.tx_iov[1].iov_base = server->packet;
687 req.tx_iov[1].iov_len = size;
688 req.tx_iovlen = 1;
689 req.tx_totallen = size;
690 req.tx_type = *(u_int16_t*)server->packet;
692 result = ncp_add_request(server, &req);
693 if (result < 0) {
694 return result;
696 if (wait_event_interruptible(req.wq, req.status == RQ_DONE)) {
697 ncp_abort_request(server, &req, -EIO);
699 return req.result;
703 * We need the server to be locked here, so check!
706 static int ncp_do_request(struct ncp_server *server, int size,
707 void* reply, int max_reply_size)
709 int result;
711 if (server->lock == 0) {
712 printk(KERN_ERR "ncpfs: Server not locked!\n");
713 return -EIO;
715 if (!ncp_conn_valid(server)) {
716 printk(KERN_ERR "ncpfs: Connection invalid!\n");
717 return -EIO;
720 sigset_t old_set;
721 unsigned long mask, flags;
723 spin_lock_irqsave(&current->sighand->siglock, flags);
724 old_set = current->blocked;
725 if (current->flags & PF_EXITING)
726 mask = 0;
727 else
728 mask = sigmask(SIGKILL);
729 if (server->m.flags & NCP_MOUNT_INTR) {
730 /* FIXME: This doesn't seem right at all. So, like,
731 we can't handle SIGINT and get whatever to stop?
732 What if we've blocked it ourselves? What about
733 alarms? Why, in fact, are we mucking with the
734 sigmask at all? -- r~ */
735 if (current->sighand->action[SIGINT - 1].sa.sa_handler == SIG_DFL)
736 mask |= sigmask(SIGINT);
737 if (current->sighand->action[SIGQUIT - 1].sa.sa_handler == SIG_DFL)
738 mask |= sigmask(SIGQUIT);
740 siginitsetinv(&current->blocked, mask);
741 recalc_sigpending();
742 spin_unlock_irqrestore(&current->sighand->siglock, flags);
744 result = do_ncp_rpc_call(server, size, reply, max_reply_size);
746 spin_lock_irqsave(&current->sighand->siglock, flags);
747 current->blocked = old_set;
748 recalc_sigpending();
749 spin_unlock_irqrestore(&current->sighand->siglock, flags);
752 DDPRINTK("do_ncp_rpc_call returned %d\n", result);
754 if (result < 0) {
755 /* There was a problem with I/O, so the connections is
756 * no longer usable. */
757 ncp_invalidate_conn(server);
759 return result;
762 /* ncp_do_request assures that at least a complete reply header is
763 * received. It assumes that server->current_size contains the ncp
764 * request size
766 int ncp_request2(struct ncp_server *server, int function,
767 void* rpl, int size)
769 struct ncp_request_header *h;
770 struct ncp_reply_header* reply = rpl;
771 int result;
773 h = (struct ncp_request_header *) (server->packet);
774 if (server->has_subfunction != 0) {
775 *(__u16 *) & (h->data[0]) = htons(server->current_size - sizeof(*h) - 2);
777 h->type = NCP_REQUEST;
779 * The server shouldn't know or care what task is making a
780 * request, so we always use the same task number.
782 h->task = 2; /* (current->pid) & 0xff; */
783 h->function = function;
785 result = ncp_do_request(server, server->current_size, reply, size);
786 if (result < 0) {
787 DPRINTK("ncp_request_error: %d\n", result);
788 goto out;
790 server->completion = reply->completion_code;
791 server->conn_status = reply->connection_state;
792 server->reply_size = result;
793 server->ncp_reply_size = result - sizeof(struct ncp_reply_header);
795 result = reply->completion_code;
797 if (result != 0)
798 PPRINTK("ncp_request: completion code=%x\n", result);
799 out:
800 return result;
803 int ncp_connect(struct ncp_server *server)
805 struct ncp_request_header *h;
806 int result;
808 server->connection = 0xFFFF;
809 server->sequence = 255;
811 h = (struct ncp_request_header *) (server->packet);
812 h->type = NCP_ALLOC_SLOT_REQUEST;
813 h->task = 2; /* see above */
814 h->function = 0;
816 result = ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
817 if (result < 0)
818 goto out;
819 server->connection = h->conn_low + (h->conn_high * 256);
820 result = 0;
821 out:
822 return result;
825 int ncp_disconnect(struct ncp_server *server)
827 struct ncp_request_header *h;
829 h = (struct ncp_request_header *) (server->packet);
830 h->type = NCP_DEALLOC_SLOT_REQUEST;
831 h->task = 2; /* see above */
832 h->function = 0;
834 return ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
837 void ncp_lock_server(struct ncp_server *server)
839 mutex_lock(&server->mutex);
840 if (server->lock)
841 printk(KERN_WARNING "ncp_lock_server: was locked!\n");
842 server->lock = 1;
845 void ncp_unlock_server(struct ncp_server *server)
847 if (!server->lock) {
848 printk(KERN_WARNING "ncp_unlock_server: was not locked!\n");
849 return;
851 server->lock = 0;
852 mutex_unlock(&server->mutex);