Re: [PATCH 2/6] nfs-utils: store the address given in the upcall for later use

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mar 11, 2009, at 12:42 PM, Jeff Layton wrote:
The current upcall is rather inefficient. We first convert the address
to a hostname, and then later when we set up the RPC client, we do a
hostname lookup to convert it back to an address.

Begin to change this by keeping the address in the clnt_info that we
get out of the upcall. Since a sockaddr has a port field, we can also
eliminate the port from the clnt_info.

Finally, switch to getnameinfo() instead of gethostbyaddr(). We'll
need to use that call anyway when we switch to using IPv6.

Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
---
utils/gssd/gssd.h      |    2 +-
utils/gssd/gssd_proc.c | 105 +++++++++++++++++++++++++++++++++++++++ +-------
2 files changed, 90 insertions(+), 17 deletions(-)

diff --git a/utils/gssd/gssd.h b/utils/gssd/gssd.h
index 082039a..20f52ff 100644
--- a/utils/gssd/gssd.h
+++ b/utils/gssd/gssd.h
@@ -83,7 +83,7 @@ struct clnt_info {
	int			krb5_poll_index;
	int			spkm3_fd;
	int			spkm3_poll_index;
-	int			port;
+	struct sockaddr_storage *addr;

By convention, if you want to store a pointer to an socket address, "struct sockaddr *" is appropriate. If you want to allocate memory to store the socket address in this field, "struct sockaddr_storage" is appropriate.

I think you will be better off with:

	struct sockaddr_storage addr;

and skipping the extra memory allocation.

};

void init_client_list(void);
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
index 509946e..4f05040 100644
--- a/utils/gssd/gssd_proc.c
+++ b/utils/gssd/gssd_proc.c
@@ -102,10 +102,80 @@ struct pollfd * pollarray;

int pollsize;  /* the size of pollaray (in pollfd's) */

