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).
static const struct timeval TIMEOUT = { 20, 0 };
static const struct timeval RETRY_TIMEOUT = { 3, 0 };
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);
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);
- 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;
cc = connect(so, (struct sockaddr *)saddr, namelen);
if (cc < 0) {
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
*/
int
clnt_ping(struct sockaddr_in *saddr, const u_long prog, const u_long vers,
*/
int
clnt_ping(struct sockaddr_in *saddr, const u_long prog, const u_long vers,
+ const u_int prot, struct sockaddr_in *caddr)
{
CLIENT *clnt=NULL;
int sock, stat;
{
CLIENT *clnt=NULL;
int sock, stat;
rpc_createerr.cf_stat = stat;
}
clnt_destroy(clnt);
rpc_createerr.cf_stat = stat;
}
clnt_destroy(clnt);
+ 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;
+ }
if (stat == RPC_SUCCESS)
return 1;
if (stat == RPC_SUCCESS)
return 1;
static struct nfs4_mount_data data;
static char hostdir[1024];
static char ip_addr[16] = "127.0.0.1";
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;
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];
char *hostname, *dirname, *old_opts;
char new_opts[1024];
opteq+1);
strncpy(ip_addr,opteq+1, sizeof(ip_addr));
ip_addr[sizeof(ip_addr)-1] = '\0';
opteq+1);
strncpy(ip_addr,opteq+1, sizeof(ip_addr));
ip_addr[sizeof(ip_addr)-1] = '\0';
} else if (!strcmp(opt, "sec")) {
num_flavour = parse_sec(opteq+1, pseudoflavour);
if (!num_flavour)
} else if (!strcmp(opt, "sec")) {
num_flavour = parse_sec(opteq+1, pseudoflavour);
if (!num_flavour)
NFS_PROGRAM, 4, data.proto == IPPROTO_UDP ? "udp" : "tcp",
ntohs(server_addr.sin_port));
}
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);
+ }
switch(rpc_createerr.cf_stat){
case RPC_TIMEDOUT:
switch(rpc_createerr.cf_stat){
case RPC_TIMEDOUT:
inet_ntoa(saddr->sin_addr), prog, *p_vers,
*p_prot == IPPROTO_UDP ? "udp" : "tcp", p_port);
}
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;
goto out_ok;
if (rpc_createerr.cf_stat == RPC_TIMEDOUT)
goto out_bad;