1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
--- a/inetd.8
+++ b/inetd.8
@@ -218,8 +218,7 @@ service type.
and
.Dq udp
will be recognized as
-.Dq TCP or UDP over default IP version .
-This is currently IPv4, but in the future it will be IPv6.
+.Dq TCP or UDP over both IPv4 and IPv6.
If you need to specify IPv4 or IPv6 explicitly, use something like
.Dq tcp4
or
@@ -389,9 +388,9 @@ and
for access control facility configurations, as described in
.Xr hosts_access 5 .
.Ss IPv6 TCP/UDP behavior
-If you wish to run a server for IPv4 and IPv6 traffic,
-you'll need to run two separate processes for the same server program,
-specified as two separate lines in
+The default is to run two servers: one for IPv4 and one for IPv6 traffic.
+If you have different requirements then you may specify one or two
+separate lines in
.Pa inetd.conf ,
for
.Dq tcp4
@@ -414,8 +413,11 @@ and
.Dq tcp6 ,
IPv4 traffic will be routed to the server on
.Dq tcp4 ,
-and IPv6 traffic will go to server on
-.Dq tcp6 .
+and IPv6 traffic will go to the server on
+.Dq tcp6 ,
+which is identical to the default behaviour when only
+.Dq tcp
+is specified.
.It
If you have only one server on
.Dq tcp6 ,
--- a/inetd.c
+++ b/inetd.c
@@ -1156,6 +1156,8 @@ getconfigent(void)
char *cp0, *buf0, *buf1, *sz0, *sz1;
int val;
int argc;
+ static int proto_override;
+ static char saved_line[1024];
sep = calloc(1, sizeof(struct servtab));
if (sep == NULL) {
@@ -1165,6 +1167,11 @@ getconfigent(void)
more:
freeconfig(sep);
+ if (proto_override) {
+ /* process again the same configuration entry */
+ cp = saved_line;
+ } else {
+
while ((cp = nextline(fconfig)) && *cp == '#')
;
if (cp == NULL) {
@@ -1172,6 +1179,11 @@ more:
return (NULL);
}
+ /* keep a copy of the configuration entry */
+ strcpy(saved_line, cp);
+
+ } /* !proto_override */
+
memset(sep, 0, sizeof *sep);
arg = skip(&cp, 0);
if (arg == NULL) {
@@ -1314,9 +1326,37 @@ do { \
} else {
int s;
- sep->se_family = AF_INET;
- if (sep->se_proto[strlen(sep->se_proto) - 1] == '6')
+ if (proto_override) {
+ size_t l;
+ char *s;
+
+ proto_override = 0;
+ /* append "6" to se_proto */
+ sep->se_family = AF_INET6;
+ l = strlen(sep->se_proto);
+ s = malloc(l + 1 + 1);
+ if (s == NULL) {
+ syslog(LOG_ERR, "Out of memory.");
+ exit(1);
+ }
+ (void)strlcpy(s, sep->se_proto, l + 1);
+ s[l] = '6';
+ s[l+1] = '\0';
+ free(sep->se_proto);
+ sep->se_proto = s;
+ } else if (sep->se_proto[strlen(sep->se_proto) - 1] == '4')
+ sep->se_family = AF_INET;
+ else if (sep->se_proto[strlen(sep->se_proto) - 1] == '6')
sep->se_family = AF_INET6;
+ else {
+ /*
+ * If no "4" or "6" was specified then process the
+ * entry as IPv4 but take note that we want to
+ * process it later a second time as "6"
+ */
+ sep->se_family = AF_INET;
+ proto_override = 1;
+ }
/* check if the family is supported */
s = socket(sep->se_family, SOCK_DGRAM, 0);
|