linux/fs/ncpfs/sock.c
<<
>>
Prefs
   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(&current->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                        /* FIXME: This doesn't seem right at all.  So, like,
 763                           we can't handle SIGINT and get whatever to stop?
 764                           What if we've blocked it ourselves?  What about
 765                           alarms?  Why, in fact, are we mucking with the
 766                           sigmask at all? -- r~ */
 767                        if (current->sighand->action[SIGINT - 1].sa.sa_handler == SIG_DFL)
 768                                mask |= sigmask(SIGINT);
 769                        if (current->sighand->action[SIGQUIT - 1].sa.sa_handler == SIG_DFL)
 770                                mask |= sigmask(SIGQUIT);
 771                }
 772                siginitsetinv(&current->blocked, mask);
 773                recalc_sigpending();
 774                spin_unlock_irqrestore(&current->sighand->siglock, flags);
 775                
 776                result = do_ncp_rpc_call(server, size, reply, max_reply_size);
 777
 778                spin_lock_irqsave(&current->sighand->siglock, flags);
 779                current->blocked = old_set;
 780                recalc_sigpending();
 781                spin_unlock_irqrestore(&current->sighand->siglock, flags);
 782        }
 783
 784        DDPRINTK("do_ncp_rpc_call returned %d\n", result);
 785
 786        return result;
 787}
 788
 789/* ncp_do_request assures that at least a complete reply header is
 790 * received. It assumes that server->current_size contains the ncp
 791 * request size
 792 */
 793int ncp_request2(struct ncp_server *server, int function, 
 794                void* rpl, int size)
 795{
 796        struct ncp_request_header *h;
 797        struct ncp_reply_header* reply = rpl;
 798        int result;
 799
 800        h = (struct ncp_request_header *) (server->packet);
 801        if (server->has_subfunction != 0) {
 802                *(__u16 *) & (h->data[0]) = htons(server->current_size - sizeof(*h) - 2);
 803        }
 804        h->type = NCP_REQUEST;
 805        /*
 806         * The server shouldn't know or care what task is making a
 807         * request, so we always use the same task number.
 808         */
 809        h->task = 2; /* (current->pid) & 0xff; */
 810        h->function = function;
 811
 812        result = ncp_do_request(server, server->current_size, reply, size);
 813        if (result < 0) {
 814                DPRINTK("ncp_request_error: %d\n", result);
 815                goto out;
 816        }
 817        server->completion = reply->completion_code;
 818        server->conn_status = reply->connection_state;
 819        server->reply_size = result;
 820        server->ncp_reply_size = result - sizeof(struct ncp_reply_header);
 821
 822        result = reply->completion_code;
 823
 824        if (result != 0)
 825                PPRINTK("ncp_request: completion code=%x\n", result);
 826out:
 827        return result;
 828}
 829
 830int ncp_connect(struct ncp_server *server)
 831{
 832        struct ncp_request_header *h;
 833        int result;
 834
 835        server->connection = 0xFFFF;
 836        server->sequence = 255;
 837
 838        h = (struct ncp_request_header *) (server->packet);
 839        h->type = NCP_ALLOC_SLOT_REQUEST;
 840        h->task         = 2; /* see above */
 841        h->function     = 0;
 842
 843        result = ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
 844        if (result < 0)
 845                goto out;
 846        server->connection = h->conn_low + (h->conn_high * 256);
 847        result = 0;
 848out:
 849        return result;
 850}
 851
 852int ncp_disconnect(struct ncp_server *server)
 853{
 854        struct ncp_request_header *h;
 855
 856        h = (struct ncp_request_header *) (server->packet);
 857        h->type = NCP_DEALLOC_SLOT_REQUEST;
 858        h->task         = 2; /* see above */
 859        h->function     = 0;
 860
 861        return ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
 862}
 863
 864void ncp_lock_server(struct ncp_server *server)
 865{
 866        mutex_lock(&server->mutex);
 867        if (server->lock)
 868                printk(KERN_WARNING "ncp_lock_server: was locked!\n");
 869        server->lock = 1;
 870}
 871
 872void ncp_unlock_server(struct ncp_server *server)
 873{
 874        if (!server->lock) {
 875                printk(KERN_WARNING "ncp_unlock_server: was not locked!\n");
 876                return;
 877        }
 878        server->lock = 0;
 879        mutex_unlock(&server->mutex);
 880}
 881