2006-11-13 15:23:36

by Chuck Lever

[permalink] [raw]
Subject: [PATCH 00/13] repost RPC server patches for IPv6 support

Hi Neil-

I think I've fixed most of the issues you and Olaf pointed out last week.
Have a look and let me know.

--
corporate: <chuck dot lever at oracle dot com>

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs


2006-11-13 15:24:19

by Chuck Lever

[permalink] [raw]
Subject: [PATCH 07/13] SUNRPC: Provide room in svc_rqst for larger addresses

Expand the rq_addr field to allow it to contain larger addresses.

Signed-off-by: Chuck Lever <[email protected]>
Cc: Aurelien Charbon <[email protected]>
---

fs/lockd/host.c | 4 ++--
fs/lockd/svc4proc.c | 7 +++++--
fs/lockd/svcproc.c | 7 +++++--
fs/nfs/callback.c | 2 +-
fs/nfs/callback_xdr.c | 4 ++--
fs/nfsd/nfs4state.c | 18 +++++++++---------
fs/nfsd/nfscache.c | 2 +-
include/linux/sunrpc/svc.h | 2 +-
net/sunrpc/svcauth_unix.c | 3 ++-
net/sunrpc/svcsock.c | 14 ++++++++------
10 files changed, 36 insertions(+), 27 deletions(-)

diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index fb24a97..ca625dd 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -55,9 +55,9 @@ struct nlm_host *
nlmsvc_lookup_host(struct svc_rqst *rqstp,
const char *hostname, int hostname_len)
{
- return nlm_lookup_host(1, &rqstp->rq_addr,
+ return nlm_lookup_host(1, (struct sockaddr_in *) &rqstp->rq_addr,
rqstp->rq_prot, rqstp->rq_vers,
- hostname, hostname_len);
+ hostname, hostname_len);
}

