Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 95756482 authored by Chuck Lever's avatar Chuck Lever Committed by Linus Torvalds
Browse files

[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: default avatarChuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon@ext.bull.net>
Signed-off-by: default avatarNeil Brown <neilb@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent cdd88b9f
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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;
+43 −10
Original line number Diff line number Diff line
@@ -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;
@@ -787,14 +827,7 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)

	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);

	/* 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 */