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