Merge tag 'seccomp-v4.16-rc3' of https://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / drivers / staging / ncpfs / sock.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  linux/fs/ncpfs/sock.c
4  *
5  *  Copyright (C) 1992, 1993  Rick Sladkey
6  *
7  *  Modified 1995, 1996 by Volker Lendecke to be usable for ncp
8  *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
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
38 static 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
46 static 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
54 struct 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
68 static 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
83 static void ncp_req_get(struct ncp_request_reply *req)
84 {
85         atomic_inc(&req->refs);
86 }
87
88 static void ncp_req_put(struct ncp_request_reply *req)
89 {
90         if (atomic_dec_and_test(&req->refs))
91                 kfree(req);
92 }
93
94 void 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
102 void 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
110 void ncp_tcp_write_space(struct sock *sk)
111 {
112         struct ncp_server *server = sk->sk_user_data;
113         
114         /* We do not need any locking: we first set tx.creq, and then we do sendmsg,
115            not vice versa... */
116         server->write_space(sk);
117         if (server->tx.creq)
118                 schedule_work(&server->tx.tq);
119 }
120
121 void 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
128 static 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
138 static 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
164 static inline int get_conn_number(struct ncp_reply_header *rp)
165 {
166         return rp->conn_low | (rp->conn_high << 8);
167 }
168
169 static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err)
170 {
171         /* If req is done, we got signal, but we also received answer... */
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
188 static 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
195 static inline void __ncptcp_abort(struct ncp_server *server)
196 {
197         __abort_ncp_connection(server);
198 }
199
200 static 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
206 static 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
235 static 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         
243 static 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                 /* NCP over UDP appends signature */
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
271 static 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         /* NCP over TCP prepends signature */
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
295 static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req)
296 {
297         /* we copy the data so that we do not depend on the caller
298            staying alive */
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
308 static 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
328 static 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
341 static 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
358 void 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                 }
444 drop:;          
445                 _recv(sock, &reply, sizeof(reply), MSG_DONTWAIT);
446         }
447 }
448
449 static void __ncpdgram_timeout_proc(struct ncp_server *server)
450 {
451         /* If timer is pending, we are processing another request... */
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                         /* Ignore errors */
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
477 void 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
486 static 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
510 static int __ncptcp_rcv_proc(struct ncp_server *server)
511 {
512         /* We have to check the result, so store the complete header */
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                              
572 cont:;                          
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);
585 skipdata2:;
586                                         server->rcv.state = 2;
587 skipdata:;
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
656 void 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
666 void 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
676 static 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
704 out:
705         ncp_req_put(req);
706
707         return result;
708 }
709
710 /*
711  * We need the server to be locked here, so check!
712  */
713
714 static 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(&current->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                         /* FIXME: This doesn't seem right at all.  So, like,
738                            we can't handle SIGINT and get whatever to stop?
739                            What if we've blocked it ourselves?  What about
740                            alarms?  Why, in fact, are we mucking with the
741                            sigmask at all? -- r~ */
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(&current->blocked, mask);
748                 recalc_sigpending();
749                 spin_unlock_irqrestore(&current->sighand->siglock, flags);
750                 
751                 result = do_ncp_rpc_call(server, size, reply, max_reply_size);
752
753                 spin_lock_irqsave(&current->sighand->siglock, flags);
754                 current->blocked = old_set;
755                 recalc_sigpending();
756                 spin_unlock_irqrestore(&current->sighand->siglock, flags);
757         }
758
759         ncp_dbg(2, "do_ncp_rpc_call returned %d\n", result);
760
761         return result;
762 }
763
764 /* ncp_do_request assures that at least a complete reply header is
765  * received. It assumes that server->current_size contains the ncp
766  * request size
767  */
768 int 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          * The server shouldn't know or care what task is making a
782          * request, so we always use the same task number.
783          */
784         h->task = 2; /* (current->pid) & 0xff; */
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);
801 out:
802         return result;
803 }
804
805 int 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; /* see above */
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;
823 out:
824         return result;
825 }
826
827 int 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; /* see above */
834         h->function     = 0;
835
836         return ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
837 }
838
839 void 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
847 void 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 }