[PATCH] knfsd: SUNRPC: support IPv6 addresses in RPC server's UDP receive 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>
This commit is contained in:
parent
cdd88b9f3e
commit
95756482c9
@ -270,6 +270,11 @@ static inline struct sockaddr_in *svc_addr_in(struct svc_rqst *rqst)
|
|||||||
return (struct sockaddr_in *) &rqst->rq_addr;
|
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)
|
static inline struct sockaddr *svc_addr(struct svc_rqst *rqst)
|
||||||
{
|
{
|
||||||
return (struct sockaddr *) &rqst->rq_addr;
|
return (struct sockaddr *) &rqst->rq_addr;
|
||||||
|
@ -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.
|
* Receive a datagram from a UDP socket.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
svc_udp_recvfrom(struct svc_rqst *rqstp)
|
svc_udp_recvfrom(struct svc_rqst *rqstp)
|
||||||
{
|
{
|
||||||
struct sockaddr_in *sin = svc_addr_in(rqstp);
|
|
||||||
struct svc_sock *svsk = rqstp->rq_sock;
|
struct svc_sock *svsk = rqstp->rq_sock;
|
||||||
struct svc_serv *serv = svsk->sk_server;
|
struct svc_serv *serv = svsk->sk_server;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
@ -785,16 +825,9 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
|
|||||||
len = skb->len - sizeof(struct udphdr);
|
len = skb->len - sizeof(struct udphdr);
|
||||||
rqstp->rq_arg.len = len;
|
rqstp->rq_arg.len = len;
|
||||||
|
|
||||||
rqstp->rq_prot = IPPROTO_UDP;
|
rqstp->rq_prot = IPPROTO_UDP;
|
||||||
|
|
||||||
/* Get sender address */
|
svc_udp_get_sender_address(rqstp, skb);
|
||||||
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;
|
|
||||||
|
|
||||||
if (skb_is_nonlinear(skb)) {
|
if (skb_is_nonlinear(skb)) {
|
||||||
/* we have to copy */
|
/* we have to copy */
|
||||||
|
Loading…
Reference in New Issue
Block a user