]> git.decadent.org.uk Git - nfs-utils.git/commitdiff
Try to make sure that clientid used for NFSv4 is reliable.
authorNeil Brown <neilb@suse.de>
Fri, 23 Jun 2006 03:37:08 +0000 (13:37 +1000)
committerNeil Brown <neilb@suse.de>
Fri, 23 Jun 2006 03:37:08 +0000 (13:37 +1000)
We need to give an IP address to identify this client to the
server.
The current code does a gethostbyname of the hostname. One
some systems this returns 127.0.0.1 or similar, which is not useful.

Instead, use getsockname of the sock used to connect to the server
to confirm that the server is working.  This gives the address on the
interface that was chosen to talk to that server, which is the
best address we can find (if there is a NAT in the way, it might
still not work, but in that case there is nothing we can do).

support/include/conn.h
support/nfs/conn.c
utils/mount/nfs4mount.c
utils/mount/nfsmount.c

index ae19a3e4912fea0ff377fb228d320860e79a2ea7..1761dc4442ddd6e2cf0a1e4c520cf3fd8346614b 100644 (file)
@@ -31,7 +31,8 @@ typedef struct {
 static const struct timeval TIMEOUT = { 20, 0 };
 static const struct timeval RETRY_TIMEOUT = { 3, 0 };
 
-int clnt_ping(struct sockaddr_in *, const u_long, const u_long, const u_int);
+int clnt_ping(struct sockaddr_in *, const u_long, const u_long, const u_int,
+             struct sockaddr_in *);
 u_long nfsvers_to_mnt(const u_long);
 u_long mntvers_to_nfs(const u_long);
 int get_socket(struct sockaddr_in *, u_int, int);
index a020394c86b7dc1541b58b3dcd823eaeefe8d6ff..5160c8b29c2fd2c1632be80cbe67adbe1a0fda38 100644 (file)
@@ -92,7 +92,7 @@ int get_socket(struct sockaddr_in *saddr, u_int p_prot, int resvp)
                        return RPC_ANYSOCK;
                }
        }
-       if (type == SOCK_STREAM) {
+       if (type == SOCK_STREAM || type == SOCK_DGRAM) {
                cc = connect(so, (struct sockaddr *)saddr, namelen);
                if (cc < 0) {
                        rpc_createerr.cf_stat = RPC_SYSTEMERROR;
@@ -118,7 +118,7 @@ int get_socket(struct sockaddr_in *saddr, u_int p_prot, int resvp)
  */
 int
 clnt_ping(struct sockaddr_in *saddr, const u_long prog, const u_long vers,
-         const u_int prot)
+         const u_int prot, struct sockaddr_in *caddr)
 {
        CLIENT *clnt=NULL;
        int sock, stat;
@@ -160,8 +160,15 @@ clnt_ping(struct sockaddr_in *saddr, const u_long prog, const u_long vers,
                rpc_createerr.cf_stat = stat;
        }
        clnt_destroy(clnt);
-       if (sock != -1)
+       if (sock != -1) {
+               if (caddr) {
+                       /* Get the address of our end of this connection */
+                       int len = sizeof(*caddr);
+                       if (getsockname(sock, caddr, &len) != 0)
+                               caddr->sin_family = 0;
+               }
                close(sock);
+       }
 
        if (stat == RPC_SUCCESS)
                return 1;
index b59c27cc319e0d27fd9fcde1dad863ee3fa3bab6..717ad56756cad43f8445b73d4064ad65d2929afb 100644 (file)
@@ -189,9 +189,10 @@ int nfs4mount(const char *spec, const char *node, int *flags,
        static struct nfs4_mount_data data;
        static char hostdir[1024];
        static char ip_addr[16] = "127.0.0.1";
-       static struct sockaddr_in server_addr;
+       static struct sockaddr_in server_addr, client_addr;
        static int pseudoflavour[MAX_USER_FLAVOUR];
        int num_flavour = 0;
+       int ip_addr_in_opts = 0;
 
        char *hostname, *dirname, *old_opts;
        char new_opts[1024];
@@ -302,6 +303,7 @@ int nfs4mount(const char *spec, const char *node, int *flags,
                                                                opteq+1);
                                strncpy(ip_addr,opteq+1, sizeof(ip_addr));
                                ip_addr[sizeof(ip_addr)-1] = '\0';
+                               ip_addr_in_opts = 1;
                        } else if (!strcmp(opt, "sec")) {
                                num_flavour = parse_sec(opteq+1, pseudoflavour);
                                if (!num_flavour)
@@ -412,9 +414,19 @@ int nfs4mount(const char *spec, const char *node, int *flags,
                                NFS_PROGRAM, 4, data.proto == IPPROTO_UDP ? "udp" : "tcp", 
                                ntohs(server_addr.sin_port));
                }
-               clnt_ping(&server_addr, NFS_PROGRAM, 4, data.proto);
-               if (rpc_createerr.cf_stat == RPC_SUCCESS)
+               client_addr.sin_family = 0;
+               client_addr.sin_addr.s_addr = 0;
+               clnt_ping(&server_addr, NFS_PROGRAM, 4, data.proto, &client_addr);
+               if (rpc_createerr.cf_stat == RPC_SUCCESS) {
+                       if (!ip_addr_in_opts &&
+                           client_addr.sin_family != 0 &&
+                           client_addr.sin_addr.s_addr != 0) {
+                               snprintf(ip_addr, sizeof(ip_addr), "%s",
+                                        inet_ntoa(client_addr.sin_addr));
+                               data.client_addr.len = strlen(ip_addr);
+                       }
                        break;
+               }
 
                switch(rpc_createerr.cf_stat){
                case RPC_TIMEDOUT:
index 1266660c7f090c50e6c60bbc970aeb8560528134..2b1eb8c593e6bcba411e01077c9e777f7950d730 100644 (file)
@@ -376,7 +376,7 @@ probe_port(clnt_addr_t *server,
                                                inet_ntoa(saddr->sin_addr), prog, *p_vers,
                                                *p_prot == IPPROTO_UDP ? "udp" : "tcp", p_port);
                                }
-                               if (clnt_ping(saddr, prog, *p_vers, *p_prot))
+                               if (clnt_ping(saddr, prog, *p_vers, *p_prot, NULL))
                                        goto out_ok;
                                if (rpc_createerr.cf_stat == RPC_TIMEDOUT)
                                        goto out_bad;