示例#1
0
文件: sock.c 项目: xricson/knoppix
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;
        }
    }
}
示例#2
0
static int do_ncp_tcp_rpc_call(struct ncp_server *server, int size,
		struct ncp_reply_header* reply_buf, int max_reply_size)
{
	struct file *file;
	struct socket *sock;
	int result;
	struct iovec iov[2];
	struct msghdr msg;
	struct scm_cookie scm;
	__u32 ncptcp_rcvd_hdr[2];
	__u32 ncptcp_xmit_hdr[4];
	int   datalen;

	/* We have to check the result, so store the complete header */
	struct ncp_request_header request =
	*((struct ncp_request_header *) (server->packet));

	file = server->ncp_filp;
	sock = &file->f_dentry->d_inode->u.socket_i;
	
	ncptcp_xmit_hdr[0] = htonl(NCP_TCP_XMIT_MAGIC);
	ncptcp_xmit_hdr[1] = htonl(size + 16);
	ncptcp_xmit_hdr[2] = htonl(NCP_TCP_XMIT_VERSION);
	ncptcp_xmit_hdr[3] = htonl(max_reply_size + 8);

	DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
		 "seq: %d",
		 request.type,
		 (request.conn_high << 8) + request.conn_low,
		 request.sequence);
	DDPRINTK(" func: %d\n",
		 request.function);

	iov[1].iov_base = (void *) server->packet;
	iov[1].iov_len = size;
	iov[0].iov_base = ncptcp_xmit_hdr;
	iov[0].iov_len = 16;
	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_control = NULL;
	msg.msg_iov = iov;
	msg.msg_iovlen = 2;
	msg.msg_flags = MSG_NOSIGNAL;

	result = scm_send(sock, &msg, &scm);
	if (result < 0) {
		return result;
	}
	result = sock->ops->sendmsg(sock, &msg, size + 16, &scm);
	scm_destroy(&scm);
	if (result < 0) {
		printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result);
		return result;
	}
rstrcv:
	result = do_tcp_rcv(server, ncptcp_rcvd_hdr, 8);
	if (result)
		return result;
	if (ncptcp_rcvd_hdr[0] != htonl(NCP_TCP_RCVD_MAGIC)) {
		printk(KERN_ERR "ncpfs: tcp: Unexpected reply type %08X\n", ntohl(ncptcp_rcvd_hdr[0]));
		return -EIO;
	}
	datalen = ntohl(ncptcp_rcvd_hdr[1]);
	if (datalen < 8 + sizeof(*reply_buf) || datalen > max_reply_size + 8) {
		printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
		return -EIO;
	}
	datalen -= 8;
	result = do_tcp_rcv(server, reply_buf, datalen);
	if (result)
		return result;
	if (reply_buf->type != NCP_REPLY) {
		DDPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", reply_buf->type);
		goto rstrcv;
	}
	if (request.type == NCP_ALLOC_SLOT_REQUEST)
		return datalen;
	if (reply_buf->sequence != request.sequence) {
		printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n");
		return -EIO;
	}
	if ((reply_buf->conn_low != request.conn_low) ||
	    (reply_buf->conn_high != request.conn_high)) {
		printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n");
		return -EIO;
	}
	return datalen;
}