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