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
11 #include <linux/config.h>
13 #include <linux/time.h>
14 #include <linux/errno.h>
15 #include <linux/socket.h>
16 #include <linux/fcntl.h>
17 #include <linux/stat.h>
18 #include <asm/uaccess.h>
20 #include <linux/net.h>
22 #include <linux/netdevice.h>
23 #include <linux/signal.h>
26 #include <linux/ipx.h>
27 #include <linux/poll.h>
28 #include <linux/file.h>
30 #include <linux/ncp_fs.h>
32 #include "ncpsign_kernel.h"
34 static int _recv(struct socket
*sock
, void *buf
, int size
, unsigned flags
)
36 struct msghdr msg
= {NULL
, };
37 struct kvec iov
= {buf
, size
};
38 return kernel_recvmsg(sock
, &msg
, &iov
, 1, size
, flags
);
41 static inline int do_send(struct socket
*sock
, struct kvec
*vec
, int count
,
42 int len
, unsigned flags
)
44 struct msghdr msg
= { .msg_flags
= flags
};
45 return kernel_sendmsg(sock
, &msg
, vec
, count
, len
);
48 static int _send(struct socket
*sock
, const void *buff
, int len
)
51 vec
.iov_base
= (void *) buff
;
53 return do_send(sock
, &vec
, 1, len
, 0);
56 struct ncp_request_reply
{
59 struct ncp_reply_header
* reply_buf
;
62 enum { RQ_DONE
, RQ_INPROGRESS
, RQ_QUEUED
, RQ_IDLE
} status
;
66 struct kvec tx_iov
[3];
71 void ncp_tcp_data_ready(struct sock
*sk
, int len
)
73 struct ncp_server
*server
= sk
->sk_user_data
;
75 server
->data_ready(sk
, len
);
76 schedule_work(&server
->rcv
.tq
);
79 void ncp_tcp_error_report(struct sock
*sk
)
81 struct ncp_server
*server
= sk
->sk_user_data
;
83 server
->error_report(sk
);
84 schedule_work(&server
->rcv
.tq
);
87 void ncp_tcp_write_space(struct sock
*sk
)
89 struct ncp_server
*server
= sk
->sk_user_data
;
91 /* We do not need any locking: we first set tx.creq, and then we do sendmsg,
93 server
->write_space(sk
);
95 schedule_work(&server
->tx
.tq
);
98 void ncpdgram_timeout_call(unsigned long v
)
100 struct ncp_server
*server
= (void*)v
;
102 schedule_work(&server
->timeout_tq
);
105 static inline void ncp_finish_request(struct ncp_request_reply
*req
, int result
)
107 req
->result
= result
;
108 req
->status
= RQ_DONE
;
109 wake_up_all(&req
->wq
);
112 static void __abort_ncp_connection(struct ncp_server
*server
, struct ncp_request_reply
*aborted
, int err
)
114 struct ncp_request_reply
*req
;
116 ncp_invalidate_conn(server
);
117 del_timer(&server
->timeout_tm
);
118 while (!list_empty(&server
->tx
.requests
)) {
119 req
= list_entry(server
->tx
.requests
.next
, struct ncp_request_reply
, req
);
121 list_del_init(&req
->req
);
122 if (req
== aborted
) {
123 ncp_finish_request(req
, err
);
125 ncp_finish_request(req
, -EIO
);
128 req
= server
->rcv
.creq
;
130 server
->rcv
.creq
= NULL
;
131 if (req
== aborted
) {
132 ncp_finish_request(req
, err
);
134 ncp_finish_request(req
, -EIO
);
136 server
->rcv
.ptr
= NULL
;
137 server
->rcv
.state
= 0;
139 req
= server
->tx
.creq
;
141 server
->tx
.creq
= NULL
;
142 if (req
== aborted
) {
143 ncp_finish_request(req
, err
);
145 ncp_finish_request(req
, -EIO
);
150 static inline int get_conn_number(struct ncp_reply_header
*rp
)
152 return rp
->conn_low
| (rp
->conn_high
<< 8);
155 static inline void __ncp_abort_request(struct ncp_server
*server
, struct ncp_request_reply
*req
, int err
)
157 /* If req is done, we got signal, but we also received answer... */
158 switch (req
->status
) {
163 list_del_init(&req
->req
);
164 ncp_finish_request(req
, err
);
167 __abort_ncp_connection(server
, req
, err
);
172 static inline void ncp_abort_request(struct ncp_server
*server
, struct ncp_request_reply
*req
, int err
)
174 mutex_lock(&server
->rcv
.creq_mutex
);
175 __ncp_abort_request(server
, req
, err
);
176 mutex_unlock(&server
->rcv
.creq_mutex
);
179 static inline void __ncptcp_abort(struct ncp_server
*server
)
181 __abort_ncp_connection(server
, NULL
, 0);
184 static int ncpdgram_send(struct socket
*sock
, struct ncp_request_reply
*req
)
187 /* sock_sendmsg updates iov pointers for us :-( */
188 memcpy(vec
, req
->tx_ciov
, req
->tx_iovlen
* sizeof(vec
[0]));
189 return do_send(sock
, vec
, req
->tx_iovlen
,
190 req
->tx_totallen
, MSG_DONTWAIT
);
193 static void __ncptcp_try_send(struct ncp_server
*server
)
195 struct ncp_request_reply
*rq
;
200 rq
= server
->tx
.creq
;
204 /* sock_sendmsg updates iov pointers for us :-( */
205 memcpy(iovc
, rq
->tx_ciov
, rq
->tx_iovlen
* sizeof(iov
[0]));
206 result
= do_send(server
->ncp_sock
, iovc
, rq
->tx_iovlen
,
207 rq
->tx_totallen
, MSG_NOSIGNAL
| MSG_DONTWAIT
);
209 if (result
== -EAGAIN
)
213 printk(KERN_ERR
"ncpfs: tcp: Send failed: %d\n", result
);
214 __ncp_abort_request(server
, rq
, result
);
217 if (result
>= rq
->tx_totallen
) {
218 server
->rcv
.creq
= rq
;
219 server
->tx
.creq
= NULL
;
222 rq
->tx_totallen
-= result
;
224 while (iov
->iov_len
<= result
) {
225 result
-= iov
->iov_len
;
229 iov
->iov_base
+= result
;
230 iov
->iov_len
-= result
;
234 static inline void ncp_init_header(struct ncp_server
*server
, struct ncp_request_reply
*req
, struct ncp_request_header
*h
)
236 req
->status
= RQ_INPROGRESS
;
237 h
->conn_low
= server
->connection
;
238 h
->conn_high
= server
->connection
>> 8;
239 h
->sequence
= ++server
->sequence
;
242 static void ncpdgram_start_request(struct ncp_server
*server
, struct ncp_request_reply
*req
)
245 struct ncp_request_header
* h
;
247 req
->tx_ciov
= req
->tx_iov
+ 1;
249 h
= req
->tx_iov
[1].iov_base
;
250 ncp_init_header(server
, req
, h
);
251 signlen
= sign_packet(server
, req
->tx_iov
[1].iov_base
+ sizeof(struct ncp_request_header
) - 1,
252 req
->tx_iov
[1].iov_len
- sizeof(struct ncp_request_header
) + 1,
253 cpu_to_le32(req
->tx_totallen
), req
->sign
);
255 req
->tx_ciov
[1].iov_base
= req
->sign
;
256 req
->tx_ciov
[1].iov_len
= signlen
;
258 req
->tx_totallen
+= 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
);
267 #define NCP_TCP_XMIT_MAGIC (0x446D6454)
268 #define NCP_TCP_XMIT_VERSION (1)
269 #define NCP_TCP_RCVD_MAGIC (0x744E6350)
271 static void ncptcp_start_request(struct ncp_server
*server
, struct ncp_request_reply
*req
)
274 struct ncp_request_header
* h
;
276 req
->tx_ciov
= req
->tx_iov
;
277 h
= req
->tx_iov
[1].iov_base
;
278 ncp_init_header(server
, req
, h
);
279 signlen
= sign_packet(server
, req
->tx_iov
[1].iov_base
+ sizeof(struct ncp_request_header
) - 1,
280 req
->tx_iov
[1].iov_len
- sizeof(struct ncp_request_header
) + 1,
281 cpu_to_be32(req
->tx_totallen
+ 24), req
->sign
+ 4) + 16;
283 req
->sign
[0] = htonl(NCP_TCP_XMIT_MAGIC
);
284 req
->sign
[1] = htonl(req
->tx_totallen
+ signlen
);
285 req
->sign
[2] = htonl(NCP_TCP_XMIT_VERSION
);
286 req
->sign
[3] = htonl(req
->datalen
+ 8);
287 req
->tx_iov
[0].iov_base
= req
->sign
;
288 req
->tx_iov
[0].iov_len
= signlen
;
290 req
->tx_totallen
+= signlen
;
292 server
->tx
.creq
= req
;
293 __ncptcp_try_send(server
);
296 static inline void __ncp_start_request(struct ncp_server
*server
, struct ncp_request_reply
*req
)
298 if (server
->ncp_sock
->type
== SOCK_STREAM
)
299 ncptcp_start_request(server
, req
);
301 ncpdgram_start_request(server
, req
);
304 static int ncp_add_request(struct ncp_server
*server
, struct ncp_request_reply
*req
)
306 mutex_lock(&server
->rcv
.creq_mutex
);
307 if (!ncp_conn_valid(server
)) {
308 mutex_unlock(&server
->rcv
.creq_mutex
);
309 printk(KERN_ERR
"ncpfs: tcp: Server died\n");
312 if (server
->tx
.creq
|| server
->rcv
.creq
) {
313 req
->status
= RQ_QUEUED
;
314 list_add_tail(&req
->req
, &server
->tx
.requests
);
315 mutex_unlock(&server
->rcv
.creq_mutex
);
318 __ncp_start_request(server
, req
);
319 mutex_unlock(&server
->rcv
.creq_mutex
);
323 static void __ncp_next_request(struct ncp_server
*server
)
325 struct ncp_request_reply
*req
;
327 server
->rcv
.creq
= NULL
;
328 if (list_empty(&server
->tx
.requests
)) {
331 req
= list_entry(server
->tx
.requests
.next
, struct ncp_request_reply
, req
);
332 list_del_init(&req
->req
);
333 __ncp_start_request(server
, req
);
336 static void info_server(struct ncp_server
*server
, unsigned int id
, const void * data
, size_t len
)
338 if (server
->info_sock
) {
342 hdr
[0] = cpu_to_be32(len
+ 8);
343 hdr
[1] = cpu_to_be32(id
);
345 iov
[0].iov_base
= hdr
;
347 iov
[1].iov_base
= (void *) data
;
348 iov
[1].iov_len
= len
;
350 do_send(server
->info_sock
, iov
, 2, len
+ 8, MSG_NOSIGNAL
);
354 void ncpdgram_rcv_proc(void *s
)
356 struct ncp_server
*server
= s
;
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(void *s
)
474 struct ncp_server
*server
= s
;
475 mutex_lock(&server
->rcv
.creq_mutex
);
476 __ncpdgram_timeout_proc(server
);
477 mutex_unlock(&server
->rcv
.creq_mutex
);
480 static inline void ncp_init_req(struct ncp_request_reply
* req
)
482 init_waitqueue_head(&req
->wq
);
483 req
->status
= RQ_IDLE
;
486 static int do_tcp_rcv(struct ncp_server
*server
, void *buffer
, size_t len
)
491 result
= _recv(server
->ncp_sock
, buffer
, len
, MSG_DONTWAIT
);
493 static unsigned char dummy
[1024];
495 if (len
> sizeof(dummy
)) {
498 result
= _recv(server
->ncp_sock
, dummy
, len
, MSG_DONTWAIT
);
504 printk(KERN_ERR
"ncpfs: tcp: bug in recvmsg (%u > %Zu)\n", result
, len
);
510 static int __ncptcp_rcv_proc(struct ncp_server
*server
)
512 /* We have to check the result, so store the complete header */
515 struct ncp_request_reply
*req
;
519 while (server
->rcv
.len
) {
520 result
= do_tcp_rcv(server
, server
->rcv
.ptr
, server
->rcv
.len
);
521 if (result
== -EAGAIN
) {
525 req
= server
->rcv
.creq
;
527 __ncp_abort_request(server
, req
, -EIO
);
529 __ncptcp_abort(server
);
532 printk(KERN_ERR
"ncpfs: tcp: error in recvmsg: %d\n", result
);
534 DPRINTK(KERN_ERR
"ncpfs: tcp: EOF\n");
538 if (server
->rcv
.ptr
) {
539 server
->rcv
.ptr
+= result
;
541 server
->rcv
.len
-= result
;
543 switch (server
->rcv
.state
) {
545 if (server
->rcv
.buf
.magic
!= htonl(NCP_TCP_RCVD_MAGIC
)) {
546 printk(KERN_ERR
"ncpfs: tcp: Unexpected reply type %08X\n", ntohl(server
->rcv
.buf
.magic
));
547 __ncptcp_abort(server
);
550 datalen
= ntohl(server
->rcv
.buf
.len
) & 0x0FFFFFFF;
552 printk(KERN_ERR
"ncpfs: tcp: Unexpected reply len %d\n", datalen
);
553 __ncptcp_abort(server
);
556 #ifdef CONFIG_NCPFS_PACKET_SIGNING
557 if (server
->sign_active
) {
559 printk(KERN_ERR
"ncpfs: tcp: Unexpected reply len %d\n", datalen
);
560 __ncptcp_abort(server
);
563 server
->rcv
.buf
.len
= datalen
- 8;
564 server
->rcv
.ptr
= (unsigned char*)&server
->rcv
.buf
.p1
;
566 server
->rcv
.state
= 4;
570 type
= ntohs(server
->rcv
.buf
.type
);
571 #ifdef CONFIG_NCPFS_PACKET_SIGNING
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;
579 server
->rcv
.state
= 5;
580 server
->rcv
.ptr
= server
->unexpected_packet
.data
+ 2;
581 server
->rcv
.len
= datalen
- 10;
584 DPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", type
);
586 server
->rcv
.state
= 2;
588 server
->rcv
.ptr
= NULL
;
589 server
->rcv
.len
= datalen
- 10;
592 req
= server
->rcv
.creq
;
594 DPRINTK(KERN_ERR
"ncpfs: Reply without appropriate request\n");
597 if (datalen
> req
->datalen
+ 8) {
598 printk(KERN_ERR
"ncpfs: tcp: Unexpected reply len %d (expected at most %Zd)\n", datalen
, req
->datalen
+ 8);
599 server
->rcv
.state
= 3;
602 req
->datalen
= datalen
- 8;
603 req
->reply_buf
->type
= NCP_REPLY
;
604 server
->rcv
.ptr
= (unsigned char*)(req
->reply_buf
) + 2;
605 server
->rcv
.len
= datalen
- 10;
606 server
->rcv
.state
= 1;
608 #ifdef CONFIG_NCPFS_PACKET_SIGNING
610 datalen
= server
->rcv
.buf
.len
;
611 type
= ntohs(server
->rcv
.buf
.type2
);
615 req
= server
->rcv
.creq
;
616 if (req
->tx_type
!= NCP_ALLOC_SLOT_REQUEST
) {
617 if (req
->reply_buf
->sequence
!= server
->sequence
) {
618 printk(KERN_ERR
"ncpfs: tcp: Bad sequence number\n");
619 __ncp_abort_request(server
, req
, -EIO
);
622 if ((req
->reply_buf
->conn_low
| (req
->reply_buf
->conn_high
<< 8)) != server
->connection
) {
623 printk(KERN_ERR
"ncpfs: tcp: Connection number mismatch\n");
624 __ncp_abort_request(server
, req
, -EIO
);
628 #ifdef CONFIG_NCPFS_PACKET_SIGNING
629 if (server
->sign_active
&& req
->tx_type
!= NCP_DEALLOC_SLOT_REQUEST
) {
630 if (sign_verify_reply(server
, (unsigned char*)(req
->reply_buf
) + 6, req
->datalen
- 6, cpu_to_be32(req
->datalen
+ 16), &server
->rcv
.buf
.type
)) {
631 printk(KERN_ERR
"ncpfs: tcp: Signature violation\n");
632 __ncp_abort_request(server
, req
, -EIO
);
637 ncp_finish_request(req
, req
->datalen
);
639 __ncp_next_request(server
);
642 server
->rcv
.ptr
= (unsigned char*)&server
->rcv
.buf
;
643 server
->rcv
.len
= 10;
644 server
->rcv
.state
= 0;
647 ncp_finish_request(server
->rcv
.creq
, -EIO
);
650 info_server(server
, 0, server
->unexpected_packet
.data
, server
->unexpected_packet
.len
);
656 void ncp_tcp_rcv_proc(void *s
)
658 struct ncp_server
*server
= s
;
660 mutex_lock(&server
->rcv
.creq_mutex
);
661 __ncptcp_rcv_proc(server
);
662 mutex_unlock(&server
->rcv
.creq_mutex
);
665 void ncp_tcp_tx_proc(void *s
)
667 struct ncp_server
*server
= s
;
669 mutex_lock(&server
->rcv
.creq_mutex
);
670 __ncptcp_try_send(server
);
671 mutex_unlock(&server
->rcv
.creq_mutex
);
674 static int do_ncp_rpc_call(struct ncp_server
*server
, int size
,
675 struct ncp_reply_header
* reply_buf
, int max_reply_size
)
678 struct ncp_request_reply req
;
681 req
.reply_buf
= reply_buf
;
682 req
.datalen
= max_reply_size
;
683 req
.tx_iov
[1].iov_base
= server
->packet
;
684 req
.tx_iov
[1].iov_len
= size
;
686 req
.tx_totallen
= size
;
687 req
.tx_type
= *(u_int16_t
*)server
->packet
;
689 result
= ncp_add_request(server
, &req
);
693 if (wait_event_interruptible(req
.wq
, req
.status
== RQ_DONE
)) {
694 ncp_abort_request(server
, &req
, -EIO
);
700 * We need the server to be locked here, so check!
703 static int ncp_do_request(struct ncp_server
*server
, int size
,
704 void* reply
, int max_reply_size
)
708 if (server
->lock
== 0) {
709 printk(KERN_ERR
"ncpfs: Server not locked!\n");
712 if (!ncp_conn_valid(server
)) {
713 printk(KERN_ERR
"ncpfs: Connection invalid!\n");
718 unsigned long mask
, flags
;
720 spin_lock_irqsave(¤t
->sighand
->siglock
, flags
);
721 old_set
= current
->blocked
;
722 if (current
->flags
& PF_EXITING
)
725 mask
= sigmask(SIGKILL
);
726 if (server
->m
.flags
& NCP_MOUNT_INTR
) {
727 /* FIXME: This doesn't seem right at all. So, like,
728 we can't handle SIGINT and get whatever to stop?
729 What if we've blocked it ourselves? What about
730 alarms? Why, in fact, are we mucking with the
731 sigmask at all? -- r~ */
732 if (current
->sighand
->action
[SIGINT
- 1].sa
.sa_handler
== SIG_DFL
)
733 mask
|= sigmask(SIGINT
);
734 if (current
->sighand
->action
[SIGQUIT
- 1].sa
.sa_handler
== SIG_DFL
)
735 mask
|= sigmask(SIGQUIT
);
737 siginitsetinv(¤t
->blocked
, mask
);
739 spin_unlock_irqrestore(¤t
->sighand
->siglock
, flags
);
741 result
= do_ncp_rpc_call(server
, size
, reply
, max_reply_size
);
743 spin_lock_irqsave(¤t
->sighand
->siglock
, flags
);
744 current
->blocked
= old_set
;
746 spin_unlock_irqrestore(¤t
->sighand
->siglock
, flags
);
749 DDPRINTK("do_ncp_rpc_call returned %d\n", result
);
752 /* There was a problem with I/O, so the connections is
753 * no longer usable. */
754 ncp_invalidate_conn(server
);
759 /* ncp_do_request assures that at least a complete reply header is
760 * received. It assumes that server->current_size contains the ncp
763 int ncp_request2(struct ncp_server
*server
, int function
,
766 struct ncp_request_header
*h
;
767 struct ncp_reply_header
* reply
= rpl
;
770 h
= (struct ncp_request_header
*) (server
->packet
);
771 if (server
->has_subfunction
!= 0) {
772 *(__u16
*) & (h
->data
[0]) = htons(server
->current_size
- sizeof(*h
) - 2);
774 h
->type
= NCP_REQUEST
;
776 * The server shouldn't know or care what task is making a
777 * request, so we always use the same task number.
779 h
->task
= 2; /* (current->pid) & 0xff; */
780 h
->function
= function
;
782 result
= ncp_do_request(server
, server
->current_size
, reply
, size
);
784 DPRINTK("ncp_request_error: %d\n", result
);
787 server
->completion
= reply
->completion_code
;
788 server
->conn_status
= reply
->connection_state
;
789 server
->reply_size
= result
;
790 server
->ncp_reply_size
= result
- sizeof(struct ncp_reply_header
);
792 result
= reply
->completion_code
;
795 PPRINTK("ncp_request: completion code=%x\n", result
);
800 int ncp_connect(struct ncp_server
*server
)
802 struct ncp_request_header
*h
;
805 server
->connection
= 0xFFFF;
806 server
->sequence
= 255;
808 h
= (struct ncp_request_header
*) (server
->packet
);
809 h
->type
= NCP_ALLOC_SLOT_REQUEST
;
810 h
->task
= 2; /* see above */
813 result
= ncp_do_request(server
, sizeof(*h
), server
->packet
, server
->packet_size
);
816 server
->connection
= h
->conn_low
+ (h
->conn_high
* 256);
822 int ncp_disconnect(struct ncp_server
*server
)
824 struct ncp_request_header
*h
;
826 h
= (struct ncp_request_header
*) (server
->packet
);
827 h
->type
= NCP_DEALLOC_SLOT_REQUEST
;
828 h
->task
= 2; /* see above */
831 return ncp_do_request(server
, sizeof(*h
), server
->packet
, server
->packet_size
);
834 void ncp_lock_server(struct ncp_server
*server
)
836 mutex_lock(&server
->mutex
);
838 printk(KERN_WARNING
"ncp_lock_server: was locked!\n");
842 void ncp_unlock_server(struct ncp_server
*server
)
845 printk(KERN_WARNING
"ncp_unlock_server: was not locked!\n");
849 mutex_unlock(&server
->mutex
);