From 8e9ccba371480fb1fb3da9235fabdbb7861523c3 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Thu, 11 Jan 2007 16:50:23 +0000 Subject: [PATCH] ipv6-ization efforts continue. Few bugs are found, unknown number likely introduced... --- include/libbb.h | 31 +++-- libbb/xconnect.c | 60 ++++++++-- networking/ftpgetput.c | 19 ++-- networking/tftp.c | 251 +++++++++++++++++------------------------ 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); extern int xconnect_tcp_v4(struct sockaddr_in *s_addr); extern struct hostent *xgethostbyname(const char *name); extern struct hostent *xgethostbyname2(const char *name, int af); - extern int setsockopt_reuseaddr(int fd); extern int setsockopt_broadcast(int fd); -/* Create server TCP socket bound to bindaddr:port. bindaddr can be NULL, - * numeric IP ("N.N.N.N") or numeric IPv6 address, - * and can have ":PORT" suffix (for IPv6 use "[X:X:...:X]:PORT"). - * If there is no suffix, port argument is used */ -extern int create_and_bind_stream_or_die(const char *bindaddr, int port); -/* Create client TCP socket connected to peer:port. Peer cannot be NULL. - * Peer can be numeric IP ("N.N.N.N"), numeric IPv6 address or hostname, - * and can have ":PORT" suffix (for IPv6 use "[X:X:...:X]:PORT"). - * If there is no suffix, port argument is used */ -extern int create_and_connect_stream_or_die(const char *peer, int port); + +/* "new" (ipv4+ipv6) API */ typedef struct len_and_sockaddr { int len; union { @@ -316,11 +307,29 @@ typedef struct len_and_sockaddr { #endif }; } len_and_sockaddr; +/* Create server TCP socket bound to bindaddr:port. bindaddr can be NULL, + * numeric IP ("N.N.N.N") or numeric IPv6 address, + * and can have ":PORT" suffix (for IPv6 use "[X:X:...:X]:PORT"). + * If there is no suffix, port argument is used */ +extern int create_and_bind_stream_or_die(const char *bindaddr, int port); +/* Create client TCP socket connected to peer:port. Peer cannot be NULL. + * Peer can be numeric IP ("N.N.N.N"), numeric IPv6 address or hostname, + * and can have ":PORT" suffix (for IPv6 use "[X:X:...:X]:PORT"). + * If there is no suffix, port argument is used */ +extern int create_and_connect_stream_or_die(const char *peer, int port); +/* Connect to peer identified by lsa */ +extern int xconnect_stream(const len_and_sockaddr *lsa); /* Return malloc'ed len_and_sockaddr with socket address of host:port * Currently will return IPv4 or IPv6 sockaddrs only * (depending on host), but in theory nothing prevents e.g. * UNIX socket address being returned, IPX sockaddr etc... */ extern len_and_sockaddr* host2sockaddr(const char *host, int port); +/* assign sin[6]_port member if the socket is of corresponding type, + * otherwise noop. Useful for ftp. + * NB: does NOT do htons() internally, just direct assignment. */ +extern void set_port(len_and_sockaddr *lsa, unsigned port); +char* xmalloc_sockaddr2host(const struct sockaddr *sa, socklen_t salen); +char* xmalloc_sockaddr2dotted(const struct sockaddr *sa, socklen_t salen); 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) /* "New" networking API */ -//extern int xsocket_stream_ip4or6(sa_family_t *fp); -//extern len_and_sockaddr* dotted2sockaddr(const char *dotted, int def_port); +void set_port(len_and_sockaddr *lsa, unsigned port) +{ +#if ENABLE_FEATURE_IPV6 + if (lsa->sa.sa_family == AF_INET6) { + lsa->sin6.sin6_port = port; + return; + } +#endif + if (lsa->sa.sa_family == AF_INET) { + lsa->sin.sin_port = port; + return; + } + /* What? UNIX socket? IPX?? :) */ +} /* peer: "1.2.3.4[:port]", "www.google.com[:port]" * port: if neither of above specifies port # @@ -96,7 +108,6 @@ static len_and_sockaddr* str2sockaddr(const char *host, int port, int ai_flags) struct addrinfo *result = NULL; const char *org_host = host; /* only for error msg */ const char *cp; - char service[sizeof(int)*3 + 1]; struct addrinfo hint; /* Ugly parsing of host:addr */ @@ -119,9 +130,7 @@ static len_and_sockaddr* str2sockaddr(const char *host, int port, int ai_flags) if (ENABLE_FEATURE_IPV6 && *cp != ':') cp++; /* skip ']' */ cp++; /* skip ':' */ - } else { - utoa_to_buf(port, service, sizeof(service)); - cp = service; + port = xatou16(cp); } memset(&hint, 0 , sizeof(hint)); @@ -132,13 +141,14 @@ static len_and_sockaddr* str2sockaddr(const char *host, int port, int ai_flags) /* Needed. Or else we will get each address thrice (or more) * for each possible socket type (tcp,udp,raw...): */ hint.ai_socktype = SOCK_STREAM; - hint.ai_flags = ai_flags | AI_NUMERICSERV; - rc = getaddrinfo(host, cp, &hint, &result); + hint.ai_flags = ai_flags; + rc = getaddrinfo(host, NULL, &hint, &result); if (rc || !result) bb_error_msg_and_die("bad address '%s'", org_host); r = xmalloc(offsetof(len_and_sockaddr, sa) + result->ai_addrlen); r->len = result->ai_addrlen; memcpy(&r->sa, result->ai_addr, result->ai_addrlen); + set_port(r, port); freeaddrinfo(result); return r; } @@ -153,7 +163,7 @@ static len_and_sockaddr* dotted2sockaddr(const char *host, int port) return str2sockaddr(host, port, NI_NUMERICHOST); } -static int xsocket_stream_ip4or6(len_and_sockaddr *lsa) +static int xsocket_stream(len_and_sockaddr *lsa) { int fd; #if ENABLE_FEATURE_IPV6 @@ -186,7 +196,7 @@ int create_and_bind_stream_or_die(const char *bindaddr, int port) USE_FEATURE_IPV6(sizeof(struct sockaddr_in6)) SKIP_FEATURE_IPV6(sizeof(struct sockaddr_in)) ); - fd = xsocket_stream_ip4or6(lsa); + fd = xsocket_stream(lsa); } setsockopt_reuseaddr(fd); xbind(fd, &lsa->sa, lsa->len); @@ -209,3 +219,33 @@ int create_and_connect_stream_or_die(const char *peer, int port) free(lsa); return fd; } + +int xconnect_stream(const len_and_sockaddr *lsa) +{ + int fd = xsocket(lsa->sa.sa_family, SOCK_STREAM, 0); + xconnect(fd, &lsa->sa, lsa->len); + return fd; +} + +static char* sockaddr2str(const struct sockaddr *sa, socklen_t salen, int flags) +{ + char host[128]; + char serv[16]; + int rc = getnameinfo(sa, salen, + host, sizeof(host), + serv, sizeof(serv), + flags | NI_NUMERICSERV /* do not resolve port# */ + ); + if (rc) return NULL; + return xasprintf("%s:%s", host, serv); +} + +char* xmalloc_sockaddr2host(const struct sockaddr *sa, socklen_t salen) +{ + return sockaddr2str(sa, salen, 0); +} + +char* xmalloc_sockaddr2dotted(const struct sockaddr *sa, socklen_t salen) +{ + return sockaddr2str(sa, salen, NI_NUMERICHOST); +} 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 @@ typedef struct ftp_host_info_s { char *user; char *password; - struct sockaddr_in *s_in; + struct len_and_sockaddr *lsa; } ftp_host_info_t; static char verbose_flag; @@ -88,8 +88,8 @@ static int xconnect_ftpdata(ftp_host_info_t *server, char *buf) *buf_ptr = '\0'; port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256; - server->s_in->sin_port = htons(port_num); - return xconnect_tcp_v4(server->s_in); + set_port(server->lsa, htons(port_num)); + return xconnect_stream(server->lsa); } static FILE *ftp_login(ftp_host_info_t *server) @@ -98,9 +98,9 @@ static FILE *ftp_login(ftp_host_info_t *server) char buf[512]; /* Connect to the command socket */ - control_stream = fdopen(xconnect_tcp_v4(server->s_in), "r+"); + control_stream = fdopen(xconnect_stream(server->lsa), "r+"); if (control_stream == NULL) { - /* Extremely unlikely */ + /* fdopen failed - extremely unlikely */ bb_perror_nomsg_and_die(); } @@ -304,7 +304,6 @@ int ftpgetput_main(int argc, char **argv) const char *port = "ftp"; /* socket to ftp server */ FILE *control_stream; - struct sockaddr_in s_in; /* continue previous transfer (-c) */ ftp_host_info_t *server; @@ -347,12 +346,10 @@ int ftpgetput_main(int argc, char **argv) /* We want to do exactly _one_ DNS lookup, since some * sites (i.e. ftp.us.debian.org) use round-robin DNS * and we want to connect to only one IP... */ - server->s_in = &s_in; - bb_lookup_host(&s_in, argv[0]); - s_in.sin_port = bb_lookup_port(port, "tcp", 21); + server->lsa = host2sockaddr(argv[0], bb_lookup_port(port, "tcp", 21)); if (verbose_flag) { - printf("Connecting to %s[%s]:%d\n", - argv[0], inet_ntoa(s_in.sin_addr), ntohs(s_in.sin_port)); + printf("Connecting to %s [%s]\n", argv[0], + xmalloc_sockaddr2dotted(&server->lsa->sa, server->lsa->len)); } /* 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 @@ #define TFTP_TIMEOUT 5 /* seconds */ #define TFTP_NUM_RETRIES 5 /* number of retries */ -static const char * const MODE_OCTET = "octet"; -#define MODE_OCTET_LEN 6 /* sizeof(MODE_OCTET)*/ - -static const char * const OPTION_BLOCKSIZE = "blksize"; -#define OPTION_BLOCKSIZE_LEN 8 /* sizeof(OPTION_BLOCKSIZE) */ - /* opcodes we support */ #define TFTP_RRQ 1 #define TFTP_WRQ 2 @@ -51,13 +45,23 @@ static const char *const tftp_bb_error_msg[] = { "No such user" }; -#define tftp_cmd_get ENABLE_FEATURE_TFTP_GET - -#if ENABLE_FEATURE_TFTP_PUT -# define tftp_cmd_put (tftp_cmd_get+ENABLE_FEATURE_TFTP_PUT) +#if ENABLE_FEATURE_TFTP_GET && !ENABLE_FEATURE_TFTP_PUT +#define USE_GETPUT(a) +#define CMD_GET(cmd) 1 +#define CMD_PUT(cmd) 0 +#elif !ENABLE_FEATURE_TFTP_GET && ENABLE_FEATURE_TFTP_PUT +#define USE_GETPUT(a) +#define CMD_GET(cmd) 0 +#define CMD_PUT(cmd) 1 #else -# define tftp_cmd_put 0 +#define USE_GETPUT(a) a +/* masks coming from getpot32 */ +#define CMD_GET(cmd) (cmd & 1) +#define CMD_PUT(cmd) (cmd & 2) #endif +/* NB: in the code below + * CMD_GET(cmd) and CMD_GET(cmd) are mutually exclusive + */ #if ENABLE_FEATURE_TFTP_BLOCKSIZE @@ -70,8 +74,9 @@ static int tftp_blocksize_check(int blocksize, int bufsize) * to use blocksizes smaller than 22 octets. */ - if ((bufsize && (blocksize > bufsize)) || - (blocksize < 8) || (blocksize > 65564)) { + if ((bufsize && (blocksize > bufsize)) + || (blocksize < 8) || (blocksize > 65564) + ) { bb_error_msg("bad blocksize"); return 0; } @@ -86,7 +91,6 @@ static char *tftp_option_get(char *buf, int len, const char * const option) int k; while (len > 0) { - /* Make sure the options are terminated correctly */ for (k = 0; k < len; k++) { @@ -122,22 +126,23 @@ static char *tftp_option_get(char *buf, int len, const char * const option) #endif -static int tftp(const int cmd, const struct hostent *host, - const char *remotefile, const int localfd, - const unsigned short port, int tftp_bufsize) +static int tftp( +#if ENABLE_FEATURE_TFTP_GET && ENABLE_FEATURE_TFTP_PUT + const int cmd, +#endif + const len_and_sockaddr *peer_lsa, + const char *remotefile, const int localfd, + const unsigned port, int tftp_bufsize) { - struct sockaddr_in sa; - struct sockaddr_in from; struct timeval tv; - socklen_t fromlen; fd_set rfds; int socketfd; int len; int opcode = 0; int finished = 0; int timeout = TFTP_NUM_RETRIES; - unsigned short block_nr = 1; - unsigned short tmp; + uint16_t block_nr = 1; + uint16_t tmp; char *cp; USE_FEATURE_TFTP_BLOCKSIZE(int want_option_ack = 0;) @@ -149,42 +154,24 @@ static int tftp(const int cmd, const struct hostent *host, char *xbuf = xmalloc(tftp_bufsize += 4); char *rbuf = xmalloc(tftp_bufsize); - if ((socketfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { - /* need to unlink the localfile, so don't use xsocket here. */ - bb_perror_msg("socket"); - return EXIT_FAILURE; - } - - len = sizeof(sa); - - memset(&sa, 0, len); - xbind(socketfd, (struct sockaddr *)&sa, len); - - sa.sin_family = host->h_addrtype; - sa.sin_port = port; - memcpy(&sa.sin_addr, (struct in_addr *) host->h_addr, - sizeof(sa.sin_addr)); + socketfd = xsocket(peer_lsa->sa.sa_family, SOCK_DGRAM, 0); /* build opcode */ - if (cmd & tftp_cmd_get) { + opcode = TFTP_WRQ; + if (CMD_GET(cmd)) { opcode = TFTP_RRQ; } - if (cmd & tftp_cmd_put) { - opcode = TFTP_WRQ; - } while (1) { cp = xbuf; /* first create the opcode part */ - *((unsigned short *) cp) = htons(opcode); + *((uint16_t*)cp) = htons(opcode); cp += 2; /* add filename and mode */ - if (((cmd & tftp_cmd_get) && (opcode == TFTP_RRQ)) || - ((cmd & tftp_cmd_put) && (opcode == TFTP_WRQ))) - { + if (CMD_GET(cmd) ? (opcode == TFTP_RRQ) : (opcode == TFTP_WRQ)) { int too_long = 0; /* see if the filename fits into xbuf @@ -198,14 +185,14 @@ static int tftp(const int cmd, const struct hostent *host, cp += len; } - if (too_long || ((&xbuf[tftp_bufsize - 1] - cp) < MODE_OCTET_LEN)) { + if (too_long || (&xbuf[tftp_bufsize - 1] - cp) < sizeof("octet")) { bb_error_msg("remote filename too long"); break; } /* add "mode" part of the package */ - memcpy(cp, MODE_OCTET, MODE_OCTET_LEN); - cp += MODE_OCTET_LEN; + memcpy(cp, "octet", sizeof("octet")); + cp += sizeof("octet"); #if ENABLE_FEATURE_TFTP_BLOCKSIZE @@ -219,8 +206,8 @@ static int tftp(const int cmd, const struct hostent *host, } /* add "blksize" + number of blocks */ - memcpy(cp, OPTION_BLOCKSIZE, OPTION_BLOCKSIZE_LEN); - cp += OPTION_BLOCKSIZE_LEN; + memcpy(cp, "blksize", sizeof("blksize")); + cp += sizeof("blksize"); cp += snprintf(cp, 6, "%d", len) + 1; want_option_ack = 1; @@ -230,16 +217,12 @@ static int tftp(const int cmd, const struct hostent *host, /* add ack and data */ - if (((cmd & tftp_cmd_get) && (opcode == TFTP_ACK)) || - ((cmd & tftp_cmd_put) && (opcode == TFTP_DATA))) { - - *((unsigned short *) cp) = htons(block_nr); - + if (CMD_GET(cmd) ? (opcode == TFTP_ACK) : (opcode == TFTP_DATA)) { + *((uint16_t*)cp) = htons(block_nr); cp += 2; - block_nr++; - if ((cmd & tftp_cmd_put) && (opcode == TFTP_DATA)) { + if (CMD_PUT(cmd) && (opcode == TFTP_DATA)) { len = full_read(localfd, cp, tftp_bufsize - 4); if (len < 0) { @@ -261,9 +244,7 @@ static int tftp(const int cmd, const struct hostent *host, timeout = TFTP_NUM_RETRIES; /* re-initialize */ do { - len = cp - xbuf; - #if ENABLE_DEBUG_TFTP fprintf(stderr, "sending %u bytes\n", len); for (cp = xbuf; cp < &xbuf[len]; cp++) @@ -271,7 +252,7 @@ static int tftp(const int cmd, const struct hostent *host, fprintf(stderr, "\n"); #endif if (sendto(socketfd, xbuf, len, 0, - (struct sockaddr *) &sa, sizeof(sa)) < 0) { + &peer_lsa->sa, peer_lsa->len) < 0) { bb_perror_msg("send"); len = -1; break; @@ -284,9 +265,6 @@ static int tftp(const int cmd, const struct hostent *host, /* receive packet */ - memset(&from, 0, sizeof(from)); - fromlen = sizeof(from); - tv.tv_sec = TFTP_TIMEOUT; tv.tv_usec = 0; @@ -294,30 +272,41 @@ static int tftp(const int cmd, const struct hostent *host, FD_SET(socketfd, &rfds); switch (select(socketfd + 1, &rfds, NULL, NULL, &tv)) { + struct sockaddr *from; + socklen_t fromlen; + case 1: - len = recvfrom(socketfd, rbuf, tftp_bufsize, 0, - (struct sockaddr *) &from, &fromlen); + fromlen = peer_lsa->len; + from = alloca(fromlen); + memset(from, 0, fromlen); + len = recvfrom(socketfd, rbuf, tftp_bufsize, 0, + from, &fromlen); if (len < 0) { bb_perror_msg("recvfrom"); break; } - timeout = 0; - - if (sa.sin_port == port) { - sa.sin_port = from.sin_port; - } - if (sa.sin_port == from.sin_port) { - break; + if (from->sa_family == peer_lsa->sa.sa_family) { +#if ENABLE_FEATURE_IPV6 + if (from->sa_family == AF_INET6 + && ((struct sockaddr_in6*)from)->sin6_port == port + ) + break; +#endif + /* Non-internet sockets are ok */ + if (from->sa_family != AF_INET) + break; + if (((struct sockaddr_in*)from)->sin_port == port) + break; } - - /* fall-through for bad packets! */ - /* discard the packet - treat as timeout */ + /* family doesn't match, or + * it is INET[v6] and port doesn't match - + * fall-through for bad packets! + * (discard the packet - treat as timeout) */ timeout = TFTP_NUM_RETRIES; case 0: bb_error_msg("timeout"); - timeout--; if (timeout == 0) { len = -1; @@ -331,14 +320,14 @@ static int tftp(const int cmd, const struct hostent *host, } while (timeout && (len >= 0)); - if ((finished) || (len < 0)) { + if (finished || (len < 0)) { break; } /* process received packet */ - opcode = ntohs(*((unsigned short *) rbuf)); - tmp = ntohs(*((unsigned short *) &rbuf[2])); + opcode = ntohs( ((uint16_t*)rbuf)[0] ); + tmp = ntohs( ((uint16_t*)rbuf)[1] ); #if ENABLE_DEBUG_TFTP 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, rbuf[tftp_bufsize - 1] = '\0'; } else if (tmp < (sizeof(tftp_bb_error_msg) / sizeof(char *))) { - msg = tftp_bb_error_msg[tmp]; } @@ -368,25 +356,22 @@ static int tftp(const int cmd, const struct hostent *host, want_option_ack = 0; if (opcode == TFTP_OACK) { - /* server seems to support options */ - char *res; - res = tftp_option_get(&rbuf[2], len - 2, OPTION_BLOCKSIZE); + res = tftp_option_get(&rbuf[2], len - 2, "blksize"); if (res) { int blksize = xatoi_u(res); if (tftp_blocksize_check(blksize, tftp_bufsize - 4)) { - - if (cmd & tftp_cmd_put) { + if (CMD_PUT(cmd)) { opcode = TFTP_DATA; } else { opcode = TFTP_ACK; } #if ENABLE_DEBUG_TFTP - fprintf(stderr, "using %s %u\n", OPTION_BLOCKSIZE, + fprintf(stderr, "using blksize %u\n", blksize); #endif tftp_bufsize = blksize + 4; @@ -407,10 +392,8 @@ static int tftp(const int cmd, const struct hostent *host, } #endif - if ((cmd & tftp_cmd_get) && (opcode == TFTP_DATA)) { - + if (CMD_GET(cmd) && (opcode == TFTP_DATA)) { if (tmp == block_nr) { - len = full_write(localfd, &rbuf[4], len - 4); if (len < 0) { @@ -430,6 +413,7 @@ static int tftp(const int cmd, const struct hostent *host, --block_nr; opcode = TFTP_ACK; continue; +// tmp==(block_nr-1) and (tmp+1)==block_nr is always same, I think. wtf? } else if (tmp + 1 == block_nr) { /* Server lost our TFTP_ACK. Resend it */ block_nr = tmp; @@ -438,9 +422,8 @@ static int tftp(const int cmd, const struct hostent *host, } } - if ((cmd & tftp_cmd_put) && (opcode == TFTP_ACK)) { - - if (tmp == (unsigned short) (block_nr - 1)) { + if (CMD_PUT(cmd) && (opcode == TFTP_ACK)) { + if (tmp == (uint16_t) (block_nr - 1)) { if (finished) { break; } @@ -462,61 +445,32 @@ static int tftp(const int cmd, const struct hostent *host, int tftp_main(int argc, char **argv) { - struct hostent *host = NULL; + len_and_sockaddr *peer_lsa; const char *localfile = NULL; const char *remotefile = NULL; +#if ENABLE_FEATURE_TFTP_BLOCKSIZE + const char *sblocksize = NULL; +#endif int port; - int cmd = 0; + USE_GETPUT(int cmd;) int fd = -1; int flags = 0; int result; int blocksize = TFTP_BLOCKSIZE_DEFAULT; - /* figure out what to pass to getopt */ - -#if ENABLE_FEATURE_TFTP_BLOCKSIZE - char *sblocksize = NULL; - -#define BS "b:" -#define BS_ARG , &sblocksize -#else -#define BS -#define BS_ARG -#endif - -#if ENABLE_FEATURE_TFTP_GET -#define GET "g" -#define GET_COMPL ":g" -#else -#define GET -#define GET_COMPL -#endif + /* -p or -g is mandatory, and they are mutually exclusive */ + opt_complementary = "" USE_FEATURE_TFTP_GET("g:") USE_FEATURE_TFTP_PUT("p:") + USE_GETPUT("?g--p:p--g"); -#if ENABLE_FEATURE_TFTP_PUT -#define PUT "p" -#define PUT_COMPL ":p" -#else -#define PUT -#define PUT_COMPL -#endif + USE_GETPUT(cmd =) getopt32(argc, argv, + USE_FEATURE_TFTP_GET("g") USE_FEATURE_TFTP_PUT("p") + "l:r:" USE_FEATURE_TFTP_BLOCKSIZE("b:"), + &localfile, &remotefile + USE_FEATURE_TFTP_BLOCKSIZE(, &sblocksize)); -#if defined(CONFIG_FEATURE_TFTP_GET) && defined(CONFIG_FEATURE_TFTP_PUT) - opt_complementary = GET_COMPL PUT_COMPL ":?g--p:p--g"; -#elif defined(CONFIG_FEATURE_TFTP_GET) || defined(CONFIG_FEATURE_TFTP_PUT) - opt_complementary = GET_COMPL PUT_COMPL; -#endif - - cmd = getopt32(argc, argv, GET PUT "l:r:" BS, &localfile, &remotefile BS_ARG); - - cmd &= (tftp_cmd_get | tftp_cmd_put); -#if ENABLE_FEATURE_TFTP_GET - if (cmd == tftp_cmd_get) + flags = O_RDONLY; + if (CMD_GET(cmd)) flags = O_WRONLY | O_CREAT | O_TRUNC; -#endif -#if ENABLE_FEATURE_TFTP_PUT - if (cmd == tftp_cmd_put) - flags = O_RDONLY; -#endif #if ENABLE_FEATURE_TFTP_BLOCKSIZE if (sblocksize) { @@ -535,30 +489,31 @@ int tftp_main(int argc, char **argv) bb_show_usage(); if (localfile == NULL || LONE_DASH(localfile)) { - fd = (cmd == tftp_cmd_get) ? STDOUT_FILENO : STDIN_FILENO; + fd = CMD_GET(cmd) ? STDOUT_FILENO : STDIN_FILENO; } else { - fd = open(localfile, flags, 0644); /* fail below */ - } - if (fd < 0) { - bb_perror_msg_and_die("local file"); + fd = xopen3(localfile, flags, 0644); } - host = xgethostbyname(argv[optind]); port = bb_lookup_port(argv[optind + 1], "udp", 69); + peer_lsa = host2sockaddr(argv[optind], port); #if ENABLE_DEBUG_TFTP - fprintf(stderr, "using server \"%s\", remotefile \"%s\", " - "localfile \"%s\".\n", - inet_ntoa(*((struct in_addr *) host->h_addr)), + fprintf(stderr, "using server \"%s\", " + "remotefile \"%s\", localfile \"%s\".\n", + xmalloc_sockaddr2dotted(&peer_lsa->sa, peer_lsa->len), remotefile, localfile); #endif - result = tftp(cmd, host, remotefile, fd, port, blocksize); + result = tftp( +#if ENABLE_FEATURE_TFTP_GET && ENABLE_FEATURE_TFTP_PUT + cmd, +#endif + peer_lsa, remotefile, fd, port, blocksize); - if (!(fd == STDOUT_FILENO || fd == STDIN_FILENO)) { + if (fd > 1) { if (ENABLE_FEATURE_CLEAN_UP) close(fd); - if (cmd == tftp_cmd_get && result != EXIT_SUCCESS) + if (CMD_GET(cmd) && result != EXIT_SUCCESS) unlink(localfile); } 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 @@ * Licensed under GPL v2 or later, see file License for details. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +//#include +//#include +//#include +//#include #include "busybox.h" -static const int RFC_868_BIAS = 2208988800UL; +enum { RFC_868_BIAS = 2208988800UL }; static void socket_timeout(int sig) { @@ -31,18 +25,14 @@ static void socket_timeout(int sig) static time_t askremotedate(const char *host) { - unsigned long nett; - struct sockaddr_in s_in; + uint32_t nett; int fd; - bb_lookup_host(&s_in, host); - s_in.sin_port = bb_lookup_port("time", "tcp", 37); - /* Add a timeout for dead or inaccessible servers */ alarm(10); signal(SIGALRM, socket_timeout); - fd = xconnect_tcp_v4(&s_in); + fd = create_and_connect_stream_or_die(host, bb_lookup_port("time", "tcp", 37)); if (safe_read(fd, (void *)&nett, 4) != 4) /* read time from server */ bb_error_msg_and_die("%s did not send the complete time", host); @@ -50,9 +40,9 @@ static time_t askremotedate(const char *host) /* convert from network byte order to local byte order. * RFC 868 time is the number of seconds - * since 00:00 (midnight) 1 January 1900 GMT - * the RFC 868 time 2,208,988,800 corresponds to 00:00 1 Jan 1970 GMT - * Subtract the RFC 868 time to get Linux epoch + * since 00:00 (midnight) 1 January 1900 GMT + * the RFC 868 time 2,208,988,800 corresponds to 00:00 1 Jan 1970 GMT + * Subtract the RFC 868 time to get Linux epoch */ return ntohl(nett) - RFC_868_BIAS; -- 2.25.1