Exemple #1
0
static void __abort_ncp_connection(struct ncp_server *server)
{
	struct ncp_request_reply *req;

	ncp_invalidate_conn(server);
	del_timer(&server->timeout_tm);
	while (!list_empty(&server->tx.requests)) {
		req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
		
		list_del_init(&req->req);
		ncp_finish_request(server, req, -EIO);
	}
	req = server->rcv.creq;
	if (req) {
		server->rcv.creq = NULL;
		ncp_finish_request(server, req, -EIO);
		server->rcv.ptr = NULL;
		server->rcv.state = 0;
	}
	req = server->tx.creq;
	if (req) {
		server->tx.creq = NULL;
		ncp_finish_request(server, req, -EIO);
	}
}
Exemple #2
0
static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err) {
    /* If req is done, we got signal, but we also received answer... */
    switch (req->status) {
    case RQ_IDLE:
    case RQ_DONE:
        break;
    case RQ_QUEUED:
        list_del_init(&req->req);
        ncp_finish_request(req, err);
        break;
    case RQ_INPROGRESS:
        __abort_ncp_connection(server, req, err);
        break;
    }
}
static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err)
{
	
	switch (req->status) {
		case RQ_IDLE:
		case RQ_DONE:
			break;
		case RQ_QUEUED:
			list_del_init(&req->req);
			ncp_finish_request(server, req, err);
			break;
		case RQ_INPROGRESS:
			req->status = RQ_ABANDONED;
			break;
		case RQ_ABANDONED:
			break;
	}
}
Exemple #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;
        }
    }
}
Exemple #5
0
static void __ncpdgram_rcv_proc(void *s) {
    struct ncp_server *server = s;
    struct socket* sock;

    sock = server->ncp_sock;

    while (1) {
        struct ncp_reply_header reply;
        int result;

        result = _recv(sock, (void*)&reply, sizeof(reply), MSG_PEEK | MSG_DONTWAIT);
        if (result < 0) {
            break;
        }
        if (result >= sizeof(reply)) {
            struct ncp_request_reply *req;

            if (reply.type == NCP_WATCHDOG) {
                unsigned char buf[10];

                if (server->connection != get_conn_number(&reply)) {
                    goto drop;
                }
                result = _recv(sock, buf, sizeof(buf), MSG_DONTWAIT);
                if (result < 0) {
                    DPRINTK("recv failed with %d\n", result);
                    continue;
                }
                if (result < 10) {
                    DPRINTK("too short (%u) watchdog packet\n", result);
                    continue;
                }
                if (buf[9] != '?') {
                    DPRINTK("bad signature (%02X) in watchdog packet\n", buf[9]);
                    continue;
                }
                buf[9] = 'Y';
                _send(sock, buf, sizeof(buf));
                continue;
            }
            if (reply.type != NCP_POSITIVE_ACK && reply.type != NCP_REPLY) {
                result = _recv(sock, server->unexpected_packet.data, sizeof(server->unexpected_packet.data), MSG_DONTWAIT);
                if (result < 0) {
                    continue;
                }
                info_server(server, 0, server->unexpected_packet.data, result);
                continue;
            }
            down(&server->rcv.creq_sem);
            req = server->rcv.creq;
            if (req && (req->tx_type == NCP_ALLOC_SLOT_REQUEST || (server->sequence == reply.sequence &&
                        server->connection == get_conn_number(&reply)))) {
                if (reply.type == NCP_POSITIVE_ACK) {
                    server->timeout_retries = server->m.retry_count;
                    server->timeout_last = NCP_MAX_RPC_TIMEOUT;
                    mod_timer(&server->timeout_tm, jiffies + NCP_MAX_RPC_TIMEOUT);
                } else if (reply.type == NCP_REPLY) {
                    result = _recv(sock, (void*)req->reply_buf, req->datalen, MSG_DONTWAIT);
#ifdef CONFIG_NCPFS_PACKET_SIGNING
                    if (result >= 0 && server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
                        if (result < 8 + 8) {
                            result = -EIO;
                        } else {
                            unsigned int hdrl;

                            result -= 8;
                            hdrl = sock->sk->sk_family == AF_INET ? 8 : 6;
                            if (sign_verify_reply(server, ((char*)req->reply_buf) + hdrl, result - hdrl, cpu_to_le32(result), ((char*)req->reply_buf) + result)) {
                                printk(KERN_INFO "ncpfs: Signature violation\n");
                                result = -EIO;
                            }
                        }
                    }
#endif
                    del_timer(&server->timeout_tm);
                    server->rcv.creq = NULL;
                    ncp_finish_request(req, result);
                    __ncp_next_request(server);
                    up(&server->rcv.creq_sem);
                    continue;
                }
            }
            up(&server->rcv.creq_sem);
        }
drop:
        ;
        _recv(sock, (void*)&reply, sizeof(reply), MSG_DONTWAIT);
    }
}