#if ENABLE_FEATURE_IPV6
struct sockaddr_in6 sin6;
#endif
- };
+ } u;
} len_and_sockaddr;
enum {
LSA_SIZEOF_SA = sizeof(
/* linux/loop.h relies on __u64. Make sure we have that as a proper type
* until userspace is widely fixed. */
-#ifndef __GNUC__
-#if defined __INTEL_COMPILER
+#if (defined __INTEL_COMPILER && !defined __GNUC__) || \
+ (defined __GNUC__ && defined __STRICT_ANSI__)
__extension__ typedef __signed__ long long __s64;
__extension__ typedef unsigned long long __u64;
-#endif /* __INTEL_COMPILER */
-#endif /* ifndef __GNUC__ */
+#endif
/*----- Kernel versioning ------------------------------------*/
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
local_port = bb_lookup_port(argv[1], tcp ? "tcp" : "udp", 0);
lsa = xhost2sockaddr(argv[0], local_port);
- sock = xsocket(lsa->sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
+ sock = xsocket(lsa->u.sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
setsockopt_reuseaddr(sock);
sa_len = lsa->len; /* I presume sockaddr len stays the same */
- xbind(sock, &lsa->sa, sa_len);
+ xbind(sock, &lsa->u.sa, sa_len);
if (tcp)
xlisten(sock, backlog);
else /* udp: needed for recv_from_to to work: */
#endif
if (verbose) {
- char *addr = xmalloc_sockaddr2dotted(&lsa->sa);
+ char *addr = xmalloc_sockaddr2dotted(&lsa->u.sa);
printf("%s: info: listening on %s", applet_name, addr);
free(addr);
#ifndef SSLSVD
sig_unblock(SIGCHLD);
if (tcp) {
remote.len = sa_len;
- conn = accept(sock, &remote.sa, &remote.len);
+ conn = accept(sock, &remote.u.sa, &remote.len);
} else {
/* In case recv_from_to won't be able to recover local addr.
* Also sets port - recv_from_to is unable to do it. */
local = *lsa;
- conn = recv_from_to(sock, NULL, 0, MSG_PEEK, &remote.sa, &local.sa, sa_len);
+ conn = recv_from_to(sock, NULL, 0, MSG_PEEK, &remote.u.sa, &local.u.sa, sa_len);
}
sig_block(SIGCHLD);
if (conn < 0) {
if (max_per_host) {
/* Drop connection immediately if cur_per_host > max_per_host
* (minimizing load under SYN flood) */
- remote_ip = xmalloc_sockaddr2dotted_noport(&remote.sa);
+ remote_ip = xmalloc_sockaddr2dotted_noport(&remote.u.sa);
cur_per_host = ipsvd_perhost_add(remote_ip, max_per_host, &hccp);
if (cur_per_host > max_per_host) {
/* ipsvd_perhost_add detected that max is exceeded
/* Make plain write/send work for this socket by supplying default
* destination address. This also restricts incoming packets
* to ones coming from this remote IP. */
- xconnect(0, &remote.sa, sa_len);
+ xconnect(0, &remote.u.sa, sa_len);
/* hole? at this point we have no wildcard udp socket...
* can this cause clients to get "port unreachable" icmp?
* Yup, time window is very small, but it exists (is it?) */
/* Open new non-connected UDP socket for further clients */
- sock = xsocket(lsa->sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
+ sock = xsocket(lsa->u.sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
setsockopt_reuseaddr(sock);
- xbind(sock, &lsa->sa, sa_len);
+ xbind(sock, &lsa->u.sa, sa_len);
socket_want_pktinfo(sock);
/* Doesn't work:
* instead - it will "intercept" all following packets, but child
* does not expect data coming *from fd #1*! */
#if 0
- /* Make it so that local addr is fixed to localp->sa
+ /* Make it so that local addr is fixed to localp->u.sa
* and we don't accidentally accept packets to other local IPs. */
/* NB: we possibly bind to the _very_ same_ address & port as the one
* already bound in parent! This seems to work in Linux.
* (otherwise we can move socket to fd #0 only if bind succeeds) */
close(0);
set_nport(localp, htons(local_port));
- xmove_fd(xsocket(localp->sa.sa_family, SOCK_DGRAM, 0), 0);
+ xmove_fd(xsocket(localp->u.sa.sa_family, SOCK_DGRAM, 0), 0);
setsockopt_reuseaddr(0); /* crucial */
- xbind(0, &localp->sa, localp->len);
+ xbind(0, &localp->u.sa, localp->len);
#endif
}
close(sock);
if (need_remote_ip)
- remote_addr = xmalloc_sockaddr2dotted(&remote.sa);
+ remote_addr = xmalloc_sockaddr2dotted(&remote.u.sa);
if (need_hostnames) {
if (option_mask32 & OPT_h) {
- remote_hostname = xmalloc_sockaddr2host_noport(&remote.sa);
+ remote_hostname = xmalloc_sockaddr2host_noport(&remote.u.sa);
if (!remote_hostname) {
bb_error_msg("warning: cannot look up hostname for %s", remote_addr);
remote_hostname = (char*)"";
* which doesn't know local IP). */
if (tcp) {
local.len = sa_len;
- getsockname(0, &local.sa, &local.len);
+ getsockname(0, &local.u.sa, &local.len);
}
- local_addr = xmalloc_sockaddr2dotted(&local.sa);
+ local_addr = xmalloc_sockaddr2dotted(&local.u.sa);
if (!local_hostname) {
- local_hostname = xmalloc_sockaddr2host_noport(&local.sa);
+ local_hostname = xmalloc_sockaddr2host_noport(&local.u.sa);
if (!local_hostname)
bb_error_msg_and_die("warning: cannot look up hostname for %s"+9, local_addr);
}
* from Linux firewall. Useful when you redirect
* an outbond connection to local handler, and it needs
* to know where it originally tried to connect */
- if (tcp && getsockopt(0, SOL_IP, SO_ORIGINAL_DST, &lsa->sa, &lsa->len) == 0) {
- char *addr = xmalloc_sockaddr2dotted(&lsa->sa);
+ if (tcp && getsockopt(0, SOL_IP, SO_ORIGINAL_DST, &lsa->u.sa, &lsa->len) == 0) {
+ char *addr = xmalloc_sockaddr2dotted(&lsa->u.sa);
xsetenv("TCPORIGDSTADDR", addr);
free(addr);
}
void set_nport(len_and_sockaddr *lsa, unsigned port)
{
#if ENABLE_FEATURE_IPV6
- if (lsa->sa.sa_family == AF_INET6) {
- lsa->sin6.sin6_port = port;
+ if (lsa->u.sa.sa_family == AF_INET6) {
+ lsa->u.sin6.sin6_port = port;
return;
}
#endif
- if (lsa->sa.sa_family == AF_INET) {
- lsa->sin.sin_port = port;
+ if (lsa->u.sa.sa_family == AF_INET) {
+ lsa->u.sin.sin_port = port;
return;
}
/* What? UNIX socket? IPX?? :) */
}
}
#endif
- r = xmalloc(offsetof(len_and_sockaddr, sa) + used_res->ai_addrlen);
+ r = xmalloc(offsetof(len_and_sockaddr, u.sa) + used_res->ai_addrlen);
r->len = used_res->ai_addrlen;
- memcpy(&r->sa, used_res->ai_addr, used_res->ai_addrlen);
+ memcpy(&r->u.sa, used_res->ai_addr, used_res->ai_addrlen);
set_nport(r, htons(port));
ret:
freeaddrinfo(result);
len = sizeof(struct sockaddr_in6);
}
#endif
- lsa = xzalloc(offsetof(len_and_sockaddr, sa) + len);
+ lsa = xzalloc(offsetof(len_and_sockaddr, u.sa) + len);
lsa->len = len;
- lsa->sa.sa_family = family;
+ lsa->u.sa.sa_family = family;
*lsap = lsa;
return fd;
}
if (bindaddr && bindaddr[0]) {
lsa = xdotted2sockaddr(bindaddr, port);
/* user specified bind addr dictates family */
- fd = xsocket(lsa->sa.sa_family, sock_type, 0);
+ fd = xsocket(lsa->u.sa.sa_family, sock_type, 0);
} else {
fd = xsocket_type(&lsa, USE_FEATURE_IPV6(AF_UNSPEC,) sock_type);
set_nport(lsa, htons(port));
}
setsockopt_reuseaddr(fd);
- xbind(fd, &lsa->sa, lsa->len);
+ xbind(fd, &lsa->u.sa, lsa->len);
free(lsa);
return fd;
}
len_and_sockaddr *lsa;
lsa = xhost2sockaddr(peer, port);
- fd = xsocket(lsa->sa.sa_family, SOCK_STREAM, 0);
+ fd = xsocket(lsa->u.sa.sa_family, SOCK_STREAM, 0);
setsockopt_reuseaddr(fd);
- xconnect(fd, &lsa->sa, lsa->len);
+ xconnect(fd, &lsa->u.sa, lsa->len);
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);
+ int fd = xsocket(lsa->u.sa.sa_family, SOCK_STREAM, 0);
+ xconnect(fd, &lsa->u.sa, lsa->len);
return fd;
}
/* if (!inet_aton(target, &dst)) - not needed */ {
len_and_sockaddr *lsa;
lsa = xhost_and_af2sockaddr(target, 0, AF_INET);
- memcpy(&dst, &lsa->sin.sin_addr.s_addr, 4);
+ memcpy(&dst, &lsa->u.sin.sin_addr.s_addr, 4);
if (ENABLE_FEATURE_CLEAN_UP)
free(lsa);
}
#endif
lsa = xdotted2sockaddr(listen_interface, port);
- udps = xsocket(lsa->sa.sa_family, SOCK_DGRAM, 0);
- xbind(udps, &lsa->sa, lsa->len);
+ udps = xsocket(lsa->u.sa.sa_family, SOCK_DGRAM, 0);
+ xbind(udps, &lsa->u.sa, lsa->len);
/* xlisten(udps, 50); - ?!! DGRAM sockets are never listened on I think? */
bb_info_msg("Accepting UDP packets on %s",
- xmalloc_sockaddr2dotted(&lsa->sa));
+ xmalloc_sockaddr2dotted(&lsa->u.sa));
while (1) {
int r;
// Or else we can exhibit usual UDP ugliness:
// [ip1.multihomed.ip2] <= query to ip1 <= peer
// [ip1.multihomed.ip2] => reply from ip2 => peer (confused)
- r = recvfrom(udps, buf, sizeof(buf), 0, &lsa->sa, &fromlen);
+ r = recvfrom(udps, buf, sizeof(buf), 0, &lsa->u.sa, &fromlen);
if (OPT_verbose)
bb_info_msg("Got UDP packet");
if (r < 12 || r > 512) {
r = process_packet(buf);
if (r <= 0)
continue;
- sendto(udps, buf, r, 0, &lsa->sa, fromlen);
+ sendto(udps, buf, r, 0, &lsa->u.sa, fromlen);
}
return 0;
}
server->lsa = xhost2sockaddr(argv[0], bb_lookup_port(port, "tcp", 21));
if (verbose_flag) {
printf("Connecting to %s (%s)\n", argv[0],
- xmalloc_sockaddr2dotted(&server->lsa->sa));
+ xmalloc_sockaddr2dotted(&server->lsa->u.sa));
}
/* Connect/Setup/Configure the FTP session */
iobuf = xmalloc(IOBUF_SIZE);
rmt_ip = 0;
- if (fromAddr->sa.sa_family == AF_INET) {
- rmt_ip = ntohl(fromAddr->sin.sin_addr.s_addr);
+ if (fromAddr->u.sa.sa_family == AF_INET) {
+ rmt_ip = ntohl(fromAddr->u.sin.sin_addr.s_addr);
}
#if ENABLE_FEATURE_IPV6
- if (fromAddr->sa.sa_family == AF_INET6
- && fromAddr->sin6.sin6_addr.s6_addr32[0] == 0
- && fromAddr->sin6.sin6_addr.s6_addr32[1] == 0
- && ntohl(fromAddr->sin6.sin6_addr.s6_addr32[2]) == 0xffff)
- rmt_ip = ntohl(fromAddr->sin6.sin6_addr.s6_addr32[3]);
+ if (fromAddr->u.sa.sa_family == AF_INET6
+ && fromAddr->u.sin6.sin6_addr.s6_addr32[0] == 0
+ && fromAddr->u.sin6.sin6_addr.s6_addr32[1] == 0
+ && ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[2]) == 0xffff)
+ rmt_ip = ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[3]);
#endif
if (ENABLE_FEATURE_HTTPD_CGI || DEBUG || verbose) {
- rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr->sa);
+ rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr->u.sa);
}
if (verbose) {
/* this trick makes -v logging much simpler */
lsa = host2sockaddr(proxy_entry->host_port, 80);
if (lsa == NULL)
send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);
- if (connect(proxy_fd, &lsa->sa, lsa->len) < 0)
+ if (connect(proxy_fd, &lsa->u.sa, lsa->len) < 0)
send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);
fdprintf(proxy_fd, "%s %s%s%s%s HTTP/%c.%c\r\n",
prequest, /* GET or POST */
/* Wait for connections... */
fromAddr.len = LSA_SIZEOF_SA;
- n = accept(server_socket, &fromAddr.sa, &fromAddr.len);
+ n = accept(server_socket, &fromAddr.u.sa, &fromAddr.len);
if (n < 0)
continue;
len_and_sockaddr fromAddr;
fromAddr.len = LSA_SIZEOF_SA;
- getpeername(0, &fromAddr.sa, &fromAddr.len);
+ getpeername(0, &fromAddr.u.sa, &fromAddr.len);
handle_incoming_and_exit(&fromAddr);
}
continue; /* compat stuff */
lsa = xhost2sockaddr(host, 0);
#if ENABLE_FEATURE_IPV6
- if (lsa->sa.sa_family == AF_INET6) {
+ if (lsa->u.sa.sa_family == AF_INET6) {
int sockfd6;
struct in6_ifreq ifr6;
memcpy((char *) &ifr6.ifr6_addr,
- (char *) &(lsa->sin6.sin6_addr),
+ (char *) &(lsa->u.sin6.sin6_addr),
sizeof(struct in6_addr));
/* Create a channel to the NET kernel. */
continue;
}
#endif
- sai.sin_addr = lsa->sin.sin_addr;
+ sai.sin_addr = lsa->u.sin.sin_addr;
if (ENABLE_FEATURE_CLEAN_UP)
free(lsa);
}
if (lport)
set_nport(lsa, htons(lport));
setsockopt_reuseaddr(sfd);
- xbind(sfd, &lsa->sa, lsa->len);
+ xbind(sfd, &lsa->u.sa, lsa->len);
xlisten(sfd, do_listen); /* can be > 1 */
/* If we didn't specify a port number,
* query and print it after listen() */
if (!lport) {
socklen_t addrlen = lsa->len;
- getsockname(sfd, &lsa->sa, &addrlen);
- lport = get_nport(&lsa->sa);
+ getsockname(sfd, &lsa->u.sa, &addrlen);
+ lport = get_nport(&lsa->u.sa);
fdprintf(2, "%d\n", ntohs(lport));
}
close_on_exec_on(sfd);
alarm(5); /* give the host 5000ms to respond */
#if ENABLE_PING6
- if (lsa->sa.sa_family == AF_INET6)
+ if (lsa->u.sa.sa_family == AF_INET6)
ping6(lsa);
else
#endif
int sockopt;
pingsock = create_icmp_socket();
- pingaddr.sin = lsa->sin;
+ pingaddr.sin = lsa->u.sin;
if (source_lsa) {
if (setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_IF,
- &source_lsa->sa, source_lsa->len))
+ &source_lsa->u.sa, source_lsa->len))
bb_error_msg_and_die("can't set multicast source interface");
- xbind(pingsock, &source_lsa->sa, source_lsa->len);
+ xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
}
if (opt_I)
setsockopt(pingsock, SOL_SOCKET, SO_BINDTODEVICE, opt_I, strlen(opt_I) + 1);
char control_buf[CMSG_SPACE(36)];
pingsock = create_icmp6_socket();
- pingaddr.sin6 = lsa->sin6;
+ pingaddr.sin6 = lsa->u.sin6;
/* untested whether "-I addr" really works for IPv6: */
if (source_lsa)
- xbind(pingsock, &source_lsa->sa, source_lsa->len);
+ xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
if (opt_I)
setsockopt(pingsock, SOL_SOCKET, SO_BINDTODEVICE, opt_I, strlen(opt_I) + 1);
printf("PING %s (%s)", hostname, dotted);
if (source_lsa) {
printf(" from %s",
- xmalloc_sockaddr2dotted_noport(&source_lsa->sa));
+ xmalloc_sockaddr2dotted_noport(&source_lsa->u.sa));
}
printf(": %d data bytes\n", datalen);
#if ENABLE_PING6
- if (lsa->sa.sa_family == AF_INET6)
+ if (lsa->u.sa.sa_family == AF_INET6)
ping6(lsa);
else
#endif
lsa = xhost_and_af2sockaddr(hostname, 0, AF_INET);
#endif
- if (source_lsa && source_lsa->sa.sa_family != lsa->sa.sa_family)
+ if (source_lsa && source_lsa->u.sa.sa_family != lsa->u.sa.sa_family)
/* leaking it here... */
source_lsa = NULL;
- dotted = xmalloc_sockaddr2dotted_noport(&lsa->sa);
+ dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
ping(lsa);
pingstats(0);
return EXIT_SUCCESS;
/* The SOCK_STREAM socket type is implemented on the TCP/IP protocol. */
set_nport(lsap, htons(port));
- s = xsocket(lsap->sa.sa_family, SOCK_STREAM, 0);
+ s = xsocket(lsap->u.sa.sa_family, SOCK_STREAM, 0);
/* We need unblocking socket so we don't need to wait for ETIMEOUT. */
/* Nonblocking connect typically "fails" with errno == EINPROGRESS */
ndelay_on(s);
DMSG("connect to port %u", port);
start = MONOTONIC_US();
- if (connect(s, &lsap->sa, lsap->len) == 0) {
+ if (connect(s, &lsap->u.sa, lsap->len) == 0) {
/* Unlikely, for me even localhost fails :) */
DMSG("connect succeeded");
goto open;
char *cp;
unsigned org_port;
- len_and_sockaddr *const from = alloca(offsetof(len_and_sockaddr, sa) + peer_lsa->len);
+ len_and_sockaddr *const from = alloca(offsetof(len_and_sockaddr, u.sa) + peer_lsa->len);
/* Can't use RESERVE_CONFIG_BUFFER here since the allocation
* size varies meaning BUFFERS_GO_ON_STACK would fail */
port = org_port = htons(port);
- socketfd = xsocket(peer_lsa->sa.sa_family, SOCK_DGRAM, 0);
+ socketfd = xsocket(peer_lsa->u.sa.sa_family, SOCK_DGRAM, 0);
/* build opcode */
opcode = TFTP_WRQ;
fprintf(stderr, "%02x ", (unsigned char) *cp);
fprintf(stderr, "\n");
#endif
- xsendto(socketfd, xbuf, send_len, &peer_lsa->sa, peer_lsa->len);
+ xsendto(socketfd, xbuf, send_len, &peer_lsa->u.sa, peer_lsa->len);
/* Was it final ACK? then exit */
if (finished && (opcode == TFTP_ACK))
goto ret;
unsigned from_port;
case 1:
from->len = peer_lsa->len;
- memset(&from->sa, 0, peer_lsa->len);
+ memset(&from->u.sa, 0, peer_lsa->len);
len = recvfrom(socketfd, rbuf, tftp_bufsize, 0,
- &from->sa, &from->len);
+ &from->u.sa, &from->len);
if (len < 0) {
bb_perror_msg("recvfrom");
goto ret;
}
- from_port = get_nport(&from->sa);
+ from_port = get_nport(&from->u.sa);
if (port == org_port) {
/* Our first query went to port 69
* but reply will come from different one.
/*static const uint16_t error_8[2] = { htons(TFTP_ERROR), htons(8) };*/
/* thus we open-code big-endian layout */
static const uint8_t error_8[4] = { 0,TFTP_ERROR, 0,8 };
- xsendto(socketfd, error_8, 4, &peer_lsa->sa, peer_lsa->len);
+ xsendto(socketfd, error_8, 4, &peer_lsa->u.sa, peer_lsa->len);
bb_error_msg("server proposes bad blksize %d, exiting", blksize);
goto ret;
}
#if ENABLE_DEBUG_TFTP
fprintf(stderr, "using server '%s', remotefile '%s', localfile '%s'\n",
- xmalloc_sockaddr2dotted(&peer_lsa->sa),
+ xmalloc_sockaddr2dotted(&peer_lsa->u.sa),
remotefile, localfile);
#endif
lsa = host_and_af2sockaddr(line, 0, AF_INET);
if (!lsa)
return 0;
- *(uint32_t*)arg = lsa->sin.sin_addr.s_addr;
+ *(uint32_t*)arg = lsa->u.sin.sin_addr.s_addr;
free(lsa);
return 1;
}
lsa = xhost2sockaddr(server.host, server.port);
if (!(opt & WGET_OPT_QUIET)) {
fprintf(stderr, "Connecting to %s (%s)\n", server.host,
- xmalloc_sockaddr2dotted(&lsa->sa));
+ xmalloc_sockaddr2dotted(&lsa->u.sa));
/* We leak result of xmalloc_sockaddr2dotted */
}
/* 9 */ char *anon;
/* 10 */ char *map;
/* 11 */ char *slab;
- };
+ } u;
char *str[11];
} Z;
-#define total Z.total
-#define mfree Z.mfree
-#define buf Z.buf
-#define cache Z.cache
-#define swaptotal Z.swaptotal
-#define swapfree Z.swapfree
-#define dirty Z.dirty
-#define mwrite Z.mwrite
-#define anon Z.anon
-#define map Z.map
-#define slab Z.slab
+#define total Z.u.total
+#define mfree Z.u.mfree
+#define buf Z.u.buf
+#define cache Z.u.cache
+#define swaptotal Z.u.swaptotal
+#define swapfree Z.u.swapfree
+#define dirty Z.u.dirty
+#define mwrite Z.u.mwrite
+#define anon Z.u.anon
+#define map Z.u.map
+#define slab Z.u.slab
#define str Z.str
memset(&Z, 0, sizeof(Z));
if (!G.remoteAddr)
return -1;
}
- return socket(G.remoteAddr->sa.sa_family, SOCK_DGRAM, 0);
+ return socket(G.remoteAddr->u.sa.sa_family, SOCK_DGRAM, 0);
}
#endif
}
/* send message to remote logger, ignore possible error */
sendto(G.remoteFD, G.recvbuf, sz, MSG_DONTWAIT,
- &G.remoteAddr->sa, G.remoteAddr->len);
+ &G.remoteAddr->u.sa, G.remoteAddr->len);
no_luck: ;
}
#endif
// insert ip=... option into string flags.
- dotted = xmalloc_sockaddr2dotted_noport(&lsa->sa);
+ dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
ip = xasprintf("ip=%s", dotted);
parse_mount_options(ip, &filteropts);