1/* 2 * linux/fs/ncpfs/sock.c 3 * 4 * Copyright (C) 1992, 1993 Rick Sladkey 5 * 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 8 * 9 */ 10 11 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> 19#include <linux/in.h> 20#include <linux/net.h> 21#include <linux/mm.h> 22#include <linux/netdevice.h> 23#include <linux/signal.h> 24#include <linux/slab.h> 25#include <net/scm.h> 26#include <net/sock.h> 27#include <linux/ipx.h> 28#include <linux/poll.h> 29#include <linux/file.h> 30 31#include <linux/ncp_fs.h> 32 33#include "ncpsign_kernel.h" 34 35static int _recv(struct socket *sock, void *buf, int size, unsigned flags) 36{ 37 struct msghdr msg = {NULL, }; 38 struct kvec iov = {buf, size}; 39 return kernel_recvmsg(sock, &msg, &iov, 1, size, flags); 40} 41 42static inline int do_send(struct socket *sock, struct kvec *vec, int count, 43 int len, unsigned flags) 44{ 45 struct msghdr msg = { .msg_flags = flags }; 46 return kernel_sendmsg(sock, &msg, vec, count, len); 47} 48 49static int _send(struct socket *sock, const void *buff, int len) 50{ 51 struct kvec vec; 52 vec.iov_base = (void *) buff; 53 vec.iov_len = len; 54 return do_send(sock, &vec, 1, len, 0); 55} 56 57struct ncp_request_reply { 58 struct list_head req; 59 wait_queue_head_t wq; 60 atomic_t refs; 61 unsigned char* reply_buf; 62 size_t datalen; 63 int result; 64 enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE, RQ_ABANDONED } status; 65 struct kvec* tx_ciov; 66 size_t tx_totallen; 67 size_t tx_iovlen; 68 struct kvec tx_iov[3]; 69 u_int16_t tx_type; 70 u_int32_t sign[6]; 71}; 72 73static inline struct ncp_request_reply* ncp_alloc_req(void) 74{ 75 struct ncp_request_reply *req; 76 77 req = kmalloc(sizeof(struct ncp_request_reply), GFP_KERNEL); 78 if (!req) 79 return NULL; 80 81 init_waitqueue_head(&req->wq); 82 atomic_set(&req->refs, (1)); 83 req->status = RQ_IDLE; 84 85 return req; 86} 87 88static void ncp_req_get(struct ncp_request_reply *req) 89{ 90 atomic_inc(&req->refs); 91} 92 93static void ncp_req_put(struct ncp_request_reply *req) 94{ 95 if (atomic_dec_and_test(&req->refs)) 96 kfree(req); 97} 98 99void ncp_tcp_data_ready(struct sock *sk, int len) 100{ 101 struct ncp_server *server = sk->sk_user_data; 102 103 server->data_ready(sk, len); 104 schedule_work(&server->rcv.tq); 105} 106 107void ncp_tcp_error_report(struct sock *sk) 108{ 109 struct ncp_server *server = sk->sk_user_data; 110 111 server->error_report(sk); 112 schedule_work(&server->rcv.tq); 113} 114 115void ncp_tcp_write_space(struct sock *sk) 116{ 117 struct ncp_server *server = sk->sk_user_data; 118 119 /* We do not need any locking: we first set tx.creq, and then we do sendmsg, 120 not vice versa... */ 121 server->write_space(sk); 122 if (server->tx.creq) 123 schedule_work(&server->tx.tq); 124} 125 126void ncpdgram_timeout_call(unsigned long v) 127{ 128 struct ncp_server *server = (void*)v; 129 130 schedule_work(&server->timeout_tq); 131} 132 133static inline void ncp_finish_request(struct ncp_server *server, struct ncp_request_reply *req, int result) 134{ 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); 140 ncp_req_put(req); 141} 142 143static void __abort_ncp_connection(struct ncp_server *server) 144{ 145 struct ncp_request_reply *req; 146 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); 151 152 list_del_init(&req->req); 153 ncp_finish_request(server, req, -EIO); 154 } 155 req = server->rcv.creq; 156 if (req) { 157 server->rcv.creq = NULL; 158 ncp_finish_request(server, req, -EIO); 159 server->rcv.ptr = NULL; 160 server->rcv.state = 0; 161 } 162 req = server->tx.creq; 163 if (req) { 164 server->tx.creq = NULL; 165 ncp_finish_request(server, req, -EIO); 166 } 167} 168 169static inline int get_conn_number(struct ncp_reply_header *rp) 170{ 171 return rp->conn_low | (rp->conn_high << 8); 172} 173 174static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err) 175{ 176 /* If req is done, we got signal, but we also received answer... */ 177 switch (req->status) { 178 case RQ_IDLE: 179 case RQ_DONE: 180 break; 181 case RQ_QUEUED: 182 list_del_init(&req->req); 183 ncp_finish_request(server, req, err); 184 break; 185 case RQ_INPROGRESS: 186 req->status = RQ_ABANDONED; 187 break; 188 case RQ_ABANDONED: 189 break; 190 } 191} 192 193static inline void ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err) 194{ 195 mutex_lock(&server->rcv.creq_mutex); 196 __ncp_abort_request(server, req, err); 197 mutex_unlock(&server->rcv.creq_mutex); 198} 199 200static inline void __ncptcp_abort(struct ncp_server *server) 201{ 202 __abort_ncp_connection(server); 203} 204 205static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req) 206{ 207 struct kvec vec[3]; 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); 212} 213 214static void __ncptcp_try_send(struct ncp_server *server) 215{ 216 struct ncp_request_reply *rq; 217 struct kvec *iov; 218 struct kvec iovc[3]; 219 int result; 220 221 rq = server->tx.creq; 222 if (!rq) 223 return; 224 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); 229 230 if (result == -EAGAIN) 231 return; 232 233 if (result < 0) { 234 printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result); 235 __ncp_abort_request(server, rq, result); 236 return; 237 } 238 if (result >= rq->tx_totallen) { 239 server->rcv.creq = rq; 240 server->tx.creq = NULL; 241 return; 242 } 243 rq->tx_totallen -= result; 244 iov = rq->tx_ciov; 245 while (iov->iov_len <= result) { 246 result -= iov->iov_len; 247 iov++; 248 rq->tx_iovlen--; 249 } 250 iov->iov_base += result; 251 iov->iov_len -= result; 252 rq->tx_ciov = iov; 253} 254 255static inline void ncp_init_header(struct ncp_server *server, struct ncp_request_reply *req, struct ncp_request_header *h) 256{ 257 req->status = RQ_INPROGRESS; 258 h->conn_low = server->connection; 259 h->conn_high = server->connection >> 8; 260 h->sequence = ++server->sequence; 261} 262 263static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request_reply *req) 264{ 265 size_t signlen; 266 struct ncp_request_header* h; 267 268 req->tx_ciov = req->tx_iov + 1; 269 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); 275 if (signlen) { 276 req->tx_ciov[1].iov_base = req->sign; 277 req->tx_ciov[1].iov_len = signlen; 278 req->tx_iovlen += 1; 279 req->tx_totallen += signlen; 280 } 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); 286} 287 288#define NCP_TCP_XMIT_MAGIC (0x446D6454) 289#define NCP_TCP_XMIT_VERSION (1) 290#define NCP_TCP_RCVD_MAGIC (0x744E6350) 291 292static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_reply *req) 293{ 294 size_t signlen; 295 struct ncp_request_header* h; 296 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; 303 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; 310 req->tx_iovlen += 1; 311 req->tx_totallen += signlen; 312 313 server->tx.creq = req; 314 __ncptcp_try_send(server); 315} 316 317static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req) 318{ 319 /* we copy the data so that we do not depend on the caller 320 staying alive */ 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; 323 324 if (server->ncp_sock->type == SOCK_STREAM) 325 ncptcp_start_request(server, req); 326 else 327 ncpdgram_start_request(server, req); 328} 329 330static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply *req) 331{ 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"); 336 return -EIO; 337 } 338 ncp_req_get(req); 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); 343 return 0; 344 } 345 __ncp_start_request(server, req); 346 mutex_unlock(&server->rcv.creq_mutex); 347 return 0; 348} 349 350static void __ncp_next_request(struct ncp_server *server) 351{ 352 struct ncp_request_reply *req; 353 354 server->rcv.creq = NULL; 355 if (list_empty(&server->tx.requests)) { 356 return; 357 } 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); 361} 362 363static void info_server(struct ncp_server *server, unsigned int id, const void * data, size_t len) 364{ 365 if (server->info_sock) { 366 struct kvec iov[2]; 367 __be32 hdr[2]; 368 369 hdr[0] = cpu_to_be32(len + 8); 370 hdr[1] = cpu_to_be32(id); 371 372 iov[0].iov_base = hdr; 373 iov[0].iov_len = 8; 374 iov[1].iov_base = (void *) data; 375 iov[1].iov_len = len; 376 377 do_send(server->info_sock, iov, 2, len + 8, MSG_NOSIGNAL); 378 } 379} 380 381void ncpdgram_rcv_proc(struct work_struct *work) 382{ 383 struct ncp_server *server = 384 container_of(work, struct ncp_server, rcv.tq); 385 struct socket* sock; 386 387 sock = server->ncp_sock; 388 389 while (1) { 390 struct ncp_reply_header reply; 391 int result; 392 393 result = _recv(sock, &reply, sizeof(reply), MSG_PEEK | MSG_DONTWAIT); 394 if (result < 0) { 395 break; 396 } 397 if (result >= sizeof(reply)) { 398 struct ncp_request_reply *req; 399 400 if (reply.type == NCP_WATCHDOG) { 401 unsigned char buf[10]; 402 403 if (server->connection != get_conn_number(&reply)) { 404 goto drop; 405 } 406 result = _recv(sock, buf, sizeof(buf), MSG_DONTWAIT); 407 if (result < 0) { 408 DPRINTK("recv failed with %d\n", result); 409 continue; 410 } 411 if (result < 10) { 412 DPRINTK("too short (%u) watchdog packet\n", result); 413 continue; 414 } 415 if (buf[9] != '?') { 416 DPRINTK("bad signature (%02X) in watchdog packet\n", buf[9]); 417 continue; 418 } 419 buf[9] = 'Y'; 420 _send(sock, buf, sizeof(buf)); 421 continue; 422 } 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); 425 if (result < 0) { 426 continue; 427 } 428 info_server(server, 0, server->unexpected_packet.data, result); 429 continue; 430 } 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) { 444 result = -EIO; 445 } else { 446 unsigned int hdrl; 447 448 result -= 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"); 452 result = -EIO; 453 } 454 } 455 } 456#endif 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); 462 continue; 463 } 464 } 465 mutex_unlock(&server->rcv.creq_mutex); 466 } 467drop:; 468 _recv(sock, &reply, sizeof(reply), MSG_DONTWAIT); 469 } 470} 471 472static void __ncpdgram_timeout_proc(struct ncp_server *server) 473{ 474 /* If timer is pending, we are processing another request... */ 475 if (!timer_pending(&server->timeout_tm)) { 476 struct ncp_request_reply* req; 477 478 req = server->rcv.creq; 479 if (req) { 480 int timeout; 481 482 if (server->m.flags & NCP_MOUNT_SOFT) { 483 if (server->timeout_retries-- == 0) { 484 __ncp_abort_request(server, req, -ETIMEDOUT); 485 return; 486 } 487 } 488 /* Ignore errors */ 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; 493 } 494 server->timeout_last = timeout; 495 mod_timer(&server->timeout_tm, jiffies + timeout); 496 } 497 } 498} 499 500void ncpdgram_timeout_proc(struct work_struct *work) 501{ 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); 507} 508 509static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len) 510{ 511 int result; 512 513 if (buffer) { 514 result = _recv(server->ncp_sock, buffer, len, MSG_DONTWAIT); 515 } else { 516 static unsigned char dummy[1024]; 517 518 if (len > sizeof(dummy)) { 519 len = sizeof(dummy); 520 } 521 result = _recv(server->ncp_sock, dummy, len, MSG_DONTWAIT); 522 } 523 if (result < 0) { 524 return result; 525 } 526 if (result > len) { 527 printk(KERN_ERR "ncpfs: tcp: bug in recvmsg (%u > %Zu)\n", result, len); 528 return -EIO; 529 } 530 return result; 531} 532 533static int __ncptcp_rcv_proc(struct ncp_server *server) 534{ 535 /* We have to check the result, so store the complete header */ 536 while (1) { 537 int result; 538 struct ncp_request_reply *req; 539 int datalen; 540 int type; 541 542 while (server->rcv.len) { 543 result = do_tcp_rcv(server, server->rcv.ptr, server->rcv.len); 544 if (result == -EAGAIN) { 545 return 0; 546 } 547 if (result <= 0) { 548 req = server->rcv.creq; 549 if (req) { 550 __ncp_abort_request(server, req, -EIO); 551 } else { 552 __ncptcp_abort(server); 553 } 554 if (result < 0) { 555 printk(KERN_ERR "ncpfs: tcp: error in recvmsg: %d\n", result); 556 } else { 557 DPRINTK(KERN_ERR "ncpfs: tcp: EOF\n"); 558 } 559 return -EIO; 560 } 561 if (server->rcv.ptr) { 562 server->rcv.ptr += result; 563 } 564 server->rcv.len -= result; 565 } 566 switch (server->rcv.state) { 567 case 0: 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); 571 return -EIO; 572 } 573 datalen = ntohl(server->rcv.buf.len) & 0x0FFFFFFF; 574 if (datalen < 10) { 575 printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen); 576 __ncptcp_abort(server); 577 return -EIO; 578 } 579#ifdef CONFIG_NCPFS_PACKET_SIGNING 580 if (server->sign_active) { 581 if (datalen < 18) { 582 printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen); 583 __ncptcp_abort(server); 584 return -EIO; 585 } 586 server->rcv.buf.len = datalen - 8; 587 server->rcv.ptr = (unsigned char*)&server->rcv.buf.p1; 588 server->rcv.len = 8; 589 server->rcv.state = 4; 590 break; 591 } 592#endif 593 type = ntohs(server->rcv.buf.type); 594#ifdef CONFIG_NCPFS_PACKET_SIGNING 595cont:; 596#endif 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; 601 602 server->rcv.state = 5; 603 server->rcv.ptr = server->unexpected_packet.data + 2; 604 server->rcv.len = datalen - 10; 605 break; 606 } 607 DPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", type); 608skipdata2:; 609 server->rcv.state = 2; 610skipdata:; 611 server->rcv.ptr = NULL; 612 server->rcv.len = datalen - 10; 613 break; 614 } 615 req = server->rcv.creq; 616 if (!req) { 617 DPRINTK(KERN_ERR "ncpfs: Reply without appropriate request\n"); 618 goto skipdata2; 619 } 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; 623 goto skipdata; 624 } 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; 630 break; 631#ifdef CONFIG_NCPFS_PACKET_SIGNING 632 case 4: 633 datalen = server->rcv.buf.len; 634 type = ntohs(server->rcv.buf.type2); 635 goto cont; 636#endif 637 case 1: 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); 643 return -EIO; 644 } 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); 648 return -EIO; 649 } 650 } 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); 656 return -EIO; 657 } 658 } 659#endif 660 ncp_finish_request(server, req, req->datalen); 661 nextreq:; 662 __ncp_next_request(server); 663 case 2: 664 next:; 665 server->rcv.ptr = (unsigned char*)&server->rcv.buf; 666 server->rcv.len = 10; 667 server->rcv.state = 0; 668 break; 669 case 3: 670 ncp_finish_request(server, server->rcv.creq, -EIO); 671 goto nextreq; 672 case 5: 673 info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len); 674 goto next; 675 } 676 } 677} 678 679void ncp_tcp_rcv_proc(struct work_struct *work) 680{ 681 struct ncp_server *server = 682 container_of(work, struct ncp_server, rcv.tq); 683 684 mutex_lock(&server->rcv.creq_mutex); 685 __ncptcp_rcv_proc(server); 686 mutex_unlock(&server->rcv.creq_mutex); 687} 688 689void ncp_tcp_tx_proc(struct work_struct *work) 690{ 691 struct ncp_server *server = 692 container_of(work, struct ncp_server, tx.tq); 693 694 mutex_lock(&server->rcv.creq_mutex); 695 __ncptcp_try_send(server); 696 mutex_unlock(&server->rcv.creq_mutex); 697} 698 699static int do_ncp_rpc_call(struct ncp_server *server, int size, 700 unsigned char* reply_buf, int max_reply_size) 701{ 702 int result; 703 struct ncp_request_reply *req; 704 705 req = ncp_alloc_req(); 706 if (!req) 707 return -ENOMEM; 708 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; 713 req->tx_iovlen = 1; 714 req->tx_totallen = size; 715 req->tx_type = *(u_int16_t*)server->packet; 716 717 result = ncp_add_request(server, req); 718 if (result < 0) 719 goto out; 720 721 if (wait_event_interruptible(req->wq, req->status == RQ_DONE)) { 722 ncp_abort_request(server, req, -EINTR); 723 result = -EINTR; 724 goto out; 725 } 726 727 result = req->result; 728 729out: 730 ncp_req_put(req); 731 732 return result; 733} 734 735/* 736 * We need the server to be locked here, so check! 737 */ 738 739static int ncp_do_request(struct ncp_server *server, int size, 740 void* reply, int max_reply_size) 741{ 742 int result; 743 744 if (server->lock == 0) { 745 printk(KERN_ERR "ncpfs: Server not locked!\n"); 746 return -EIO; 747 } 748 if (!ncp_conn_valid(server)) { 749 printk(KERN_ERR "ncpfs: Connection invalid!\n"); 750 return -EIO; 751 } 752 { 753 sigset_t old_set; 754 unsigned long mask, flags; 755 756 spin_lock_irqsave(¤t->sighand->siglock, flags); 757 old_set = current->blocked; 758 if (current->flags & PF_EXITING) 759 mask = 0; 760 else 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); 767 } 768 siginitsetinv(¤t->blocked, mask); 769 recalc_sigpending(); 770 spin_unlock_irqrestore(¤t->sighand->siglock, flags); 771 772 result = do_ncp_rpc_call(server, size, reply, max_reply_size); 773 774 spin_lock_irqsave(¤t->sighand->siglock, flags); 775 current->blocked = old_set; 776 recalc_sigpending(); 777 spin_unlock_irqrestore(¤t->sighand->siglock, flags); 778 } 779 780 DDPRINTK("do_ncp_rpc_call returned %d\n", result); 781 782 return result; 783} 784 785/* ncp_do_request assures that at least a complete reply header is 786 * received. It assumes that server->current_size contains the ncp 787 * request size 788 */ 789int ncp_request2(struct ncp_server *server, int function, 790 void* rpl, int size) 791{ 792 struct ncp_request_header *h; 793 struct ncp_reply_header* reply = rpl; 794 int result; 795 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); 799 } 800 h->type = NCP_REQUEST; 801 /* 802 * The server shouldn't know or care what task is making a 803 * request, so we always use the same task number. 804 */ 805 h->task = 2; /* (current->pid) & 0xff; */ 806 h->function = function; 807 808 result = ncp_do_request(server, server->current_size, reply, size); 809 if (result < 0) { 810 DPRINTK("ncp_request_error: %d\n", result); 811 goto out; 812 } 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); 817 818 result = reply->completion_code; 819 820 if (result != 0) 821 PPRINTK("ncp_request: completion code=%x\n", result); 822out: 823 return result; 824} 825 826int ncp_connect(struct ncp_server *server) 827{ 828 struct ncp_request_header *h; 829 int result; 830 831 server->connection = 0xFFFF; 832 server->sequence = 255; 833 834 h = (struct ncp_request_header *) (server->packet); 835 h->type = NCP_ALLOC_SLOT_REQUEST; 836 h->task = 2; /* see above */ 837 h->function = 0; 838 839 result = ncp_do_request(server, sizeof(*h), server->packet, server->packet_size); 840 if (result < 0) 841 goto out; 842 server->connection = h->conn_low + (h->conn_high * 256); 843 result = 0; 844out: 845 return result; 846} 847 848int ncp_disconnect(struct ncp_server *server) 849{ 850 struct ncp_request_header *h; 851 852 h = (struct ncp_request_header *) (server->packet); 853 h->type = NCP_DEALLOC_SLOT_REQUEST; 854 h->task = 2; /* see above */ 855 h->function = 0; 856 857 return ncp_do_request(server, sizeof(*h), server->packet, server->packet_size); 858} 859 860void ncp_lock_server(struct ncp_server *server) 861{ 862 mutex_lock(&server->mutex); 863 if (server->lock) 864 printk(KERN_WARNING "ncp_lock_server: was locked!\n"); 865 server->lock = 1; 866} 867 868void ncp_unlock_server(struct ncp_server *server) 869{ 870 if (!server->lock) { 871 printk(KERN_WARNING "ncp_unlock_server: was not locked!\n"); 872 return; 873 } 874 server->lock = 0; 875 mutex_unlock(&server->mutex); 876} 877