int inflate(int in, int out);
+/* NB: returns port in host byte order */
unsigned bb_lookup_port(const char *port, const char *protocol, unsigned default_port);
void bb_lookup_host(struct sockaddr_in *s_in, const char *host);
* default_port */
unsigned bb_lookup_port(const char *port, const char *protocol, unsigned default_port)
{
- unsigned port_nr = htons(default_port);
+ unsigned port_nr = default_port;
if (port) {
int old_errno;
if (errno || port_nr > 65535) {
struct servent *tserv = getservbyname(port, protocol);
if (tserv)
- port_nr = tserv->s_port;
- } else {
- port_nr = htons(port_nr);
+ port_nr = ntohs(tserv->s_port);
}
errno = old_errno;
}
- return port_nr;
+ return (uint16_t)port_nr;
}
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);
+ set_port(r, htons(port));
freeaddrinfo(result);
return r;
}
flags | NI_NUMERICSERV /* do not resolve port# */
);
if (rc) return NULL;
+// We probably need to use [%s]:%s for IPv6...
return xasprintf("%s:%s", host, serv);
}
unsigned int rmt_ip;
#if ENABLE_FEATURE_HTTPD_CGI || DEBUG
- char rmt_ip_str[16]; /* for set env REMOTE_ADDR */
+ char *rmt_ip_str; /* for set env REMOTE_ADDR */
#endif
unsigned port; /* server initial port and for
set env REMOTE_PORT */
****************************************************************************/
static int openServer(void)
{
- struct sockaddr_in lsocket;
int fd;
/* create the socket right now */
- /* inet_addr() returns a value that is already in network order */
- memset(&lsocket, 0, sizeof(lsocket));
- lsocket.sin_family = AF_INET;
- lsocket.sin_addr.s_addr = INADDR_ANY;
- lsocket.sin_port = htons(config->port);
- fd = xsocket(AF_INET, SOCK_STREAM, 0);
- /* tell the OS it's OK to reuse a previous address even though */
- /* it may still be in a close down state. Allows bind to succeed. */
-#ifdef SO_REUSEPORT
- {
- static const int on = 1;
- setsockopt(fd, SOL_SOCKET, SO_REUSEPORT,
- (void *)&on, sizeof(on));
- }
-#else
- setsockopt_reuseaddr(fd);
-#endif
- xbind(fd, (struct sockaddr *)&lsocket, sizeof(lsocket));
+ fd = create_and_bind_stream_or_die(NULL, config->port);
xlisten(fd, 9);
- signal(SIGCHLD, SIG_IGN); /* prevent zombie (defunct) processes */
return fd;
}
setenv1("SERVER_SOFTWARE", httpdVersion);
putenv("SERVER_PROTOCOL=HTTP/1.0");
putenv("GATEWAY_INTERFACE=CGI/1.1");
- setenv1("REMOTE_ADDR", config->rmt_ip_str);
+ /* Having _separate_ variables for IP and port defeats
+ * the purpose of having socket abstraction. Which "port"
+ * are you using on Unix domain socket?
+ * IOW - REMOTE_PEER="1.2.3.4:56" makes much more sense.
+ * Oh well... */
+ {
+ char *p = config->rmt_ip_str ? : "";
+ char *cp = strrchr(p, ':');
+ if (ENABLE_FEATURE_IPV6 && cp && strchr(cp, ']'))
+ cp = NULL;
+ if (cp) *cp = '\0'; /* delete :PORT */
+ setenv1("REMOTE_ADDR", p);
+ }
#if ENABLE_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV
setenv_long("REMOTE_PORT", config->port);
#endif
for (cur = config->ip_a_d; cur; cur = cur->next) {
#if DEBUG
fprintf(stderr, "checkPermIP: '%s' ? ", config->rmt_ip_str);
+ fprintf(stderr, "'%u.%u.%u.%u/%u.%u.%u.%u'\n",
+ (unsigned char)(cur->ip >> 24),
+ (unsigned char)(cur->ip >> 16),
+ (unsigned char)(cur->ip >> 8),
+ (unsigned char)(cur->ip),
+ (unsigned char)(cur->mask >> 24),
+ (unsigned char)(cur->mask >> 16),
+ (unsigned char)(cur->mask >> 8),
+ (unsigned char)(cur->mask)
+ );
#endif
- if (DEBUG)
- fprintf(stderr, "'%u.%u.%u.%u/%u.%u.%u.%u'\n",
- (unsigned char)(cur->ip >> 24),
- (unsigned char)(cur->ip >> 16),
- (unsigned char)(cur->ip >> 8),
- cur->ip & 0xff,
- (unsigned char)(cur->mask >> 24),
- (unsigned char)(cur->mask >> 16),
- (unsigned char)(cur->mask >> 8),
- cur->mask & 0xff);
if ((config->rmt_ip & cur->mask) == cur->ip)
return cur->allow_deny == 'A'; /* Allow/Deny */
}
****************************************************************************/
static int miniHttpd(int server)
{
+ static const int on = 1;
+
fd_set readfd, portfd;
FD_ZERO(&portfd);
/* copy the ports we are watching to the readfd set */
while (1) {
- int on, s;
- socklen_t fromAddrLen;
- struct sockaddr_in fromAddr;
+ int s;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ USE_FEATURE_IPV6(struct sockaddr_in6 sin6;)
+ } fromAddr;
+ socklen_t fromAddrLen = sizeof(fromAddr);
/* Now wait INDEFINITELY on the set of sockets! */
readfd = portfd;
continue;
if (!FD_ISSET(server, &readfd))
continue;
- fromAddrLen = sizeof(fromAddr);
- s = accept(server, (struct sockaddr *)&fromAddr, &fromAddrLen);
+ s = accept(server, &fromAddr.sa, &fromAddrLen);
if (s < 0)
continue;
config->accepted_socket = s;
- config->rmt_ip = ntohl(fromAddr.sin_addr.s_addr);
+ config->rmt_ip = 0;
+ config->port = 0;
#if ENABLE_FEATURE_HTTPD_CGI || DEBUG
- sprintf(config->rmt_ip_str, "%u.%u.%u.%u",
- (unsigned char)(config->rmt_ip >> 24),
- (unsigned char)(config->rmt_ip >> 16),
- (unsigned char)(config->rmt_ip >> 8),
- config->rmt_ip & 0xff);
- config->port = ntohs(fromAddr.sin_port);
+ free(config->rmt_ip_str);
+ config->rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen);
#if DEBUG
- bb_error_msg("connection from IP=%s, port %u",
- config->rmt_ip_str, config->port);
+ bb_error_msg("connection from '%s'", config->rmt_ip_str);
#endif
#endif /* FEATURE_HTTPD_CGI */
+ if (fromAddr.sa.sa_family == AF_INET) {
+ config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
+ config->port = ntohs(fromAddr.sin.sin_port);
+ }
+#if ENABLE_FEATURE_IPV6
+ if (fromAddr.sa.sa_family == AF_INET6) {
+ //config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
+ config->port = ntohs(fromAddr.sin6.sin6_port);
+ }
+#endif
/* set the KEEPALIVE option to cull dead connections */
- on = 1;
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on));
if (DEBUG || fork() == 0) {
/* from inetd */
static int miniHttpd_inetd(void)
{
- struct sockaddr_in fromAddrLen;
- socklen_t sinlen = sizeof(struct sockaddr_in);
-
- getpeername(0, (struct sockaddr *)&fromAddrLen, &sinlen);
- config->rmt_ip = ntohl(fromAddrLen.sin_addr.s_addr);
-#if ENABLE_FEATURE_HTTPD_CGI
- sprintf(config->rmt_ip_str, "%u.%u.%u.%u",
- (unsigned char)(config->rmt_ip >> 24),
- (unsigned char)(config->rmt_ip >> 16),
- (unsigned char)(config->rmt_ip >> 8),
- config->rmt_ip & 0xff);
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ USE_FEATURE_IPV6(struct sockaddr_in6 sin6;)
+ } fromAddr;
+ socklen_t fromAddrLen = sizeof(fromAddr);
+
+ getpeername(0, &fromAddr.sa, &fromAddrLen);
+ config->rmt_ip = 0;
+ config->port = 0;
+#if ENABLE_FEATURE_HTTPD_CGI || DEBUG
+ free(config->rmt_ip_str);
+ config->rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr.sa, fromAddrLen);
+#endif
+ if (fromAddr.sa.sa_family == AF_INET) {
+ config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
+ config->port = ntohs(fromAddr.sin.sin_port);
+ }
+#if ENABLE_FEATURE_IPV6
+ if (fromAddr.sa.sa_family == AF_INET6) {
+ //config->rmt_ip = ntohl(fromAddr.sin.sin_addr.s_addr);
+ config->port = ntohs(fromAddr.sin6.sin6_port);
+ }
#endif
- config->port = ntohs(fromAddrLen.sin_port);
handleIncoming();
return 0;
}
xchdir(home_httpd);
if (!(opt & OPT_INETD)) {
+ signal(SIGCHLD, SIG_IGN);
config->server_socket = openServer();
#if ENABLE_FEATURE_HTTPD_SETUID
/* drop privileges */
"" USE_NC_SERVER("lp:") USE_NC_EXTRA("w:i:f:e:") )) > 0
) {
if (ENABLE_NC_SERVER && opt=='l') USE_NC_SERVER(do_listen++);
- else if (ENABLE_NC_SERVER && opt=='p') USE_NC_SERVER(lport = bb_lookup_port(optarg, "tcp", 0));
+ else if (ENABLE_NC_SERVER && opt=='p') {
+ USE_NC_SERVER(lport = bb_lookup_port(optarg, "tcp", 0));
+ USE_NC_SERVER(lport = htons(lport));
+ }
else if (ENABLE_NC_EXTRA && opt=='w') USE_NC_EXTRA( wsecs = xatou(optarg));
else if (ENABLE_NC_EXTRA && opt=='i') USE_NC_EXTRA( delay = xatou(optarg));
else if (ENABLE_NC_EXTRA && opt=='f') USE_NC_EXTRA( cfd = xopen(optarg, O_RDWR));
address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list;
address.sin_port = bb_lookup_port(argv[1], "tcp", 0);
+ address.sin_port = htons(address.sin_port);
xconnect(sfd, (struct sockaddr *) &address, sizeof(address));
cfd = sfd;
#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
if (1 & getopt32(argc, argv, "al:", &autologin))
autologin = getenv("USER");
-
- if (optind < argc) {
- host = argv[optind++];
- port = bb_lookup_port((optind < argc) ? argv[optind++] :
- "telnet", "tcp", 23);
- if (optind < argc)
- bb_show_usage();
- } else
- bb_show_usage();
+ argv += optind;
#else
- host = argv[1];
- port = bb_lookup_port((argc > 2) ? argv[2] : "telnet", "tcp", 23);
+ argv++;
#endif
+ if (!*argv)
+ bb_show_usage();
+ host = *argv++;
+ port = bb_lookup_port(*argv ? *argv++ : "telnet", "tcp", 23);
+ if (*argv) /* extra params?? */
+ bb_show_usage();
+
G.netfd = create_and_connect_stream_or_die(host, port);
setsockopt(G.netfd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof one);
#endif
const len_and_sockaddr *peer_lsa,
const char *remotefile, const int localfd,
- const unsigned port, int tftp_bufsize)
+ unsigned port, int tftp_bufsize)
{
struct timeval tv;
fd_set rfds;
char *xbuf = xmalloc(tftp_bufsize += 4);
char *rbuf = xmalloc(tftp_bufsize);
+ port = htons(port);
+
socketfd = xsocket(peer_lsa->sa.sa_family, SOCK_DGRAM, 0);
/* build opcode */
};
static void parse_url(char *url, struct host_info *h);
-static FILE *open_socket(struct sockaddr_in *s_in);
+static FILE *open_socket(len_and_sockaddr *lsa);
static char *gethdr(char *buf, size_t bufsiz, FILE *fp, int *istrunc);
static int ftpcmd(char *s1, char *s2, FILE *fp, char *buf);
{
char buf[512];
struct host_info server, target;
- struct sockaddr_in s_in;
+ len_and_sockaddr *lsa;
int n, status;
int port;
int try = 5;
if (!fname_out) {
// Dirty hack. Needed because bb_get_last_path_component
// will destroy trailing / by storing '\0' in last byte!
- if (*target.path && target.path[strlen(target.path)-1] != '/') {
+ if (!last_char_is(target.path, '/')) {
fname_out =
#if ENABLE_FEATURE_WGET_STATUSBAR
curfile =
/* 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... */
- bb_lookup_host(&s_in, server.host);
- s_in.sin_port = server.port;
+ lsa = host2sockaddr(server.host, server.port);
if (!(opt & WGET_OPT_QUIET)) {
- fprintf(stderr, "Connecting to %s[%s]:%d\n",
- server.host, inet_ntoa(s_in.sin_addr), ntohs(server.port));
+ fprintf(stderr, "Connecting to %s [%s]\n", server.host,
+ xmalloc_sockaddr2dotted(&lsa->sa, lsa->len));
+ /* We leak xmalloc_sockaddr2dotted result */
}
if (use_proxy || !target.is_ftp) {
* Open socket to http server
*/
if (sfp) fclose(sfp);
- sfp = open_socket(&s_in);
+ sfp = open_socket(lsa);
/*
* Send HTTP request.
*/
if (use_proxy) {
- const char *format = "GET %stp://%s:%d/%s HTTP/1.1\r\n";
-#if ENABLE_FEATURE_WGET_IP6_LITERAL
- if (strchr(target.host, ':'))
- format = "GET %stp://[%s]:%d/%s HTTP/1.1\r\n";
-#endif
- fprintf(sfp, format,
+// const char *format = "GET %stp://%s:%d/%s HTTP/1.1\r\n";
+//#if ENABLE_FEATURE_WGET_IP6_LITERAL
+// if (strchr(target.host, ':'))
+// format = "GET %stp://[%s]:%d/%s HTTP/1.1\r\n";
+//#endif
+// fprintf(sfp, format,
+// target.is_ftp ? "f" : "ht", target.host,
+// ntohs(target.port), target.path);
+ fprintf(sfp, "GET %stp://%s/%s HTTP/1.1\r\n",
target.is_ftp ? "f" : "ht", target.host,
- ntohs(target.port), target.path);
+ target.path);
} else {
fprintf(sfp, "GET /%s HTTP/1.1\r\n", target.path);
}
- fprintf(sfp, "Host: %s:%u\r\nUser-Agent: %s\r\n",
- target.host, target.port, user_agent);
+ fprintf(sfp, "Host: %s\r\nUser-Agent: %s\r\n",
+ target.host, user_agent);
#if ENABLE_FEATURE_WGET_AUTHENTICATION
if (target.user) {
server.host = target.host;
server.port = target.port;
}
- bb_lookup_host(&s_in, server.host);
- s_in.sin_port = server.port;
+ free(lsa);
+ lsa = host2sockaddr(server.host, server.port);
break;
}
}
if (!target.user)
target.user = xstrdup("anonymous:busybox@");
- sfp = open_socket(&s_in);
+ sfp = open_socket(lsa);
if (ftpcmd(NULL, NULL, sfp, buf) != 220)
bb_error_msg_and_die("%s", buf+4);
s = strrchr(buf, ',');
if (!s) goto pasv_error;
port += xatou_range(s+1, 0, 255) * 256;
- s_in.sin_port = htons(port);
- dfp = open_socket(&s_in);
+ set_port(lsa, htons(port));
+ dfp = open_socket(lsa);
if (beg_range) {
sprintf(buf, "REST %"OFF_FMT"d", beg_range);
sp = h->host;
-#if ENABLE_FEATURE_WGET_IP6_LITERAL
- if (sp[0] == '[') {
- char *ep;
-
- ep = sp + 1;
- while (*ep == ':' || isxdigit(*ep))
- ep++;
- if (*ep == ']') {
- h->host++;
- *ep = '\0';
- sp = ep + 1;
- }
- }
-#endif
-
- p = strchr(sp, ':');
- if (p != NULL) {
- *p = '\0';
- h->port = htons(xatou16(p + 1));
- }
+//host2sockaddr does this itself
+//#if ENABLE_FEATURE_WGET_IP6_LITERAL
+// if (sp[0] == '[') {
+// char *ep;
+//
+// ep = sp + 1;
+// while (*ep == ':' || isxdigit(*ep))
+// ep++;
+// if (*ep == ']') {
+// h->host++;
+// *ep = '\0';
+// sp = ep + 1;
+// }
+// }
+//#endif
+//
+// p = strchr(sp, ':');
+// if (p != NULL) {
+// *p = '\0';
+// h->port = htons(xatou16(p + 1));
+// }
}
-static FILE *open_socket(struct sockaddr_in *s_in)
+static FILE *open_socket(len_and_sockaddr *lsa)
{
FILE *fp;
/* glibc 2.4 seems to try seeking on it - ??! */
/* hopefully it understands what ESPIPE means... */
- fp = fdopen(xconnect_tcp_v4(s_in), "r+");
+ fp = fdopen(xconnect_stream(lsa), "r+");
if (fp == NULL)
bb_perror_msg_and_die("fdopen");
CONFIG_WGET=y
CONFIG_FEATURE_WGET_STATUSBAR=y
CONFIG_FEATURE_WGET_AUTHENTICATION=y
-CONFIG_FEATURE_WGET_IP6_LITERAL=y
CONFIG_FEATURE_WGET_LONG_OPTIONS=y
CONFIG_ZCIP=y