diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2006-11-22 16:10:39 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2006-11-22 16:10:39 +0000 |
commit | c8717cd8571cd35d71696aab8aa847169756bd9f (patch) | |
tree | 254a736d3e761bddc4ba4b00a8f6af1d430ad18f | |
parent | 0801ef28ca655a28543b28754fd804ba0616c21c (diff) | |
download | busybox-w32-c8717cd8571cd35d71696aab8aa847169756bd9f.tar.gz busybox-w32-c8717cd8571cd35d71696aab8aa847169756bd9f.tar.bz2 busybox-w32-c8717cd8571cd35d71696aab8aa847169756bd9f.zip |
telnetd: move generic stuff into libbb. It will make it easy
to make other server applets IPv6-aware too.
-rw-r--r-- | include/libbb.h | 12 | ||||
-rw-r--r-- | libbb/xconnect.c | 152 | ||||
-rw-r--r-- | networking/fakeidentd.c | 4 | ||||
-rw-r--r-- | networking/telnetd.c | 80 |
4 files changed, 168 insertions, 80 deletions
diff --git a/include/libbb.h b/include/libbb.h index 1c82cbbba..c30c5a73d 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -226,6 +226,7 @@ extern int xopen3(const char *pathname, int flags, int mode); | |||
226 | extern off_t xlseek(int fd, off_t offset, int whence); | 226 | extern off_t xlseek(int fd, off_t offset, int whence); |
227 | extern off_t fdlength(int fd); | 227 | extern off_t fdlength(int fd); |
228 | 228 | ||
229 | |||
229 | extern int xsocket(int domain, int type, int protocol); | 230 | extern int xsocket(int domain, int type, int protocol); |
230 | extern void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen); | 231 | extern void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen); |
231 | extern void xlisten(int s, int backlog); | 232 | extern void xlisten(int s, int backlog); |
@@ -233,6 +234,17 @@ extern void xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen); | |||
233 | extern int xconnect_tcp_v4(struct sockaddr_in *s_addr); | 234 | extern int xconnect_tcp_v4(struct sockaddr_in *s_addr); |
234 | extern struct hostent *xgethostbyname(const char *name); | 235 | extern struct hostent *xgethostbyname(const char *name); |
235 | extern struct hostent *xgethostbyname2(const char *name, int af); | 236 | extern struct hostent *xgethostbyname2(const char *name, int af); |
237 | extern int xsocket_stream_ip4or6(sa_family_t *fp); | ||
238 | typedef union { | ||
239 | struct sockaddr sa; | ||
240 | struct sockaddr_in sin; | ||
241 | #if ENABLE_FEATURE_IPV6 | ||
242 | struct sockaddr_in6 sin6; | ||
243 | #endif | ||
244 | } sockaddr_inet; | ||
245 | extern int dotted2sockaddr(const char *dotted, struct sockaddr* sp, int socklen); | ||
246 | extern int create_and_bind_socket_ip4or6(const char *hostaddr, int port); | ||
247 | |||
236 | 248 | ||
237 | extern char *xstrdup(const char *s); | 249 | extern char *xstrdup(const char *s); |
238 | extern char *xstrndup(const char *s, int n); | 250 | extern char *xstrndup(const char *s, int n); |
diff --git a/libbb/xconnect.c b/libbb/xconnect.c index 21ec2761a..cf1f9d59a 100644 --- a/libbb/xconnect.c +++ b/libbb/xconnect.c | |||
@@ -66,3 +66,155 @@ int xconnect_tcp_v4(struct sockaddr_in *s_addr) | |||
66 | xconnect(s, (struct sockaddr*) s_addr, sizeof(*s_addr)); | 66 | xconnect(s, (struct sockaddr*) s_addr, sizeof(*s_addr)); |
67 | return s; | 67 | return s; |
68 | } | 68 | } |
69 | |||
70 | int dotted2sockaddr(const char *dotted, struct sockaddr* sp, int socklen) | ||
71 | { | ||
72 | union { | ||
73 | struct in_addr a4; | ||
74 | #if ENABLE_FEATURE_IPV6 | ||
75 | struct in6_addr a6; | ||
76 | #endif | ||
77 | } a; | ||
78 | |||
79 | /* TODO maybe: port spec? like n.n.n.n:nn */ | ||
80 | |||
81 | #if ENABLE_FEATURE_IPV6 | ||
82 | if (socklen >= sizeof(struct sockaddr_in6) | ||
83 | && inet_pton(AF_INET6, dotted, &a.a6) > 0 | ||
84 | ) { | ||
85 | ((struct sockaddr_in6*)sp)->sin6_family = AF_INET6; | ||
86 | ((struct sockaddr_in6*)sp)->sin6_addr = a.a6; | ||
87 | /* ((struct sockaddr_in6*)sp)->sin6_port = */ | ||
88 | return 0; /* success */ | ||
89 | } | ||
90 | #endif | ||
91 | if (socklen >= sizeof(struct sockaddr_in) | ||
92 | && inet_pton(AF_INET, dotted, &a.a4) > 0 | ||
93 | ) { | ||
94 | ((struct sockaddr_in*)sp)->sin_family = AF_INET; | ||
95 | ((struct sockaddr_in*)sp)->sin_addr = a.a4; | ||
96 | /* ((struct sockaddr_in*)sp)->sin_port = */ | ||
97 | return 0; /* success */ | ||
98 | } | ||
99 | return 1; | ||
100 | } | ||
101 | |||
102 | int xsocket_stream_ip4or6(sa_family_t *fp) | ||
103 | { | ||
104 | int fd; | ||
105 | #if ENABLE_FEATURE_IPV6 | ||
106 | fd = socket(AF_INET6, SOCK_STREAM, 0); | ||
107 | if (fp) *fp = AF_INET6; | ||
108 | if (fd < 0) | ||
109 | #endif | ||
110 | { | ||
111 | fd = xsocket(AF_INET, SOCK_STREAM, 0); | ||
112 | if (fp) *fp = AF_INET; | ||
113 | } | ||
114 | return fd; | ||
115 | } | ||
116 | |||
117 | int create_and_bind_socket_ip4or6(const char *hostaddr, int port) | ||
118 | { | ||
119 | static const int on = 1; | ||
120 | int fd; | ||
121 | sockaddr_inet sa; | ||
122 | |||
123 | memset(&sa, 0, sizeof(sa)); | ||
124 | if (hostaddr && dotted2sockaddr(hostaddr, &sa.sa, sizeof(sa))) | ||
125 | bb_show_usage(); | ||
126 | |||
127 | if (!sa.sa.sa_family) | ||
128 | fd = xsocket_stream_ip4or6(&sa.sa.sa_family); | ||
129 | else /* user specified bind addr dictates family */ | ||
130 | fd = xsocket(sa.sa.sa_family, SOCK_STREAM, 0); | ||
131 | setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); | ||
132 | |||
133 | /* if (port >= 0) { */ | ||
134 | #if ENABLE_FEATURE_IPV6 | ||
135 | if (sa.sa.sa_family == AF_INET6 /* && !sa.sin6.sin6_port */) | ||
136 | sa.sin6.sin6_port = htons(port); | ||
137 | #endif | ||
138 | if (sa.sa.sa_family == AF_INET /* && !sa.sin.sin_port */) | ||
139 | sa.sin.sin_port = htons(port); | ||
140 | /* } */ | ||
141 | |||
142 | xbind(fd, &sa.sa, sizeof(sa)); | ||
143 | return fd; | ||
144 | } | ||
145 | |||
146 | int dotted2sockaddr(const char *dotted, struct sockaddr* sp, int socklen) | ||
147 | { | ||
148 | union { | ||
149 | struct in_addr a4; | ||
150 | #if ENABLE_FEATURE_IPV6 | ||
151 | struct in6_addr a6; | ||
152 | #endif | ||
153 | } a; | ||
154 | |||
155 | /* TODO maybe: port spec? like n.n.n.n:nn */ | ||
156 | |||
157 | #if ENABLE_FEATURE_IPV6 | ||
158 | if (socklen >= sizeof(struct sockaddr_in6) | ||
159 | && inet_pton(AF_INET6, dotted, &a.a6) > 0 | ||
160 | ) { | ||
161 | ((struct sockaddr_in6*)sp)->sin6_family = AF_INET6; | ||
162 | ((struct sockaddr_in6*)sp)->sin6_addr = a.a6; | ||
163 | /* ((struct sockaddr_in6*)sp)->sin6_port = */ | ||
164 | return 0; /* success */ | ||
165 | } | ||
166 | #endif | ||
167 | if (socklen >= sizeof(struct sockaddr_in) | ||
168 | && inet_pton(AF_INET, dotted, &a.a4) > 0 | ||
169 | ) { | ||
170 | ((struct sockaddr_in*)sp)->sin_family = AF_INET; | ||
171 | ((struct sockaddr_in*)sp)->sin_addr = a.a4; | ||
172 | /* ((struct sockaddr_in*)sp)->sin_port = */ | ||
173 | return 0; /* success */ | ||
174 | } | ||
175 | return 1; | ||
176 | } | ||
177 | |||
178 | int xsocket_stream_ip4or6(sa_family_t *fp) | ||
179 | { | ||
180 | int fd; | ||
181 | #if ENABLE_FEATURE_IPV6 | ||
182 | fd = socket(AF_INET6, SOCK_STREAM, 0); | ||
183 | if (fp) *fp = AF_INET6; | ||
184 | if (fd < 0) | ||
185 | #endif | ||
186 | { | ||
187 | fd = xsocket(AF_INET, SOCK_STREAM, 0); | ||
188 | if (fp) *fp = AF_INET; | ||
189 | } | ||
190 | return fd; | ||
191 | } | ||
192 | |||
193 | int create_and_bind_socket_ip4or6(const char *hostaddr, int port) | ||
194 | { | ||
195 | static const int on = 1; | ||
196 | int fd; | ||
197 | sockaddr_inet sa; | ||
198 | |||
199 | memset(&sa, 0, sizeof(sa)); | ||
200 | if (hostaddr) { | ||
201 | if (dotted2sockaddr(hostaddr, &sa.sa, sizeof(sa))) | ||
202 | bb_error_msg_and_die("bad address '%s'", hostaddr); | ||
203 | /* user specified bind addr dictates family */ | ||
204 | fd = xsocket(sa.sa.sa_family, SOCK_STREAM, 0); | ||
205 | } else | ||
206 | fd = xsocket_stream_ip4or6(&sa.sa.sa_family); | ||
207 | setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); | ||
208 | |||
209 | /* if (port >= 0) { */ | ||
210 | #if ENABLE_FEATURE_IPV6 | ||
211 | if (sa.sa.sa_family == AF_INET6 /* && !sa.sin6.sin6_port */) | ||
212 | sa.sin6.sin6_port = htons(port); | ||
213 | #endif | ||
214 | if (sa.sa.sa_family == AF_INET /* && !sa.sin.sin_port */) | ||
215 | sa.sin.sin_port = htons(port); | ||
216 | /* } */ | ||
217 | |||
218 | xbind(fd, &sa.sa, sizeof(sa)); | ||
219 | return fd; | ||
220 | } | ||
diff --git a/networking/fakeidentd.c b/networking/fakeidentd.c index 18e86c50b..0e543e772 100644 --- a/networking/fakeidentd.c +++ b/networking/fakeidentd.c | |||
@@ -110,13 +110,13 @@ static void handlexitsigs(int signum) | |||
110 | /* May succeed. If not, won't care. */ | 110 | /* May succeed. If not, won't care. */ |
111 | static void writepid(uid_t nobody, uid_t nogrp) | 111 | static void writepid(uid_t nobody, uid_t nogrp) |
112 | { | 112 | { |
113 | char buf[24]; | 113 | char buf[sizeof(int)*3 + 2]; |
114 | int fd = open(PIDFILE, O_WRONLY|O_CREAT|O_TRUNC, 0664); | 114 | int fd = open(PIDFILE, O_WRONLY|O_CREAT|O_TRUNC, 0664); |
115 | 115 | ||
116 | if (fd < 0) | 116 | if (fd < 0) |
117 | return; | 117 | return; |
118 | 118 | ||
119 | snprintf(buf, 23, "%d\n", getpid()); | 119 | sprintf(buf, "%d\n", getpid()); |
120 | write(fd, buf, strlen(buf)); | 120 | write(fd, buf, strlen(buf)); |
121 | fchown(fd, nobody, nogrp); | 121 | fchown(fd, nobody, nogrp); |
122 | close(fd); | 122 | close(fd); |
diff --git a/networking/telnetd.c b/networking/telnetd.c index d524ac891..604f65c91 100644 --- a/networking/telnetd.c +++ b/networking/telnetd.c | |||
@@ -354,87 +354,10 @@ free_session(struct tsession *ts) | |||
354 | } | 354 | } |
355 | } | 355 | } |
356 | 356 | ||
357 | static int | ||
358 | dotted2sockaddr(const char *dotted, struct sockaddr* sp, int socklen) | ||
359 | { | ||
360 | union { | ||
361 | struct in_addr a4; | ||
362 | #if ENABLE_FEATURE_IPV6 | ||
363 | struct in6_addr a6; | ||
364 | #endif | ||
365 | } a; | ||
366 | |||
367 | #if ENABLE_FEATURE_IPV6 | ||
368 | if (socklen >= sizeof(struct sockaddr_in6) | ||
369 | && inet_pton(AF_INET6, dotted, &a) > 0 | ||
370 | ) { | ||
371 | ((struct sockaddr_in6*)sp)->sin6_family = AF_INET6; | ||
372 | ((struct sockaddr_in6*)sp)->sin6_addr = a.a6; | ||
373 | } else | ||
374 | #endif | ||
375 | if (socklen >= sizeof(struct sockaddr_in) | ||
376 | && inet_pton(AF_INET, dotted, &a) > 0 | ||
377 | ) { | ||
378 | ((struct sockaddr_in*)sp)->sin_family = AF_INET; | ||
379 | ((struct sockaddr_in*)sp)->sin_addr = a.a4; | ||
380 | } else | ||
381 | return 1; | ||
382 | |||
383 | return 0; /* success */ | ||
384 | } | ||
385 | |||
386 | static int | ||
387 | xsocket_stream_ip4or6(sa_family_t *fp) | ||
388 | { | ||
389 | int fd = socket(AF_INET6, SOCK_STREAM, 0); | ||
390 | if (fp) *fp = AF_INET6; | ||
391 | if (fd < 0) { | ||
392 | fd = xsocket(AF_INET, SOCK_STREAM, 0); | ||
393 | if (fp) *fp = AF_INET; | ||
394 | } | ||
395 | return fd; | ||
396 | } | ||
397 | |||
398 | static int | ||
399 | create_socket(const char *hostaddr, int port) | ||
400 | { | ||
401 | static const int on = 1; | ||
402 | int fd; | ||
403 | union { | ||
404 | struct sockaddr sa; | ||
405 | struct sockaddr_in sin; | ||
406 | #if ENABLE_FEATURE_IPV6 | ||
407 | struct sockaddr_in6 sin6; | ||
408 | #endif | ||
409 | } sa; | ||
410 | |||
411 | memset(&sa, 0, sizeof(sa)); | ||
412 | if (hostaddr && dotted2sockaddr(hostaddr, &sa.sa, sizeof(sa))) | ||
413 | bb_show_usage(); | ||
414 | |||
415 | if (!sa.sa.sa_family) | ||
416 | fd = xsocket_stream_ip4or6(&sa.sa.sa_family); | ||
417 | else /* user specified -b ADDR dictates family */ | ||
418 | fd = xsocket(sa.sa.sa_family, SOCK_STREAM, 0); | ||
419 | setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); | ||
420 | |||
421 | #if ENABLE_FEATURE_IPV6 | ||
422 | if (sa.sa.sa_family == AF_INET6) | ||
423 | sa.sin6.sin6_port = htons(port); | ||
424 | #endif | ||
425 | if (sa.sa.sa_family == AF_INET) | ||
426 | sa.sin.sin_port = htons(port); | ||
427 | |||
428 | xbind(fd, &sa.sa, sizeof(sa)); | ||
429 | xlisten(fd, 1); | ||
430 | return fd; | ||
431 | } | ||
432 | |||
433 | #else /* !FEATURE_TELNETD_STANDALONE */ | 357 | #else /* !FEATURE_TELNETD_STANDALONE */ |
434 | 358 | ||
435 | /* Never actually called */ | 359 | /* Never actually called */ |
436 | void free_session(struct tsession *ts); | 360 | void free_session(struct tsession *ts); |
437 | int create_socket(const char *hostaddr, int port); | ||
438 | 361 | ||
439 | #endif | 362 | #endif |
440 | 363 | ||
@@ -491,7 +414,8 @@ telnetd_main(int argc, char **argv) | |||
491 | if (IS_INETD) { | 414 | if (IS_INETD) { |
492 | sessions = make_new_session(0, 1); | 415 | sessions = make_new_session(0, 1); |
493 | } else { | 416 | } else { |
494 | master_fd = create_socket(opt_bindaddr, portnbr); | 417 | master_fd = create_and_bind_socket_ip4or6(opt_bindaddr, portnbr); |
418 | xlisten(master_fd, 1); | ||
495 | if (!(opt & OPT_FOREGROUND)) | 419 | if (!(opt & OPT_FOREGROUND)) |
496 | xdaemon(0, 0); | 420 | xdaemon(0, 0); |
497 | } | 421 | } |