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 <asm/uaccess.h>
19 #include <linux/net.h>
21 #include <linux/netdevice.h>
22 #include <linux/signal.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
)
50 vec
.iov_base
= (void *) buff
;
52 return do_send(sock
, &vec
, 1, len
, 0);
55 struct ncp_request_reply
{
58 struct ncp_reply_header
* reply_buf
;
61 enum { RQ_DONE
, RQ_INPROGRESS
, RQ_QUEUED
, RQ_IDLE
} status
;
65 struct kvec tx_iov
[3];
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,
92 server
->write_space(sk
);
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
);
124 ncp_finish_request(req
, -EIO
);
127 req
= server
->rcv
.creq
;
129 server
->rcv
.creq
= NULL
;
130 if (req
== aborted
) {
131 ncp_finish_request(req
, err
);
133 ncp_finish_request(req
, -EIO
);
135 server
->rcv
.ptr
= NULL
;
136 server
->rcv
.state
= 0;
138 req
= server
->tx
.creq
;
140 server
->tx
.creq
= NULL
;
141 if (req
== aborted
) {
142 ncp_finish_request(req
, err
);
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
) {
162 list_del_init(&req
->req
);
163 ncp_finish_request(req
, err
);
166 __abort_ncp_connection(server
, req
, err
);
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
)
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
;
199 rq
= server
->tx
.creq
;
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
)
212 printk(KERN_ERR
"ncpfs: tcp: Send failed: %d\n", result
);
213 __ncp_abort_request(server
, rq
, result
);
216 if (result
>= rq
->tx_totallen
) {
217 server
->rcv
.creq
= rq
;
218 server
->tx
.creq
= NULL
;
221 rq
->tx_totallen
-= result
;
223 while (iov
->iov_len
<= result
) {
224 result
-= iov
->iov_len
;
228 iov
->iov_base
+= result
;
229 iov
->iov_len
-= result
;
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
)
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
);
254 req
->tx_ciov
[1].iov_base
= req
->sign
;
255 req
->tx_ciov
[1].iov_len
= signlen
;
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
)
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
;
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
);
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");
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
);
317 __ncp_start_request(server
, req
);
318 mutex_unlock(&server
->rcv
.creq_mutex
);
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
)) {
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
) {
341 hdr
[0] = cpu_to_be32(len
+ 8);
342 hdr
[1] = cpu_to_be32(id
);
344 iov
[0].iov_base
= hdr
;
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
);
359 sock
= server
->ncp_sock
;
362 struct ncp_reply_header reply
;
365 result
= _recv(sock
, &reply
, sizeof(reply
), MSG_PEEK
| MSG_DONTWAIT
);
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
)) {
378 result
= _recv(sock
, buf
, sizeof(buf
), MSG_DONTWAIT
);
380 DPRINTK("recv failed with %d\n", result
);
384 DPRINTK("too short (%u) watchdog packet\n", result
);
388 DPRINTK("bad signature (%02X) in watchdog packet\n", buf
[9]);
392 _send(sock
, buf
, sizeof(buf
));
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
);
400 info_server(server
, 0, server
->unexpected_packet
.data
, result
);
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) {
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");
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
);
437 mutex_unlock(&server
->rcv
.creq_mutex
);
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
;
454 if (server
->m
.flags
& NCP_MOUNT_SOFT
) {
455 if (server
->timeout_retries
-- == 0) {
456 __ncp_abort_request(server
, req
, -ETIMEDOUT
);
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
)
492 result
= _recv(server
->ncp_sock
, buffer
, len
, MSG_DONTWAIT
);
494 static unsigned char dummy
[1024];
496 if (len
> sizeof(dummy
)) {
499 result
= _recv(server
->ncp_sock
, dummy
, len
, MSG_DONTWAIT
);
505 printk(KERN_ERR
"ncpfs: tcp: bug in recvmsg (%u > %Zu)\n", result
, len
);
511 static int __ncptcp_rcv_proc(struct ncp_server
*server
)
513 /* We have to check the result, so store the complete header */
516 struct ncp_request_reply
*req
;
520 while (server
->rcv
.len
) {
521 result
= do_tcp_rcv(server
, server
->rcv
.ptr
, server
->rcv
.len
);
522 if (result
== -EAGAIN
) {
526 req
= server
->rcv
.creq
;
528 __ncp_abort_request(server
, req
, -EIO
);
530 __ncptcp_abort(server
);
533 printk(KERN_ERR
"ncpfs: tcp: error in recvmsg: %d\n", result
);
535 DPRINTK(KERN_ERR
"ncpfs: tcp: EOF\n");
539 if (server
->rcv
.ptr
) {
540 server
->rcv
.ptr
+= result
;
542 server
->rcv
.len
-= result
;
544 switch (server
->rcv
.state
) {
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
);
551 datalen
= ntohl(server
->rcv
.buf
.len
) & 0x0FFFFFFF;
553 printk(KERN_ERR
"ncpfs: tcp: Unexpected reply len %d\n", datalen
);
554 __ncptcp_abort(server
);
557 #ifdef CONFIG_NCPFS_PACKET_SIGNING
558 if (server
->sign_active
) {
560 printk(KERN_ERR
"ncpfs: tcp: Unexpected reply len %d\n", datalen
);
561 __ncptcp_abort(server
);
564 server
->rcv
.buf
.len
= datalen
- 8;
565 server
->rcv
.ptr
= (unsigned char*)&server
->rcv
.buf
.p1
;
567 server
->rcv
.state
= 4;
571 type
= ntohs(server
->rcv
.buf
.type
);
572 #ifdef CONFIG_NCPFS_PACKET_SIGNING
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;
585 DPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", type
);
587 server
->rcv
.state
= 2;
589 server
->rcv
.ptr
= NULL
;
590 server
->rcv
.len
= datalen
- 10;
593 req
= server
->rcv
.creq
;
595 DPRINTK(KERN_ERR
"ncpfs: Reply without appropriate request\n");
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;
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;
609 #ifdef CONFIG_NCPFS_PACKET_SIGNING
611 datalen
= server
->rcv
.buf
.len
;
612 type
= ntohs(server
->rcv
.buf
.type2
);
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
);
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
);
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
);
638 ncp_finish_request(req
, req
->datalen
);
640 __ncp_next_request(server
);
643 server
->rcv
.ptr
= (unsigned char*)&server
->rcv
.buf
;
644 server
->rcv
.len
= 10;
645 server
->rcv
.state
= 0;
648 ncp_finish_request(server
->rcv
.creq
, -EIO
);
651 info_server(server
, 0, server
->unexpected_packet
.data
, server
->unexpected_packet
.len
);
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
)
681 struct ncp_request_reply 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
;
689 req
.tx_totallen
= size
;
690 req
.tx_type
= *(u_int16_t
*)server
->packet
;
692 result
= ncp_add_request(server
, &req
);
696 if (wait_event_interruptible(req
.wq
, req
.status
== RQ_DONE
)) {
697 ncp_abort_request(server
, &req
, -EIO
);
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
)
711 if (server
->lock
== 0) {
712 printk(KERN_ERR
"ncpfs: Server not locked!\n");
715 if (!ncp_conn_valid(server
)) {
716 printk(KERN_ERR
"ncpfs: Connection invalid!\n");
721 unsigned long mask
, flags
;
723 spin_lock_irqsave(¤t
->sighand
->siglock
, flags
);
724 old_set
= current
->blocked
;
725 if (current
->flags
& PF_EXITING
)
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(¤t
->blocked
, mask
);
742 spin_unlock_irqrestore(¤t
->sighand
->siglock
, flags
);
744 result
= do_ncp_rpc_call(server
, size
, reply
, max_reply_size
);
746 spin_lock_irqsave(¤t
->sighand
->siglock
, flags
);
747 current
->blocked
= old_set
;
749 spin_unlock_irqrestore(¤t
->sighand
->siglock
, flags
);
752 DDPRINTK("do_ncp_rpc_call returned %d\n", result
);
755 /* There was a problem with I/O, so the connections is
756 * no longer usable. */
757 ncp_invalidate_conn(server
);
762 /* ncp_do_request assures that at least a complete reply header is
763 * received. It assumes that server->current_size contains the ncp
766 int ncp_request2(struct ncp_server
*server
, int function
,
769 struct ncp_request_header
*h
;
770 struct ncp_reply_header
* reply
= rpl
;
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
);
787 DPRINTK("ncp_request_error: %d\n", result
);
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
;
798 PPRINTK("ncp_request: completion code=%x\n", result
);
803 int ncp_connect(struct ncp_server
*server
)
805 struct ncp_request_header
*h
;
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 */
816 result
= ncp_do_request(server
, sizeof(*h
), server
->packet
, server
->packet_size
);
819 server
->connection
= h
->conn_low
+ (h
->conn_high
* 256);
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 */
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
);
841 printk(KERN_WARNING
"ncp_lock_server: was locked!\n");
845 void ncp_unlock_server(struct ncp_server
*server
)
848 printk(KERN_WARNING
"ncp_unlock_server: was not locked!\n");
852 mutex_unlock(&server
->mutex
);