diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2006-11-22 15:57:52 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2006-11-22 15:57:52 +0000 |
commit | 0801ef28ca655a28543b28754fd804ba0616c21c (patch) | |
tree | a6398d8c1b03893866954f3a2042ff1807101512 | |
parent | 75f8d080a28f2a9076a5f60afeba41ac876a78a4 (diff) | |
download | busybox-w32-0801ef28ca655a28543b28754fd804ba0616c21c.tar.gz busybox-w32-0801ef28ca655a28543b28754fd804ba0616c21c.tar.bz2 busybox-w32-0801ef28ca655a28543b28754fd804ba0616c21c.zip |
telnetd: if FEATURE_IPV6 is on, telnet will NOT work on IPv4
which is kind of stupid
-rw-r--r-- | networking/telnetd.c | 86 |
1 files changed, 65 insertions, 21 deletions
diff --git a/networking/telnetd.c b/networking/telnetd.c index 549488507..d524ac891 100644 --- a/networking/telnetd.c +++ b/networking/telnetd.c | |||
@@ -37,10 +37,8 @@ | |||
37 | #define BUFSIZE 4000 | 37 | #define BUFSIZE 4000 |
38 | 38 | ||
39 | #if ENABLE_FEATURE_IPV6 | 39 | #if ENABLE_FEATURE_IPV6 |
40 | #define SOCKET_TYPE AF_INET6 | ||
41 | typedef struct sockaddr_in6 sockaddr_type; | 40 | typedef struct sockaddr_in6 sockaddr_type; |
42 | #else | 41 | #else |
43 | #define SOCKET_TYPE AF_INET | ||
44 | typedef struct sockaddr_in sockaddr_type; | 42 | typedef struct sockaddr_in sockaddr_type; |
45 | #endif | 43 | #endif |
46 | 44 | ||
@@ -357,31 +355,77 @@ free_session(struct tsession *ts) | |||
357 | } | 355 | } |
358 | 356 | ||
359 | static int | 357 | static int |
360 | create_socket(int port, const char *opt_bindaddr) | 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) | ||
361 | { | 400 | { |
362 | static const int on = 1; | 401 | static const int on = 1; |
363 | int fd; | 402 | int fd; |
364 | sockaddr_type sa; | 403 | union { |
365 | #if !ENABLE_FEATURE_IPV6 | 404 | struct sockaddr sa; |
366 | struct in_addr bind_addr = { .s_addr = 0x0 }; | 405 | struct sockaddr_in sin; |
406 | #if ENABLE_FEATURE_IPV6 | ||
407 | struct sockaddr_in6 sin6; | ||
408 | #endif | ||
409 | } sa; | ||
367 | 410 | ||
368 | /* TODO: generic string -> sockaddr converter */ | 411 | memset(&sa, 0, sizeof(sa)); |
369 | if (opt_bindaddr && inet_aton(opt_bindaddr, &bind_addr) == 0) | 412 | if (hostaddr && dotted2sockaddr(hostaddr, &sa.sa, sizeof(sa))) |
370 | bb_show_usage(); | 413 | bb_show_usage(); |
371 | #endif | 414 | |
372 | fd = xsocket(SOCKET_TYPE, SOCK_STREAM, 0); | 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); | ||
373 | setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); | 419 | setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); |
374 | memset((void *)&sa, 0, sizeof(sa)); | 420 | |
375 | #if ENABLE_FEATURE_IPV6 | 421 | #if ENABLE_FEATURE_IPV6 |
376 | sa.sin6_family = AF_INET6; | 422 | if (sa.sa.sa_family == AF_INET6) |
377 | sa.sin6_port = htons(port); | 423 | sa.sin6.sin6_port = htons(port); |
378 | /* sa.sin6_addr = bind_addr6; */ | ||
379 | #else | ||
380 | sa.sin_family = AF_INET; | ||
381 | sa.sin_port = htons(port); | ||
382 | sa.sin_addr = bind_addr; | ||
383 | #endif | 424 | #endif |
384 | xbind(fd, (struct sockaddr *) &sa, sizeof(sa)); | 425 | if (sa.sa.sa_family == AF_INET) |
426 | sa.sin.sin_port = htons(port); | ||
427 | |||
428 | xbind(fd, &sa.sa, sizeof(sa)); | ||
385 | xlisten(fd, 1); | 429 | xlisten(fd, 1); |
386 | return fd; | 430 | return fd; |
387 | } | 431 | } |
@@ -390,7 +434,7 @@ create_socket(int port, const char *opt_bindaddr) | |||
390 | 434 | ||
391 | /* Never actually called */ | 435 | /* Never actually called */ |
392 | void free_session(struct tsession *ts); | 436 | void free_session(struct tsession *ts); |
393 | int create_socket(int port, const char *opt_bindaddr); | 437 | int create_socket(const char *hostaddr, int port); |
394 | 438 | ||
395 | #endif | 439 | #endif |
396 | 440 | ||
@@ -447,7 +491,7 @@ telnetd_main(int argc, char **argv) | |||
447 | if (IS_INETD) { | 491 | if (IS_INETD) { |
448 | sessions = make_new_session(0, 1); | 492 | sessions = make_new_session(0, 1); |
449 | } else { | 493 | } else { |
450 | master_fd = create_socket(portnbr, opt_bindaddr); | 494 | master_fd = create_socket(opt_bindaddr, portnbr); |
451 | if (!(opt & OPT_FOREGROUND)) | 495 | if (!(opt & OPT_FOREGROUND)) |
452 | xdaemon(0, 0); | 496 | xdaemon(0, 0); |
453 | } | 497 | } |