/* * Receive a datagram from a UDP socket. */ static int svc_udp_recvfrom(struct svc_rqst *rqstp) { struct svc_sock *svsk = rqstp->rq_sock; struct svc_serv *serv = svsk->sk_server; struct sk_buff *skb; u32 *data; int err, len; svsk->sk_data = 0; while ((skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err)) == NULL) { svc_sock_received(svsk, 0); if (err == -EAGAIN) return err; /* possibly an icmp error */ dprintk("svc: recvfrom returned error %d\n", -err); } if (skb->ip_summed != CHECKSUM_UNNECESSARY) { unsigned int csum = skb->csum; csum = csum_partial(skb->h.raw, skb->len, csum); if ((unsigned short)csum_fold(csum)) { skb_free_datagram(svsk->sk_sk, skb); svc_sock_received(svsk, 0); return 0; } } /* There may be more data */ svsk->sk_data = 1; len = skb->len - sizeof(struct udphdr); data = (u32 *) (skb->h.raw + sizeof(struct udphdr)); rqstp->rq_skbuff = skb; rqstp->rq_argbuf.base = data; rqstp->rq_argbuf.buf = data; rqstp->rq_argbuf.len = (len >> 2); /* rqstp->rq_resbuf = rqstp->rq_defbuf; */ rqstp->rq_prot = IPPROTO_UDP; /* Get sender address */ rqstp->rq_addr.sin_family = AF_INET; rqstp->rq_addr.sin_port = skb->h.uh->source; rqstp->rq_addr.sin_addr.s_addr = skb->nh.iph->saddr; if (serv->sv_stats) serv->sv_stats->netudpcnt++; /* One down, maybe more to go... */ svsk->sk_sk->stamp = skb->stamp; svc_sock_received(svsk, 0); return len; }
/* * Receive a datagram from a UDP socket. */ static int svc_udp_recvfrom(struct svc_rqst *rqstp) { struct svc_sock *svsk = rqstp->rq_sock; struct svc_serv *serv = svsk->sk_server; struct sk_buff *skb; u32 *data; int err, len; svsk->sk_data = 0; while ((skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err)) == NULL) { svc_sock_received(svsk, 0); if (err == -EAGAIN) return err; /* possibly an icmp error */ dprintk("svc: recvfrom returned error %d\n", -err); } /* There may be more data */ svsk->sk_data = 1; len = skb->len - sizeof(struct udphdr); data = (u32 *) (skb->h.raw + sizeof(struct udphdr)); rqstp->rq_skbuff = skb; rqstp->rq_argbuf.base = data; rqstp->rq_argbuf.buf = data; rqstp->rq_argbuf.len = (len >> 2); /* rqstp->rq_resbuf = rqstp->rq_defbuf; */ rqstp->rq_prot = IPPROTO_UDP; /* Get sender address */ rqstp->rq_addr.sin_family = AF_INET; rqstp->rq_addr.sin_port = skb->h.uh->source; #if LINUX_VERSION_CODE >= 0x020100 rqstp->rq_addr.sin_addr.s_addr = skb->nh.iph->saddr; #else rqstp->rq_addr.sin_addr.s_addr = skb->saddr; #endif if (serv->sv_stats) serv->sv_stats->netudpcnt++; /* One down, maybe more to go... */ svsk->sk_sk->stamp = skb->stamp; svc_sock_received(svsk, 0); return len; }
/* * Receive data from a TCP socket. */ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) { struct svc_sock *svsk = rqstp->rq_sock; struct svc_serv *serv = svsk->sk_server; struct svc_buf *bufp = &rqstp->rq_argbuf; int len, ready, used; dprintk("svc: tcp_recv %p data %d conn %d close %d\n", svsk, svsk->sk_data, svsk->sk_conn, svsk->sk_close); if (svsk->sk_close) { svc_delete_socket(svsk); return 0; } if (svsk->sk_conn) { svc_tcp_accept(svsk); svc_sock_accepted(svsk); return 0; } ready = svsk->sk_data; /* Receive data. If we haven't got the record length yet, get * the next four bytes. Otherwise try to gobble up as much as * possible up to the complete record length. */ if (svsk->sk_tcplen < 4) { unsigned long want = 4 - svsk->sk_tcplen; struct iovec iov; iov.iov_base = ((char *) &svsk->sk_reclen) + svsk->sk_tcplen; iov.iov_len = want; if ((len = svc_recvfrom(rqstp, &iov, 1, want)) < 0) goto error; svsk->sk_tcplen += len; svsk->sk_reclen = ntohl(svsk->sk_reclen); if (!(svsk->sk_reclen & 0x80000000)) { /* FIXME: technically, a record can be fragmented, * and non-terminal fragments will not have the top * bit set in the fragment length header. * But apparently no known nfs clients send fragmented * records. */ /* FIXME: shutdown socket */ printk(KERN_NOTICE "RPC: bad TCP reclen %08lx", (unsigned long) svsk->sk_reclen); return -EIO; } svsk->sk_reclen &= 0x7fffffff; dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen); } /* Check whether enough data is available */ len = svc_recv_available(svsk); if (len < 0) goto error; if (len < svsk->sk_reclen) { /* FIXME: if sk_reclen > window-size, then we will * never be able to receive the record, so should * shutdown the connection */ dprintk("svc: incomplete TCP record (%d of %d)\n", len, svsk->sk_reclen); svc_sock_received(svsk, ready); return -EAGAIN; /* record not complete */ } /* if we think there is only one more record to read, but * it is bigger than we expect, then two records must have arrived * together, so pretend we aren't using the record.. */ if (len > svsk->sk_reclen && ready == 1) used = 0; else used = 1; /* Frob argbuf */ bufp->iov[0].iov_base += 4; bufp->iov[0].iov_len -= 4; /* Now receive data */ len = svc_recvfrom(rqstp, bufp->iov, bufp->nriov, svsk->sk_reclen); if (len < 0) goto error; dprintk("svc: TCP complete record (%d bytes)\n", len); /* Position reply write pointer immediately after * record length */ rqstp->rq_resbuf.buf += 1; rqstp->rq_resbuf.len = 1; rqstp->rq_skbuff = 0; rqstp->rq_argbuf.buf += 1; rqstp->rq_argbuf.len = (len >> 2); rqstp->rq_prot = IPPROTO_TCP; /* Reset TCP read info */ svsk->sk_reclen = 0; svsk->sk_tcplen = 0; svc_sock_received(svsk, used); if (serv->sv_stats) serv->sv_stats->nettcpcnt++; return len; error: if (len == -EAGAIN) { dprintk("RPC: TCP recvfrom got EAGAIN\n"); svc_sock_received(svsk, ready); /* Clear data ready */ } else { printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", svsk->sk_server->sv_name, -len); svc_sock_received(svsk, 0); } return len; }
/* * Receive data from a TCP socket. */ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) { struct svc_sock *svsk = rqstp->rq_sock; struct svc_serv *serv = svsk->sk_server; struct svc_buf *bufp = &rqstp->rq_argbuf; int len, ready; dprintk("svc: tcp_recv %p data %d conn %d close %d\n", svsk, svsk->sk_data, svsk->sk_conn, svsk->sk_close); if (svsk->sk_close) { svc_delete_socket(svsk); return 0; } if (svsk->sk_conn) { svc_tcp_accept(svsk); svc_sock_accepted(svsk); return 0; } ready = svsk->sk_data; /* Receive data. If we haven't got the record length yet, get * the next four bytes. Otherwise try to gobble up as much as * possible up to the complete record length. */ if (svsk->sk_tcplen < 4) { unsigned long want = 4 - svsk->sk_tcplen; struct iovec iov; iov.iov_base = ((u32 *) &svsk->sk_reclen) + svsk->sk_tcplen; iov.iov_len = want; if ((len = svc_recvfrom(rqstp, &iov, 1, want)) < 0) goto error; svsk->sk_tcplen += len; svsk->sk_reclen = ntohl(svsk->sk_reclen); if (!(svsk->sk_reclen & 0x80000000)) { /* FIXME: shutdown socket */ printk(KERN_NOTICE "RPC: bad TCP reclen %08lx", (unsigned long) svsk->sk_reclen); return -EIO; } svsk->sk_reclen &= 0x7fffffff; dprintk("svc: TCP record, %ld bytes\n", svsk->sk_reclen); } /* Check whether enough data is available */ len = svc_recv_available(svsk); if (len < 0) goto error; if (len < svsk->sk_reclen) { dprintk("svc: incomplete TCP record (%d of %ld)\n", len, svsk->sk_reclen); svc_sock_received(svsk, ready); len = -EAGAIN; /* record not complete */ } /* Frob argbuf */ bufp->iov[0].iov_base += 4; bufp->iov[0].iov_len -= 4; /* Now receive data */ len = svc_recvfrom(rqstp, bufp->iov, bufp->nriov, svsk->sk_reclen); if (len < 0) goto error; dprintk("svc: TCP complete record (%d bytes)\n", len); /* Position reply write pointer immediately after * record length */ rqstp->rq_resbuf.buf += 1; rqstp->rq_resbuf.len = 1; rqstp->rq_skbuff = 0; rqstp->rq_argbuf.buf += 1; rqstp->rq_argbuf.len = (len >> 2); rqstp->rq_prot = IPPROTO_TCP; /* Reset TCP read info */ svsk->sk_reclen = 0; svsk->sk_tcplen = 0; svc_sock_received(svsk, 1); if (serv->sv_stats) serv->sv_stats->nettcpcnt++; return len; error: if (len == -EAGAIN) { dprintk("RPC: TCP recvfrom got EAGAIN\n"); svc_sock_received(svsk, ready); /* Clear data ready */ } else { printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", svsk->sk_server->sv_name, -len); svc_sock_received(svsk, 0); } return len; }