mount.nfs: Create a new API to find out client's address
authorChuck Lever <chuck.lever@oracle.com>
Fri, 24 Aug 2007 17:11:38 +0000 (13:11 -0400)
committerNeil Brown <neilb@suse.de>
Fri, 24 Aug 2007 22:19:33 +0000 (08:19 +1000)
Provide a version of clnt_ping() that discovers the client's address, but
doesn't do an RPC ping.  The in-kernel text-based mount code already does
a ping, so all we need here is address discovery.

As well, add a block comment in front of clnt_ping() that hopefully
elucidates the differences.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Neil Brown <neilb@suse.de>
utils/mount/network.c
utils/mount/network.h

index 9f803a4..16b802d 100644 (file)
@@ -642,10 +642,23 @@ void mnt_closeclnt(CLIENT *clnt, int msock)
 }
 
 /*
+ * clnt_ping - send an RPC ping to the remote RPC service endpoint
+ * @saddr: server's address
+ * @prog: target RPC program number
+ * @vers: target RPC version number
+ * @prot: target RPC protocol
+ * @caddr: filled in with our network address
+ *
  * Sigh... getport() doesn't actually check the version number.
  * In order to make sure that the server actually supports the service
  * we're requesting, we open and RPC client, and fire off a NULL
  * RPC call.
+ *
+ * caddr is the network address that the server will use to call us back.
+ * On multi-homed clients, this address depends on which NIC we use to
+ * route requests to the server.
+ *
+ * Returns one if successful, otherwise zero.
  */
 int clnt_ping(struct sockaddr_in *saddr, const unsigned long prog,
                const unsigned long vers, const unsigned int prot,
@@ -715,3 +728,36 @@ int clnt_ping(struct sockaddr_in *saddr, const unsigned long prog,
        else
                return 0;
 }
+
+/*
+ * get_client_address - acquire our local network address
+ * @saddr: server's address
+ * @caddr: filled in with our network address
+ *
+ * Discover a network address that the server will use to call us back.
+ * On multi-homed clients, this address depends on which NIC we use to
+ * route requests to the server.
+ *
+ * Use a connected datagram socket so as not to leave a socket in TIME_WAIT.
+ *
+ * Returns one if successful, otherwise zero.
+ */
+int get_client_address(struct sockaddr_in *saddr, struct sockaddr_in *caddr)
+{
+       socklen_t len = sizeof(*caddr);
+       int socket, err;
+
+       socket = get_socket(saddr, IPPROTO_UDP, CONNECT_TIMEOUT, FALSE, TRUE);
+       if (socket == RPC_ANYSOCK)
+               return 0;
+
+       err = getsockname(socket, caddr, &len);
+       close(socket);
+
+       if (err && verbose) {
+               nfs_error(_("%s: getsockname failed: %s"),
+                               progname, strerror(errno));
+               return 0;
+       }
+       return 1;
+}
index 2e4dbbc..99ecc1e 100644 (file)
@@ -48,6 +48,7 @@ static const struct timeval RETRY_TIMEOUT = { 3, 0 };
 
 int probe_bothports(clnt_addr_t *, clnt_addr_t *);
 int nfs_gethostbyname(const char *, struct sockaddr_in *);
+int get_client_address(struct sockaddr_in *, struct sockaddr_in *);
 int nfs_call_umount(clnt_addr_t *, dirpath *);
 int clnt_ping(struct sockaddr_in *, const unsigned long,
                const unsigned long, const unsigned int,