diff options
| author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-01-11 16:50:23 +0000 |
|---|---|---|
| committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-01-11 16:50:23 +0000 |
| commit | 2aef1bcb59b97f647bf63b5025c069200f42ec97 (patch) | |
| tree | 369636a4a765a571e1c6a6ecf2a52ca0131cc90e | |
| parent | a4c67f25b5e304a1b0666bdf1ae3d4c96cecc1e7 (diff) | |
| download | busybox-w32-2aef1bcb59b97f647bf63b5025c069200f42ec97.tar.gz busybox-w32-2aef1bcb59b97f647bf63b5025c069200f42ec97.tar.bz2 busybox-w32-2aef1bcb59b97f647bf63b5025c069200f42ec97.zip | |
ipv6-ization efforts continue. Few bugs are found,
unknown number likely introduced...
git-svn-id: svn://busybox.net/trunk/busybox@17250 69ca8d6d-28ef-0310-b511-8ec308f3f277
| -rw-r--r-- | include/libbb.h | 31 | ||||
| -rw-r--r-- | libbb/xconnect.c | 60 | ||||
| -rw-r--r-- | networking/ftpgetput.c | 19 | ||||
| -rw-r--r-- | networking/tftp.c | 251 | ||||
| -rw-r--r-- | util-linux/rdate.c | 30 |
5 files changed, 191 insertions, 200 deletions
diff --git a/include/libbb.h b/include/libbb.h index 62d5fcee4..c4d187e00 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
| @@ -293,19 +293,10 @@ extern void xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen); | |||
| 293 | extern int xconnect_tcp_v4(struct sockaddr_in *s_addr); | 293 | extern int xconnect_tcp_v4(struct sockaddr_in *s_addr); |
| 294 | extern struct hostent *xgethostbyname(const char *name); | 294 | extern struct hostent *xgethostbyname(const char *name); |
| 295 | extern struct hostent *xgethostbyname2(const char *name, int af); | 295 | extern struct hostent *xgethostbyname2(const char *name, int af); |
| 296 | |||
| 297 | extern int setsockopt_reuseaddr(int fd); | 296 | extern int setsockopt_reuseaddr(int fd); |
| 298 | extern int setsockopt_broadcast(int fd); | 297 | extern int setsockopt_broadcast(int fd); |
| 299 | /* Create server TCP socket bound to bindaddr:port. bindaddr can be NULL, | 298 | |
| 300 | * numeric IP ("N.N.N.N") or numeric IPv6 address, | 299 | /* "new" (ipv4+ipv6) API */ |
| 301 | * and can have ":PORT" suffix (for IPv6 use "[X:X:...:X]:PORT"). | ||
| 302 | * If there is no suffix, port argument is used */ | ||
| 303 | extern int create_and_bind_stream_or_die(const char *bindaddr, int port); | ||
| 304 | /* Create client TCP socket connected to peer:port. Peer cannot be NULL. | ||
| 305 | * Peer can be numeric IP ("N.N.N.N"), numeric IPv6 address or hostname, | ||
| 306 | * and can have ":PORT" suffix (for IPv6 use "[X:X:...:X]:PORT"). | ||
| 307 | * If there is no suffix, port argument is used */ | ||
| 308 | extern int create_and_connect_stream_or_die(const char *peer, int port); | ||
| 309 | typedef struct len_and_sockaddr { | 300 | typedef struct len_and_sockaddr { |
| 310 | int len; | 301 | int len; |
| 311 | union { | 302 | union { |
| @@ -316,11 +307,29 @@ typedef struct len_and_sockaddr { | |||
| 316 | #endif | 307 | #endif |
| 317 | }; | 308 | }; |
| 318 | } len_and_sockaddr; | 309 | } len_and_sockaddr; |
| 310 | /* Create server TCP socket bound to bindaddr:port. bindaddr can be NULL, | ||
| 311 | * numeric IP ("N.N.N.N") or numeric IPv6 address, | ||
| 312 | * and can have ":PORT" suffix (for IPv6 use "[X:X:...:X]:PORT"). | ||
| 313 | * If there is no suffix, port argument is used */ | ||
| 314 | extern int create_and_bind_stream_or_die(const char *bindaddr, int port); | ||
| 315 | /* Create client TCP socket connected to peer:port. Peer cannot be NULL. | ||
| 316 | * Peer can be numeric IP ("N.N.N.N"), numeric IPv6 address or hostname, | ||
| 317 | * and can have ":PORT" suffix (for IPv6 use "[X:X:...:X]:PORT"). | ||
| 318 | * If there is no suffix, port argument is used */ | ||
| 319 | extern int create_and_connect_stream_or_die(const char *peer, int port); | ||
| 320 | /* Connect to peer identified by lsa */ | ||
| 321 | extern int xconnect_stream(const len_and_sockaddr *lsa); | ||
| 319 | /* Return malloc'ed len_and_sockaddr with socket address of host:port | 322 | /* Return malloc'ed len_and_sockaddr with socket address of host:port |
| 320 | * Currently will return IPv4 or IPv6 sockaddrs only | 323 | * Currently will return IPv4 or IPv6 sockaddrs only |
| 321 | * (depending on host), but in theory nothing prevents e.g. | 324 | * (depending on host), but in theory nothing prevents e.g. |
| 322 | * UNIX socket address being returned, IPX sockaddr etc... */ | 325 | * UNIX socket address being returned, IPX sockaddr etc... */ |
| 323 | extern len_and_sockaddr* host2sockaddr(const char *host, int port); | 326 | extern len_and_sockaddr* host2sockaddr(const char *host, int port); |
| 327 | /* assign sin[6]_port member if the socket is of corresponding type, | ||
| 328 | * otherwise noop. Useful for ftp. | ||
| 329 | * NB: does NOT do htons() internally, just direct assignment. */ | ||
| 330 | extern void set_port(len_and_sockaddr *lsa, unsigned port); | ||
| 331 | char* xmalloc_sockaddr2host(const struct sockaddr *sa, socklen_t salen); | ||
| 332 | char* xmalloc_sockaddr2dotted(const struct sockaddr *sa, socklen_t salen); | ||
| 324 | 333 | ||
| 325 | 334 | ||
| 326 | extern char *xstrdup(const char *s); | 335 | extern char *xstrdup(const char *s); |
diff --git a/libbb/xconnect.c b/libbb/xconnect.c index 6e85322cf..a5b16d982 100644 --- a/libbb/xconnect.c +++ b/libbb/xconnect.c | |||
| @@ -83,8 +83,20 @@ int xconnect_tcp_v4(struct sockaddr_in *s_addr) | |||
| 83 | /* "New" networking API */ | 83 | /* "New" networking API */ |
| 84 | 84 | ||
| 85 | 85 | ||
| 86 | //extern int xsocket_stream_ip4or6(sa_family_t *fp); | 86 | void set_port(len_and_sockaddr *lsa, unsigned port) |
| 87 | //extern len_and_sockaddr* dotted2sockaddr(const char *dotted, int def_port); | 87 | { |
| 88 | #if ENABLE_FEATURE_IPV6 | ||
| 89 | if (lsa->sa.sa_family == AF_INET6) { | ||
| 90 | lsa->sin6.sin6_port = port; | ||
| 91 | return; | ||
| 92 | } | ||
| 93 | #endif | ||
| 94 | if (lsa->sa.sa_family == AF_INET) { | ||
| 95 | lsa->sin.sin_port = port; | ||
| 96 | return; | ||
| 97 | } | ||
| 98 | /* What? UNIX socket? IPX?? :) */ | ||
| 99 | } | ||
| 88 | 100 | ||
| 89 | /* peer: "1.2.3.4[:port]", "www.google.com[:port]" | 101 | /* peer: "1.2.3.4[:port]", "www.google.com[:port]" |
| 90 | * port: if neither of above specifies port # | 102 | * port: if neither of above specifies port # |
| @@ -96,7 +108,6 @@ static len_and_sockaddr* str2sockaddr(const char *host, int port, int ai_flags) | |||
| 96 | struct addrinfo *result = NULL; | 108 | struct addrinfo *result = NULL; |
| 97 | const char *org_host = host; /* only for error msg */ | 109 | const char *org_host = host; /* only for error msg */ |
| 98 | const char *cp; | 110 | const char *cp; |
| 99 | char service[sizeof(int)*3 + 1]; | ||
| 100 | struct addrinfo hint; | 111 | struct addrinfo hint; |
| 101 | 112 | ||
| 102 | /* Ugly parsing of host:addr */ | 113 | /* Ugly parsing of host:addr */ |
| @@ -119,9 +130,7 @@ static len_and_sockaddr* str2sockaddr(const char *host, int port, int ai_flags) | |||
| 119 | if (ENABLE_FEATURE_IPV6 && *cp != ':') | 130 | if (ENABLE_FEATURE_IPV6 && *cp != ':') |
| 120 | cp++; /* skip ']' */ | 131 | cp++; /* skip ']' */ |
| 121 | cp++; /* skip ':' */ | 132 | cp++; /* skip ':' */ |
| 122 | } else { | 133 | port = xatou16(cp); |
| 123 | utoa_to_buf(port, service, sizeof(service)); | ||
| 124 | cp = service; | ||
| 125 | } | 134 | } |
| 126 | 135 | ||
| 127 | memset(&hint, 0 , sizeof(hint)); | 136 | memset(&hint, 0 , sizeof(hint)); |
| @@ -132,13 +141,14 @@ static len_and_sockaddr* str2sockaddr(const char *host, int port, int ai_flags) | |||
| 132 | /* Needed. Or else we will get each address thrice (or more) | 141 | /* Needed. Or else we will get each address thrice (or more) |
| 133 | * for each possible socket type (tcp,udp,raw...): */ | 142 | * for each possible socket type (tcp,udp,raw...): */ |
| 134 | hint.ai_socktype = SOCK_STREAM; | 143 | hint.ai_socktype = SOCK_STREAM; |
| 135 | hint.ai_flags = ai_flags | AI_NUMERICSERV; | 144 | hint.ai_flags = ai_flags; |
| 136 | rc = getaddrinfo(host, cp, &hint, &result); | 145 | rc = getaddrinfo(host, NULL, &hint, &result); |
| 137 | if (rc || !result) | 146 | if (rc || !result) |
| 138 | bb_error_msg_and_die("bad address '%s'", org_host); | 147 | bb_error_msg_and_die("bad address '%s'", org_host); |
| 139 | r = xmalloc(offsetof(len_and_sockaddr, sa) + result->ai_addrlen); | 148 | r = xmalloc(offsetof(len_and_sockaddr, sa) + result->ai_addrlen); |
| 140 | r->len = result->ai_addrlen; | 149 | r->len = result->ai_addrlen; |
| 141 | memcpy(&r->sa, result->ai_addr, result->ai_addrlen); | 150 | memcpy(&r->sa, result->ai_addr, result->ai_addrlen); |
| 151 | set_port(r, port); | ||
| 142 | freeaddrinfo(result); | 152 | freeaddrinfo(result); |
| 143 | return r; | 153 | return r; |
| 144 | } | 154 | } |
| @@ -153,7 +163,7 @@ static len_and_sockaddr* dotted2sockaddr(const char *host, int port) | |||
| 153 | return str2sockaddr(host, port, NI_NUMERICHOST); | 163 | return str2sockaddr(host, port, NI_NUMERICHOST); |
| 154 | } | 164 | } |
| 155 | 165 | ||
| 156 | static int xsocket_stream_ip4or6(len_and_sockaddr *lsa) | 166 | static int xsocket_stream(len_and_sockaddr *lsa) |
| 157 | { | 167 | { |
| 158 | int fd; | 168 | int fd; |
| 159 | #if ENABLE_FEATURE_IPV6 | 169 | #if ENABLE_FEATURE_IPV6 |
| @@ -186,7 +196,7 @@ int create_and_bind_stream_or_die(const char *bindaddr, int port) | |||
| 186 | USE_FEATURE_IPV6(sizeof(struct sockaddr_in6)) | 196 | USE_FEATURE_IPV6(sizeof(struct sockaddr_in6)) |
| 187 | SKIP_FEATURE_IPV6(sizeof(struct sockaddr_in)) | 197 | SKIP_FEATURE_IPV6(sizeof(struct sockaddr_in)) |
| 188 | ); | 198 | ); |
| 189 | fd = xsocket_stream_ip4or6(lsa); | 199 | fd = xsocket_stream(lsa); |
| 190 | } | 200 | } |
| 191 | setsockopt_reuseaddr(fd); | 201 | setsockopt_reuseaddr(fd); |
| 192 | xbind(fd, &lsa->sa, lsa->len); | 202 | xbind(fd, &lsa->sa, lsa->len); |
| @@ -209,3 +219,33 @@ int create_and_connect_stream_or_die(const char *peer, int port) | |||
| 209 | free(lsa); | 219 | free(lsa); |
| 210 | return fd; | 220 | return fd; |
| 211 | } | 221 | } |
| 222 | |||
| 223 | int xconnect_stream(const len_and_sockaddr *lsa) | ||
| 224 | { | ||
| 225 | int fd = xsocket(lsa->sa.sa_family, SOCK_STREAM, 0); | ||
| 226 | xconnect(fd, &lsa->sa, lsa->len); | ||
| 227 | return fd; | ||
| 228 | } | ||
| 229 | |||
| 230 | static char* sockaddr2str(const struct sockaddr *sa, socklen_t salen, int flags) | ||
| 231 | { | ||
| 232 | char host[128]; | ||
| 233 | char serv[16]; | ||
| 234 | int rc = getnameinfo(sa, salen, | ||
| 235 | host, sizeof(host), | ||
| 236 | serv, sizeof(serv), | ||
| 237 | flags | NI_NUMERICSERV /* do not resolve port# */ | ||
| 238 | ); | ||
| 239 | if (rc) return NULL; | ||
| 240 | return xasprintf("%s:%s", host, serv); | ||
| 241 | } | ||
| 242 | |||
| 243 | char* xmalloc_sockaddr2host(const struct sockaddr *sa, socklen_t salen) | ||
| 244 | { | ||
| 245 | return sockaddr2str(sa, salen, 0); | ||
| 246 | } | ||
| 247 | |||
| 248 | char* xmalloc_sockaddr2dotted(const struct sockaddr *sa, socklen_t salen) | ||
| 249 | { | ||
| 250 | return sockaddr2str(sa, salen, NI_NUMERICHOST); | ||
| 251 | } | ||
diff --git a/networking/ftpgetput.c b/networking/ftpgetput.c index 9e64ff98a..9086cb126 100644 --- a/networking/ftpgetput.c +++ b/networking/ftpgetput.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | typedef struct ftp_host_info_s { | 19 | typedef struct ftp_host_info_s { |
| 20 | char *user; | 20 | char *user; |
| 21 | char *password; | 21 | char *password; |
| 22 | struct sockaddr_in *s_in; | 22 | struct len_and_sockaddr *lsa; |
| 23 | } ftp_host_info_t; | 23 | } ftp_host_info_t; |
| 24 | 24 | ||
| 25 | static char verbose_flag; | 25 | static char verbose_flag; |
| @@ -88,8 +88,8 @@ static int xconnect_ftpdata(ftp_host_info_t *server, char *buf) | |||
| 88 | *buf_ptr = '\0'; | 88 | *buf_ptr = '\0'; |
| 89 | port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256; | 89 | port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256; |
| 90 | 90 | ||
| 91 | server->s_in->sin_port = htons(port_num); | 91 | set_port(server->lsa, htons(port_num)); |
| 92 | return xconnect_tcp_v4(server->s_in); | 92 | return xconnect_stream(server->lsa); |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | static FILE *ftp_login(ftp_host_info_t *server) | 95 | static FILE *ftp_login(ftp_host_info_t *server) |
| @@ -98,9 +98,9 @@ static FILE *ftp_login(ftp_host_info_t *server) | |||
| 98 | char buf[512]; | 98 | char buf[512]; |
| 99 | 99 | ||
| 100 | /* Connect to the command socket */ | 100 | /* Connect to the command socket */ |
| 101 | control_stream = fdopen(xconnect_tcp_v4(server->s_in), "r+"); | 101 | control_stream = fdopen(xconnect_stream(server->lsa), "r+"); |
| 102 | if (control_stream == NULL) { | 102 | if (control_stream == NULL) { |
| 103 | /* Extremely unlikely */ | 103 | /* fdopen failed - extremely unlikely */ |
| 104 | bb_perror_nomsg_and_die(); | 104 | bb_perror_nomsg_and_die(); |
| 105 | } | 105 | } |
| 106 | 106 | ||
| @@ -304,7 +304,6 @@ int ftpgetput_main(int argc, char **argv) | |||
| 304 | const char *port = "ftp"; | 304 | const char *port = "ftp"; |
| 305 | /* socket to ftp server */ | 305 | /* socket to ftp server */ |
| 306 | FILE *control_stream; | 306 | FILE *control_stream; |
| 307 | struct sockaddr_in s_in; | ||
| 308 | /* continue previous transfer (-c) */ | 307 | /* continue previous transfer (-c) */ |
| 309 | ftp_host_info_t *server; | 308 | ftp_host_info_t *server; |
| 310 | 309 | ||
| @@ -347,12 +346,10 @@ int ftpgetput_main(int argc, char **argv) | |||
| 347 | /* We want to do exactly _one_ DNS lookup, since some | 346 | /* We want to do exactly _one_ DNS lookup, since some |
| 348 | * sites (i.e. ftp.us.debian.org) use round-robin DNS | 347 | * sites (i.e. ftp.us.debian.org) use round-robin DNS |
| 349 | * and we want to connect to only one IP... */ | 348 | * and we want to connect to only one IP... */ |
| 350 | server->s_in = &s_in; | 349 | server->lsa = host2sockaddr(argv[0], bb_lookup_port(port, "tcp", 21)); |
| 351 | bb_lookup_host(&s_in, argv[0]); | ||
| 352 | s_in.sin_port = bb_lookup_port(port, "tcp", 21); | ||
| 353 | if (verbose_flag) { | 350 | if (verbose_flag) { |
| 354 | printf("Connecting to %s[%s]:%d\n", | 351 | printf("Connecting to %s [%s]\n", argv[0], |
| 355 | argv[0], inet_ntoa(s_in.sin_addr), ntohs(s_in.sin_port)); | 352 | xmalloc_sockaddr2dotted(&server->lsa->sa, server->lsa->len)); |
| 356 | } | 353 | } |
| 357 | 354 | ||
| 358 | /* Connect/Setup/Configure the FTP session */ | 355 | /* Connect/Setup/Configure the FTP session */ |
diff --git a/networking/tftp.c b/networking/tftp.c index 2d28973dc..eaeb80857 100644 --- a/networking/tftp.c +++ b/networking/tftp.c | |||
| @@ -26,12 +26,6 @@ | |||
| 26 | #define TFTP_TIMEOUT 5 /* seconds */ | 26 | #define TFTP_TIMEOUT 5 /* seconds */ |
| 27 | #define TFTP_NUM_RETRIES 5 /* number of retries */ | 27 | #define TFTP_NUM_RETRIES 5 /* number of retries */ |
| 28 | 28 | ||
| 29 | static const char * const MODE_OCTET = "octet"; | ||
| 30 | #define MODE_OCTET_LEN 6 /* sizeof(MODE_OCTET)*/ | ||
| 31 | |||
| 32 | static const char * const OPTION_BLOCKSIZE = "blksize"; | ||
| 33 | #define OPTION_BLOCKSIZE_LEN 8 /* sizeof(OPTION_BLOCKSIZE) */ | ||
| 34 | |||
| 35 | /* opcodes we support */ | 29 | /* opcodes we support */ |
| 36 | #define TFTP_RRQ 1 | 30 | #define TFTP_RRQ 1 |
| 37 | #define TFTP_WRQ 2 | 31 | #define TFTP_WRQ 2 |
| @@ -51,13 +45,23 @@ static const char *const tftp_bb_error_msg[] = { | |||
| 51 | "No such user" | 45 | "No such user" |
| 52 | }; | 46 | }; |
| 53 | 47 | ||
| 54 | #define tftp_cmd_get ENABLE_FEATURE_TFTP_GET | 48 | #if ENABLE_FEATURE_TFTP_GET && !ENABLE_FEATURE_TFTP_PUT |
| 55 | 49 | #define USE_GETPUT(a) | |
| 56 | #if ENABLE_FEATURE_TFTP_PUT | 50 | #define CMD_GET(cmd) 1 |
| 57 | # define tftp_cmd_put (tftp_cmd_get+ENABLE_FEATURE_TFTP_PUT) | 51 | #define CMD_PUT(cmd) 0 |
| 52 | #elif !ENABLE_FEATURE_TFTP_GET && ENABLE_FEATURE_TFTP_PUT | ||
| 53 | #define USE_GETPUT(a) | ||
| 54 | #define CMD_GET(cmd) 0 | ||
| 55 | #define CMD_PUT(cmd) 1 | ||
| 58 | #else | 56 | #else |
| 59 | # define tftp_cmd_put 0 | 57 | #define USE_GETPUT(a) a |
| 58 | /* masks coming from getpot32 */ | ||
| 59 | #define CMD_GET(cmd) (cmd & 1) | ||
| 60 | #define CMD_PUT(cmd) (cmd & 2) | ||
| 60 | #endif | 61 | #endif |
| 62 | /* NB: in the code below | ||
| 63 | * CMD_GET(cmd) and CMD_GET(cmd) are mutually exclusive | ||
| 64 | */ | ||
| 61 | 65 | ||
| 62 | 66 | ||
| 63 | #if ENABLE_FEATURE_TFTP_BLOCKSIZE | 67 | #if ENABLE_FEATURE_TFTP_BLOCKSIZE |
| @@ -70,8 +74,9 @@ static int tftp_blocksize_check(int blocksize, int bufsize) | |||
| 70 | * to use blocksizes smaller than 22 octets. | 74 | * to use blocksizes smaller than 22 octets. |
| 71 | */ | 75 | */ |
| 72 | 76 | ||
| 73 | if ((bufsize && (blocksize > bufsize)) || | 77 | if ((bufsize && (blocksize > bufsize)) |
| 74 | (blocksize < 8) || (blocksize > 65564)) { | 78 | || (blocksize < 8) || (blocksize > 65564) |
| 79 | ) { | ||
| 75 | bb_error_msg("bad blocksize"); | 80 | bb_error_msg("bad blocksize"); |
| 76 | return 0; | 81 | return 0; |
| 77 | } | 82 | } |
| @@ -86,7 +91,6 @@ static char *tftp_option_get(char *buf, int len, const char * const option) | |||
| 86 | int k; | 91 | int k; |
| 87 | 92 | ||
| 88 | while (len > 0) { | 93 | while (len > 0) { |
| 89 | |||
| 90 | /* Make sure the options are terminated correctly */ | 94 | /* Make sure the options are terminated correctly */ |
| 91 | 95 | ||
| 92 | for (k = 0; k < len; k++) { | 96 | for (k = 0; k < len; k++) { |
| @@ -122,22 +126,23 @@ static char *tftp_option_get(char *buf, int len, const char * const option) | |||
| 122 | 126 | ||
| 123 | #endif | 127 | #endif |
| 124 | 128 | ||
| 125 | static int tftp(const int cmd, const struct hostent *host, | 129 | static int tftp( |
| 126 | const char *remotefile, const int localfd, | 130 | #if ENABLE_FEATURE_TFTP_GET && ENABLE_FEATURE_TFTP_PUT |
| 127 | const unsigned short port, int tftp_bufsize) | 131 | const int cmd, |
| 132 | #endif | ||
| 133 | const len_and_sockaddr *peer_lsa, | ||
| 134 | const char *remotefile, const int localfd, | ||
| 135 | const unsigned port, int tftp_bufsize) | ||
| 128 | { | 136 | { |
| 129 | struct sockaddr_in sa; | ||
| 130 | struct sockaddr_in from; | ||
| 131 | struct timeval tv; | 137 | struct timeval tv; |
| 132 | socklen_t fromlen; | ||
| 133 | fd_set rfds; | 138 | fd_set rfds; |
| 134 | int socketfd; | 139 | int socketfd; |
| 135 | int len; | 140 | int len; |
| 136 | int opcode = 0; | 141 | int opcode = 0; |
| 137 | int finished = 0; | 142 | int finished = 0; |
| 138 | int timeout = TFTP_NUM_RETRIES; | 143 | int timeout = TFTP_NUM_RETRIES; |
| 139 | unsigned short block_nr = 1; | 144 | uint16_t block_nr = 1; |
| 140 | unsigned short tmp; | 145 | uint16_t tmp; |
| 141 | char *cp; | 146 | char *cp; |
| 142 | 147 | ||
| 143 | USE_FEATURE_TFTP_BLOCKSIZE(int want_option_ack = 0;) | 148 | USE_FEATURE_TFTP_BLOCKSIZE(int want_option_ack = 0;) |
| @@ -149,42 +154,24 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 149 | char *xbuf = xmalloc(tftp_bufsize += 4); | 154 | char *xbuf = xmalloc(tftp_bufsize += 4); |
| 150 | char *rbuf = xmalloc(tftp_bufsize); | 155 | char *rbuf = xmalloc(tftp_bufsize); |
| 151 | 156 | ||
| 152 | if ((socketfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { | 157 | socketfd = xsocket(peer_lsa->sa.sa_family, SOCK_DGRAM, 0); |
| 153 | /* need to unlink the localfile, so don't use xsocket here. */ | ||
| 154 | bb_perror_msg("socket"); | ||
| 155 | return EXIT_FAILURE; | ||
| 156 | } | ||
| 157 | |||
| 158 | len = sizeof(sa); | ||
| 159 | |||
| 160 | memset(&sa, 0, len); | ||
| 161 | xbind(socketfd, (struct sockaddr *)&sa, len); | ||
| 162 | |||
| 163 | sa.sin_family = host->h_addrtype; | ||
| 164 | sa.sin_port = port; | ||
| 165 | memcpy(&sa.sin_addr, (struct in_addr *) host->h_addr, | ||
| 166 | sizeof(sa.sin_addr)); | ||
| 167 | 158 | ||
| 168 | /* build opcode */ | 159 | /* build opcode */ |
| 169 | if (cmd & tftp_cmd_get) { | 160 | opcode = TFTP_WRQ; |
| 161 | if (CMD_GET(cmd)) { | ||
| 170 | opcode = TFTP_RRQ; | 162 | opcode = TFTP_RRQ; |
| 171 | } | 163 | } |
| 172 | if (cmd & tftp_cmd_put) { | ||
| 173 | opcode = TFTP_WRQ; | ||
| 174 | } | ||
| 175 | 164 | ||
| 176 | while (1) { | 165 | while (1) { |
| 177 | 166 | ||
| 178 | cp = xbuf; | 167 | cp = xbuf; |
| 179 | 168 | ||
| 180 | /* first create the opcode part */ | 169 | /* first create the opcode part */ |
| 181 | *((unsigned short *) cp) = htons(opcode); | 170 | *((uint16_t*)cp) = htons(opcode); |
| 182 | cp += 2; | 171 | cp += 2; |
| 183 | 172 | ||
| 184 | /* add filename and mode */ | 173 | /* add filename and mode */ |
| 185 | if (((cmd & tftp_cmd_get) && (opcode == TFTP_RRQ)) || | 174 | if (CMD_GET(cmd) ? (opcode == TFTP_RRQ) : (opcode == TFTP_WRQ)) { |
| 186 | ((cmd & tftp_cmd_put) && (opcode == TFTP_WRQ))) | ||
| 187 | { | ||
| 188 | int too_long = 0; | 175 | int too_long = 0; |
| 189 | 176 | ||
| 190 | /* see if the filename fits into xbuf | 177 | /* see if the filename fits into xbuf |
| @@ -198,14 +185,14 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 198 | cp += len; | 185 | cp += len; |
| 199 | } | 186 | } |
| 200 | 187 | ||
| 201 | if (too_long || ((&xbuf[tftp_bufsize - 1] - cp) < MODE_OCTET_LEN)) { | 188 | if (too_long || (&xbuf[tftp_bufsize - 1] - cp) < sizeof("octet")) { |
| 202 | bb_error_msg("remote filename too long"); | 189 | bb_error_msg("remote filename too long"); |
| 203 | break; | 190 | break; |
| 204 | } | 191 | } |
| 205 | 192 | ||
| 206 | /* add "mode" part of the package */ | 193 | /* add "mode" part of the package */ |
| 207 | memcpy(cp, MODE_OCTET, MODE_OCTET_LEN); | 194 | memcpy(cp, "octet", sizeof("octet")); |
| 208 | cp += MODE_OCTET_LEN; | 195 | cp += sizeof("octet"); |
| 209 | 196 | ||
| 210 | #if ENABLE_FEATURE_TFTP_BLOCKSIZE | 197 | #if ENABLE_FEATURE_TFTP_BLOCKSIZE |
| 211 | 198 | ||
| @@ -219,8 +206,8 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 219 | } | 206 | } |
| 220 | 207 | ||
| 221 | /* add "blksize" + number of blocks */ | 208 | /* add "blksize" + number of blocks */ |
| 222 | memcpy(cp, OPTION_BLOCKSIZE, OPTION_BLOCKSIZE_LEN); | 209 | memcpy(cp, "blksize", sizeof("blksize")); |
| 223 | cp += OPTION_BLOCKSIZE_LEN; | 210 | cp += sizeof("blksize"); |
| 224 | cp += snprintf(cp, 6, "%d", len) + 1; | 211 | cp += snprintf(cp, 6, "%d", len) + 1; |
| 225 | 212 | ||
| 226 | want_option_ack = 1; | 213 | want_option_ack = 1; |
| @@ -230,16 +217,12 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 230 | 217 | ||
| 231 | /* add ack and data */ | 218 | /* add ack and data */ |
| 232 | 219 | ||
| 233 | if (((cmd & tftp_cmd_get) && (opcode == TFTP_ACK)) || | 220 | if (CMD_GET(cmd) ? (opcode == TFTP_ACK) : (opcode == TFTP_DATA)) { |
| 234 | ((cmd & tftp_cmd_put) && (opcode == TFTP_DATA))) { | 221 | *((uint16_t*)cp) = htons(block_nr); |
| 235 | |||
| 236 | *((unsigned short *) cp) = htons(block_nr); | ||
| 237 | |||
| 238 | cp += 2; | 222 | cp += 2; |
| 239 | |||
| 240 | block_nr++; | 223 | block_nr++; |
| 241 | 224 | ||
| 242 | if ((cmd & tftp_cmd_put) && (opcode == TFTP_DATA)) { | 225 | if (CMD_PUT(cmd) && (opcode == TFTP_DATA)) { |
| 243 | len = full_read(localfd, cp, tftp_bufsize - 4); | 226 | len = full_read(localfd, cp, tftp_bufsize - 4); |
| 244 | 227 | ||
| 245 | if (len < 0) { | 228 | if (len < 0) { |
| @@ -261,9 +244,7 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 261 | 244 | ||
| 262 | timeout = TFTP_NUM_RETRIES; /* re-initialize */ | 245 | timeout = TFTP_NUM_RETRIES; /* re-initialize */ |
| 263 | do { | 246 | do { |
| 264 | |||
| 265 | len = cp - xbuf; | 247 | len = cp - xbuf; |
| 266 | |||
| 267 | #if ENABLE_DEBUG_TFTP | 248 | #if ENABLE_DEBUG_TFTP |
| 268 | fprintf(stderr, "sending %u bytes\n", len); | 249 | fprintf(stderr, "sending %u bytes\n", len); |
| 269 | for (cp = xbuf; cp < &xbuf[len]; cp++) | 250 | for (cp = xbuf; cp < &xbuf[len]; cp++) |
| @@ -271,7 +252,7 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 271 | fprintf(stderr, "\n"); | 252 | fprintf(stderr, "\n"); |
| 272 | #endif | 253 | #endif |
| 273 | if (sendto(socketfd, xbuf, len, 0, | 254 | if (sendto(socketfd, xbuf, len, 0, |
| 274 | (struct sockaddr *) &sa, sizeof(sa)) < 0) { | 255 | &peer_lsa->sa, peer_lsa->len) < 0) { |
| 275 | bb_perror_msg("send"); | 256 | bb_perror_msg("send"); |
| 276 | len = -1; | 257 | len = -1; |
| 277 | break; | 258 | break; |
| @@ -284,9 +265,6 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 284 | 265 | ||
| 285 | /* receive packet */ | 266 | /* receive packet */ |
| 286 | 267 | ||
| 287 | memset(&from, 0, sizeof(from)); | ||
| 288 | fromlen = sizeof(from); | ||
| 289 | |||
| 290 | tv.tv_sec = TFTP_TIMEOUT; | 268 | tv.tv_sec = TFTP_TIMEOUT; |
| 291 | tv.tv_usec = 0; | 269 | tv.tv_usec = 0; |
| 292 | 270 | ||
| @@ -294,30 +272,41 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 294 | FD_SET(socketfd, &rfds); | 272 | FD_SET(socketfd, &rfds); |
| 295 | 273 | ||
| 296 | switch (select(socketfd + 1, &rfds, NULL, NULL, &tv)) { | 274 | switch (select(socketfd + 1, &rfds, NULL, NULL, &tv)) { |
| 275 | struct sockaddr *from; | ||
| 276 | socklen_t fromlen; | ||
| 277 | |||
| 297 | case 1: | 278 | case 1: |
| 298 | len = recvfrom(socketfd, rbuf, tftp_bufsize, 0, | 279 | fromlen = peer_lsa->len; |
| 299 | (struct sockaddr *) &from, &fromlen); | 280 | from = alloca(fromlen); |
| 281 | memset(from, 0, fromlen); | ||
| 300 | 282 | ||
| 283 | len = recvfrom(socketfd, rbuf, tftp_bufsize, 0, | ||
| 284 | from, &fromlen); | ||
| 301 | if (len < 0) { | 285 | if (len < 0) { |
| 302 | bb_perror_msg("recvfrom"); | 286 | bb_perror_msg("recvfrom"); |
| 303 | break; | 287 | break; |
| 304 | } | 288 | } |
| 305 | |||
| 306 | timeout = 0; | 289 | timeout = 0; |
| 307 | 290 | if (from->sa_family == peer_lsa->sa.sa_family) { | |
| 308 | if (sa.sin_port == port) { | 291 | #if ENABLE_FEATURE_IPV6 |
| 309 | sa.sin_port = from.sin_port; | 292 | if (from->sa_family == AF_INET6 |
| 310 | } | 293 | && ((struct sockaddr_in6*)from)->sin6_port == port |
| 311 | if (sa.sin_port == from.sin_port) { | 294 | ) |
| 312 | break; | 295 | break; |
| 296 | #endif | ||
| 297 | /* Non-internet sockets are ok */ | ||
| 298 | if (from->sa_family != AF_INET) | ||
| 299 | break; | ||
| 300 | if (((struct sockaddr_in*)from)->sin_port == port) | ||
| 301 | break; | ||
| 313 | } | 302 | } |
| 314 | 303 | /* family doesn't match, or | |
| 315 | /* fall-through for bad packets! */ | 304 | * it is INET[v6] and port doesn't match - |
| 316 | /* discard the packet - treat as timeout */ | 305 | * fall-through for bad packets! |
| 306 | * (discard the packet - treat as timeout) */ | ||
| 317 | timeout = TFTP_NUM_RETRIES; | 307 | timeout = TFTP_NUM_RETRIES; |
| 318 | case 0: | 308 | case 0: |
| 319 | bb_error_msg("timeout"); | 309 | bb_error_msg("timeout"); |
| 320 | |||
| 321 | timeout--; | 310 | timeout--; |
| 322 | if (timeout == 0) { | 311 | if (timeout == 0) { |
| 323 | len = -1; | 312 | len = -1; |
| @@ -331,14 +320,14 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 331 | 320 | ||
| 332 | } while (timeout && (len >= 0)); | 321 | } while (timeout && (len >= 0)); |
| 333 | 322 | ||
| 334 | if ((finished) || (len < 0)) { | 323 | if (finished || (len < 0)) { |
| 335 | break; | 324 | break; |
| 336 | } | 325 | } |
| 337 | 326 | ||
| 338 | /* process received packet */ | 327 | /* process received packet */ |
| 339 | 328 | ||
| 340 | opcode = ntohs(*((unsigned short *) rbuf)); | 329 | opcode = ntohs( ((uint16_t*)rbuf)[0] ); |
| 341 | tmp = ntohs(*((unsigned short *) &rbuf[2])); | 330 | tmp = ntohs( ((uint16_t*)rbuf)[1] ); |
| 342 | 331 | ||
| 343 | #if ENABLE_DEBUG_TFTP | 332 | #if ENABLE_DEBUG_TFTP |
| 344 | fprintf(stderr, "received %d bytes: %04x %04x\n", len, opcode, tmp); | 333 | fprintf(stderr, "received %d bytes: %04x %04x\n", len, opcode, tmp); |
| @@ -352,7 +341,6 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 352 | rbuf[tftp_bufsize - 1] = '\0'; | 341 | rbuf[tftp_bufsize - 1] = '\0'; |
| 353 | } else if (tmp < (sizeof(tftp_bb_error_msg) | 342 | } else if (tmp < (sizeof(tftp_bb_error_msg) |
| 354 | / sizeof(char *))) { | 343 | / sizeof(char *))) { |
| 355 | |||
| 356 | msg = tftp_bb_error_msg[tmp]; | 344 | msg = tftp_bb_error_msg[tmp]; |
| 357 | } | 345 | } |
| 358 | 346 | ||
| @@ -368,25 +356,22 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 368 | want_option_ack = 0; | 356 | want_option_ack = 0; |
| 369 | 357 | ||
| 370 | if (opcode == TFTP_OACK) { | 358 | if (opcode == TFTP_OACK) { |
| 371 | |||
| 372 | /* server seems to support options */ | 359 | /* server seems to support options */ |
| 373 | |||
| 374 | char *res; | 360 | char *res; |
| 375 | 361 | ||
| 376 | res = tftp_option_get(&rbuf[2], len - 2, OPTION_BLOCKSIZE); | 362 | res = tftp_option_get(&rbuf[2], len - 2, "blksize"); |
| 377 | 363 | ||
| 378 | if (res) { | 364 | if (res) { |
| 379 | int blksize = xatoi_u(res); | 365 | int blksize = xatoi_u(res); |
| 380 | 366 | ||
| 381 | if (tftp_blocksize_check(blksize, tftp_bufsize - 4)) { | 367 | if (tftp_blocksize_check(blksize, tftp_bufsize - 4)) { |
| 382 | 368 | if (CMD_PUT(cmd)) { | |
| 383 | if (cmd & tftp_cmd_put) { | ||
| 384 | opcode = TFTP_DATA; | 369 | opcode = TFTP_DATA; |
| 385 | } else { | 370 | } else { |
| 386 | opcode = TFTP_ACK; | 371 | opcode = TFTP_ACK; |
| 387 | } | 372 | } |
| 388 | #if ENABLE_DEBUG_TFTP | 373 | #if ENABLE_DEBUG_TFTP |
| 389 | fprintf(stderr, "using %s %u\n", OPTION_BLOCKSIZE, | 374 | fprintf(stderr, "using blksize %u\n", |
| 390 | blksize); | 375 | blksize); |
| 391 | #endif | 376 | #endif |
| 392 | tftp_bufsize = blksize + 4; | 377 | tftp_bufsize = blksize + 4; |
| @@ -407,10 +392,8 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 407 | } | 392 | } |
| 408 | #endif | 393 | #endif |
| 409 | 394 | ||
| 410 | if ((cmd & tftp_cmd_get) && (opcode == TFTP_DATA)) { | 395 | if (CMD_GET(cmd) && (opcode == TFTP_DATA)) { |
| 411 | |||
| 412 | if (tmp == block_nr) { | 396 | if (tmp == block_nr) { |
| 413 | |||
| 414 | len = full_write(localfd, &rbuf[4], len - 4); | 397 | len = full_write(localfd, &rbuf[4], len - 4); |
| 415 | 398 | ||
| 416 | if (len < 0) { | 399 | if (len < 0) { |
| @@ -430,6 +413,7 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 430 | --block_nr; | 413 | --block_nr; |
| 431 | opcode = TFTP_ACK; | 414 | opcode = TFTP_ACK; |
| 432 | continue; | 415 | continue; |
| 416 | // tmp==(block_nr-1) and (tmp+1)==block_nr is always same, I think. wtf? | ||
| 433 | } else if (tmp + 1 == block_nr) { | 417 | } else if (tmp + 1 == block_nr) { |
| 434 | /* Server lost our TFTP_ACK. Resend it */ | 418 | /* Server lost our TFTP_ACK. Resend it */ |
| 435 | block_nr = tmp; | 419 | block_nr = tmp; |
| @@ -438,9 +422,8 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 438 | } | 422 | } |
| 439 | } | 423 | } |
| 440 | 424 | ||
| 441 | if ((cmd & tftp_cmd_put) && (opcode == TFTP_ACK)) { | 425 | if (CMD_PUT(cmd) && (opcode == TFTP_ACK)) { |
| 442 | 426 | if (tmp == (uint16_t) (block_nr - 1)) { | |
| 443 | if (tmp == (unsigned short) (block_nr - 1)) { | ||
| 444 | if (finished) { | 427 | if (finished) { |
| 445 | break; | 428 | break; |
| 446 | } | 429 | } |
| @@ -462,61 +445,32 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 462 | 445 | ||
| 463 | int tftp_main(int argc, char **argv) | 446 | int tftp_main(int argc, char **argv) |
| 464 | { | 447 | { |
| 465 | struct hostent *host = NULL; | 448 | len_and_sockaddr *peer_lsa; |
| 466 | const char *localfile = NULL; | 449 | const char *localfile = NULL; |
| 467 | const char *remotefile = NULL; | 450 | const char *remotefile = NULL; |
| 451 | #if ENABLE_FEATURE_TFTP_BLOCKSIZE | ||
| 452 | const char *sblocksize = NULL; | ||
| 453 | #endif | ||
| 468 | int port; | 454 | int port; |
| 469 | int cmd = 0; | 455 | USE_GETPUT(int cmd;) |
| 470 | int fd = -1; | 456 | int fd = -1; |
| 471 | int flags = 0; | 457 | int flags = 0; |
| 472 | int result; | 458 | int result; |
| 473 | int blocksize = TFTP_BLOCKSIZE_DEFAULT; | 459 | int blocksize = TFTP_BLOCKSIZE_DEFAULT; |
| 474 | 460 | ||
| 475 | /* figure out what to pass to getopt */ | 461 | /* -p or -g is mandatory, and they are mutually exclusive */ |
| 476 | 462 | opt_complementary = "" USE_FEATURE_TFTP_GET("g:") USE_FEATURE_TFTP_PUT("p:") | |
| 477 | #if ENABLE_FEATURE_TFTP_BLOCKSIZE | 463 | USE_GETPUT("?g--p:p--g"); |
| 478 | char *sblocksize = NULL; | ||
| 479 | |||
| 480 | #define BS "b:" | ||
| 481 | #define BS_ARG , &sblocksize | ||
| 482 | #else | ||
| 483 | #define BS | ||
| 484 | #define BS_ARG | ||
| 485 | #endif | ||
| 486 | |||
| 487 | #if ENABLE_FEATURE_TFTP_GET | ||
| 488 | #define GET "g" | ||
| 489 | #define GET_COMPL ":g" | ||
| 490 | #else | ||
| 491 | #define GET | ||
| 492 | #define GET_COMPL | ||
| 493 | #endif | ||
| 494 | 464 | ||
| 495 | #if ENABLE_FEATURE_TFTP_PUT | 465 | USE_GETPUT(cmd =) getopt32(argc, argv, |
| 496 | #define PUT "p" | 466 | USE_FEATURE_TFTP_GET("g") USE_FEATURE_TFTP_PUT("p") |
| 497 | #define PUT_COMPL ":p" | 467 | "l:r:" USE_FEATURE_TFTP_BLOCKSIZE("b:"), |
| 498 | #else | 468 | &localfile, &remotefile |
| 499 | #define PUT | 469 | USE_FEATURE_TFTP_BLOCKSIZE(, &sblocksize)); |
| 500 | #define PUT_COMPL | ||
| 501 | #endif | ||
| 502 | 470 | ||
| 503 | #if defined(CONFIG_FEATURE_TFTP_GET) && defined(CONFIG_FEATURE_TFTP_PUT) | 471 | flags = O_RDONLY; |
| 504 | opt_complementary = GET_COMPL PUT_COMPL ":?g--p:p--g"; | 472 | if (CMD_GET(cmd)) |
| 505 | #elif defined(CONFIG_FEATURE_TFTP_GET) || defined(CONFIG_FEATURE_TFTP_PUT) | ||
| 506 | opt_complementary = GET_COMPL PUT_COMPL; | ||
| 507 | #endif | ||
| 508 | |||
| 509 | cmd = getopt32(argc, argv, GET PUT "l:r:" BS, &localfile, &remotefile BS_ARG); | ||
| 510 | |||
| 511 | cmd &= (tftp_cmd_get | tftp_cmd_put); | ||
| 512 | #if ENABLE_FEATURE_TFTP_GET | ||
| 513 | if (cmd == tftp_cmd_get) | ||
| 514 | flags = O_WRONLY | O_CREAT | O_TRUNC; | 473 | flags = O_WRONLY | O_CREAT | O_TRUNC; |
| 515 | #endif | ||
| 516 | #if ENABLE_FEATURE_TFTP_PUT | ||
| 517 | if (cmd == tftp_cmd_put) | ||
| 518 | flags = O_RDONLY; | ||
| 519 | #endif | ||
| 520 | 474 | ||
| 521 | #if ENABLE_FEATURE_TFTP_BLOCKSIZE | 475 | #if ENABLE_FEATURE_TFTP_BLOCKSIZE |
| 522 | if (sblocksize) { | 476 | if (sblocksize) { |
| @@ -535,30 +489,31 @@ int tftp_main(int argc, char **argv) | |||
| 535 | bb_show_usage(); | 489 | bb_show_usage(); |
| 536 | 490 | ||
| 537 | if (localfile == NULL || LONE_DASH(localfile)) { | 491 | if (localfile == NULL || LONE_DASH(localfile)) { |
| 538 | fd = (cmd == tftp_cmd_get) ? STDOUT_FILENO : STDIN_FILENO; | 492 | fd = CMD_GET(cmd) ? STDOUT_FILENO : STDIN_FILENO; |
| 539 | } else { | 493 | } else { |
| 540 | fd = open(localfile, flags, 0644); /* fail below */ | 494 | fd = xopen3(localfile, flags, 0644); |
| 541 | } | ||
| 542 | if (fd < 0) { | ||
| 543 | bb_perror_msg_and_die("local file"); | ||
| 544 | } | 495 | } |
| 545 | 496 | ||
| 546 | host = xgethostbyname(argv[optind]); | ||
| 547 | port = bb_lookup_port(argv[optind + 1], "udp", 69); | 497 | port = bb_lookup_port(argv[optind + 1], "udp", 69); |
| 498 | peer_lsa = host2sockaddr(argv[optind], port); | ||
| 548 | 499 | ||
| 549 | #if ENABLE_DEBUG_TFTP | 500 | #if ENABLE_DEBUG_TFTP |
| 550 | fprintf(stderr, "using server \"%s\", remotefile \"%s\", " | 501 | fprintf(stderr, "using server \"%s\", " |
| 551 | "localfile \"%s\".\n", | 502 | "remotefile \"%s\", localfile \"%s\".\n", |
| 552 | inet_ntoa(*((struct in_addr *) host->h_addr)), | 503 | xmalloc_sockaddr2dotted(&peer_lsa->sa, peer_lsa->len), |
| 553 | remotefile, localfile); | 504 | remotefile, localfile); |
| 554 | #endif | 505 | #endif |
| 555 | 506 | ||
| 556 | result = tftp(cmd, host, remotefile, fd, port, blocksize); | 507 | result = tftp( |
| 508 | #if ENABLE_FEATURE_TFTP_GET && ENABLE_FEATURE_TFTP_PUT | ||
| 509 | cmd, | ||
| 510 | #endif | ||
| 511 | peer_lsa, remotefile, fd, port, blocksize); | ||
| 557 | 512 | ||
| 558 | if (!(fd == STDOUT_FILENO || fd == STDIN_FILENO)) { | 513 | if (fd > 1) { |
| 559 | if (ENABLE_FEATURE_CLEAN_UP) | 514 | if (ENABLE_FEATURE_CLEAN_UP) |
| 560 | close(fd); | 515 | close(fd); |
| 561 | if (cmd == tftp_cmd_get && result != EXIT_SUCCESS) | 516 | if (CMD_GET(cmd) && result != EXIT_SUCCESS) |
| 562 | unlink(localfile); | 517 | unlink(localfile); |
| 563 | } | 518 | } |
| 564 | return result; | 519 | return result; |
diff --git a/util-linux/rdate.c b/util-linux/rdate.c index 12105953d..ccbf96966 100644 --- a/util-linux/rdate.c +++ b/util-linux/rdate.c | |||
| @@ -8,21 +8,15 @@ | |||
| 8 | * Licensed under GPL v2 or later, see file License for details. | 8 | * Licensed under GPL v2 or later, see file License for details. |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #include <sys/types.h> | 11 | //#include <sys/socket.h> |
| 12 | #include <sys/socket.h> | 12 | //#include <netinet/in.h> |
| 13 | #include <netinet/in.h> | 13 | //#include <netdb.h> |
| 14 | #include <netdb.h> | 14 | //#include <signal.h> |
| 15 | #include <stdio.h> | ||
| 16 | #include <string.h> | ||
| 17 | #include <time.h> | ||
| 18 | #include <stdlib.h> | ||
| 19 | #include <unistd.h> | ||
| 20 | #include <signal.h> | ||
| 21 | 15 | ||
| 22 | #include "busybox.h" | 16 | #include "busybox.h" |
| 23 | 17 | ||
| 24 | 18 | ||
| 25 | static const int RFC_868_BIAS = 2208988800UL; | 19 | enum { RFC_868_BIAS = 2208988800UL }; |
| 26 | 20 | ||
| 27 | static void socket_timeout(int sig) | 21 | static void socket_timeout(int sig) |
| 28 | { | 22 | { |
| @@ -31,18 +25,14 @@ static void socket_timeout(int sig) | |||
| 31 | 25 | ||
| 32 | static time_t askremotedate(const char *host) | 26 | static time_t askremotedate(const char *host) |
| 33 | { | 27 | { |
| 34 | unsigned long nett; | 28 | uint32_t nett; |
| 35 | struct sockaddr_in s_in; | ||
| 36 | int fd; | 29 | int fd; |
| 37 | 30 | ||
| 38 | bb_lookup_host(&s_in, host); | ||
| 39 | s_in.sin_port = bb_lookup_port("time", "tcp", 37); | ||
| 40 | |||
| 41 | /* Add a timeout for dead or inaccessible servers */ | 31 | /* Add a timeout for dead or inaccessible servers */ |
| 42 | alarm(10); | 32 | alarm(10); |
| 43 | signal(SIGALRM, socket_timeout); | 33 | signal(SIGALRM, socket_timeout); |
| 44 | 34 | ||
| 45 | fd = xconnect_tcp_v4(&s_in); | 35 | fd = create_and_connect_stream_or_die(host, bb_lookup_port("time", "tcp", 37)); |
| 46 | 36 | ||
| 47 | if (safe_read(fd, (void *)&nett, 4) != 4) /* read time from server */ | 37 | if (safe_read(fd, (void *)&nett, 4) != 4) /* read time from server */ |
| 48 | bb_error_msg_and_die("%s did not send the complete time", host); | 38 | bb_error_msg_and_die("%s did not send the complete time", host); |
| @@ -50,9 +40,9 @@ static time_t askremotedate(const char *host) | |||
| 50 | 40 | ||
| 51 | /* convert from network byte order to local byte order. | 41 | /* convert from network byte order to local byte order. |
| 52 | * RFC 868 time is the number of seconds | 42 | * RFC 868 time is the number of seconds |
| 53 | * since 00:00 (midnight) 1 January 1900 GMT | 43 | * since 00:00 (midnight) 1 January 1900 GMT |
| 54 | * the RFC 868 time 2,208,988,800 corresponds to 00:00 1 Jan 1970 GMT | 44 | * the RFC 868 time 2,208,988,800 corresponds to 00:00 1 Jan 1970 GMT |
| 55 | * Subtract the RFC 868 time to get Linux epoch | 45 | * Subtract the RFC 868 time to get Linux epoch |
| 56 | */ | 46 | */ |
| 57 | 47 | ||
| 58 | return ntohl(nett) - RFC_868_BIAS; | 48 | return ntohl(nett) - RFC_868_BIAS; |
