Ejemplo n.º 1
0
static void __ncpdgram_timeout_proc(struct ncp_server *server) {
    /* If timer is pending, we are processing another request... */
    if (!timer_pending(&server->timeout_tm)) {
        struct ncp_request_reply* req;

        req = server->rcv.creq;
        if (req) {
            int timeout;

            if (server->m.flags & NCP_MOUNT_SOFT) {
                if (server->timeout_retries-- == 0) {
                    __ncp_abort_request(server, req, -ETIMEDOUT);
                    return;
                }
            }
            /* Ignore errors */
            ncpdgram_send(server->ncp_sock, req);
            timeout = server->timeout_last << 1;
            if (timeout > NCP_MAX_RPC_TIMEOUT) {
                timeout = NCP_MAX_RPC_TIMEOUT;
            }
            server->timeout_last = timeout;
            mod_timer(&server->timeout_tm, jiffies + timeout);
        }
    }
}
Ejemplo n.º 2
0
static void __ncptcp_try_send(struct ncp_server *server) {
	struct ncp_request_reply *rq;
	struct msghdr msg;
	struct iovec* iov;
	struct iovec iovc[3];
	int result;

	rq = server->tx.creq;
	if (!rq) {
		return;
	}

	/* sock_sendmsg updates iov pointers for us :-( */
	memcpy(iovc, rq->tx_ciov, rq->tx_iovlen * sizeof(iov[0]));
	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_control = NULL;
	msg.msg_iov = iovc;
	msg.msg_iovlen = rq->tx_iovlen;
	msg.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT;
	result = sock_sendmsg(server->ncp_sock, &msg, rq->tx_totallen);
	if (result == -EAGAIN) {
		return;
	}
	if (result < 0) {
		printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result);
		__ncp_abort_request(server, rq, result);
		return;
	}
	if (result >= rq->tx_totallen) {
		server->rcv.creq = rq;
		server->tx.creq = NULL;
		return;
	}
	rq->tx_totallen -= result;
	iov = rq->tx_ciov;
	while (iov->iov_len <= result) {
		result -= iov->iov_len;
		iov++;
		rq->tx_iovlen--;
	}
	iov->iov_base += result;
	iov->iov_len -= result;
	rq->tx_ciov = iov;
}
Ejemplo n.º 3
0
static void __ncptcp_try_send(struct ncp_server *server)
{
	struct ncp_request_reply *rq;
	struct kvec *iov;
	struct kvec iovc[3];
	int result;

	rq = server->tx.creq;
	if (!rq)
		return;

	
	memcpy(iovc, rq->tx_ciov, rq->tx_iovlen * sizeof(iov[0]));
	result = do_send(server->ncp_sock, iovc, rq->tx_iovlen,
			 rq->tx_totallen, MSG_NOSIGNAL | MSG_DONTWAIT);

	if (result == -EAGAIN)
		return;

	if (result < 0) {
		printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result);
		__ncp_abort_request(server, rq, result);
		return;
	}
	if (result >= rq->tx_totallen) {
		server->rcv.creq = rq;
		server->tx.creq = NULL;
		return;
	}
	rq->tx_totallen -= result;
	iov = rq->tx_ciov;
	while (iov->iov_len <= result) {
		result -= iov->iov_len;
		iov++;
		rq->tx_iovlen--;
	}
	iov->iov_base += result;
	iov->iov_len -= result;
	rq->tx_ciov = iov;
}
Ejemplo n.º 4
0
static int __ncptcp_rcv_proc(struct ncp_server *server) {
    /* We have to check the result, so store the complete header */
    while (1) {
        int result;
        struct ncp_request_reply *req;
        int datalen;
        int type;

        while (server->rcv.len) {
            result = do_tcp_rcv(server, server->rcv.ptr, server->rcv.len);
            if (result == -EAGAIN) {
                return 0;
            }
            if (result <= 0) {
                req = server->rcv.creq;
                if (req) {
                    __ncp_abort_request(server, req, -EIO);
                } else {
                    __ncptcp_abort(server);
                }
                if (result < 0) {
                    printk(KERN_ERR "ncpfs: tcp: error in recvmsg: %d\n", result);
                } else {
                    DPRINTK(KERN_ERR "ncpfs: tcp: EOF\n");
                }
                return -EIO;
            }
            if (server->rcv.ptr) {
                server->rcv.ptr += result;
            }
            server->rcv.len -= result;
        }
        switch (server->rcv.state) {
        case 0:
            if (server->rcv.buf.magic != htonl(NCP_TCP_RCVD_MAGIC)) {
                printk(KERN_ERR "ncpfs: tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic));
                __ncptcp_abort(server);
                return -EIO;
            }
            datalen = ntohl(server->rcv.buf.len) & 0x0FFFFFFF;
            if (datalen < 10) {
                printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
                __ncptcp_abort(server);
                return -EIO;
            }
#ifdef CONFIG_NCPFS_PACKET_SIGNING
            if (server->sign_active) {
                if (datalen < 18) {
                    printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
                    __ncptcp_abort(server);
                    return -EIO;
                }
                server->rcv.buf.len = datalen - 8;
                server->rcv.ptr = (unsigned char*)&server->rcv.buf.p1;
                server->rcv.len = 8;
                server->rcv.state = 4;
                break;
            }
#endif
            type = ntohs(server->rcv.buf.type);
#ifdef CONFIG_NCPFS_PACKET_SIGNING
cont:
            ;
#endif
            if (type != NCP_REPLY) {
                if (datalen - 8 <= sizeof(server->unexpected_packet.data)) {
                    *(__u16*)(server->unexpected_packet.data) = htons(type);
                    server->unexpected_packet.len = datalen - 8;

                    server->rcv.state = 5;
                    server->rcv.ptr = server->unexpected_packet.data + 2;
                    server->rcv.len = datalen - 10;
                    break;
                }
                DPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", type);
skipdata2:
                ;
                server->rcv.state = 2;
skipdata:
                ;
                server->rcv.ptr = NULL;
                server->rcv.len = datalen - 10;
                break;
            }
            req = server->rcv.creq;
            if (!req) {
                DPRINTK(KERN_ERR "ncpfs: Reply without appropriate request\n");
                goto skipdata2;
            }
            if (datalen > req->datalen + 8) {
                printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d (expected at most %Zd)\n", datalen, req->datalen + 8);
                server->rcv.state = 3;
                goto skipdata;
            }
            req->datalen = datalen - 8;
            req->reply_buf->type = NCP_REPLY;
            server->rcv.ptr = (unsigned char*)(req->reply_buf) + 2;
            server->rcv.len = datalen - 10;
            server->rcv.state = 1;
            break;
#ifdef CONFIG_NCPFS_PACKET_SIGNING
        case 4:
            datalen = server->rcv.buf.len;
            type = ntohs(server->rcv.buf.type2);
            goto cont;
#endif
        case 1:
            req = server->rcv.creq;
            if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) {
                if (req->reply_buf->sequence != server->sequence) {
                    printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n");
                    __ncp_abort_request(server, req, -EIO);
                    return -EIO;
                }
                if ((req->reply_buf->conn_low | (req->reply_buf->conn_high << 8)) != server->connection) {
                    printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n");
                    __ncp_abort_request(server, req, -EIO);
                    return -EIO;
                }
            }
#ifdef CONFIG_NCPFS_PACKET_SIGNING
            if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
                if (sign_verify_reply(server, (unsigned char*)(req->reply_buf) + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) {
                    printk(KERN_ERR "ncpfs: tcp: Signature violation\n");
                    __ncp_abort_request(server, req, -EIO);
                    return -EIO;
                }
            }
#endif
            ncp_finish_request(req, req->datalen);
nextreq:
            ;
            __ncp_next_request(server);
        case 2:
next:
            ;
            server->rcv.ptr = (unsigned char*)&server->rcv.buf;
            server->rcv.len = 10;
            server->rcv.state = 0;
            break;
        case 3:
            ncp_finish_request(server->rcv.creq, -EIO);
            goto nextreq;
        case 5:
            info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len);
            goto next;
        }
    }
}
Ejemplo n.º 5
0
static inline void ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err) {
    down(&server->rcv.creq_sem);
    __ncp_abort_request(server, req, err);
    up(&server->rcv.creq_sem);
}
Ejemplo n.º 6
0
static inline void ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err)
{
	mutex_lock(&server->rcv.creq_mutex);
	__ncp_abort_request(server, req, err);
	mutex_unlock(&server->rcv.creq_mutex);
}