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(void *s
)
355 struct ncp_server
*server
= s
;
358 sock
= server
->ncp_sock
;
361 struct ncp_reply_header reply
;
364 result
= _recv(sock
, &reply
, sizeof(reply
), MSG_PEEK
| MSG_DONTWAIT
);
368 if (result
>= sizeof(reply
)) {
369 struct ncp_request_reply
*req
;
371 if (reply
.type
== NCP_WATCHDOG
) {
372 unsigned char buf
[10];
374 if (server
->connection
!= get_conn_number(&reply
)) {
377 result
= _recv(sock
, buf
, sizeof(buf
), MSG_DONTWAIT
);
379 DPRINTK("recv failed with %d\n", result
);
383 DPRINTK("too short (%u) watchdog packet\n", result
);
387 DPRINTK("bad signature (%02X) in watchdog packet\n", buf
[9]);
391 _send(sock
, buf
, sizeof(buf
));
394 if (reply
.type
!= NCP_POSITIVE_ACK
&& reply
.type
!= NCP_REPLY
) {
395 result
= _recv(sock
, server
->unexpected_packet
.data
, sizeof(server
->unexpected_packet
.data
), MSG_DONTWAIT
);
399 info_server(server
, 0, server
->unexpected_packet
.data
, result
);
402 mutex_lock(&server
->rcv
.creq_mutex
);
403 req
= server
->rcv
.creq
;
404 if (req
&& (req
->tx_type
== NCP_ALLOC_SLOT_REQUEST
|| (server
->sequence
== reply
.sequence
&&
405 server
->connection
== get_conn_number(&reply
)))) {
406 if (reply
.type
== NCP_POSITIVE_ACK
) {
407 server
->timeout_retries
= server
->m
.retry_count
;
408 server
->timeout_last
= NCP_MAX_RPC_TIMEOUT
;
409 mod_timer(&server
->timeout_tm
, jiffies
+ NCP_MAX_RPC_TIMEOUT
);
410 } else if (reply
.type
== NCP_REPLY
) {
411 result
= _recv(sock
, (void*)req
->reply_buf
, req
->datalen
, MSG_DONTWAIT
);
412 #ifdef CONFIG_NCPFS_PACKET_SIGNING
413 if (result
>= 0 && server
->sign_active
&& req
->tx_type
!= NCP_DEALLOC_SLOT_REQUEST
) {
414 if (result
< 8 + 8) {
420 hdrl
= sock
->sk
->sk_family
== AF_INET
? 8 : 6;
421 if (sign_verify_reply(server
, ((char*)req
->reply_buf
) + hdrl
, result
- hdrl
, cpu_to_le32(result
), ((char*)req
->reply_buf
) + result
)) {
422 printk(KERN_INFO
"ncpfs: Signature violation\n");
428 del_timer(&server
->timeout_tm
);
429 server
->rcv
.creq
= NULL
;
430 ncp_finish_request(req
, result
);
431 __ncp_next_request(server
);
432 mutex_unlock(&server
->rcv
.creq_mutex
);
436 mutex_unlock(&server
->rcv
.creq_mutex
);
439 _recv(sock
, &reply
, sizeof(reply
), MSG_DONTWAIT
);
443 static void __ncpdgram_timeout_proc(struct ncp_server
*server
)
445 /* If timer is pending, we are processing another request... */
446 if (!timer_pending(&server
->timeout_tm
)) {
447 struct ncp_request_reply
* req
;
449 req
= server
->rcv
.creq
;
453 if (server
->m
.flags
& NCP_MOUNT_SOFT
) {
454 if (server
->timeout_retries
-- == 0) {
455 __ncp_abort_request(server
, req
, -ETIMEDOUT
);
460 ncpdgram_send(server
->ncp_sock
, req
);
461 timeout
= server
->timeout_last
<< 1;
462 if (timeout
> NCP_MAX_RPC_TIMEOUT
) {
463 timeout
= NCP_MAX_RPC_TIMEOUT
;
465 server
->timeout_last
= timeout
;
466 mod_timer(&server
->timeout_tm
, jiffies
+ timeout
);
471 void ncpdgram_timeout_proc(void *s
)
473 struct ncp_server
*server
= s
;
474 mutex_lock(&server
->rcv
.creq_mutex
);
475 __ncpdgram_timeout_proc(server
);
476 mutex_unlock(&server
->rcv
.creq_mutex
);
479 static inline void ncp_init_req(struct ncp_request_reply
* req
)
481 init_waitqueue_head(&req
->wq
);
482 req
->status
= RQ_IDLE
;
485 static int do_tcp_rcv(struct ncp_server
*server
, void *buffer
, size_t len
)
490 result
= _recv(server
->ncp_sock
, buffer
, len
, MSG_DONTWAIT
);
492 static unsigned char dummy
[1024];
494 if (len
> sizeof(dummy
)) {
497 result
= _recv(server
->ncp_sock
, dummy
, len
, MSG_DONTWAIT
);
503 printk(KERN_ERR
"ncpfs: tcp: bug in recvmsg (%u > %Zu)\n", result
, len
);
509 static int __ncptcp_rcv_proc(struct ncp_server
*server
)
511 /* We have to check the result, so store the complete header */
514 struct ncp_request_reply
*req
;
518 while (server
->rcv
.len
) {
519 result
= do_tcp_rcv(server
, server
->rcv
.ptr
, server
->rcv
.len
);
520 if (result
== -EAGAIN
) {
524 req
= server
->rcv
.creq
;
526 __ncp_abort_request(server
, req
, -EIO
);
528 __ncptcp_abort(server
);
531 printk(KERN_ERR
"ncpfs: tcp: error in recvmsg: %d\n", result
);
533 DPRINTK(KERN_ERR
"ncpfs: tcp: EOF\n");
537 if (server
->rcv
.ptr
) {
538 server
->rcv
.ptr
+= result
;
540 server
->rcv
.len
-= result
;
542 switch (server
->rcv
.state
) {
544 if (server
->rcv
.buf
.magic
!= htonl(NCP_TCP_RCVD_MAGIC
)) {
545 printk(KERN_ERR
"ncpfs: tcp: Unexpected reply type %08X\n", ntohl(server
->rcv
.buf
.magic
));
546 __ncptcp_abort(server
);
549 datalen
= ntohl(server
->rcv
.buf
.len
) & 0x0FFFFFFF;
551 printk(KERN_ERR
"ncpfs: tcp: Unexpected reply len %d\n", datalen
);
552 __ncptcp_abort(server
);
555 #ifdef CONFIG_NCPFS_PACKET_SIGNING
556 if (server
->sign_active
) {
558 printk(KERN_ERR
"ncpfs: tcp: Unexpected reply len %d\n", datalen
);
559 __ncptcp_abort(server
);
562 server
->rcv
.buf
.len
= datalen
- 8;
563 server
->rcv
.ptr
= (unsigned char*)&server
->rcv
.buf
.p1
;
565 server
->rcv
.state
= 4;
569 type
= ntohs(server
->rcv
.buf
.type
);
570 #ifdef CONFIG_NCPFS_PACKET_SIGNING
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;
578 server
->rcv
.state
= 5;
579 server
->rcv
.ptr
= server
->unexpected_packet
.data
+ 2;
580 server
->rcv
.len
= datalen
- 10;
583 DPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", type
);
585 server
->rcv
.state
= 2;
587 server
->rcv
.ptr
= NULL
;
588 server
->rcv
.len
= datalen
- 10;
591 req
= server
->rcv
.creq
;
593 DPRINTK(KERN_ERR
"ncpfs: Reply without appropriate request\n");
596 if (datalen
> req
->datalen
+ 8) {
597 printk(KERN_ERR
"ncpfs: tcp: Unexpected reply len %d (expected at most %Zd)\n", datalen
, req
->datalen
+ 8);
598 server
->rcv
.state
= 3;
601 req
->datalen
= datalen
- 8;
602 req
->reply_buf
->type
= NCP_REPLY
;
603 server
->rcv
.ptr
= (unsigned char*)(req
->reply_buf
) + 2;
604 server
->rcv
.len
= datalen
- 10;
605 server
->rcv
.state
= 1;
607 #ifdef CONFIG_NCPFS_PACKET_SIGNING
609 datalen
= server
->rcv
.buf
.len
;
610 type
= ntohs(server
->rcv
.buf
.type2
);
614 req
= server
->rcv
.creq
;
615 if (req
->tx_type
!= NCP_ALLOC_SLOT_REQUEST
) {
616 if (req
->reply_buf
->sequence
!= server
->sequence
) {
617 printk(KERN_ERR
"ncpfs: tcp: Bad sequence number\n");
618 __ncp_abort_request(server
, req
, -EIO
);
621 if ((req
->reply_buf
->conn_low
| (req
->reply_buf
->conn_high
<< 8)) != server
->connection
) {
622 printk(KERN_ERR
"ncpfs: tcp: Connection number mismatch\n");
623 __ncp_abort_request(server
, req
, -EIO
);
627 #ifdef CONFIG_NCPFS_PACKET_SIGNING
628 if (server
->sign_active
&& req
->tx_type
!= NCP_DEALLOC_SLOT_REQUEST
) {
629 if (sign_verify_reply(server
, (unsigned char*)(req
->reply_buf
) + 6, req
->datalen
- 6, cpu_to_be32(req
->datalen
+ 16), &server
->rcv
.buf
.type
)) {
630 printk(KERN_ERR
"ncpfs: tcp: Signature violation\n");
631 __ncp_abort_request(server
, req
, -EIO
);
636 ncp_finish_request(req
, req
->datalen
);
638 __ncp_next_request(server
);
641 server
->rcv
.ptr
= (unsigned char*)&server
->rcv
.buf
;
642 server
->rcv
.len
= 10;
643 server
->rcv
.state
= 0;
646 ncp_finish_request(server
->rcv
.creq
, -EIO
);
649 info_server(server
, 0, server
->unexpected_packet
.data
, server
->unexpected_packet
.len
);
655 void ncp_tcp_rcv_proc(void *s
)
657 struct ncp_server
*server
= s
;
659 mutex_lock(&server
->rcv
.creq_mutex
);
660 __ncptcp_rcv_proc(server
);
661 mutex_unlock(&server
->rcv
.creq_mutex
);
664 void ncp_tcp_tx_proc(void *s
)
666 struct ncp_server
*server
= s
;
668 mutex_lock(&server
->rcv
.creq_mutex
);
669 __ncptcp_try_send(server
);
670 mutex_unlock(&server
->rcv
.creq_mutex
);
673 static int do_ncp_rpc_call(struct ncp_server
*server
, int size
,
674 struct ncp_reply_header
* reply_buf
, int max_reply_size
)
677 struct ncp_request_reply req
;
680 req
.reply_buf
= reply_buf
;
681 req
.datalen
= max_reply_size
;
682 req
.tx_iov
[1].iov_base
= server
->packet
;
683 req
.tx_iov
[1].iov_len
= size
;
685 req
.tx_totallen
= size
;
686 req
.tx_type
= *(u_int16_t
*)server
->packet
;
688 result
= ncp_add_request(server
, &req
);
692 if (wait_event_interruptible(req
.wq
, req
.status
== RQ_DONE
)) {
693 ncp_abort_request(server
, &req
, -EIO
);
699 * We need the server to be locked here, so check!
702 static int ncp_do_request(struct ncp_server
*server
, int size
,
703 void* reply
, int max_reply_size
)
707 if (server
->lock
== 0) {
708 printk(KERN_ERR
"ncpfs: Server not locked!\n");
711 if (!ncp_conn_valid(server
)) {
712 printk(KERN_ERR
"ncpfs: Connection invalid!\n");
717 unsigned long mask
, flags
;
719 spin_lock_irqsave(¤t
->sighand
->siglock
, flags
);
720 old_set
= current
->blocked
;
721 if (current
->flags
& PF_EXITING
)
724 mask
= sigmask(SIGKILL
);
725 if (server
->m
.flags
& NCP_MOUNT_INTR
) {
726 /* FIXME: This doesn't seem right at all. So, like,
727 we can't handle SIGINT and get whatever to stop?
728 What if we've blocked it ourselves? What about
729 alarms? Why, in fact, are we mucking with the
730 sigmask at all? -- r~ */
731 if (current
->sighand
->action
[SIGINT
- 1].sa
.sa_handler
== SIG_DFL
)
732 mask
|= sigmask(SIGINT
);
733 if (current
->sighand
->action
[SIGQUIT
- 1].sa
.sa_handler
== SIG_DFL
)
734 mask
|= sigmask(SIGQUIT
);
736 siginitsetinv(¤t
->blocked
, mask
);
738 spin_unlock_irqrestore(¤t
->sighand
->siglock
, flags
);
740 result
= do_ncp_rpc_call(server
, size
, reply
, max_reply_size
);
742 spin_lock_irqsave(¤t
->sighand
->siglock
, flags
);
743 current
->blocked
= old_set
;
745 spin_unlock_irqrestore(¤t
->sighand
->siglock
, flags
);
748 DDPRINTK("do_ncp_rpc_call returned %d\n", result
);
751 /* There was a problem with I/O, so the connections is
752 * no longer usable. */
753 ncp_invalidate_conn(server
);
758 /* ncp_do_request assures that at least a complete reply header is
759 * received. It assumes that server->current_size contains the ncp
762 int ncp_request2(struct ncp_server
*server
, int function
,
765 struct ncp_request_header
*h
;
766 struct ncp_reply_header
* reply
= rpl
;
769 h
= (struct ncp_request_header
*) (server
->packet
);
770 if (server
->has_subfunction
!= 0) {
771 *(__u16
*) & (h
->data
[0]) = htons(server
->current_size
- sizeof(*h
) - 2);
773 h
->type
= NCP_REQUEST
;
775 * The server shouldn't know or care what task is making a
776 * request, so we always use the same task number.
778 h
->task
= 2; /* (current->pid) & 0xff; */
779 h
->function
= function
;
781 result
= ncp_do_request(server
, server
->current_size
, reply
, size
);
783 DPRINTK("ncp_request_error: %d\n", result
);
786 server
->completion
= reply
->completion_code
;
787 server
->conn_status
= reply
->connection_state
;
788 server
->reply_size
= result
;
789 server
->ncp_reply_size
= result
- sizeof(struct ncp_reply_header
);
791 result
= reply
->completion_code
;
794 PPRINTK("ncp_request: completion code=%x\n", result
);
799 int ncp_connect(struct ncp_server
*server
)
801 struct ncp_request_header
*h
;
804 server
->connection
= 0xFFFF;
805 server
->sequence
= 255;
807 h
= (struct ncp_request_header
*) (server
->packet
);
808 h
->type
= NCP_ALLOC_SLOT_REQUEST
;
809 h
->task
= 2; /* see above */
812 result
= ncp_do_request(server
, sizeof(*h
), server
->packet
, server
->packet_size
);
815 server
->connection
= h
->conn_low
+ (h
->conn_high
* 256);
821 int ncp_disconnect(struct ncp_server
*server
)
823 struct ncp_request_header
*h
;
825 h
= (struct ncp_request_header
*) (server
->packet
);
826 h
->type
= NCP_DEALLOC_SLOT_REQUEST
;
827 h
->task
= 2; /* see above */
830 return ncp_do_request(server
, sizeof(*h
), server
->packet
, server
->packet_size
);
833 void ncp_lock_server(struct ncp_server
*server
)
835 mutex_lock(&server
->mutex
);
837 printk(KERN_WARNING
"ncp_lock_server: was locked!\n");
841 void ncp_unlock_server(struct ncp_server
*server
)
844 printk(KERN_WARNING
"ncp_unlock_server: was not locked!\n");
848 mutex_unlock(&server
->mutex
);