All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jeff Layton <jlayton@redhat.com>
To: linux-nfs@vger.kernel.org, nfsv4@linux-nfs.org
Cc: kwc@citi.umich.edu, chuck.lever@oracle.com
Subject: [PATCH 2/6] nfs-utils: store the address given in the upcall for later use
Date: Wed, 11 Mar 2009 12:42:58 -0400	[thread overview]
Message-ID: <1236789782-8867-3-git-send-email-jlayton@redhat.com> (raw)
In-Reply-To: <1236789782-8867-1-git-send-email-jlayton@redhat.com>

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@redhat.com>
---
 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;
 };
 
 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


  parent reply	other threads:[~2009-03-11 16:43 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-11 16:42 [PATCH 0/6] nfs-utils: convert gssd to TI-RPC and add IPv6 support (RFC) Jeff Layton
2009-03-11 16:42 ` [PATCH 1/6] nfs-utils: make getnameinfo() required for --enable-gss Jeff Layton
2009-03-11 16:42 ` Jeff Layton [this message]
2009-03-11 21:41   ` [PATCH 2/6] nfs-utils: store the address given in the upcall for later use Chuck Lever
2009-03-11 16:42 ` [PATCH 3/6] nfs-utils: skip getaddrinfo in create_auth_rpc_client unless we need port Jeff Layton
2009-03-11 22:09   ` Chuck Lever
2009-03-12 21:48     ` Jeff Layton
2009-03-11 16:43 ` [PATCH 4/6] nfs-utils: split out gssd rpc client creation into separate function Jeff Layton
2009-03-11 16:43 ` [PATCH 5/6] nfs-utils: when TIRPC is enabled, use new API to create RPC client Jeff Layton
2009-03-11 16:43 ` [PATCH 6/6] nfs-utils: add IPv6 code to gssd Jeff Layton
2009-04-01 14:23 [PATCH 0/6] nfs-utils: convert gssd to TI-RPC and add IPv6 support (try #2) Jeff Layton
2009-04-01 14:24 ` [PATCH 2/6] nfs-utils: store the address given in the upcall for later use Jeff Layton
2009-04-01 16:58   ` Chuck Lever
2009-04-01 17:06     ` Jeff Layton
2009-04-01 17:14       ` Chuck Lever

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1236789782-8867-3-git-send-email-jlayton@redhat.com \
    --to=jlayton@redhat.com \
    --cc=chuck.lever@oracle.com \
    --cc=kwc@citi.umich.edu \
    --cc=linux-nfs@vger.kernel.org \
    --cc=nfsv4@linux-nfs.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.