+/*
+ * convert an address string to a sockaddr_storage struct
+ */
+static struct sockaddr_storage *
+addrstr_to_sockaddr(const char *addr, const int port)
+{
+	struct sockaddr_storage *ss;
+	struct sockaddr_in	*s4;
+
+	ss = calloc(1, sizeof(struct sockaddr_storage));
+	if (!ss) {
+		printerr(0, "ERROR: unable to allocate storage to convert "
+			    "address %s\n", addr);
+		goto out;
+	}
+
+	s4 = (struct sockaddr_in *) ss;
+
+	if (inet_pton(AF_INET, addr, &s4->sin_addr)) {
+		s4->sin_family = AF_INET;
+		s4->sin_port = htons(port);
+	} else {
+		printerr(0, "ERROR: unable to convert %s to address\n", addr);
+		free(ss);
+		ss = NULL;
+	}
+out:
+	return ss;
+}
+
+/*
+ * convert a sockaddr to a hostname
+ */
+static char *
+sockaddr_to_hostname(const struct sockaddr *sa, const char *addr)
+{
+#define MAX_HOSTNAME_LEN 127
+	char 			*hostname;
+	socklen_t		addrlen;
+	int			err;
+
+	switch (sa->sa_family) {
+	case AF_INET:
+		addrlen = sizeof(struct sockaddr_in);
+		break;
+	default:
+		printerr(0, "ERROR: unrecognized addr family %d\n",
+			 sa->sa_family);
+		return NULL;
+	}
+
+	hostname = calloc(1, MAX_HOSTNAME_LEN + 1);
+	if (!hostname) {
+		printerr(0, "ERROR: unable to allocate hostname string\n");
+		return NULL;
+	}
+
+	err = getnameinfo(sa, addrlen, hostname, MAX_HOSTNAME_LEN, NULL,
+			  0, NI_NAMEREQD);
+	if (err) {
+		free(hostname);
+		hostname = NULL;
+		printerr(0, "ERROR: unable to resolve %s to hostname: %s\n",
+			 addr, gai_strerror(err));
+	}
+
+	return hostname;
+}
+
/* XXX buffer problems: */
static int
read_service_info(char *info_file_name, char **servicename, char **servername,
-		  int *prog, int *vers, char **protocol, int *port) {
+		  int *prog, int *vers, char **protocol,
+		  struct sockaddr_storage **addr) {
#define INFOBUFLEN 256
	char		buf[INFOBUFLEN + 1];
	static char	dummy[128];
@@ -117,12 +187,12 @@ read_service_info(char *info_file_name, char **servicename, char **servername,
	char		protoname[16];
	char		cb_port[128];
	char		*p;
-	in_addr_t	inaddr;
	int		fd = -1;
-	struct hostent	*ent = NULL;
	int		numfields;
+	int		port = 0;

	*servicename = *servername = *protocol = NULL;
+	*addr = NULL;

	if ((fd = open(info_file_name, O_RDONLY)) == -1) {
		printerr(0, "ERROR: can't open %s: %s\n", info_file_name,
@@ -160,21 +230,20 @@ read_service_info(char *info_file_name, char **servicename, char **servername, if((*prog != 100003) || ((*vers != 2) && (*vers != 3) && (*vers != 4)))
		goto fail;

-	/* create service name */
-	inaddr = inet_addr(address);
-	if (!(ent = gethostbyaddr(&inaddr, sizeof(inaddr), AF_INET))) {
-		printerr(0, "ERROR: can't resolve server %s name\n", address);
+	if (cb_port[0] != '\0')
+		port = atoi(cb_port);
+	*addr = addrstr_to_sockaddr(address, port);
+	if (*addr == NULL)
		goto fail;
-	}
-	if (!(*servername = calloc(strlen(ent->h_name) + 1, 1)))
+
+ *servername = sockaddr_to_hostname((struct sockaddr *) *addr, address);
+	if (*servername == NULL)
		goto fail;
-	memcpy(*servername, ent->h_name, strlen(ent->h_name));
-	snprintf(buf, INFOBUFLEN, "%s@%s", service, ent->h_name);
+
+	snprintf(buf, INFOBUFLEN, "%s@%s", service, *servername);
	if (!(*servicename = calloc(strlen(buf) + 1, 1)))
		goto fail;
	memcpy(*servicename, buf, strlen(buf));
-	if (cb_port[0] != '\0')
-		*port = atoi(cb_port);

	if (!(*protocol = strdup(protoname)))
		goto fail;
@@ -185,7 +254,9 @@ fail:
	free(*servername);
	free(*servicename);
	free(*protocol);
+	free(*addr);
	*servicename = *servername = *protocol = NULL;
+	*addr = NULL;
	return -1;
}

@@ -205,6 +276,7 @@ destroy_client(struct clnt_info *clp)
	free(clp->servicename);
	free(clp->servername);
	free(clp->protocol);
+	free(clp->addr);
	free(clp);
}

@@ -251,7 +323,7 @@ process_clnt_dir_files(struct clnt_info * clp)
	if ((clp->servicename == NULL) &&
	     read_service_info(info_file_name, &clp->servicename,
				&clp->servername, &clp->prog, &clp->vers,
-				&clp->protocol, &clp->port))
+				&clp->protocol, &clp->addr))
		return -1;
	return 0;
}
@@ -599,8 +671,9 @@ int create_auth_rpc_client(struct clnt_info *clp,
			 clp->servername, uid);
		goto out_fail;
	}
-	if (clp->port)
-		((struct sockaddr_in *)a->ai_addr)->sin_port = htons(clp->port);
+	if (((struct sockaddr_in *) clp->addr)->sin_port != 0)
+		((struct sockaddr_in *) a->ai_addr)->sin_port =
+				((struct sockaddr_in *) clp->addr)->sin_port;
	if (a->ai_protocol == IPPROTO_TCP) {
		if ((rpc_clnt = clnttcp_create(
					(struct sockaddr_in *) a->ai_addr,
--
1.6.0.6


--
Chuck Lever
chuck[dot]lever[at]oracle[dot]com



--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux