diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-11 23:26:13 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-11 23:26:13 +0000 |
commit | f8138d1f91c913166bffb0077a0fe06831a77ecf (patch) | |
tree | ad67c96ccbbce0620186dd2926451f69c0831f0f | |
parent | 4fa5e8b455c732db3176c7dbd58dec63d38f4273 (diff) | |
download | busybox-w32-f8138d1f91c913166bffb0077a0fe06831a77ecf.tar.gz busybox-w32-f8138d1f91c913166bffb0077a0fe06831a77ecf.tar.bz2 busybox-w32-f8138d1f91c913166bffb0077a0fe06831a77ecf.zip |
fakeinetd: attempted ipv6-ization (and it's done)
but entire applet can be orders of magnitude smaller
if written as an inetd service.
So did that (#ifdef'ed out entire old version).
inetd version is less than 10% of old one!
function old new delta
packed_usage 22083 22105 +22
nobodystr 4 - -4
bind_ip_address 4 - -4
ident_substr 20 - -20
chmatch 22 - -22
movefd 25 - -25
skipchars 49 - -49
handlexitsigs 51 - -51
replyError 70 - -70
.rodata 158120 158024 -96
deleteConn 102 - -102
G 524 388 -136
conns 560 - -560
fakeidentd_main 1457 143 -1314
------------------------------------------------------------------------------
(add/remove: 0/10 grow/shrink: 1/3 up/down: 22/-2453) Total: -2431 bytes
-rw-r--r-- | include/usage.h | 9 | ||||
-rw-r--r-- | networking/fakeidentd.c | 346 | ||||
-rw-r--r-- | networking/inetd.c | 49 |
3 files changed, 214 insertions, 190 deletions
diff --git a/include/usage.h b/include/usage.h index 14650e5de..4e5206558 100644 --- a/include/usage.h +++ b/include/usage.h | |||
@@ -826,6 +826,7 @@ | |||
826 | "\\( and \\) or null; if \\( and \\) are not used, they return the number\n" \ | 826 | "\\( and \\) or null; if \\( and \\) are not used, they return the number\n" \ |
827 | "of characters matched or 0." | 827 | "of characters matched or 0." |
828 | 828 | ||
829 | #if 0 /* bloaty */ | ||
829 | #define fakeidentd_trivial_usage \ | 830 | #define fakeidentd_trivial_usage \ |
830 | "[-b ip] [STRING]" | 831 | "[-b ip] [STRING]" |
831 | #define fakeidentd_full_usage \ | 832 | #define fakeidentd_full_usage \ |
@@ -833,6 +834,14 @@ | |||
833 | "\n\nOptions:\n" \ | 834 | "\n\nOptions:\n" \ |
834 | " -b Bind to ip address\n" \ | 835 | " -b Bind to ip address\n" \ |
835 | " STRING The ident answer string (default is nobody)" | 836 | " STRING The ident answer string (default is nobody)" |
837 | #else /* inetd-only */ | ||
838 | #define fakeidentd_trivial_usage \ | ||
839 | "[username]" | ||
840 | #define fakeidentd_full_usage \ | ||
841 | "Return a (faked) ident response.\n" \ | ||
842 | "This applet is meant to run from inetd.\n" \ | ||
843 | "Optional argument is the username to return (default is 'nobody')." | ||
844 | #endif | ||
836 | 845 | ||
837 | #define false_trivial_usage \ | 846 | #define false_trivial_usage \ |
838 | "" | 847 | "" |
diff --git a/networking/fakeidentd.c b/networking/fakeidentd.c index 7eac48065..8c07082fc 100644 --- a/networking/fakeidentd.c +++ b/networking/fakeidentd.c | |||
@@ -9,12 +9,62 @@ | |||
9 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | 9 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | /* Ident crash course | ||
13 | * | ||
14 | * Incoming requests are of form "6191, 23\r\n" - peer asks us | ||
15 | * "which user connected from your port 6191 to my port 23?" | ||
16 | * We should answer: | ||
17 | * "6193, 23 : USERID : UNIX : username\r\n" | ||
18 | * and close the connection. | ||
19 | * We can also reply: | ||
20 | * "6195, 23 : USERID : OTHER[,US-ASCII] : username\r\n" | ||
21 | * "6195, 23 : ERROR : INVALID-PORT/NO-USER/HIDDEN-USER/UNKNOWN-ERROR\r\n" | ||
22 | * but we probably will never want that. | ||
23 | */ | ||
24 | |||
12 | #include "busybox.h" | 25 | #include "busybox.h" |
26 | |||
27 | #define SANE_INETD_ONLY_VERSION | ||
28 | |||
29 | #ifdef SANE_INETD_ONLY_VERSION | ||
30 | |||
31 | int fakeidentd_main(int argc, char **argv) | ||
32 | { | ||
33 | char buf[64]; | ||
34 | const char *bogouser = "nobody"; | ||
35 | char *cur = buf; | ||
36 | int rem = sizeof(buf)-1; | ||
37 | |||
38 | if (argv[1]) | ||
39 | bogouser = argv[1]; | ||
40 | |||
41 | alarm(30); | ||
42 | while (1) { | ||
43 | char *p; | ||
44 | int sz = safe_read(0, cur, rem); | ||
45 | if (sz < 0) return 1; | ||
46 | cur[sz] = '\0'; | ||
47 | p = strpbrk(cur, "\r\n"); | ||
48 | if (p) { | ||
49 | *p = '\0'; | ||
50 | break; | ||
51 | } | ||
52 | cur += sz; | ||
53 | rem -= sz; | ||
54 | if (!rem || !sz) | ||
55 | break; | ||
56 | } | ||
57 | printf("%s : USERID : UNIX : %s\r\n", buf, bogouser); | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | #else | ||
62 | |||
63 | /* Welcome to the bloaty horrors */ | ||
64 | |||
13 | #include <sys/syslog.h> | 65 | #include <sys/syslog.h> |
14 | #include <sys/uio.h> | 66 | #include <sys/uio.h> |
15 | 67 | ||
16 | |||
17 | #define IDENT_PORT 113 | ||
18 | #define MAXCONNS 20 | 68 | #define MAXCONNS 20 |
19 | #define MAXIDLETIME 45 | 69 | #define MAXIDLETIME 45 |
20 | 70 | ||
@@ -43,9 +93,9 @@ enum { ident_substr_len = sizeof(ident_substr) - 1 }; | |||
43 | * in `conns' array + FCS | 93 | * in `conns' array + FCS |
44 | */ | 94 | */ |
45 | static struct { | 95 | static struct { |
46 | char buf[20]; | ||
47 | int len; | ||
48 | time_t lasttime; | 96 | time_t lasttime; |
97 | int len; | ||
98 | char buf[20]; | ||
49 | } conns[MAXCONNS]; | 99 | } conns[MAXCONNS]; |
50 | 100 | ||
51 | /* When using global variables, bind those at least to a structure. */ | 101 | /* When using global variables, bind those at least to a structure. */ |
@@ -55,111 +105,92 @@ static struct { | |||
55 | int conncnt; | 105 | int conncnt; |
56 | } G; | 106 | } G; |
57 | 107 | ||
58 | /* | 108 | static char *bind_ip_address; |
59 | * Prototypes | ||
60 | */ | ||
61 | static void reply(int s, char *buf); | ||
62 | static void replyError(int s, char *buf); | ||
63 | 109 | ||
64 | static const char *nobodystr = "nobody"; /* this needs to be declared like this */ | 110 | static int chmatch(char c, char *chars) |
65 | static char *bind_ip_address = "0.0.0.0"; | 111 | { |
112 | for (; *chars; chars++) | ||
113 | if (c == *chars) | ||
114 | return 1; | ||
115 | return 0; | ||
116 | } | ||
66 | 117 | ||
67 | static void movefd(int from, int to) | 118 | static int skipchars(char **p, char *chars) |
68 | { | 119 | { |
69 | if (from != to) { | 120 | while (chmatch(**p, chars)) |
70 | dup2(from, to); | 121 | (*p)++; |
71 | close(from); | 122 | if (**p == '\r' || **p == '\n') |
72 | } | 123 | return 0; |
124 | return 1; | ||
73 | } | 125 | } |
74 | 126 | ||
75 | static void inetbind(void) | 127 | static int parseAddrs(char *ptr, char **myaddr, char **heraddr) |
76 | { | 128 | { |
77 | int s, port; | 129 | /* parse <port-on-server> , <port-on-client> */ |
78 | struct sockaddr_in addr; | ||
79 | int len = sizeof(addr); | ||
80 | struct servent *se; | ||
81 | 130 | ||
82 | se = getservbyname("identd", "tcp"); | 131 | if (!skipchars(&ptr, " \t")) |
83 | port = IDENT_PORT; | 132 | return -1; |
84 | if (se) | ||
85 | port = se->s_port; | ||
86 | 133 | ||
87 | s = xsocket(AF_INET, SOCK_STREAM, 0); | 134 | *myaddr = ptr; |
88 | 135 | ||
89 | setsockopt_reuseaddr(s); | 136 | if (!skipchars(&ptr, "1234567890")) |
137 | return -1; | ||
90 | 138 | ||
91 | memset(&addr, 0, sizeof(addr)); | 139 | if (!chmatch(*ptr, " \t,")) |
92 | addr.sin_addr.s_addr = inet_addr(bind_ip_address); | 140 | return -1; |
93 | addr.sin_family = AF_INET; | ||
94 | addr.sin_port = htons(port); | ||
95 | 141 | ||
96 | xbind(s, (struct sockaddr *)&addr, len); | 142 | *ptr++ = '\0'; |
97 | xlisten(s, 5); | ||
98 | 143 | ||
99 | movefd(s, 0); | 144 | if (!skipchars(&ptr, " \t,") ) |
100 | } | 145 | return -1; |
101 | 146 | ||
102 | static void handlexitsigs(int signum) | 147 | *heraddr = ptr; |
103 | { | ||
104 | if (unlink(PIDFILE) < 0) | ||
105 | close(open(PIDFILE, O_WRONLY|O_CREAT|O_TRUNC, 0644)); | ||
106 | exit(0); | ||
107 | } | ||
108 | 148 | ||
109 | /* May succeed. If not, won't care. */ | 149 | skipchars(&ptr, "1234567890"); |
110 | static void writepid(uid_t nobody, uid_t nogrp) | ||
111 | { | ||
112 | char buf[sizeof(int)*3 + 2]; | ||
113 | int fd = open(PIDFILE, O_WRONLY|O_CREAT|O_TRUNC, 0664); | ||
114 | 150 | ||
115 | if (fd < 0) | 151 | if (!chmatch(*ptr, " \n\r")) |
116 | return; | 152 | return -1; |
117 | 153 | ||
118 | sprintf(buf, "%d\n", getpid()); | 154 | *ptr = '\0'; |
119 | write(fd, buf, strlen(buf)); | ||
120 | fchown(fd, nobody, nogrp); | ||
121 | close(fd); | ||
122 | 155 | ||
123 | /* should this handle ILL, ... (see signal(7)) */ | 156 | return 0; |
124 | signal(SIGTERM, handlexitsigs); | ||
125 | signal(SIGINT, handlexitsigs); | ||
126 | signal(SIGQUIT, handlexitsigs); | ||
127 | } | 157 | } |
128 | 158 | ||
129 | /* return 0 as parent, 1 as child */ | 159 | static void replyError(int s, char *buf) |
130 | static int godaemon(void) | ||
131 | { | 160 | { |
132 | uid_t nobody, nogrp; | 161 | struct iovec iv[3]; |
133 | struct passwd *pw; | 162 | iv[0].iov_base = "0, 0 : ERROR : "; iv[0].iov_len = 15; |
134 | 163 | iv[1].iov_base = buf; iv[1].iov_len = strlen(buf); | |
135 | switch (fork()) { | 164 | iv[2].iov_base = "\r\n"; iv[2].iov_len = 2; |
136 | case -1: | 165 | writev(s, iv, 3); |
137 | bb_perror_msg_and_die("fork"); | 166 | } |
138 | |||
139 | case 0: | ||
140 | pw = getpwnam(nobodystr); | ||
141 | if (pw == NULL) | ||
142 | bb_error_msg_and_die("cannot find uid/gid of user '%s'", nobodystr); | ||
143 | nobody = pw->pw_uid; | ||
144 | nogrp = pw->pw_gid; | ||
145 | writepid(nobody, nogrp); | ||
146 | |||
147 | close(0); | ||
148 | inetbind(); | ||
149 | xsetgid(nogrp); | ||
150 | xsetuid(nobody); | ||
151 | close(1); | ||
152 | close(2); | ||
153 | 167 | ||
154 | signal(SIGHUP, SIG_IGN); | 168 | static void reply(int s, char *buf) |
155 | signal(SIGPIPE, SIG_IGN); /* connection closed when writing (raises ???) */ | 169 | { |
170 | char *myaddr, *heraddr; | ||
156 | 171 | ||
157 | setsid(); | 172 | myaddr = heraddr = NULL; |
158 | 173 | ||
159 | return 1; | 174 | if (parseAddrs(buf, &myaddr, &heraddr)) |
175 | replyError(s, "X-INVALID-REQUEST"); | ||
176 | else { | ||
177 | struct iovec iv[6]; | ||
178 | iv[0].iov_base = myaddr; iv[0].iov_len = strlen(myaddr); | ||
179 | iv[1].iov_base = ", "; iv[1].iov_len = 2; | ||
180 | iv[2].iov_base = heraddr; iv[2].iov_len = strlen(heraddr); | ||
181 | iv[3].iov_base = (void *)ident_substr; iv[3].iov_len = ident_substr_len; | ||
182 | iv[4].iov_base = (void *)G.identuser; iv[4].iov_len = strlen(G.identuser); | ||
183 | iv[5].iov_base = "\r\n"; iv[5].iov_len = 2; | ||
184 | writev(s, iv, 6); | ||
160 | } | 185 | } |
186 | } | ||
161 | 187 | ||
162 | return 0; | 188 | static void movefd(int from, int to) |
189 | { | ||
190 | if (from != to) { | ||
191 | dup2(from, to); | ||
192 | close(from); | ||
193 | } | ||
163 | } | 194 | } |
164 | 195 | ||
165 | static void deleteConn(int s) | 196 | static void deleteConn(int s) |
@@ -215,15 +246,32 @@ static int checkInput(char *buf, int len, int l) | |||
215 | return 0; | 246 | return 0; |
216 | } | 247 | } |
217 | 248 | ||
249 | /* May succeed. If not, won't care. */ | ||
250 | static const char *to_unlink; | ||
251 | static void writepid(void) | ||
252 | { | ||
253 | int fd = open(PIDFILE, O_WRONLY|O_CREAT|O_TRUNC, 0664); | ||
254 | if (fd < 0) | ||
255 | return; | ||
256 | to_unlink = PIDFILE; | ||
257 | fdprintf(fd, "%d\n", getpid()); | ||
258 | close(fd); | ||
259 | } | ||
260 | |||
261 | static void handlexitsigs(int signum) | ||
262 | { | ||
263 | if (to_unlink) | ||
264 | if (unlink(to_unlink) < 0) | ||
265 | close(open(to_unlink, O_WRONLY|O_CREAT|O_TRUNC, 0644)); | ||
266 | exit(0); | ||
267 | } | ||
268 | |||
218 | int fakeidentd_main(int argc, char **argv) | 269 | int fakeidentd_main(int argc, char **argv) |
219 | { | 270 | { |
220 | /* This applet is an inetd-style daemon */ | 271 | int fd; |
221 | openlog(applet_name, 0, LOG_DAEMON); | 272 | pid_t pid; |
222 | logmode = LOGMODE_SYSLOG; | ||
223 | 273 | ||
224 | memset(conns, 0, sizeof(conns)); | 274 | /* FD_ZERO(&G.readfds); - in bss, already zeroed */ |
225 | memset(&G, 0, sizeof(G)); | ||
226 | FD_ZERO(&G.readfds); | ||
227 | FD_SET(0, &G.readfds); | 275 | FD_SET(0, &G.readfds); |
228 | 276 | ||
229 | /* handle -b <ip> parameter */ | 277 | /* handle -b <ip> parameter */ |
@@ -232,11 +280,30 @@ int fakeidentd_main(int argc, char **argv) | |||
232 | if (optind < argc) | 280 | if (optind < argc) |
233 | G.identuser = argv[optind]; | 281 | G.identuser = argv[optind]; |
234 | else | 282 | else |
235 | G.identuser = nobodystr; | 283 | G.identuser = "nobody"; |
236 | 284 | ||
237 | /* daemonize and have the parent return */ | 285 | writepid(); |
238 | if (godaemon() == 0) | 286 | signal(SIGTERM, handlexitsigs); |
239 | return 0; | 287 | signal(SIGINT, handlexitsigs); |
288 | signal(SIGQUIT, handlexitsigs); | ||
289 | signal(SIGHUP, SIG_IGN); | ||
290 | signal(SIGPIPE, SIG_IGN); /* ignore closed connections when writing */ | ||
291 | |||
292 | fd = create_and_bind_stream_or_die(bind_ip_address, bb_lookup_port("identd", "tcp", 113)); | ||
293 | xlisten(fd, 5); | ||
294 | |||
295 | pid = fork(); | ||
296 | if (pid < 0) | ||
297 | bb_perror_msg_and_die("fork"); | ||
298 | if (pid != 0) /* parent */ | ||
299 | exit(0); | ||
300 | /* child */ | ||
301 | setsid(); | ||
302 | movefd(fd, 0); | ||
303 | while (fd) | ||
304 | close(fd--); | ||
305 | openlog(applet_name, 0, LOG_DAEMON); | ||
306 | logmode = LOGMODE_SYSLOG; | ||
240 | 307 | ||
241 | /* main loop where we process all events and never exit */ | 308 | /* main loop where we process all events and never exit */ |
242 | while (1) { | 309 | while (1) { |
@@ -252,10 +319,11 @@ int fakeidentd_main(int argc, char **argv) | |||
252 | 319 | ||
253 | if (FD_ISSET(s, &rfds)) { | 320 | if (FD_ISSET(s, &rfds)) { |
254 | char *buf = conns[i].buf; | 321 | char *buf = conns[i].buf; |
255 | unsigned int len = conns[i].len; | 322 | unsigned len = conns[i].len; |
256 | unsigned int l; | 323 | unsigned l; |
257 | 324 | ||
258 | if ((l = read(s, buf + len, sizeof(conns[0].buf) - len)) > 0) { | 325 | l = read(s, buf + len, sizeof(conns[0].buf) - len); |
326 | if (l > 0) { | ||
259 | if (checkInput(buf, len, l)) { | 327 | if (checkInput(buf, len, l)) { |
260 | reply(s, buf); | 328 | reply(s, buf); |
261 | goto deleteconn; | 329 | goto deleteconn; |
@@ -268,10 +336,8 @@ int fakeidentd_main(int argc, char **argv) | |||
268 | } else { | 336 | } else { |
269 | goto deleteconn; | 337 | goto deleteconn; |
270 | } | 338 | } |
271 | |||
272 | conns[i].lasttime = tim; | 339 | conns[i].lasttime = tim; |
273 | continue; | 340 | continue; |
274 | |||
275 | deleteconn: | 341 | deleteconn: |
276 | deleteConn(s); | 342 | deleteConn(s); |
277 | } else { | 343 | } else { |
@@ -287,7 +353,7 @@ deleteconn: | |||
287 | int s = accept(0, NULL, 0); | 353 | int s = accept(0, NULL, 0); |
288 | 354 | ||
289 | if (s < 0) { | 355 | if (s < 0) { |
290 | if (errno != EINTR) /* EINTR */ | 356 | if (errno != EINTR) |
291 | bb_perror_msg("accept"); | 357 | bb_perror_msg("accept"); |
292 | } else { | 358 | } else { |
293 | if (G.conncnt == MAXCONNS) | 359 | if (G.conncnt == MAXCONNS) |
@@ -297,7 +363,6 @@ deleteconn: | |||
297 | 363 | ||
298 | movefd(s, i + FCS); /* move if not already there */ | 364 | movefd(s, i + FCS); /* move if not already there */ |
299 | FD_SET(i + FCS, &G.readfds); | 365 | FD_SET(i + FCS, &G.readfds); |
300 | |||
301 | conns[i].len = 0; | 366 | conns[i].len = 0; |
302 | conns[i].lasttime = time(NULL); | 367 | conns[i].lasttime = time(NULL); |
303 | } | 368 | } |
@@ -307,81 +372,4 @@ deleteconn: | |||
307 | return 0; | 372 | return 0; |
308 | } | 373 | } |
309 | 374 | ||
310 | static int parseAddrs(char *ptr, char **myaddr, char **heraddr); | 375 | #endif /* !SANE_INETD_ONLY_VERSION */ |
311 | static void reply(int s, char *buf) | ||
312 | { | ||
313 | char *myaddr, *heraddr; | ||
314 | |||
315 | myaddr = heraddr = NULL; | ||
316 | |||
317 | if (parseAddrs(buf, &myaddr, &heraddr)) | ||
318 | replyError(s, "X-INVALID-REQUEST"); | ||
319 | else { | ||
320 | struct iovec iv[6]; | ||
321 | iv[0].iov_base = myaddr; iv[0].iov_len = strlen(myaddr); | ||
322 | iv[1].iov_base = ", "; iv[1].iov_len = 2; | ||
323 | iv[2].iov_base = heraddr; iv[2].iov_len = strlen(heraddr); | ||
324 | iv[3].iov_base = (void *)ident_substr; iv[3].iov_len = ident_substr_len; | ||
325 | iv[4].iov_base = (void *)G.identuser; iv[4].iov_len = strlen(G.identuser); | ||
326 | iv[5].iov_base = "\r\n"; iv[5].iov_len = 2; | ||
327 | writev(s, iv, 6); | ||
328 | } | ||
329 | } | ||
330 | |||
331 | static void replyError(int s, char *buf) | ||
332 | { | ||
333 | struct iovec iv[3]; | ||
334 | iv[0].iov_base = "0, 0 : ERROR : "; iv[0].iov_len = 15; | ||
335 | iv[1].iov_base = buf; iv[1].iov_len = strlen(buf); | ||
336 | iv[2].iov_base = "\r\n"; iv[2].iov_len = 2; | ||
337 | writev(s, iv, 3); | ||
338 | } | ||
339 | |||
340 | static int chmatch(char c, char *chars) | ||
341 | { | ||
342 | for (; *chars; chars++) | ||
343 | if (c == *chars) | ||
344 | return 1; | ||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | static int skipchars(char **p, char *chars) | ||
349 | { | ||
350 | while (chmatch(**p, chars)) | ||
351 | (*p)++; | ||
352 | if (**p == '\r' || **p == '\n') | ||
353 | return 0; | ||
354 | return 1; | ||
355 | } | ||
356 | |||
357 | static int parseAddrs(char *ptr, char **myaddr, char **heraddr) | ||
358 | { | ||
359 | /* parse <port-on-server> , <port-on-client> */ | ||
360 | |||
361 | if (!skipchars(&ptr, " \t")) | ||
362 | return -1; | ||
363 | |||
364 | *myaddr = ptr; | ||
365 | |||
366 | if (!skipchars(&ptr, "1234567890")) | ||
367 | return -1; | ||
368 | |||
369 | if (!chmatch(*ptr, " \t,")) | ||
370 | return -1; | ||
371 | |||
372 | *ptr++ = '\0'; | ||
373 | |||
374 | if (!skipchars(&ptr, " \t,") ) | ||
375 | return -1; | ||
376 | |||
377 | *heraddr = ptr; | ||
378 | |||
379 | skipchars(&ptr, "1234567890"); | ||
380 | |||
381 | if (!chmatch(*ptr, " \n\r")) | ||
382 | return -1; | ||
383 | |||
384 | *ptr = '\0'; | ||
385 | |||
386 | return 0; | ||
387 | } | ||
diff --git a/networking/inetd.c b/networking/inetd.c index 75665ba3e..93c16bf60 100644 --- a/networking/inetd.c +++ b/networking/inetd.c | |||
@@ -23,7 +23,7 @@ | |||
23 | * may be used to endorse or promote products derived from this software | 23 | * may be used to endorse or promote products derived from this software |
24 | * without specific prior written permission. | 24 | * without specific prior written permission. |
25 | * | 25 | * |
26 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | 26 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND |
27 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 27 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
28 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 28 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
29 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 29 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
@@ -36,8 +36,7 @@ | |||
36 | * SUCH DAMAGE. | 36 | * SUCH DAMAGE. |
37 | */ | 37 | */ |
38 | 38 | ||
39 | /* | 39 | /* Inetd - Internet super-server |
40 | * Inetd - Internet super-server | ||
41 | * | 40 | * |
42 | * This program invokes all internet services as needed. | 41 | * This program invokes all internet services as needed. |
43 | * connection-oriented services are invoked each time a | 42 | * connection-oriented services are invoked each time a |
@@ -50,14 +49,14 @@ | |||
50 | * arrives; a process is created and passed a pending message | 49 | * arrives; a process is created and passed a pending message |
51 | * on file descriptor 0. Datagram servers may either connect | 50 | * on file descriptor 0. Datagram servers may either connect |
52 | * to their peer, freeing up the original socket for inetd | 51 | * to their peer, freeing up the original socket for inetd |
53 | * to receive further messages on, or ``take over the socket'', | 52 | * to receive further messages on, or "take over the socket", |
54 | * processing all arriving datagrams and, eventually, timing | 53 | * processing all arriving datagrams and, eventually, timing |
55 | * out. The first type of server is said to be ``multi-threaded''; | 54 | * out. The first type of server is said to be "multi-threaded"; |
56 | * the second type of server ``single-threaded''. | 55 | * the second type of server "single-threaded". |
57 | * | 56 | * |
58 | * Inetd uses a configuration file which is read at startup | 57 | * Inetd uses a configuration file which is read at startup |
59 | * and, possibly, at some later time in response to a hangup signal. | 58 | * and, possibly, at some later time in response to a hangup signal. |
60 | * The configuration file is ``free format'' with fields given in the | 59 | * The configuration file is "free format" with fields given in the |
61 | * order shown below. Continuation lines for an entry must begin with | 60 | * order shown below. Continuation lines for an entry must begin with |
62 | * a space or tab. All fields must be present in each entry. | 61 | * a space or tab. All fields must be present in each entry. |
63 | * | 62 | * |
@@ -105,8 +104,37 @@ | |||
105 | * Comment lines are indicated by a `#' in column 1. | 104 | * Comment lines are indicated by a `#' in column 1. |
106 | */ | 105 | */ |
107 | 106 | ||
108 | /* | 107 | /* inetd rules for passing file descriptors to children |
109 | * Here's the scoop concerning the user[.:]group feature: | 108 | * (http://www.freebsd.org/cgi/man.cgi?query=inetd): |
109 | * | ||
110 | * The wait/nowait entry specifies whether the server that is invoked by | ||
111 | * inetd will take over the socket associated with the service access point, | ||
112 | * and thus whether inetd should wait for the server to exit before listen- | ||
113 | * ing for new service requests. Datagram servers must use "wait", as | ||
114 | * they are always invoked with the original datagram socket bound to the | ||
115 | * specified service address. These servers must read at least one datagram | ||
116 | * from the socket before exiting. If a datagram server connects to its | ||
117 | * peer, freeing the socket so inetd can receive further messages on the | ||
118 | * socket, it is said to be a "multi-threaded" server; it should read one | ||
119 | * datagram from the socket and create a new socket connected to the peer. | ||
120 | * It should fork, and the parent should then exit to allow inetd to check | ||
121 | * for new service requests to spawn new servers. Datagram servers which | ||
122 | * process all incoming datagrams on a socket and eventually time out are | ||
123 | * said to be "single-threaded". The comsat(8), (biff(1)) and talkd(8) | ||
124 | * utilities are both examples of the latter type of datagram server. The | ||
125 | * tftpd(8) utility is an example of a multi-threaded datagram server. | ||
126 | * | ||
127 | * Servers using stream sockets generally are multi-threaded and use the | ||
128 | * "nowait" entry. Connection requests for these services are accepted by | ||
129 | * inetd, and the server is given only the newly-accepted socket connected | ||
130 | * to a client of the service. Most stream-based services operate in this | ||
131 | * manner. Stream-based servers that use "wait" are started with the lis- | ||
132 | * tening service socket, and must accept at least one connection request | ||
133 | * before exiting. Such a server would normally accept and process incoming | ||
134 | * connection requests until a timeout. | ||
135 | */ | ||
136 | |||
137 | /* Here's the scoop concerning the user[.:]group feature: | ||
110 | * | 138 | * |
111 | * 1) set-group-option off. | 139 | * 1) set-group-option off. |
112 | * | 140 | * |
@@ -125,7 +153,6 @@ | |||
125 | * b) other: setgid(specified group) | 153 | * b) other: setgid(specified group) |
126 | * initgroups(name, specified group) | 154 | * initgroups(name, specified group) |
127 | * setuid() | 155 | * setuid() |
128 | * | ||
129 | */ | 156 | */ |
130 | 157 | ||
131 | #include "busybox.h" | 158 | #include "busybox.h" |
@@ -161,7 +188,7 @@ | |||
161 | #endif | 188 | #endif |
162 | 189 | ||
163 | /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */ | 190 | /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */ |
164 | #define FD_MARGIN (8) | 191 | #define FD_MARGIN 8 |
165 | static rlim_t rlim_ofile_cur = OPEN_MAX; | 192 | static rlim_t rlim_ofile_cur = OPEN_MAX; |
166 | static struct rlimit rlim_ofile; | 193 | static struct rlimit rlim_ofile; |
167 | 194 | ||