/*
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index d724eac..15fa167 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -224,7 +224,8 @@ nlm4svc_proc_granted(struct svc_rqst *rq
resp->cookie = argp->cookie;

dprintk("lockd: GRANTED called\n");
- resp->status = nlmclnt_grant(&rqstp->rq_addr, &argp->lock);
+ resp->status = nlmclnt_grant((struct sockaddr_in *) &rqstp->rq_addr,
+ &argp->lock);
dprintk("lockd: GRANTED status %d\n", ntohl(resp->status));
return rpc_success;
}
@@ -421,7 +422,9 @@ static __be32
nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
void *resp)
{
- struct sockaddr_in saddr = rqstp->rq_addr;
+ struct sockaddr_in saddr;
+
+ memcpy(&saddr, &rqstp->rq_addr, sizeof(saddr));

dprintk("lockd: SM_NOTIFY called\n");
if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index f590304..0cc9ab1 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -253,7 +253,8 @@ nlmsvc_proc_granted(struct svc_rqst *rqs
resp->cookie = argp->cookie;

dprintk("lockd: GRANTED called\n");
- resp->status = nlmclnt_grant(&rqstp->rq_addr, &argp->lock);
+ resp->status = nlmclnt_grant((struct sockaddr_in *) &rqstp->rq_addr,
+ &argp->lock);
dprintk("lockd: GRANTED status %d\n", ntohl(resp->status));
return rpc_success;
}
@@ -452,7 +453,9 @@ static __be32
nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
void *resp)
{
- struct sockaddr_in saddr = rqstp->rq_addr;
+ struct sockaddr_in saddr;
+
+ memcpy(&saddr, &rqstp->rq_addr, sizeof(saddr));

dprintk("lockd: SM_NOTIFY called\n");
if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index d277ff9..c6be8ac 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -166,7 +166,7 @@ void nfs_callback_down(void)

static int nfs_callback_authenticate(struct svc_rqst *rqstp)
{
- struct sockaddr_in *addr = &rqstp->rq_addr;
+ struct sockaddr_in *addr = (struct sockaddr_in *) &rqstp->rq_addr;
struct nfs_client *clp;
char buf[RPC_MAX_ADDRBUFLEN];

diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index f8ea1f5..70ae2ef 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -176,7 +176,7 @@ static __be32 decode_getattr_args(struct
status = decode_fh(xdr, &args->fh);
if (unlikely(status != 0))
goto out;
- args->addr = &rqstp->rq_addr;
+ args->addr = (struct sockaddr_in *) &rqstp->rq_addr;
status = decode_bitmap(xdr, args->bitmap);
out:
dprintk("%s: exit with status = %d\n", __FUNCTION__, status);
@@ -188,7 +188,7 @@ static __be32 decode_recall_args(struct
__be32 *p;
__be32 status;

- args->addr = &rqstp->rq_addr;
+ args->addr = (struct sockaddr_in *) &rqstp->rq_addr;
status = decode_stateid(xdr, &args->stateid);
if (unlikely(status != 0))
goto out;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 293b649..f6af541 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -713,7 +713,7 @@ out_err:
__be32
nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
{
- __be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
+ struct sockaddr_in *sin = (struct sockaddr_in *) &rqstp->rq_addr;
struct xdr_netobj clname = {
.len = setclid->se_namelen,
.data = setclid->se_name,
@@ -748,7 +748,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp
*/
status = nfserr_clid_inuse;
if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred)
- || conf->cl_addr != ip_addr) {
+ || conf->cl_addr != sin->sin_addr.s_addr) {
printk("NFSD: setclientid: string in use by client"
"(clientid %08x/%08x)\n",
conf->cl_clientid.cl_boot, conf->cl_clientid.cl_id);
@@ -768,7 +768,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp
if (new == NULL)
goto out;
copy_verf(new, &clverifier);
- new->cl_addr = ip_addr;
+ new->cl_addr = sin->sin_addr.s_addr;
copy_cred(&new->cl_cred,&rqstp->rq_cred);
gen_clid(new);
gen_confirm(new);
@@ -800,7 +800,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp
if (new == NULL)
goto out;
copy_verf(new,&conf->cl_verifier);
- new->cl_addr = ip_addr;
+ new->cl_addr = sin->sin_addr.s_addr;
copy_cred(&new->cl_cred,&rqstp->rq_cred);
copy_clid(new, conf);
gen_confirm(new);
@@ -819,7 +819,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp
if (new == NULL)
goto out;
copy_verf(new,&clverifier);
- new->cl_addr = ip_addr;
+ new->cl_addr = sin->sin_addr.s_addr;
copy_cred(&new->cl_cred,&rqstp->rq_cred);
gen_clid(new);
gen_confirm(new);
@@ -846,7 +846,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp
if (new == NULL)
goto out;
copy_verf(new,&clverifier);
- new->cl_addr = ip_addr;
+ new->cl_addr = sin->sin_addr.s_addr;
copy_cred(&new->cl_cred,&rqstp->rq_cred);
gen_clid(new);
gen_confirm(new);
@@ -878,7 +878,7 @@ out:
__be32
nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
{
- __be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
+ struct sockaddr_in *sin = (struct sockaddr_in *) &rqstp->rq_addr;
struct nfs4_client *conf, *unconf;
nfs4_verifier confirm = setclientid_confirm->sc_confirm;
clientid_t * clid = &setclientid_confirm->sc_clientid;
@@ -897,9 +897,9 @@ nfsd4_setclientid_confirm(struct svc_rqs
unconf = find_unconfirmed_client(clid);

status = nfserr_clid_inuse;
- if (conf && conf->cl_addr != ip_addr)
+ if (conf && conf->cl_addr != sin->sin_addr.s_addr)
goto out;
- if (unconf && unconf->cl_addr != ip_addr)
+ if (unconf && unconf->cl_addr != sin->sin_addr.s_addr)
goto out;

if ((conf && unconf) &&
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index 6100bbe..b2da4f9 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -186,7 +186,7 @@ nfsd_cache_lookup(struct svc_rqst *rqstp
rp->c_state = RC_INPROG;
rp->c_xid = xid;
rp->c_proc = proc;
- rp->c_addr = rqstp->rq_addr;
+ memcpy(&rp->c_addr, &rqstp->rq_addr, sizeof(rp->c_addr));
rp->c_prot = proto;
rp->c_vers = vers;
rp->c_timestamp = jiffies;
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 8720aa5..7aa11f2 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -197,7 +197,7 @@ struct svc_rqst {
struct list_head rq_list; /* idle list */
struct list_head rq_all; /* all threads list */
struct svc_sock * rq_sock; /* socket */
- struct sockaddr_in rq_addr; /* peer address */
+ struct sockaddr_storage rq_addr; /* peer address */
int rq_addrlen;

struct svc_serv * rq_server; /* RPC service definition */
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index e1bd933..21d392a 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -417,6 +417,7 @@ svcauth_unix_info_release(void *info)
static int
svcauth_unix_set_client(struct svc_rqst *rqstp)
{
+ struct sockaddr_in *sin = (struct sockaddr_in *) &rqstp->rq_addr;
struct ip_map *ipm;

rqstp->rq_client = NULL;
@@ -426,7 +427,7 @@ svcauth_unix_set_client(struct svc_rqst
ipm = ip_map_cached_get(rqstp);
if (ipm == NULL)
ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
- rqstp->rq_addr.sin_addr);
+ sin->sin_addr);

if (ipm == NULL)
return SVC_DENIED;
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index d93b7cb..2e6e3e4 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -435,7 +435,7 @@ svc_sendto(struct svc_rqst *rqstp, struc
/* set the source and destination */
struct msghdr msg;
msg.msg_name = &rqstp->rq_addr;
- msg.msg_namelen = sizeof(rqstp->rq_addr);
+ msg.msg_namelen = rqstp->rq_addrlen;
msg.msg_iov = NULL;
msg.msg_iovlen = 0;
msg.msg_flags = MSG_MORE;
@@ -658,6 +658,7 @@ svc_write_space(struct sock *sk)
static int
svc_udp_recvfrom(struct svc_rqst *rqstp)
{
+ struct sockaddr_in *sin = (struct sockaddr_in *) &rqstp->rq_addr;
struct svc_sock *svsk = rqstp->rq_sock;
struct svc_serv *serv = svsk->sk_server;
struct sk_buff *skb;
@@ -713,9 +714,9 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
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;
+ sin->sin_family = AF_INET;
+ sin->sin_port = skb->h.uh->source;
+ sin->sin_addr.s_addr = skb->nh.iph->saddr;
rqstp->rq_daddr = skb->nh.iph->daddr;

if (skb_is_nonlinear(skb)) {
@@ -1245,7 +1246,8 @@ svc_sock_update_bufs(struct svc_serv *se
int
svc_recv(struct svc_rqst *rqstp, long timeout)
{
- struct svc_sock *svsk =NULL;
+ struct svc_sock *svsk = NULL;
+ struct sockaddr_in *sin = (struct sockaddr_in *) &rqstp->rq_addr;
struct svc_serv *serv = rqstp->rq_server;
struct svc_pool *pool = rqstp->rq_pool;
int len, i;
@@ -1340,7 +1342,7 @@ svc_recv(struct svc_rqst *rqstp, long ti
svsk->sk_lastrecv = get_seconds();
clear_bit(SK_OLD, &svsk->sk_flags);

- rqstp->rq_secure = ntohs(rqstp->rq_addr.sin_port) < 1024;
+ rqstp->rq_secure = ntohs(sin->sin_port) < 1024;
rqstp->rq_chandle.defer = svc_defer;

if (serv->sv_stats)

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-11-13 15:24:25

by Chuck Lever

[permalink] [raw]
Subject: [PATCH 10/13] SUNRPC: add a "generic" function to see if the peer uses a secure port

The only reason svcsock.c looks at a sockaddr's port is to check whether
the remote peer is connecting from a privileged port. Refactor this check
to hide processing that is specific to address format.

Signed-off-by: Chuck Lever <[email protected]>
Cc: Aurelien Charbon <[email protected]>
---

net/sunrpc/svcsock.c | 20 +++++++++++++++++---
1 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index e8a9379..47ed8d3 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -896,6 +896,20 @@ svc_tcp_data_ready(struct sock *sk, int
wake_up_interruptible(sk->sk_sleep);
}

+static inline int svc_port_is_privileged(struct sockaddr *sin)
+{
+ switch (sin->sa_family) {
+ case AF_INET:
+ return ntohs(((struct sockaddr_in *)sin)->sin_port) < 1024;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ case AF_INET6:
+ return ntohs(((struct sockaddr_in6 *)sin)->sin6_port) < 1024;
+#endif
+ default:
+ return 0;
+ }
+}
+
/*
* Accept a TCP connection
*/
@@ -942,7 +956,7 @@ svc_tcp_accept(struct svc_sock *svsk)
* hosts here, but when we get encryption, the IP of the host won't
* tell us anything. For now just warn about unpriv connections.
*/
- if (ntohs(sin.sin_port) >= 1024) {
+ if (!svc_port_is_privileged((struct sockaddr *) &sin)) {
dprintk(KERN_WARNING
"%s: connect from unprivileged port: %s\n",
serv->sv_name,
@@ -1282,7 +1296,6 @@ int
svc_recv(struct svc_rqst *rqstp, long timeout)
{
struct svc_sock *svsk = NULL;
- struct sockaddr_in *sin = (struct sockaddr_in *) &rqstp->rq_addr;
struct svc_serv *serv = rqstp->rq_server;
struct svc_pool *pool = rqstp->rq_pool;
int len, i;
@@ -1377,7 +1390,8 @@ svc_recv(struct svc_rqst *rqstp, long ti
svsk->sk_lastrecv = get_seconds();
clear_bit(SK_OLD, &svsk->sk_flags);

- rqstp->rq_secure = ntohs(sin->sin_port) < 1024;
+ rqstp->rq_secure =
+ svc_port_is_privileged((struct sockaddr *) &rqstp->rq_addr);
rqstp->rq_chandle.defer = svc_defer;

if (serv->sv_stats)

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-11-13 15:24:50

by Chuck Lever

[permalink] [raw]
Subject: [PATCH 13/13] SUNRPC: fix up svc_create_socket() to take a sockaddr struct + length

Replace existing svc_create_socket() API to allow callers to pass addresses
larger than a sockaddr_in.

Signed-off-by: Chuck Lever <[email protected]>
Cc: Aurelien Charbon <[email protected]>
---

net/sunrpc/svcsock.c | 15 +++++++--------
1 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index f75d9d5..d1e2fa8 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1649,7 +1649,7 @@ EXPORT_SYMBOL_GPL(svc_addsock);
* Create socket for RPC service.
*/
static int svc_create_socket(struct svc_serv *serv, int protocol,
- struct sockaddr_in *sin, int flags)
+ struct sockaddr *sin, int len, int flags)
{
struct svc_sock *svsk;
struct socket *sock;
@@ -1659,8 +1659,7 @@ static int svc_create_socket(struct svc_

dprintk("svc: svc_create_socket(%s, %d, %s)\n",
serv->sv_program->pg_name, protocol,
- __svc_print_addr((struct sockaddr *) sin, buf,
- sizeof(buf)));
+ __svc_print_addr(sin, buf, sizeof(buf)));

if (protocol != IPPROTO_UDP && protocol != IPPROTO_TCP) {
printk(KERN_WARNING "svc: only UDP and TCP "
@@ -1669,13 +1668,12 @@ static int svc_create_socket(struct svc_
}
type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;

- if ((error = sock_create_kern(PF_INET, type, protocol, &sock)) < 0)
+ if ((error = sock_create_kern(sin->sa_family, type, protocol, &sock)) < 0)
return error;

if (type == SOCK_STREAM)
- sock->sk->sk_reuse = 1; /* allow address reuse */
- error = kernel_bind(sock, (struct sockaddr *) sin,
- sizeof(*sin));
+ sock->sk->sk_reuse = 1; /* allow address reuse */
+ error = kernel_bind(sock, sin, len);
if (error < 0)
goto bummer;

@@ -1753,7 +1751,8 @@ int svc_makesock(struct svc_serv *serv,
};

dprintk("svc: creating socket proto = %d\n", protocol);
- return svc_create_socket(serv, protocol, &sin, flags);
+ return svc_create_socket(serv, protocol, (struct sockaddr *) &sin,
+ sizeof(sin), flags);
}

/*

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-11-13 15:24:42

by Chuck Lever

[permalink] [raw]
Subject: [PATCH 12/13] SUNRPC: support IPv6 addresses in RPC server's UDP receive path

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

Signed-off-by: Chuck Lever <[email protected]>
Cc: Aurelien Charbon <[email protected]>
---

net/sunrpc/svcsock.c | 51 ++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 0d53aad..f75d9d5 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -687,13 +687,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 */
+ do {
+ struct sockaddr_in *sin =
+ (struct sockaddr_in *) &rqstp->rq_addr;
+
+ sin->sin_family = AF_INET;
+ sin->sin_port = skb->h.uh->source;
+ sin->sin_addr.s_addr = skb->nh.iph->saddr;
+ rqstp->rq_daddr.addr.s_addr = skb->nh.iph->daddr;
+ } while (0);
+ break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ case AF_INET6:
+ /* this is derived from net/ipv6/udp.c:udpv6_recvmesg */
+ do {
+ struct sockaddr_in6 *sin6 =
+ (struct sockaddr_in6 *) &rqstp->rq_addr;
+
+ 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);
+ ipv6_addr_copy(&rqstp->rq_daddr.addr6,
+ &skb->nh.ipv6h->saddr);
+ } while (0);
+ break;
+#endif
+ }
+ return;
+}
+
/*
* Receive a datagram from a UDP socket.
*/
static int
svc_udp_recvfrom(struct svc_rqst *rqstp)
{
- struct sockaddr_in *sin = (struct sockaddr_in *) &rqstp->rq_addr;
struct svc_sock *svsk = rqstp->rq_sock;
struct svc_serv *serv = svsk->sk_server;
struct sk_buff *skb;
@@ -745,14 +785,9 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)

len = skb->len - sizeof(struct udphdr);
rqstp->rq_arg.len = len;
+ rqstp->rq_prot = IPPROTO_UDP;

- 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_daddr.addr.s_addr = skb->nh.iph->daddr;
+ svc_udp_get_sender_address(rqstp, skb);

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

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-11-13 15:24:36

by Chuck Lever

[permalink] [raw]
Subject: [PATCH 11/13] SUNRPC: Support IPv6 addresses in svc_tcp_accept

Modify svc_tcp_accept to support connecting on IPv6 sockets.

Signed-off-by: Chuck Lever <[email protected]>
Cc: Aurelien Charbon <[email protected]>
---

net/sunrpc/svcsock.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 47ed8d3..0d53aad 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -916,7 +916,7 @@ #endif
static void
svc_tcp_accept(struct svc_sock *svsk)
{
- struct sockaddr_in sin;
+ struct sockaddr_storage sin;
struct svc_serv *serv = svsk->sk_server;
struct socket *sock = svsk->sk_sock;
struct socket *newsock;

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-11-13 15:40:24

by Olaf Kirch

[permalink] [raw]
Subject: Re: [PATCH 00/13] repost RPC server patches for IPv6 support

On Mon, Nov 13, 2006 at 07:56:40AM -0500, Chuck Lever wrote:
> Hi Neil-
>
> I think I've fixed most of the issues you and Olaf pointed out last week.
> Have a look and let me know.

The patches look good, no additional comments from my side.

Olaf
--
Walks like a duck. Quacks like a duck. Must be a chicken.

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-11-13 21:32:27

by Trond Myklebust

[permalink] [raw]
Subject: Re: [PATCH 02/13] SUNRPC: allow creating an RPC service without registering with portmapper

On Mon, 2006-11-13 at 07:57 -0500, Chuck Lever wrote:
> Sometimes we need to create an RPC service but not register it with the
> local portmapper. NFSv4 delegation callback, for example.
>
> Change the svc_makesock() API to allow optionally creating temporary or
> permanent sockets, optionally registering with the local portmapper, and
> make it return the ephemeral port of the new socket.
>
> Signed-off-by: Chuck Lever <[email protected]>
> Cc: Aurelien Charbon <[email protected]>
> ---
>
> fs/lockd/svc.c | 26 ++++++++++++++++----------
> fs/nfs/callback.c | 20 +++++++++-----------
> fs/nfsd/nfssvc.c | 6 ++++--
> include/linux/sunrpc/svcsock.h | 2 +-
> net/sunrpc/svcsock.c | 6 ++++--
> 5 files changed, 34 insertions(+), 26 deletions(-)
>
> diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
> index 8ca1808..2c3d5ac 100644
> --- a/fs/lockd/svc.c
> +++ b/fs/lockd/svc.c
> @@ -223,23 +223,29 @@ static int find_socket(struct svc_serv *
> return found;
> }
>
> +/*
> + * Make any sockets that are needed but not present.
> + * If nlm_udpport or nlm_tcpport were set as module
> + * options, make those sockets unconditionally
> + */
> static int make_socks(struct svc_serv *serv, int proto)
> {
> - /* Make any sockets that are needed but not present.
> - * If nlm_udpport or nlm_tcpport were set as module
> - * options, make those sockets unconditionally
> - */
> - static int warned;
> + static int warned;
> int err = 0;
> +
> if (proto == IPPROTO_UDP || nlm_udpport)
> if (!find_socket(serv, IPPROTO_UDP))
> - err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport);
> - if (err == 0 && (proto == IPPROTO_TCP || nlm_tcpport))
> + err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport,
> + SVC_SOCK_DEFAULTS);
> + if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport))
> if (!find_socket(serv, IPPROTO_TCP))
> - err= svc_makesock(serv, IPPROTO_TCP, nlm_tcpport);
> - if (!err)
> + err = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport,
> + SVC_SOCK_DEFAULTS);
> +
> + if (err >= 0) {
> warned = 0;
> - else if (warned++ == 0)
> + err = 0;
> + } else if (warned++ == 0)
> printk(KERN_WARNING
> "lockd_up: makesock failed, error=%d\n", err);
> return err;
> diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
> index 7933e2e..e393532 100644
> --- a/fs/nfs/callback.c
> +++ b/fs/nfs/callback.c
> @@ -106,7 +106,6 @@ static void nfs_callback_svc(struct svc_
> int nfs_callback_up(void)
> {
> struct svc_serv *serv;
> - struct svc_sock *svsk;
> int ret = 0;
>
> lock_kernel();
> @@ -119,17 +118,14 @@ int nfs_callback_up(void)
> ret = -ENOMEM;
> if (!serv)
> goto out_err;
> - /* FIXME: We don't want to register this socket with the portmapper */
> - ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport);
> - if (ret < 0)
> +
> + ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport,
> + (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY));

Why are you requesting that this socket to be put on the sv_tempsocks
list? That has got to be wrong.

Trond


-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-11-13 21:51:00

by Chuck Lever

[permalink] [raw]
Subject: Re: [PATCH 02/13] SUNRPC: allow creating an RPC service without registering with portmapper

On 11/13/06, Trond Myklebust <[email protected]> wrote:
> On Mon, 2006-11-13 at 07:57 -0500, Chuck Lever wrote:
> > + ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport,
> > + (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY));
>
> Why are you requesting that this socket to be put on the sv_tempsocks
> list? That has got to be wrong.

Yeah, that's probably a bug. The way svc_makesock() currently works,
if you don't register the socket with the local port mapper, it makes
it a temporary socket. I'm just carrying that behavior over, and as
you point out, it's not correct; we want ANONYMOUS only here.

I'll send out a new version of this patch with that fixed.

--
"We who cut mere stones must always be envisioning cathedrals"
-- Quarry worker's creed

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-11-13 15:23:35

by Chuck Lever

[permalink] [raw]
Subject: [PATCH 01/13] SUNRPC: update internal API: separate pmap register and temp sockets

Currently in the RPC server, registering with the local portmapper and
creating "permanent" sockets are tied together. Expand the internal APIs
to allow these two socket characteristics to be separately specified.

This will be externalized in the next patch.

Signed-off-by: Chuck Lever <[email protected]>
Cc: Aurelien Charbon <[email protected]>
---

include/linux/sunrpc/svcsock.h | 7 ++++++
net/sunrpc/svcsock.c | 47 +++++++++++++++++++++++-----------------
2 files changed, 34 insertions(+), 20 deletions(-)

diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
index 98b21ad..3c38789 100644
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -74,4 +74,11 @@ int svc_addsock(struct svc_serv *serv,
char *name_return,
int *proto);

+/*
+ * svc_makesock socket characteristics
+ */
+#define SVC_SOCK_DEFAULTS (0U)
+#define SVC_SOCK_ANONYMOUS (1U << 0) /* don't register with pmap */
+#define SVC_SOCK_TEMPORARY (1U << 1) /* flag socket as temporary */
+
#endif /* SUNRPC_SVCSOCK_H */
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 64ca1f6..f42d29d 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -68,7 +68,7 @@ #define RPCDBG_FACILITY RPCDBG_SVCSOCK


static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *,
- int *errp, int pmap_reg);
+ int *, int);
static void svc_udp_data_ready(struct sock *, int);
static int svc_udp_recvfrom(struct svc_rqst *);
static int svc_udp_sendto(struct svc_rqst *);
@@ -892,7 +892,8 @@ svc_tcp_accept(struct svc_sock *svsk)
*/
newsock->sk->sk_sndtimeo = HZ*30;

- if (!(newsvsk = svc_setup_socket(serv, newsock, &err, 0)))
+ if (!(newsvsk = svc_setup_socket(serv, newsock, &err,
+ (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY))))
goto failed;


@@ -1426,12 +1427,14 @@ svc_age_temp_sockets(unsigned long closu
* Initialize socket for RPC use and create svc_sock struct
* XXX: May want to setsockopt SO_SNDBUF and SO_RCVBUF.
*/
-static struct svc_sock *
-svc_setup_socket(struct svc_serv *serv, struct socket *sock,
- int *errp, int pmap_register)
+static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
+ struct socket *sock,
+ int *errp, int flags)
{
struct svc_sock *svsk;
struct sock *inet;
+ int pmap_register = !(flags & SVC_SOCK_ANONYMOUS);
+ int is_temporary = flags & SVC_SOCK_TEMPORARY;

dprintk("svc: svc_setup_socket %p\n", sock);
if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) {
@@ -1473,7 +1476,7 @@ svc_setup_socket(struct svc_serv *serv,
svc_tcp_init(svsk);

spin_lock_bh(&serv->sv_lock);
- if (!pmap_register) {
+ if (is_temporary) {
set_bit(SK_TEMP, &svsk->sk_flags);
list_add(&svsk->sk_list, &serv->sv_tempsocks);
serv->sv_tmpcnt++;
@@ -1517,7 +1520,7 @@ int svc_addsock(struct svc_serv *serv,
else if (so->state > SS_UNCONNECTED)
err = -EISCONN;
else {
- svsk = svc_setup_socket(serv, so, &err, 1);
+ svsk = svc_setup_socket(serv, so, &err, SVC_SOCK_DEFAULTS);
if (svsk)
err = 0;
}
@@ -1533,8 +1536,8 @@ EXPORT_SYMBOL_GPL(svc_addsock);
/*
* Create socket for RPC service.
*/
-static int
-svc_create_socket(struct svc_serv *serv, int protocol, struct sockaddr_in *sin)
+static int svc_create_socket(struct svc_serv *serv, int protocol,
+ struct sockaddr_in *sin, int flags)
{
struct svc_sock *svsk;
struct socket *sock;
@@ -1568,8 +1571,8 @@ svc_create_socket(struct svc_serv *serv,
goto bummer;
}

- if ((svsk = svc_setup_socket(serv, sock, &error, 1)) != NULL)
- return 0;
+ if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL)
+ return ntohs(inet_sk(svsk->sk_sk)->sport);

bummer:
dprintk("svc: svc_create_socket error = %d\n", -error);
@@ -1619,19 +1622,23 @@ svc_delete_socket(struct svc_sock *svsk)
svc_sock_put(svsk);
}

-/*
- * Make a socket for nfsd and lockd
+/**
+ * svc_makesock - Make a socket for nfsd and lockd
+ * @serv: RPC server structure
+ * @protocol: transport protocol to use
+ * @port: port to use
+ *
*/
-int
-svc_makesock(struct svc_serv *serv, int protocol, unsigned short port)
+int svc_makesock(struct svc_serv *serv, int protocol, unsigned short port)
{
- struct sockaddr_in sin;
+ struct sockaddr_in sin = {
+ .sin_family = AF_INET,
+ .sin_addr.s_addr = INADDR_ANY,
+ .sin_port = htons(port),
+ };

dprintk("svc: creating socket proto = %d\n", protocol);
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = INADDR_ANY;
- sin.sin_port = htons(port);
- return svc_create_socket(serv, protocol, &sin);
+ return svc_create_socket(serv, protocol, &sin, SVC_SOCK_DEFAULTS);
}

/*

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-11-13 15:23:42

by Chuck Lever

[permalink] [raw]
Subject: [PATCH 02/13] SUNRPC: allow creating an RPC service without registering with portmapper

Sometimes we need to create an RPC service but not register it with the
local portmapper. NFSv4 delegation callback, for example.

Change the svc_makesock() API to allow optionally creating temporary or
permanent sockets, optionally registering with the local portmapper, and
make it return the ephemeral port of the new socket.

Signed-off-by: Chuck Lever <[email protected]>
Cc: Aurelien Charbon <[email protected]>
---

fs/lockd/svc.c | 26 ++++++++++++++++----------
fs/nfs/callback.c | 20 +++++++++-----------
fs/nfsd/nfssvc.c | 6 ++++--
include/linux/sunrpc/svcsock.h | 2 +-
net/sunrpc/svcsock.c | 6 ++++--
5 files changed, 34 insertions(+), 26 deletions(-)

diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 8ca1808..2c3d5ac 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -223,23 +223,29 @@ static int find_socket(struct svc_serv *
return found;
}

+/*
+ * Make any sockets that are needed but not present.
+ * If nlm_udpport or nlm_tcpport were set as module
+ * options, make those sockets unconditionally
+ */
static int make_socks(struct svc_serv *serv, int proto)
{
- /* Make any sockets that are needed but not present.
- * If nlm_udpport or nlm_tcpport were set as module
- * options, make those sockets unconditionally
- */
- static int warned;
+ static int warned;
int err = 0;
+
if (proto == IPPROTO_UDP || nlm_udpport)
if (!find_socket(serv, IPPROTO_UDP))
- err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport);
- if (err == 0 && (proto == IPPROTO_TCP || nlm_tcpport))
+ err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport,
+ SVC_SOCK_DEFAULTS);
+ if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport))
if (!find_socket(serv, IPPROTO_TCP))
- err= svc_makesock(serv, IPPROTO_TCP, nlm_tcpport);
- if (!err)
+ err = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport,
+ SVC_SOCK_DEFAULTS);
+
+ if (err >= 0) {
warned = 0;
- else if (warned++ == 0)
+ err = 0;
+ } else if (warned++ == 0)
printk(KERN_WARNING
"lockd_up: makesock failed, error=%d\n", err);
return err;
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 7933e2e..e393532 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -106,7 +106,6 @@ static void nfs_callback_svc(struct svc_
int nfs_callback_up(void)
{
struct svc_serv *serv;
- struct svc_sock *svsk;
int ret = 0;

lock_kernel();
@@ -119,17 +118,14 @@ int nfs_callback_up(void)
ret = -ENOMEM;
if (!serv)
goto out_err;
- /* FIXME: We don't want to register this socket with the portmapper */
- ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport);
- if (ret < 0)
+
+ ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport,
+ (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY));
+ if (ret <= 0)
goto out_destroy;
- if (!list_empty(&serv->sv_permsocks)) {
- svsk = list_entry(serv->sv_permsocks.next,
- struct svc_sock, sk_list);
- nfs_callback_tcpport = ntohs(inet_sk(svsk->sk_sk)->sport);
- dprintk ("Callback port = 0x%x\n", nfs_callback_tcpport);
- } else
- BUG();
+ nfs_callback_tcpport = ret;
+ dprintk("Callback port = 0x%x\n", nfs_callback_tcpport);
+
ret = svc_create_thread(nfs_callback_svc, serv);
if (ret < 0)
goto out_destroy;
@@ -140,6 +136,8 @@ out:
unlock_kernel();
return ret;
out_destroy:
+ dprintk("Couldn't create callback socket or server thread; err = %d\n",
+ ret);
svc_destroy(serv);
out_err:
nfs_callback_info.users--;
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 0aaccb0..dc1b8e1 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -235,7 +235,8 @@ static int nfsd_init_socks(int port)

error = lockd_up(IPPROTO_UDP);
if (error >= 0) {
- error = svc_makesock(nfsd_serv, IPPROTO_UDP, port);
+ error = svc_makesock(nfsd_serv, IPPROTO_UDP, port,
+ SVC_SOCK_DEFAULTS);
if (error < 0)
lockd_down();
}
@@ -245,7 +246,8 @@ static int nfsd_init_socks(int port)
#ifdef CONFIG_NFSD_TCP
error = lockd_up(IPPROTO_TCP);
if (error >= 0) {
- error = svc_makesock(nfsd_serv, IPPROTO_TCP, port);
+ error = svc_makesock(nfsd_serv, IPPROTO_TCP, port,
+ SVC_SOCK_DEFAULTS);
if (error < 0)
lockd_down();
}
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
index 3c38789..c476a82 100644
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -62,7 +62,7 @@ #define SK_DETACHED 10 /* detached fro
/*
* Function prototypes.
*/
-int svc_makesock(struct svc_serv *, int, unsigned short);
+int svc_makesock(struct svc_serv *, int, unsigned short, int flags);
void svc_delete_socket(struct svc_sock *);
int svc_recv(struct svc_rqst *, long);
int svc_send(struct svc_rqst *);
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index f42d29d..bfe95a6 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1627,9 +1627,11 @@ svc_delete_socket(struct svc_sock *svsk)
* @serv: RPC server structure
* @protocol: transport protocol to use
* @port: port to use
+ * @flags: requested socket characteristics
*
*/
-int svc_makesock(struct svc_serv *serv, int protocol, unsigned short port)
+int svc_makesock(struct svc_serv *serv, int protocol, unsigned short port,
+ int flags)
{
struct sockaddr_in sin = {
.sin_family = AF_INET,
@@ -1638,7 +1640,7 @@ int svc_makesock(struct svc_serv *serv,
};

dprintk("svc: creating socket proto = %d\n", protocol);
- return svc_create_socket(serv, protocol, &sin, SVC_SOCK_DEFAULTS);
+ return svc_create_socket(serv, protocol, &sin, flags);
}

/*

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-11-13 15:23:54

by Chuck Lever

[permalink] [raw]
Subject: [PATCH 03/13] SUNRPC: Cache remote peer's address in svc_sock.

The remote peer's address won't change after the socket has been
accepted. We don't need to call ->getname on every incoming request.

Signed-off-by: Chuck Lever <[email protected]>
Cc: Aurelien Charbon <[email protected]>
---

include/linux/sunrpc/svcsock.h | 3 +++
net/sunrpc/svcsock.c | 11 +++++------
2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
index c476a82..fd3f43c 100644
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -57,6 +57,9 @@ #define SK_DETACHED 10 /* detached fro

/* cache of various info for TCP sockets */
void *sk_info_authunix;
+
+ struct sockaddr_storage sk_remote; /* remote peer's address */
+ int sk_remotelen; /* length of address */
};

/*
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index bfe95a6..d7b2ac3 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -547,11 +547,9 @@ svc_recvfrom(struct svc_rqst *rqstp, str
len = kernel_recvmsg(sock, &msg, iov, nr, buflen, MSG_DONTWAIT);

/* sock_recvmsg doesn't fill in the name/namelen, so we must..
- * possibly we should cache this in the svc_sock structure
- * at accept time. FIXME
*/
- alen = sizeof(rqstp->rq_addr);
- kernel_getpeername(sock, (struct sockaddr *)&rqstp->rq_addr, &alen);
+ memcpy(&rqstp->rq_addr, &svsk->sk_remote, svsk->sk_remotelen);
+ rqstp->rq_addrlen = svsk->sk_remotelen;

dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
rqstp->rq_sock, iov[0].iov_base, iov[0].iov_len, len);
@@ -843,7 +841,7 @@ svc_tcp_accept(struct svc_sock *svsk)
struct socket *sock = svsk->sk_sock;
struct socket *newsock;
struct svc_sock *newsvsk;
- int err, slen;
+ int err, slen = 0;

dprintk("svc: tcp_accept %p sock %p\n", svsk, sock);
if (!sock)
@@ -895,7 +893,8 @@ svc_tcp_accept(struct svc_sock *svsk)
if (!(newsvsk = svc_setup_socket(serv, newsock, &err,
(SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY))))
goto failed;
-
+ memcpy(&newsvsk->sk_remote, &sin, slen);
+ newsvsk->sk_remotelen = slen;

/* make sure that we don't have too many active connections.
* If we have, something must be dropped.

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-11-13 15:23:51

by Chuck Lever

[permalink] [raw]
Subject: [PATCH 05/13] SUNRPC: Use sockaddr_storage to store address in svc_deferred_req

Sockaddr_storage will allow us to store arbitrary socket addresses in
the svc_deferred_req struct.

Signed-off-by: Chuck Lever <[email protected]>
Cc: Aurelien Charbon <[email protected]>
---

include/linux/sunrpc/svc.h | 3 ++-
net/sunrpc/svcsock.c | 6 ++++--
2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 965d6c2..6fc2684 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -289,7 +289,8 @@ static inline void svc_free_res_pages(st

struct svc_deferred_req {
u32 prot; /* protocol (UDP or TCP) */
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
+ int addrlen;
struct svc_sock *svsk; /* where reply must go */
__be32 daddr; /* where reply must come from */
struct cache_deferred_req handle;
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 5a251ae..8fa40cf 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1681,7 +1681,8 @@ svc_defer(struct cache_req *req)

dr->handle.owner = rqstp->rq_server;
dr->prot = rqstp->rq_prot;
- dr->addr = rqstp->rq_addr;
+ memcpy(&dr->addr, &rqstp->rq_addr, rqstp->rq_addrlen);
+ dr->addrlen = rqstp->rq_addrlen;
dr->daddr = rqstp->rq_daddr;
dr->argslen = rqstp->rq_arg.len >> 2;
memcpy(dr->args, rqstp->rq_arg.head[0].iov_base-skip, dr->argslen<<2);
@@ -1705,7 +1706,8 @@ static int svc_deferred_recv(struct svc_
rqstp->rq_arg.page_len = 0;
rqstp->rq_arg.len = dr->argslen<<2;
rqstp->rq_prot = dr->prot;
- rqstp->rq_addr = dr->addr;
+ memcpy(&rqstp->rq_addr, &dr->addr, dr->addrlen);
+ rqstp->rq_addrlen = dr->addrlen;
rqstp->rq_daddr = dr->daddr;
rqstp->rq_respages = rqstp->rq_pages;
return dr->argslen<<2;

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-11-13 15:23:59

by Chuck Lever

[permalink] [raw]
Subject: [PATCH 06/13] SUNRPC: Add a function to format the address in an svc_rqst for printing

There are loads of places where the RPC server assumes that the rq_addr
fields contains an IPv4 address. Top among these are error and debugging
messages that display the server's IP address.

Let's refactor the address printing into a separate function that's smart
enough to figure out the difference between IPv4 and IPv6 addresses.

Signed-off-by: Chuck Lever <[email protected]>
Cc: Aurelien Charbon <[email protected]>
---

fs/lockd/svc.c | 6 ++--
fs/lockd/svc4proc.c | 7 ++--
fs/lockd/svcproc.c | 7 ++--
fs/nfs/callback.c | 12 +++++--
fs/nfsd/nfsfh.c | 8 ++---
fs/nfsd/nfsproc.c | 7 ++--
include/linux/sunrpc/svc.h | 3 ++
net/sunrpc/svcsock.c | 75 ++++++++++++++++++++++++++++++++------------
8 files changed, 84 insertions(+), 41 deletions(-)

diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 2c3d5ac..d42be4f 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -141,6 +141,7 @@ lockd(struct svc_rqst *rqstp)
*/
while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->pid) {
long timeout = MAX_SCHEDULE_TIMEOUT;
+ char buf[RPC_MAX_ADDRBUFLEN];

if (signalled()) {
flush_signals(current);
@@ -175,11 +176,10 @@ lockd(struct svc_rqst *rqstp)
break;
}

- dprintk("lockd: request from %08x\n",
- (unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr));
+ dprintk("lockd: request from %s\n",
+ svc_print_addr(rqstp, buf, sizeof(buf)));

svc_process(rqstp);
-
}

flush_signals(current);
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index f67146a..d724eac 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -426,10 +426,9 @@ nlm4svc_proc_sm_notify(struct svc_rqst *
dprintk("lockd: SM_NOTIFY called\n");
if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
|| ntohs(saddr.sin_port) >= 1024) {
- printk(KERN_WARNING
- "lockd: rejected NSM callback from %08x:%d\n",
- ntohl(rqstp->rq_addr.sin_addr.s_addr),
- ntohs(rqstp->rq_addr.sin_port));
+ char buf[RPC_MAX_ADDRBUFLEN];
+ printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
+ svc_print_addr(rqstp, buf, sizeof(buf)));
return rpc_system_err;
}

diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 3707c3a..f590304 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -457,10 +457,9 @@ nlmsvc_proc_sm_notify(struct svc_rqst *r
dprintk("lockd: SM_NOTIFY called\n");
if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
|| ntohs(saddr.sin_port) >= 1024) {
- printk(KERN_WARNING
- "lockd: rejected NSM callback from %08x:%d\n",
- ntohl(rqstp->rq_addr.sin_addr.s_addr),
- ntohs(rqstp->rq_addr.sin_port));
+ char buf[RPC_MAX_ADDRBUFLEN];
+ printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
+ svc_print_addr(rqstp, buf, sizeof(buf)));
return rpc_system_err;
}

diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index e393532..d277ff9 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -71,6 +71,8 @@ static void nfs_callback_svc(struct svc_
complete(&nfs_callback_info.started);

for(;;) {
+ char buf[RPC_MAX_ADDRBUFLEN];
+
if (signalled()) {
if (nfs_callback_info.users == 0)
break;
@@ -88,8 +90,8 @@ static void nfs_callback_svc(struct svc_
__FUNCTION__, -err);
break;
}
- dprintk("%s: request from %u.%u.%u.%u\n", __FUNCTION__,
- NIPQUAD(rqstp->rq_addr.sin_addr.s_addr));
+ dprintk("%s: request from %s\n", __FUNCTION__,
+ svc_print_addr(rqstp, buf, sizeof(buf)));
svc_process(rqstp);
}

@@ -166,13 +168,17 @@ static int nfs_callback_authenticate(str
{
struct sockaddr_in *addr = &rqstp->rq_addr;
struct nfs_client *clp;
+ char buf[RPC_MAX_ADDRBUFLEN];

/* Don't talk to strangers */
clp = nfs_find_client(addr, 4);
if (clp == NULL)
return SVC_DROP;
- dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr->sin_addr));
+
+ dprintk("%s: %s NFSv4 callback!\n", __FUNCTION__,
+ svc_print_addr(rqstp, buf, sizeof(buf)));
nfs_put_client(clp);
+
switch (rqstp->rq_authop->flavour) {
case RPC_AUTH_NULL:
if (rqstp->rq_proc != CB_NULL)
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 727ab3b..badb2bd 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -20,6 +20,7 @@ #include <linux/dcache.h>
#include <linux/mount.h>
#include <asm/pgtable.h>

+#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>

@@ -180,10 +181,9 @@ fh_verify(struct svc_rqst *rqstp, struct
/* Check if the request originated from a secure port. */
error = nfserr_perm;
if (!rqstp->rq_secure && EX_SECURE(exp)) {
- printk(KERN_WARNING
- "nfsd: request from insecure port (%u.%u.%u.%u:%d)!\n",
- NIPQUAD(rqstp->rq_addr.sin_addr.s_addr),
- ntohs(rqstp->rq_addr.sin_port));
+ char buf[RPC_MAX_ADDRBUFLEN];
+ printk(KERN_WARNING "nfsd: request from insecure port %s!\n",
+ svc_print_addr(rqstp, buf, sizeof(buf)));
goto out;
}

diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index ec983b7..5cc2eec 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -19,6 +19,7 @@ #include <linux/namei.h>
#include <linux/unistd.h>
#include <linux/slab.h>

+#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/cache.h>
@@ -147,10 +148,10 @@ nfsd_proc_read(struct svc_rqst *rqstp, s
*/

if (NFSSVC_MAXBLKSIZE_V2 < argp->count) {
+ char buf[RPC_MAX_ADDRBUFLEN];
printk(KERN_NOTICE
- "oversized read request from %u.%u.%u.%u:%d (%d bytes)\n",
- NIPQUAD(rqstp->rq_addr.sin_addr.s_addr),
- ntohs(rqstp->rq_addr.sin_port),
+ "oversized read request from %s (%d bytes)\n",
+ svc_print_addr(rqstp, buf, sizeof(buf)),
argp->count);
argp->count = NFSSVC_MAXBLKSIZE_V2;
}
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 6fc2684..8720aa5 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -366,5 +366,8 @@ int svc_register(struct svc_serv *,
void svc_wake_up(struct svc_serv *);
void svc_reserve(struct svc_rqst *rqstp, int space);
struct svc_pool * svc_pool_for_cpu(struct svc_serv *serv, int cpu);
+char * svc_print_addr(struct svc_rqst *, char *, size_t);
+
+#define RPC_MAX_ADDRBUFLEN (63U)

#endif /* SUNRPC_SVC_H */
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 8fa40cf..d93b7cb 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -40,6 +40,7 @@ #include <asm/uaccess.h>
#include <asm/ioctls.h>

#include <linux/sunrpc/types.h>
+#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/sunrpc/stats.h>
@@ -84,6 +85,41 @@ static struct cache_deferred_req *svc_de
*/
static int svc_conn_age_period = 6*60;

+static char *__svc_print_addr(struct sockaddr *addr, char *buf, size_t len)
+{
+ switch (addr->sa_family) {
+ case AF_INET:
+ snprintf(buf, len, "%u.%u.%u.%u, port=%u",
+ NIPQUAD(((struct sockaddr_in *) addr)->sin_addr),
+ htons(((struct sockaddr_in *) addr)->sin_port));
+ break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ case AF_INET6:
+ snprintf(buf, len, "%x:%x:%x:%x:%x:%x:%x:%x, port=%u",
+ NIP6(((struct sockaddr_in6 *) addr)->sin6_addr),
+ htons(((struct sockaddr_in6 *) addr)->sin6_port));
+ break;
+#endif
+ default:
+ snprintf(buf, len, "unknown address type");
+ break;
+ }
+ return buf;
+}
+
+/**
+ * svc_print_addr - Format rq_addr field for printing
+ * @rqstp: svc_rqst struct containing address to print
+ * @buf: target buffer for formatted address
+ * @len: length of target buffer
+ *
+ */
+char *svc_print_addr(struct svc_rqst *rqstp, char *buf, size_t len)
+{
+ return __svc_print_addr((struct sockaddr *) &rqstp->rq_addr, buf, len);
+}
+EXPORT_SYMBOL_GPL(svc_print_addr);
+
/*
* Queue up an idle server thread. Must have pool->sp_lock held.
* Note: this is really a stack rather than a queue, so that we only
@@ -391,6 +427,7 @@ svc_sendto(struct svc_rqst *rqstp, struc
size_t base = xdr->page_base;
unsigned int pglen = xdr->page_len;
unsigned int flags = MSG_MORE;
+ char buf[RPC_MAX_ADDRBUFLEN];

slen = xdr->len;

@@ -453,9 +490,9 @@ svc_sendto(struct svc_rqst *rqstp, struc
len += result;
}
out:
- dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (addr %x)\n",
- rqstp->rq_sock, xdr->head[0].iov_base, xdr->head[0].iov_len, xdr->len, len,
- rqstp->rq_addr.sin_addr.s_addr);
+ dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (addr %s)\n",
+ rqstp->rq_sock, xdr->head[0].iov_base, xdr->head[0].iov_len,
+ xdr->len, len, svc_print_addr(rqstp, buf, sizeof(buf)));

return len;
}
@@ -835,6 +872,7 @@ svc_tcp_accept(struct svc_sock *svsk)
struct socket *newsock;
struct svc_sock *newsvsk;
int err, slen = 0;
+ char buf[RPC_MAX_ADDRBUFLEN];

dprintk("svc: tcp_accept %p sock %p\n", svsk, sock);
if (!sock)
@@ -865,18 +903,17 @@ svc_tcp_accept(struct svc_sock *svsk)
}

/* Ideally, we would want to reject connections from unauthorized
- * hosts here, but when we get encription, the IP of the host won't
- * tell us anything. For now just warn about unpriv connections.
+ * hosts here, but when we get encryption, the IP of the host won't
+ * tell us anything. For now just warn about unpriv connections.
*/
if (ntohs(sin.sin_port) >= 1024) {
dprintk(KERN_WARNING
- "%s: connect from unprivileged port: %u.%u.%u.%u:%d\n",
- serv->sv_name,
- NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+ "%s: connect from unprivileged port: %s\n",
+ serv->sv_name,
+ __svc_print_addr((struct sockaddr *) &sin, buf,
+ sizeof(buf)));
}
-
- dprintk("%s: connect from %u.%u.%u.%u:%04x\n", serv->sv_name,
- NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+ dprintk("%s: connect from %s\n", serv->sv_name, buf);

/* make sure that a write doesn't block forever when
* low on memory
@@ -910,11 +947,8 @@ svc_tcp_accept(struct svc_sock *svsk)
"sockets, consider increasing the "
"number of nfsd threads\n",
serv->sv_name);
- printk(KERN_NOTICE "%s: last TCP connect from "
- "%u.%u.%u.%u:%d\n",
- serv->sv_name,
- NIPQUAD(sin.sin_addr.s_addr),
- ntohs(sin.sin_port));
+ printk(KERN_NOTICE "%s: last TCP connect from %s\n",
+ serv->sv_name, buf);
}
/*
* Always select the oldest socket. It's not fair,
@@ -1535,11 +1569,12 @@ static int svc_create_socket(struct svc_
struct socket *sock;
int error;
int type;
+ char buf[RPC_MAX_ADDRBUFLEN];

- dprintk("svc: svc_create_socket(%s, %d, %u.%u.%u.%u:%d)\n",
- serv->sv_program->pg_name, protocol,
- NIPQUAD(sin->sin_addr.s_addr),
- ntohs(sin->sin_port));
+ dprintk("svc: svc_create_socket(%s, %d, %s)\n",
+ serv->sv_program->pg_name, protocol,
+ __svc_print_addr((struct sockaddr *) sin, buf,
+ sizeof(buf)));

if (protocol != IPPROTO_UDP && protocol != IPPROTO_TCP) {
printk(KERN_WARNING "svc: only UDP and TCP "

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-11-13 15:24:13

by Chuck Lever

[permalink] [raw]
Subject: [PATCH 08/13] SUNRPC: Make rq_daddr field address-version independent

The rq_daddr field must support larger addresses.

Signed-off-by: Chuck Lever <[email protected]>
Cc: Aurelien Charbon <[email protected]>
---

include/linux/sunrpc/svc.h | 14 ++++++++++----
net/sunrpc/svcsock.c | 4 ++--
2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 7aa11f2..f3afdcb 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -11,6 +11,7 @@ #ifndef SUNRPC_SVC_H
#define SUNRPC_SVC_H

#include <linux/in.h>
+#include <linux/in6.h>
#include <linux/sunrpc/types.h>
#include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/auth.h>
@@ -188,7 +189,13 @@ static inline void svc_putu32(struct kve
iov->iov_len += sizeof(__be32);
}

-
+union svc_addr_u {
+ struct in_addr addr;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ struct in6_addr addr6;
+#endif
+};
+
/*
* The context of a single thread, including the request currently being
* processed.
@@ -224,8 +231,7 @@ struct svc_rqst {
unsigned short
rq_secure : 1; /* secure port */

-
- __be32 rq_daddr; /* dest addr of request - reply from here */
+ union svc_addr_u rq_daddr; /* dest addr of request - reply from here */

void * rq_argp; /* decoded arguments */
void * rq_resp; /* xdr'd results */
@@ -292,7 +298,7 @@ struct svc_deferred_req {
struct sockaddr_storage addr;
int addrlen;
struct svc_sock *svsk; /* where reply must go */
- __be32 daddr; /* where reply must come from */
+ union svc_addr_u daddr; /* where reply must come from */
struct cache_deferred_req handle;
int argslen;
__be32 args[0];
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 2e6e3e4..cced146 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -446,7 +446,7 @@ svc_sendto(struct svc_rqst *rqstp, struc
cmh->cmsg_level = SOL_IP;
cmh->cmsg_type = IP_PKTINFO;
pki->ipi_ifindex = 0;
- pki->ipi_spec_dst.s_addr = rqstp->rq_daddr;
+ pki->ipi_spec_dst.s_addr = rqstp->rq_daddr.addr.s_addr;

if (sock_sendmsg(sock, &msg, 0) < 0)
goto out;
@@ -717,7 +717,7 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
sin->sin_family = AF_INET;
sin->sin_port = skb->h.uh->source;
sin->sin_addr.s_addr = skb->nh.iph->saddr;
- rqstp->rq_daddr = skb->nh.iph->daddr;
+ rqstp->rq_daddr.addr.s_addr = skb->nh.iph->daddr;

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

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-11-13 15:24:13

by Chuck Lever

[permalink] [raw]
Subject: [PATCH 04/13] SUNRPC: Don't set msg_name and msg_namelen when calling sock_recvmsg

Clean-up: msg_name and msg_namelen are not used by sock_recvmsg, so
don't bother to set them in svc_recvfrom.

Signed-off-by: Chuck Lever <[email protected]>
---

net/sunrpc/svcsock.c | 23 ++++++++---------------
1 files changed, 8 insertions(+), 15 deletions(-)

diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index d7b2ac3..5a251ae 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -530,21 +530,14 @@ svc_recv_available(struct svc_sock *svsk
static int
svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen)
{
- struct msghdr msg;
- struct socket *sock;
- int len, alen;
-
- rqstp->rq_addrlen = sizeof(rqstp->rq_addr);
- sock = rqstp->rq_sock->sk_sock;
-
- msg.msg_name = &rqstp->rq_addr;
- msg.msg_namelen = sizeof(rqstp->rq_addr);
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
-
- msg.msg_flags = MSG_DONTWAIT;
+ struct svc_sock *svsk = rqstp->rq_sock;
+ struct msghdr msg = {
+ .msg_flags = MSG_DONTWAIT,
+ };
+ int len;

- len = kernel_recvmsg(sock, &msg, iov, nr, buflen, MSG_DONTWAIT);
+ len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen,
+ msg.msg_flags);

/* sock_recvmsg doesn't fill in the name/namelen, so we must..
*/
@@ -552,7 +545,7 @@ svc_recvfrom(struct svc_rqst *rqstp, str
rqstp->rq_addrlen = svsk->sk_remotelen;

dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
- rqstp->rq_sock, iov[0].iov_base, iov[0].iov_len, len);
+ svsk, iov[0].iov_base, iov[0].iov_len, len);

return len;
}

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

2006-11-13 15:24:21

by Chuck Lever

[permalink] [raw]
Subject: [PATCH 09/13] SUNRPC: teach svc_sendto() to deal with IPv6 addresses

CMSG_DATA comes in different sizes, depending on address family.

Signed-off-by: Chuck Lever <[email protected]>
Cc: Aurelien Charbon <[email protected]>
---

net/sunrpc/svcsock.c | 69 ++++++++++++++++++++++++++++++++++++++------------
1 files changed, 52 insertions(+), 17 deletions(-)

diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index cced146..e8a9379 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -35,6 +35,7 @@ #include <linux/file.h>
#include <net/sock.h>
#include <net/checksum.h>
#include <net/ip.h>
+#include <net/ipv6.h>
#include <net/tcp_states.h>
#include <asm/uaccess.h>
#include <asm/ioctls.h>
@@ -408,6 +409,47 @@ svc_wake_up(struct svc_serv *serv)
}
}

+union svc_pktinfo_u {
+ struct in_pktinfo pkti;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ struct in6_pktinfo pkti6;
+#endif
+};
+
+static void svc_set_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh)
+{
+ switch (rqstp->rq_sock->sk_sk->sk_family) {
+ case AF_INET:
+ do {
+ struct in_pktinfo *pki =
+ (struct in_pktinfo *) CMSG_DATA(cmh);
+
+ cmh->cmsg_level = SOL_IP;
+ cmh->cmsg_type = IP_PKTINFO;
+ pki->ipi_ifindex = 0;
+ pki->ipi_spec_dst.s_addr = rqstp->rq_daddr.addr.s_addr;
+ cmh->cmsg_len = CMSG_LEN(sizeof(*pki));
+ } while (0);
+ break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ case AF_INET6:
+ do {
+ struct in6_pktinfo *pki =
+ (struct in6_pktinfo *) CMSG_DATA(cmh);
+
+ cmh->cmsg_level = SOL_IPV6;
+ cmh->cmsg_type = IPV6_PKTINFO;
+ pki->ipi6_ifindex = 0;
+ ipv6_addr_copy(&pki->ipi6_addr,
+ &rqstp->rq_daddr.addr6);
+ cmh->cmsg_len = CMSG_LEN(sizeof(*pki));
+ } while (0);
+ break;
+#endif
+ }
+ return;
+}
+
/*
* Generic sendto routine
*/
@@ -417,9 +459,8 @@ svc_sendto(struct svc_rqst *rqstp, struc
struct svc_sock *svsk = rqstp->rq_sock;
struct socket *sock = svsk->sk_sock;
int slen;
- char buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
+ char buffer[CMSG_SPACE(sizeof(union svc_pktinfo_u))];
struct cmsghdr *cmh = (struct cmsghdr *)buffer;
- struct in_pktinfo *pki = (struct in_pktinfo *)CMSG_DATA(cmh);
int len = 0;
int result;
int size;
@@ -432,21 +473,15 @@ svc_sendto(struct svc_rqst *rqstp, struc
slen = xdr->len;

if (rqstp->rq_prot == IPPROTO_UDP) {
- /* set the source and destination */
- struct msghdr msg;
- msg.msg_name = &rqstp->rq_addr;
- msg.msg_namelen = rqstp->rq_addrlen;
- msg.msg_iov = NULL;
- msg.msg_iovlen = 0;
- msg.msg_flags = MSG_MORE;
-
- msg.msg_control = cmh;
- msg.msg_controllen = sizeof(buffer);
- cmh->cmsg_len = CMSG_LEN(sizeof(*pki));
- cmh->cmsg_level = SOL_IP;
- cmh->cmsg_type = IP_PKTINFO;
- pki->ipi_ifindex = 0;
- pki->ipi_spec_dst.s_addr = rqstp->rq_daddr.addr.s_addr;
+ struct msghdr msg = {
+ .msg_name = &rqstp->rq_addr,
+ .msg_namelen = rqstp->rq_addrlen,
+ .msg_control = cmh,
+ .msg_controllen = sizeof(buffer),
+ .msg_flags = MSG_MORE,
+ };
+
+ svc_set_cmsg_data(rqstp, cmh);

if (sock_sendmsg(sock, &msg, 0) < 0)
goto out;

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs