Package: openbsd-inetd / 0.20221205-2~deb12u1

default_v4v6 Patch series | download
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);