diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-11 16:50:23 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-11 16:50:23 +0000 |
commit | 8e9ccba371480fb1fb3da9235fabdbb7861523c3 (patch) | |
tree | 369636a4a765a571e1c6a6ecf2a52ca0131cc90e | |
parent | 085231fbbad159d2275cbd5ecdcf4732512bb80f (diff) | |
download | busybox-w32-8e9ccba371480fb1fb3da9235fabdbb7861523c3.tar.gz busybox-w32-8e9ccba371480fb1fb3da9235fabdbb7861523c3.tar.bz2 busybox-w32-8e9ccba371480fb1fb3da9235fabdbb7861523c3.zip |
ipv6-ization efforts continue. Few bugs are found,
unknown number likely introduced...
-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; |