Skip to content

Commit

Permalink
[PATCH] knfsd: SUNRPC: support IPv6 addresses in RPC server's UDP rec…
Browse files Browse the repository at this point in the history
…eive path

Add support for IPv6 addresses in the RPC server's UDP receive path.

[akpm@linux-foundation.org: cleanups]
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon@ext.bull.net>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Chuck Lever authored and Linus Torvalds committed Feb 12, 2007
1 parent cdd88b9 commit 9575648
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 10 deletions.
5 changes: 5 additions & 0 deletions include/linux/sunrpc/svc.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,11 @@ static inline struct sockaddr_in *svc_addr_in(struct svc_rqst *rqst)
return (struct sockaddr_in *) &rqst->rq_addr;
}

static inline struct sockaddr_in6 *svc_addr_in6(struct svc_rqst *rqst)
{
return (struct sockaddr_in6 *) &rqst->rq_addr;
}

static inline struct sockaddr *svc_addr(struct svc_rqst *rqst)
{
return (struct sockaddr *) &rqst->rq_addr;
Expand Down
53 changes: 43 additions & 10 deletions net/sunrpc/svcsock.c
Original file line number Diff line number Diff line change
Expand Up @@ -721,13 +721,53 @@ svc_write_space(struct sock *sk)
}
}

static void svc_udp_get_sender_address(struct svc_rqst *rqstp,
struct sk_buff *skb)
{
switch (rqstp->rq_sock->sk_sk->sk_family) {
case AF_INET: {
/* this seems to come from net/ipv4/udp.c:udp_recvmsg */
struct sockaddr_in *sin = svc_addr_in(rqstp);

sin->sin_family = AF_INET;
sin->sin_port = skb->h.uh->source;
sin->sin_addr.s_addr = skb->nh.iph->saddr;
rqstp->rq_addrlen = sizeof(struct sockaddr_in);
/* Remember which interface received this request */
rqstp->rq_daddr.addr.s_addr = skb->nh.iph->daddr;
}
break;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case AF_INET6: {
/* this is derived from net/ipv6/udp.c:udpv6_recvmesg */
struct sockaddr_in6 *sin6 = svc_addr_in6(rqstp);

sin6->sin6_family = AF_INET6;
sin6->sin6_port = skb->h.uh->source;
sin6->sin6_flowinfo = 0;
sin6->sin6_scope_id = 0;
if (ipv6_addr_type(&sin6->sin6_addr) &
IPV6_ADDR_LINKLOCAL)
sin6->sin6_scope_id = IP6CB(skb)->iif;
ipv6_addr_copy(&sin6->sin6_addr,
&skb->nh.ipv6h->saddr);
rqstp->rq_addrlen = sizeof(struct sockaddr_in);
/* Remember which interface received this request */
ipv6_addr_copy(&rqstp->rq_daddr.addr6,
&skb->nh.ipv6h->saddr);
}
break;
#endif
}
return;
}

/*
* Receive a datagram from a UDP socket.
*/
static int
svc_udp_recvfrom(struct svc_rqst *rqstp)
{
struct sockaddr_in *sin = svc_addr_in(rqstp);
struct svc_sock *svsk = rqstp->rq_sock;
struct svc_serv *serv = svsk->sk_server;
struct sk_buff *skb;
Expand Down Expand Up @@ -785,16 +825,9 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
len = skb->len - sizeof(struct udphdr);
rqstp->rq_arg.len = len;

rqstp->rq_prot = IPPROTO_UDP;

/* Get sender address */
sin->sin_family = AF_INET;
sin->sin_port = skb->h.uh->source;
sin->sin_addr.s_addr = skb->nh.iph->saddr;
rqstp->rq_addrlen = sizeof(struct sockaddr_in);
rqstp->rq_prot = IPPROTO_UDP;

/* Remember which interface received this request */
rqstp->rq_daddr.addr.s_addr = skb->nh.iph->daddr;
svc_udp_get_sender_address(rqstp, skb);

if (skb_is_nonlinear(skb)) {
/* we have to copy */
Expand Down

0 comments on commit 9575648

Please sign in to comment.