Hello all,

I would like to submit a patch that implements for Inetd
the exporting of environment variables also with IPv6.

Until yesterday, environments variables could only be
set for IPv4 hosts. The mechanism is a migration to use
getnameinfo(3) as only resolver, and the usual changes
of improved book keeping of socket lengths.


Best regards,

Mats
From 78fcde1eafe9484a866b7484537f82363fc12b78 Mon Sep 17 00:00:00 2001
From: Mats Erik Andersson <[email protected]>
Date: Mon, 8 Nov 2010 17:29:36 +0100
Subject: [PATCH] inetd: Environment variables also for IPv6.

---
 ChangeLog   |   14 +++++++++++
 src/inetd.c |   76 ++++++++++++++++++++++++++++++++++++----------------------
 2 files changed, 61 insertions(+), 29 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index f757a82..fadabfc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2010-11-08  Mats Erik Andersson <[email protected]>
+
+	* src/inetd.c (prepenv): New prototype:
+	`prepenv(int, struct sockaddr *, socklen_t)'.
+	(prepenv): Change type of IP to `char []' of fixed length.
+	New integer variable RET.  Make type of SA_SERVER depend on
+	macro IPV6: `struct sockaddr_storage' or `struct sockaddr_in'.
+	(prepenv): Eliminate uses of `inet_ntoa', `gethostbyaddr' by
+	new calls to `getnameinfo', with and without demand on numeric
+	results.  Debugging output on three select environment variables.
+	(main): Make type of SA_CLIENT depend on macro IPV6:
+	`struct sockaddr_storage' or `struct sockaddr_in'.
+	Adaption to new prototype for `prepenv'.
+
 2010-10-31  Mats Erik Andersson <[email protected]>
 
 	* ifconfig/if_index.c (if_nametoindex, if_freenameindex)
diff --git a/src/inetd.c b/src/inetd.c
index f5f7d32..e711095 100644
--- a/src/inetd.c
+++ b/src/inetd.c
@@ -1690,15 +1690,18 @@ tcpmux (int s, struct servtab *sep)
 
 /* Set TCP environment variables, modelled after djb's ucspi-tcp tools:
    http://cr.yp.to/ucspi-tcp/environment.html
-   FIXME: This needs support for IPv6.
 */
 void
-prepenv (int ctrl, struct sockaddr_in sa_client)
+prepenv (int ctrl, struct sockaddr *sa_client, socklen_t sa_len)
 {
   char str[16];
-  char *ip;
-  struct hostent *host;
+  char ip[4 * INET6_ADDRSTRLEN];
+  int ret;
+#ifdef IPV6
+  struct sockaddr_storage sa_server;
+#else
   struct sockaddr_in sa_server;
+#endif
   socklen_t len = sizeof (sa_server);
 
   setenv ("PROTO", "TCP", 1);
@@ -1713,47 +1716,58 @@ prepenv (int ctrl, struct sockaddr_in sa_client)
     syslog (LOG_WARNING, "getsockname(): %m");
   else
     {
-      ip = inet_ntoa (sa_server.sin_addr);
-      if (ip)
+      ret = getnameinfo ((struct sockaddr *) &sa_server, len,
+			  ip, sizeof (ip), str, sizeof (str),
+			  NI_NUMERICHOST | NI_NUMERICSERV);
+      if (ret == 0)
 	{
 	  if (setenv ("TCPLOCALIP", ip, 1) < 0)
 	    syslog (LOG_WARNING, "setenv (TCPLOCALIP): %m");
-	}
+	  else if (debug)
+	    fprintf (stderr, "Assigned TCPLOCALIP = %s\n", ip);
 
-      snprintf (str, sizeof (str), "%d", ntohs (sa_server.sin_port));
-      setenv ("TCPLOCALPORT", str, 1);
+	  if (setenv ("TCPLOCALPORT", str, 1) < 0)
+	    syslog (LOG_WARNING, "setenv (TCPLOCALPORT): %m");
+	}
+      else
+	syslog (LOG_WARNING, "getnameinfo: %s", gai_strerror (ret));
 
       if (resolve_option)
 	{
-	  if ((host = gethostbyaddr ((char *) &sa_server.sin_addr,
-				     sizeof (sa_server.sin_addr),
-				     AF_INET)) == NULL)
-	    syslog (LOG_WARNING, "gethostbyaddr: %m");
-	  else if (setenv ("TCPLOCALHOST", host->h_name, 1) < 0)
+	  ret = getnameinfo ((struct sockaddr *) &sa_server, len,
+			      ip, sizeof (ip), NULL, 0, 0);
+	  if (ret != 0)
+	    syslog (LOG_WARNING, "getnameinfo: %s", gai_strerror (ret));
+	  else if (setenv ("TCPLOCALHOST", ip, 1) < 0)
 	    syslog (LOG_WARNING, "setenv(TCPLOCALHOST): %m");
 	}
     }
 
-  ip = inet_ntoa (sa_client.sin_addr);
-  if (ip)
+  ret = getnameinfo (sa_client, sa_len, ip, sizeof (ip), str, sizeof (str),
+		      NI_NUMERICHOST | NI_NUMERICSERV);
+  if (ret == 0)
     {
       if (setenv ("TCPREMOTEIP", ip, 1) < 0)
 	syslog (LOG_WARNING, "setenv(TCPREMOTEIP): %m");
-    }
+      else if (debug)
+	fprintf (stderr, "Assigned TCPREMOTEIP = %s\n", ip);
 
-  snprintf (str, sizeof (str), "%d", ntohs (sa_client.sin_port));
-  if (setenv ("TCPREMOTEPORT", str, 1) < 0)
-    syslog (LOG_WARNING, "setenv(TCPREMOTEPORT): %m");
+      if (setenv ("TCPREMOTEPORT", str, 1) < 0)
+	syslog (LOG_WARNING, "setenv(TCPREMOTEPORT): %m");
 
-  if (resolve_option)
-    {
-      if ((host = gethostbyaddr ((char *) &sa_client.sin_addr,
-				 sizeof (sa_client.sin_addr),
-				 AF_INET)) == NULL)
-	syslog (LOG_WARNING, "gethostbyaddr: %m");
-      else if (setenv ("TCPREMOTEHOST", host->h_name, 1) < 0)
-	syslog (LOG_WARNING, "setenv(TCPREMOTEHOST): %m");
+      if (resolve_option)
+	{
+	  ret = getnameinfo (sa_client, sa_len, ip, sizeof (ip), NULL, 0, 0);
+	  if (ret != 0)
+	    syslog (LOG_WARNING, "getnameinfo: %s", gai_strerror (ret));
+	  else if (setenv ("TCPREMOTEHOST", ip, 1) < 0)
+	    syslog (LOG_WARNING, "setenv(TCPREMOTEHOST): %m");
+	  else if (debug)
+	    fprintf (stderr, "Assigned TCPREMOTEHOST = %s\n", ip);
+	}
     }
+  else
+    syslog (LOG_WARNING, "getnameinfo: %s", gai_strerror (ret));
 }
 
 
@@ -1864,7 +1878,11 @@ main (int argc, char *argv[], char *envp[])
 	      fprintf (stderr, "someone wants %s\n", sep->se_service);
 	    if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
 	      {
+#ifdef IPV6
+		struct sockaddr_storage sa_client;
+#else
 		struct sockaddr_in sa_client;
+#endif
 		socklen_t len = sizeof (sa_client);
 
 		ctrl = accept (sep->se_fd, (struct sockaddr *) &sa_client,
@@ -1879,7 +1897,7 @@ main (int argc, char *argv[], char *envp[])
 		    continue;
 		  }
 		if (env_option)
-		  prepenv (ctrl, sa_client);
+		  prepenv (ctrl, (struct sockaddr *) &sa_client, len);
 	      }
 	    else
 	      ctrl = sep->se_fd;
-- 
1.7.1

Attachment: signature.asc
Description: Digital signature

Reply via email to