diff options
| author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2006-11-22 16:10:39 +0000 |
|---|---|---|
| committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2006-11-22 16:10:39 +0000 |
| commit | b8debef6acddb4a4f111b5a9afc9289aba1cd95b (patch) | |
| tree | 254a736d3e761bddc4ba4b00a8f6af1d430ad18f | |
| parent | 0673fdad46e62414befb318bec061952c33dfc3d (diff) | |
| download | busybox-w32-b8debef6acddb4a4f111b5a9afc9289aba1cd95b.tar.gz busybox-w32-b8debef6acddb4a4f111b5a9afc9289aba1cd95b.tar.bz2 busybox-w32-b8debef6acddb4a4f111b5a9afc9289aba1cd95b.zip | |
telnetd: move generic stuff into libbb. It will make it easy
to make other server applets IPv6-aware too.
git-svn-id: svn://busybox.net/trunk/busybox@16624 69ca8d6d-28ef-0310-b511-8ec308f3f277
| -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 | } |
