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
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 <linux/string.h>
18 #include <asm/uaccess.h>
20 #include <linux/net.h>
22 #include <linux/netdevice.h>
23 #include <linux/signal.h>
24 #include <linux/slab.h>
27 #include <linux/ipx.h>
28 #include <linux/poll.h>
29 #include <linux/file.h>
31 #include <linux/ncp_fs.h>
33 #include "ncpsign_kernel.h"
35 static int _recv(struct socket
*sock
, void *buf
, int size
, unsigned flags
)
37 struct msghdr msg
= {NULL
, };
38 struct kvec iov
= {buf
, size
};
39 return kernel_recvmsg(sock
, &msg
, &iov
, 1, size
, flags
);
42 static inline int do_send(struct socket
*sock
, struct kvec
*vec
, int count
,
43 int len
, unsigned flags
)
45 struct msghdr msg
= { .msg_flags
= flags
};
46 return kernel_sendmsg(sock
, &msg
, vec
, count
, len
);
49 static int _send(struct socket
*sock
, const void *buff
, int len
)
52 vec
.iov_base
= (void *) buff
;
54 return do_send(sock
, &vec
, 1, len
, 0);
57 struct ncp_request_reply
{
61 unsigned char* reply_buf
;
64 enum { RQ_DONE
, RQ_INPROGRESS
, RQ_QUEUED
, RQ_IDLE
, RQ_ABANDONED
} status
;
68 struct kvec tx_iov
[3];
73 static inline struct ncp_request_reply
* ncp_alloc_req(void)
75 struct ncp_request_reply
*req
;
77 req
= kmalloc(sizeof(struct ncp_request_reply
), GFP_KERNEL
);
81 init_waitqueue_head(&req
->wq
);
82 atomic_set(&req
->refs
, (1));
83 req
->status
= RQ_IDLE
;
88 static void ncp_req_get(struct ncp_request_reply
*req
)
90 atomic_inc(&req
->refs
);
93 static void ncp_req_put(struct ncp_request_reply
*req
)
95 if (atomic_dec_and_test(&req
->refs
))
99 void ncp_tcp_data_ready(struct sock
*sk
, int len
)
101 struct ncp_server
*server
= sk
->sk_user_data
;
103 server
->data_ready(sk
, len
);
104 schedule_work(&server
->rcv
.tq
);
107 void ncp_tcp_error_report(struct sock
*sk
)
109 struct ncp_server
*server
= sk
->sk_user_data
;
111 server
->error_report(sk
);
112 schedule_work(&server
->rcv
.tq
);
115 void ncp_tcp_write_space(struct sock
*sk
)
117 struct ncp_server
*server
= sk
->sk_user_data
;
119 /* We do not need any locking: we first set tx.creq, and then we do sendmsg,
121 server
->write_space(sk
);
123 schedule_work(&server
->tx
.tq
);
126 void ncpdgram_timeout_call(unsigned long v
)
128 struct ncp_server
*server
= (void*)v
;
130 schedule_work(&server
->timeout_tq
);
133 static inline void ncp_finish_request(struct ncp_server
*server
, struct ncp_request_reply
*req
, int result
)
135 req
->result
= result
;
136 if (req
->status
!= RQ_ABANDONED
)
137 memcpy(req
->reply_buf
, server
->rxbuf
, req
->datalen
);
138 req
->status
= RQ_DONE
;
139 wake_up_all(&req
->wq
);
143 static void __abort_ncp_connection(struct ncp_server
*server
)
145 struct ncp_request_reply
*req
;
147 ncp_invalidate_conn(server
);
148 del_timer(&server
->timeout_tm
);
149 while (!list_empty(&server
->tx
.requests
)) {
150 req
= list_entry(server
->tx
.requests
.next
, struct ncp_request_reply
, req
);
152 list_del_init(&req
->req
);
153 ncp_finish_request(server
, req
, -EIO
);
155 req
= server
->rcv
.creq
;
157 server
->rcv
.creq
= NULL
;
158 ncp_finish_request(server
, req
, -EIO
);
159 server
->rcv
.ptr
= NULL
;
160 server
->rcv
.state
= 0;
162 req
= server
->tx
.creq
;
164 server
->tx
.creq
= NULL
;
165 ncp_finish_request(server
, req
, -EIO
);
169 static inline int get_conn_number(struct ncp_reply_header
*rp
)
171 return rp
->conn_low
| (rp
->conn_high
<< 8);
174 static inline void __ncp_abort_request(struct ncp_server
*server
, struct ncp_request_reply
*req
, int err
)
176 /* If req is done, we got signal, but we also received answer... */
177 switch (req
->status
) {
182 list_del_init(&req
->req
);
183 ncp_finish_request(server
, req
, err
);
186 req
->status
= RQ_ABANDONED
;
193 static inline void ncp_abort_request(struct ncp_server
*server
, struct ncp_request_reply
*req
, int err
)
195 mutex_lock(&server
->rcv
.creq_mutex
);
196 __ncp_abort_request(server
, req
, err
);
197 mutex_unlock(&server
->rcv
.creq_mutex
);
200 static inline void __ncptcp_abort(struct ncp_server
*server
)
202 __abort_ncp_connection(server
);
205 static int ncpdgram_send(struct socket
*sock
, struct ncp_request_reply
*req
)
208 /* sock_sendmsg updates iov pointers for us :-( */
209 memcpy(vec
, req
->tx_ciov
, req
->tx_iovlen
* sizeof(vec
[0]));
210 return do_send(sock
, vec
, req
->tx_iovlen
,
211 req
->tx_totallen
, MSG_DONTWAIT
);
214 static void __ncptcp_try_send(struct ncp_server
*server
)
216 struct ncp_request_reply
*rq
;
221 rq
= server
->tx
.creq
;
225 /* sock_sendmsg updates iov pointers for us :-( */
226 memcpy(iovc
, rq
->tx_ciov
, rq
->tx_iovlen
* sizeof(iov
[0]));
227 result
= do_send(server
->ncp_sock
, iovc
, rq
->tx_iovlen
,
228 rq
->tx_totallen
, MSG_NOSIGNAL
| MSG_DONTWAIT
);
230 if (result
== -EAGAIN
)
234 printk(KERN_ERR
"ncpfs: tcp: Send failed: %d\n", result
);
235 __ncp_abort_request(server
, rq
, result
);
238 if (result
>= rq
->tx_totallen
) {
239 server
->rcv
.creq
= rq
;
240 server
->tx
.creq
= NULL
;
243 rq
->tx_totallen
-= result
;
245 while (iov
->iov_len
<= result
) {
246 result
-= iov
->iov_len
;
250 iov
->iov_base
+= result
;
251 iov
->iov_len
-= result
;
255 static inline void ncp_init_header(struct ncp_server
*server
, struct ncp_request_reply
*req
, struct ncp_request_header
*h
)
257 req
->status
= RQ_INPROGRESS
;
258 h
->conn_low
= server
->connection
;
259 h
->conn_high
= server
->connection
>> 8;
260 h
->sequence
= ++server
->sequence
;
263 static void ncpdgram_start_request(struct ncp_server
*server
, struct ncp_request_reply
*req
)
266 struct ncp_request_header
* h
;
268 req
->tx_ciov
= req
->tx_iov
+ 1;
270 h
= req
->tx_iov
[1].iov_base
;
271 ncp_init_header(server
, req
, h
);
272 signlen
= sign_packet(server
, req
->tx_iov
[1].iov_base
+ sizeof(struct ncp_request_header
) - 1,
273 req
->tx_iov
[1].iov_len
- sizeof(struct ncp_request_header
) + 1,
274 cpu_to_le32(req
->tx_totallen
), req
->sign
);
276 req
->tx_ciov
[1].iov_base
= req
->sign
;
277 req
->tx_ciov
[1].iov_len
= signlen
;
279 req
->tx_totallen
+= signlen
;
281 server
->rcv
.creq
= req
;
282 server
->timeout_last
= server
->m
.time_out
;
283 server
->timeout_retries
= server
->m
.retry_count
;
284 ncpdgram_send(server
->ncp_sock
, req
);
285 mod_timer(&server
->timeout_tm
, jiffies
+ server
->m
.time_out
);
288 #define NCP_TCP_XMIT_MAGIC (0x446D6454)
289 #define NCP_TCP_XMIT_VERSION (1)
290 #define NCP_TCP_RCVD_MAGIC (0x744E6350)
292 static void ncptcp_start_request(struct ncp_server
*server
, struct ncp_request_reply
*req
)
295 struct ncp_request_header
* h
;
297 req
->tx_ciov
= req
->tx_iov
;
298 h
= req
->tx_iov
[1].iov_base
;
299 ncp_init_header(server
, req
, h
);
300 signlen
= sign_packet(server
, req
->tx_iov
[1].iov_base
+ sizeof(struct ncp_request_header
) - 1,
301 req
->tx_iov
[1].iov_len
- sizeof(struct ncp_request_header
) + 1,
302 cpu_to_be32(req
->tx_totallen
+ 24), req
->sign
+ 4) + 16;
304 req
->sign
[0] = htonl(NCP_TCP_XMIT_MAGIC
);
305 req
->sign
[1] = htonl(req
->tx_totallen
+ signlen
);
306 req
->sign
[2] = htonl(NCP_TCP_XMIT_VERSION
);
307 req
->sign
[3] = htonl(req
->datalen
+ 8);
308 req
->tx_iov
[0].iov_base
= req
->sign
;
309 req
->tx_iov
[0].iov_len
= signlen
;
311 req
->tx_totallen
+= signlen
;
313 server
->tx
.creq
= req
;
314 __ncptcp_try_send(server
);
317 static inline void __ncp_start_request(struct ncp_server
*server
, struct ncp_request_reply
*req
)
319 /* we copy the data so that we do not depend on the caller
321 memcpy(server
->txbuf
, req
->tx_iov
[1].iov_base
, req
->tx_iov
[1].iov_len
);
322 req
->tx_iov
[1].iov_base
= server
->txbuf
;
324 if (server
->ncp_sock
->type
== SOCK_STREAM
)
325 ncptcp_start_request(server
, req
);
327 ncpdgram_start_request(server
, req
);
330 static int ncp_add_request(struct ncp_server
*server
, struct ncp_request_reply
*req
)
332 mutex_lock(&server
->rcv
.creq_mutex
);
333 if (!ncp_conn_valid(server
)) {
334 mutex_unlock(&server
->rcv
.creq_mutex
);
335 printk(KERN_ERR
"ncpfs: tcp: Server died\n");
339 if (server
->tx
.creq
|| server
->rcv
.creq
) {
340 req
->status
= RQ_QUEUED
;
341 list_add_tail(&req
->req
, &server
->tx
.requests
);
342 mutex_unlock(&server
->rcv
.creq_mutex
);
345 __ncp_start_request(server
, req
);
346 mutex_unlock(&server
->rcv
.creq_mutex
);
350 static void __ncp_next_request(struct ncp_server
*server
)
352 struct ncp_request_reply
*req
;
354 server
->rcv
.creq
= NULL
;
355 if (list_empty(&server
->tx
.requests
)) {
358 req
= list_entry(server
->tx
.requests
.next
, struct ncp_request_reply
, req
);
359 list_del_init(&req
->req
);
360 __ncp_start_request(server
, req
);
363 static void info_server(struct ncp_server
*server
, unsigned int id
, const void * data
, size_t len
)
365 if (server
->info_sock
) {
369 hdr
[0] = cpu_to_be32(len
+ 8);
370 hdr
[1] = cpu_to_be32(id
);
372 iov
[0].iov_base
= hdr
;
374 iov
[1].iov_base
= (void *) data
;
375 iov
[1].iov_len
= len
;
377 do_send(server
->info_sock
, iov
, 2, len
+ 8, MSG_NOSIGNAL
);
381 void ncpdgram_rcv_proc(struct work_struct
*work
)
383 struct ncp_server
*server
=
384 container_of(work
, struct ncp_server
, rcv
.tq
);
387 sock
= server
->ncp_sock
;
390 struct ncp_reply_header reply
;
393 result
= _recv(sock
, &reply
, sizeof(reply
), MSG_PEEK
| MSG_DONTWAIT
);
397 if (result
>= sizeof(reply
)) {
398 struct ncp_request_reply
*req
;
400 if (reply
.type
== NCP_WATCHDOG
) {
401 unsigned char buf
[10];
403 if (server
->connection
!= get_conn_number(&reply
)) {
406 result
= _recv(sock
, buf
, sizeof(buf
), MSG_DONTWAIT
);
408 DPRINTK("recv failed with %d\n", result
);
412 DPRINTK("too short (%u) watchdog packet\n", result
);
416 DPRINTK("bad signature (%02X) in watchdog packet\n", buf
[9]);
420 _send(sock
, buf
, sizeof(buf
));
423 if (reply
.type
!= NCP_POSITIVE_ACK
&& reply
.type
!= NCP_REPLY
) {
424 result
= _recv(sock
, server
->unexpected_packet
.data
, sizeof(server
->unexpected_packet
.data
), MSG_DONTWAIT
);
428 info_server(server
, 0, server
->unexpected_packet
.data
, result
);
431 mutex_lock(&server
->rcv
.creq_mutex
);
432 req
= server
->rcv
.creq
;
433 if (req
&& (req
->tx_type
== NCP_ALLOC_SLOT_REQUEST
|| (server
->sequence
== reply
.sequence
&&
434 server
->connection
== get_conn_number(&reply
)))) {
435 if (reply
.type
== NCP_POSITIVE_ACK
) {
436 server
->timeout_retries
= server
->m
.retry_count
;
437 server
->timeout_last
= NCP_MAX_RPC_TIMEOUT
;
438 mod_timer(&server
->timeout_tm
, jiffies
+ NCP_MAX_RPC_TIMEOUT
);
439 } else if (reply
.type
== NCP_REPLY
) {
440 result
= _recv(sock
, server
->rxbuf
, req
->datalen
, MSG_DONTWAIT
);
441 #ifdef CONFIG_NCPFS_PACKET_SIGNING
442 if (result
>= 0 && server
->sign_active
&& req
->tx_type
!= NCP_DEALLOC_SLOT_REQUEST
) {
443 if (result
< 8 + 8) {
449 hdrl
= sock
->sk
->sk_family
== AF_INET
? 8 : 6;
450 if (sign_verify_reply(server
, server
->rxbuf
+ hdrl
, result
- hdrl
, cpu_to_le32(result
), server
->rxbuf
+ result
)) {
451 printk(KERN_INFO
"ncpfs: Signature violation\n");
457 del_timer(&server
->timeout_tm
);
458 server
->rcv
.creq
= NULL
;
459 ncp_finish_request(server
, req
, result
);
460 __ncp_next_request(server
);
461 mutex_unlock(&server
->rcv
.creq_mutex
);
465 mutex_unlock(&server
->rcv
.creq_mutex
);
468 _recv(sock
, &reply
, sizeof(reply
), MSG_DONTWAIT
);
472 static void __ncpdgram_timeout_proc(struct ncp_server
*server
)
474 /* If timer is pending, we are processing another request... */
475 if (!timer_pending(&server
->timeout_tm
)) {
476 struct ncp_request_reply
* req
;
478 req
= server
->rcv
.creq
;
482 if (server
->m
.flags
& NCP_MOUNT_SOFT
) {
483 if (server
->timeout_retries
-- == 0) {
484 __ncp_abort_request(server
, req
, -ETIMEDOUT
);
489 ncpdgram_send(server
->ncp_sock
, req
);
490 timeout
= server
->timeout_last
<< 1;
491 if (timeout
> NCP_MAX_RPC_TIMEOUT
) {
492 timeout
= NCP_MAX_RPC_TIMEOUT
;
494 server
->timeout_last
= timeout
;
495 mod_timer(&server
->timeout_tm
, jiffies
+ timeout
);
500 void ncpdgram_timeout_proc(struct work_struct
*work
)
502 struct ncp_server
*server
=
503 container_of(work
, struct ncp_server
, timeout_tq
);
504 mutex_lock(&server
->rcv
.creq_mutex
);
505 __ncpdgram_timeout_proc(server
);
506 mutex_unlock(&server
->rcv
.creq_mutex
);
509 static int do_tcp_rcv(struct ncp_server
*server
, void *buffer
, size_t len
)
514 result
= _recv(server
->ncp_sock
, buffer
, len
, MSG_DONTWAIT
);
516 static unsigned char dummy
[1024];
518 if (len
> sizeof(dummy
)) {
521 result
= _recv(server
->ncp_sock
, dummy
, len
, MSG_DONTWAIT
);
527 printk(KERN_ERR
"ncpfs: tcp: bug in recvmsg (%u > %Zu)\n", result
, len
);
533 static int __ncptcp_rcv_proc(struct ncp_server
*server
)
535 /* We have to check the result, so store the complete header */
538 struct ncp_request_reply
*req
;
542 while (server
->rcv
.len
) {
543 result
= do_tcp_rcv(server
, server
->rcv
.ptr
, server
->rcv
.len
);
544 if (result
== -EAGAIN
) {
548 req
= server
->rcv
.creq
;
550 __ncp_abort_request(server
, req
, -EIO
);
552 __ncptcp_abort(server
);
555 printk(KERN_ERR
"ncpfs: tcp: error in recvmsg: %d\n", result
);
557 DPRINTK(KERN_ERR
"ncpfs: tcp: EOF\n");
561 if (server
->rcv
.ptr
) {
562 server
->rcv
.ptr
+= result
;
564 server
->rcv
.len
-= result
;
566 switch (server
->rcv
.state
) {
568 if (server
->rcv
.buf
.magic
!= htonl(NCP_TCP_RCVD_MAGIC
)) {
569 printk(KERN_ERR
"ncpfs: tcp: Unexpected reply type %08X\n", ntohl(server
->rcv
.buf
.magic
));
570 __ncptcp_abort(server
);
573 datalen
= ntohl(server
->rcv
.buf
.len
) & 0x0FFFFFFF;
575 printk(KERN_ERR
"ncpfs: tcp: Unexpected reply len %d\n", datalen
);
576 __ncptcp_abort(server
);
579 #ifdef CONFIG_NCPFS_PACKET_SIGNING
580 if (server
->sign_active
) {
582 printk(KERN_ERR
"ncpfs: tcp: Unexpected reply len %d\n", datalen
);
583 __ncptcp_abort(server
);
586 server
->rcv
.buf
.len
= datalen
- 8;
587 server
->rcv
.ptr
= (unsigned char*)&server
->rcv
.buf
.p1
;
589 server
->rcv
.state
= 4;
593 type
= ntohs(server
->rcv
.buf
.type
);
594 #ifdef CONFIG_NCPFS_PACKET_SIGNING
597 if (type
!= NCP_REPLY
) {
598 if (datalen
- 8 <= sizeof(server
->unexpected_packet
.data
)) {
599 *(__u16
*)(server
->unexpected_packet
.data
) = htons(type
);
600 server
->unexpected_packet
.len
= datalen
- 8;
602 server
->rcv
.state
= 5;
603 server
->rcv
.ptr
= server
->unexpected_packet
.data
+ 2;
604 server
->rcv
.len
= datalen
- 10;
607 DPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", type
);
609 server
->rcv
.state
= 2;
611 server
->rcv
.ptr
= NULL
;
612 server
->rcv
.len
= datalen
- 10;
615 req
= server
->rcv
.creq
;
617 DPRINTK(KERN_ERR
"ncpfs: Reply without appropriate request\n");
620 if (datalen
> req
->datalen
+ 8) {
621 printk(KERN_ERR
"ncpfs: tcp: Unexpected reply len %d (expected at most %Zd)\n", datalen
, req
->datalen
+ 8);
622 server
->rcv
.state
= 3;
625 req
->datalen
= datalen
- 8;
626 ((struct ncp_reply_header
*)server
->rxbuf
)->type
= NCP_REPLY
;
627 server
->rcv
.ptr
= server
->rxbuf
+ 2;
628 server
->rcv
.len
= datalen
- 10;
629 server
->rcv
.state
= 1;
631 #ifdef CONFIG_NCPFS_PACKET_SIGNING
633 datalen
= server
->rcv
.buf
.len
;
634 type
= ntohs(server
->rcv
.buf
.type2
);
638 req
= server
->rcv
.creq
;
639 if (req
->tx_type
!= NCP_ALLOC_SLOT_REQUEST
) {
640 if (((struct ncp_reply_header
*)server
->rxbuf
)->sequence
!= server
->sequence
) {
641 printk(KERN_ERR
"ncpfs: tcp: Bad sequence number\n");
642 __ncp_abort_request(server
, req
, -EIO
);
645 if ((((struct ncp_reply_header
*)server
->rxbuf
)->conn_low
| (((struct ncp_reply_header
*)server
->rxbuf
)->conn_high
<< 8)) != server
->connection
) {
646 printk(KERN_ERR
"ncpfs: tcp: Connection number mismatch\n");
647 __ncp_abort_request(server
, req
, -EIO
);
651 #ifdef CONFIG_NCPFS_PACKET_SIGNING
652 if (server
->sign_active
&& req
->tx_type
!= NCP_DEALLOC_SLOT_REQUEST
) {
653 if (sign_verify_reply(server
, server
->rxbuf
+ 6, req
->datalen
- 6, cpu_to_be32(req
->datalen
+ 16), &server
->rcv
.buf
.type
)) {
654 printk(KERN_ERR
"ncpfs: tcp: Signature violation\n");
655 __ncp_abort_request(server
, req
, -EIO
);
660 ncp_finish_request(server
, req
, req
->datalen
);
662 __ncp_next_request(server
);
665 server
->rcv
.ptr
= (unsigned char*)&server
->rcv
.buf
;
666 server
->rcv
.len
= 10;
667 server
->rcv
.state
= 0;
670 ncp_finish_request(server
, server
->rcv
.creq
, -EIO
);
673 info_server(server
, 0, server
->unexpected_packet
.data
, server
->unexpected_packet
.len
);
679 void ncp_tcp_rcv_proc(struct work_struct
*work
)
681 struct ncp_server
*server
=
682 container_of(work
, struct ncp_server
, rcv
.tq
);
684 mutex_lock(&server
->rcv
.creq_mutex
);
685 __ncptcp_rcv_proc(server
);
686 mutex_unlock(&server
->rcv
.creq_mutex
);
689 void ncp_tcp_tx_proc(struct work_struct
*work
)
691 struct ncp_server
*server
=
692 container_of(work
, struct ncp_server
, tx
.tq
);
694 mutex_lock(&server
->rcv
.creq_mutex
);
695 __ncptcp_try_send(server
);
696 mutex_unlock(&server
->rcv
.creq_mutex
);
699 static int do_ncp_rpc_call(struct ncp_server
*server
, int size
,
700 unsigned char* reply_buf
, int max_reply_size
)
703 struct ncp_request_reply
*req
;
705 req
= ncp_alloc_req();
709 req
->reply_buf
= reply_buf
;
710 req
->datalen
= max_reply_size
;
711 req
->tx_iov
[1].iov_base
= server
->packet
;
712 req
->tx_iov
[1].iov_len
= size
;
714 req
->tx_totallen
= size
;
715 req
->tx_type
= *(u_int16_t
*)server
->packet
;
717 result
= ncp_add_request(server
, req
);
721 if (wait_event_interruptible(req
->wq
, req
->status
== RQ_DONE
)) {
722 ncp_abort_request(server
, req
, -EINTR
);
727 result
= req
->result
;
736 * We need the server to be locked here, so check!
739 static int ncp_do_request(struct ncp_server
*server
, int size
,
740 void* reply
, int max_reply_size
)
744 if (server
->lock
== 0) {
745 printk(KERN_ERR
"ncpfs: Server not locked!\n");
748 if (!ncp_conn_valid(server
)) {
749 printk(KERN_ERR
"ncpfs: Connection invalid!\n");
754 unsigned long mask
, flags
;
756 spin_lock_irqsave(¤t
->sighand
->siglock
, flags
);
757 old_set
= current
->blocked
;
758 if (current
->flags
& PF_EXITING
)
761 mask
= sigmask(SIGKILL
);
762 if (server
->m
.flags
& NCP_MOUNT_INTR
) {
763 if (current
->sighand
->action
[SIGINT
- 1].sa
.sa_handler
== SIG_DFL
)
764 mask
|= sigmask(SIGINT
);
765 if (current
->sighand
->action
[SIGQUIT
- 1].sa
.sa_handler
== SIG_DFL
)
766 mask
|= sigmask(SIGQUIT
);
768 siginitsetinv(¤t
->blocked
, mask
);
770 spin_unlock_irqrestore(¤t
->sighand
->siglock
, flags
);
772 result
= do_ncp_rpc_call(server
, size
, reply
, max_reply_size
);
774 spin_lock_irqsave(¤t
->sighand
->siglock
, flags
);
775 current
->blocked
= old_set
;
777 spin_unlock_irqrestore(¤t
->sighand
->siglock
, flags
);
780 DDPRINTK("do_ncp_rpc_call returned %d\n", result
);
785 /* ncp_do_request assures that at least a complete reply header is
786 * received. It assumes that server->current_size contains the ncp
789 int ncp_request2(struct ncp_server
*server
, int function
,
792 struct ncp_request_header
*h
;
793 struct ncp_reply_header
* reply
= rpl
;
796 h
= (struct ncp_request_header
*) (server
->packet
);
797 if (server
->has_subfunction
!= 0) {
798 *(__u16
*) & (h
->data
[0]) = htons(server
->current_size
- sizeof(*h
) - 2);
800 h
->type
= NCP_REQUEST
;
802 * The server shouldn't know or care what task is making a
803 * request, so we always use the same task number.
805 h
->task
= 2; /* (current->pid) & 0xff; */
806 h
->function
= function
;
808 result
= ncp_do_request(server
, server
->current_size
, reply
, size
);
810 DPRINTK("ncp_request_error: %d\n", result
);
813 server
->completion
= reply
->completion_code
;
814 server
->conn_status
= reply
->connection_state
;
815 server
->reply_size
= result
;
816 server
->ncp_reply_size
= result
- sizeof(struct ncp_reply_header
);
818 result
= reply
->completion_code
;
821 PPRINTK("ncp_request: completion code=%x\n", result
);
826 int ncp_connect(struct ncp_server
*server
)
828 struct ncp_request_header
*h
;
831 server
->connection
= 0xFFFF;
832 server
->sequence
= 255;
834 h
= (struct ncp_request_header
*) (server
->packet
);
835 h
->type
= NCP_ALLOC_SLOT_REQUEST
;
836 h
->task
= 2; /* see above */
839 result
= ncp_do_request(server
, sizeof(*h
), server
->packet
, server
->packet_size
);
842 server
->connection
= h
->conn_low
+ (h
->conn_high
* 256);
848 int ncp_disconnect(struct ncp_server
*server
)
850 struct ncp_request_header
*h
;
852 h
= (struct ncp_request_header
*) (server
->packet
);
853 h
->type
= NCP_DEALLOC_SLOT_REQUEST
;
854 h
->task
= 2; /* see above */
857 return ncp_do_request(server
, sizeof(*h
), server
->packet
, server
->packet_size
);
860 void ncp_lock_server(struct ncp_server
*server
)
862 mutex_lock(&server
->mutex
);
864 printk(KERN_WARNING
"ncp_lock_server: was locked!\n");
868 void ncp_unlock_server(struct ncp_server
*server
)
871 printk(KERN_WARNING
"ncp_unlock_server: was not locked!\n");
875 mutex_unlock(&server
->mutex
);