[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [bug-inetutils] [patch] inetd: set environment variables for remote
From: |
Sergey Poznyakoff |
Subject: |
Re: [bug-inetutils] [patch] inetd: set environment variables for remote host, ip and local port |
Date: |
Fri, 28 Jul 2006 12:43:48 +0300 |
Hello,
Based on Dirk's patch, I have installed the following modifications
to inetd. Passing the environment variables is enabled
by --environment option. The TCP.*HOST variables are set only if the
--resolve option has been specified.
The functionality is limited to IPv4 TCP nowait connection, but I
believe it should be expanded to other connection types as well.
In addition, this patch allows to pass numeric port numbers in
'service' field.
Regards,
Sergey
Index: inetd.c
===================================================================
RCS file: /cvsroot/inetutils/inetutils/inetd/inetd.c,v
retrieving revision 1.32
diff -p -u -r1.32 inetd.c
--- inetd.c 20 Apr 2006 08:16:11 -0000 1.32
+++ inetd.c 28 Jul 2006 09:29:47 -0000
@@ -227,6 +227,7 @@ void set_proc_title __P ((char *, int))
void initring __P((void));
long machtime __P((void));
void run_service __P ((int ctrl, struct servtab *sep));
+void prepenv __P ((int ctrl, struct sockaddr_in sa_client));
struct biltin {
const char *bi_service; /* internally provided service name */
@@ -354,7 +355,11 @@ usage (int err)
__progname);
puts ("Internet super-server.\n\n\
-d, --debug Debug mode\n\
+ --environment Pass local and remote socket information in\n\
+ environment variables\n\
-R, --rate NUMBER Maximum invocation rate (per second)\n\
+ --resolve Resolve IP addresses when setting environment\n\
+ variables (see --environment)\n\
--help Display this help and exit\n\
-V, --version Output version information and exit");
@@ -363,6 +368,9 @@ usage (int err)
exit (err);
}
+static int env_option; /* Set environment variables */
+static int resolve_option; /* Resolve IP addresses */
+
static const char *short_options = "dR:V";
static struct option long_options[] =
{
@@ -370,6 +378,8 @@ static struct option long_options[] =
{ "rate", required_argument, 0, 'R' },
{ "help", no_argument, 0, '&' },
{ "version", no_argument, 0, 'V' },
+ { "resolve", no_argument, &resolve_option, 1 },
+ { "environment", no_argument, &env_option, 1 },
{ 0, 0, 0, 0 }
};
@@ -425,6 +435,9 @@ main (int argc, char *argv[], char *envp
exit (0);
/* Not reached. */
+ case 0:
+ break;
+
case '?':
default:
usage (1);
@@ -432,6 +445,9 @@ main (int argc, char *argv[], char *envp
}
}
+ if (resolve_option)
+ env_option = 1;
+
if (optind < argc)
{
int i;
@@ -514,7 +530,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)
{
- ctrl = accept (sep->se_fd, NULL, NULL);
+ struct sockaddr_in sa_client;
+ socklen_t len = sizeof (sa_client);
+
+ ctrl = accept (sep->se_fd, (struct sockaddr *)&sa_client,
+ &len);
if (debug)
fprintf (stderr, "accept, ctrl %d\n", ctrl);
if (ctrl < 0)
@@ -524,6 +544,8 @@ main (int argc, char *argv[], char *envp
sep->se_service);
continue;
}
+ if (env_option)
+ prepenv (ctrl, sa_client);
}
else
ctrl = sep->se_fd;
@@ -821,14 +843,26 @@ nextconfig (const char *file)
sep->se_fd = -1;
continue;
}
-#ifndef IPV6 /* This code is moved to setup() for IPV6. */
+#ifndef IPV6 /* FIXME: This code is moved to setup() for IPV6, which is
+ wrong */
sp = getservbyname (sep->se_service, sep->se_proto);
if (sp == 0)
{
- syslog (LOG_ERR, "%s/%s: unknown service",
- sep->se_service, sep->se_proto);
- sep->se_checked = 0;
- continue;
+ static struct servent servent;
+ char *p;
+ unsigned long val;
+ unsigned short port;
+
+ val = strtoul (sep->se_service, &p, 0);
+ if (*p || (port = val) != val)
+ {
+ syslog (LOG_ERR, "%s/%s: unknown service",
+ sep->se_service, sep->se_proto);
+ sep->se_checked = 0;
+ continue;
+ }
+ servent.s_port = htons (port);
+ sp = &servent;
}
if (sp->s_port != sep->se_ctrladdr.sin_port)
{
@@ -1712,3 +1746,71 @@ tcpmux(int s, struct servtab *sep)
strwrite (s, "-Service not available\r\n");
exit (1);
}
+
+/* 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)
+{
+ char str[16];
+ char *ip;
+ struct hostent *host;
+ struct sockaddr_in sa_server;
+ socklen_t len = sizeof (sa_server);
+
+ setenv ("PROTO", "TCP", 1);
+ unsetenv ("TCPLOCALIP");
+ unsetenv ("TCPLOCALHOST");
+ unsetenv ("TCPLOCALPORT");
+ unsetenv ("TCPREMOTEIP");
+ unsetenv ("TCPREMOTEPORT");
+ unsetenv ("TCPREMOTEHOST");
+
+ if (getsockname (ctrl, (struct sockaddr*)&sa_server, &len) < 0)
+ syslog (LOG_WARNING, "getsockname(): %m");
+ else
+ {
+ ip = inet_ntoa (sa_server.sin_addr);
+ if (ip)
+ {
+ if (setenv ("TCPLOCALIP", ip, 1) < 0)
+ syslog (LOG_WARNING, "setenv (TCPLOCALIP): %m");
+ }
+
+ snprintf (str, sizeof (str), "%d", ntohs (sa_server.sin_port));
+ setenv ("TCPLOCALPORT", str, 1);
+
+ 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)
+ syslog (LOG_WARNING, "setenv(TCPLOCALHOST): %m");
+ }
+ }
+
+ ip = inet_ntoa (sa_client.sin_addr);
+ if (ip)
+ {
+ if (setenv ("TCPREMOTEIP", ip, 1) < 0)
+ syslog (LOG_WARNING, "setenv(TCPREMOTEIP): %m");
+ }
+
+ snprintf (str, sizeof (str), "%d", ntohs (sa_client.sin_port));
+ 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");
+ }
+}