#include <netinet/in.h>
#include <net/if.h>
+#include <sys/un.h>
#include "libbb.h"
void FAST_FUNC setsockopt_reuseaddr(int fd)
int ai_flags)
{
int rc;
- len_and_sockaddr *r = NULL;
+ len_and_sockaddr *r;
struct addrinfo *result = NULL;
struct addrinfo *used_res;
const char *org_host = host; /* only for error msg */
const char *cp;
struct addrinfo hint;
+ if (ENABLE_FEATURE_UNIX_LOCAL && strncmp(host, "local:", 6) == 0) {
+ struct sockaddr_un *sun;
+
+ r = xzalloc(LSA_LEN_SIZE + sizeof(struct sockaddr_un));
+ r->len = sizeof(struct sockaddr_un);
+ r->u.sa.sa_family = AF_UNIX;
+ sun = (struct sockaddr_un *)&r->u.sa;
+ safe_strncpy(sun->sun_path, host + 6, sizeof(sun->sun_path));
+ return r;
+ }
+
+ r = NULL;
+
/* Ugly parsing of host:addr */
if (ENABLE_FEATURE_IPV6 && host[0] == '[') {
/* Even uglier parsing of [xx]:nn */
}
if (cp) { /* points to ":" or "]:" */
int sz = cp - host + 1;
+
host = safe_strncpy(alloca(sz), host, sz);
if (ENABLE_FEATURE_IPV6 && *cp != ':') {
cp++; /* skip ']' */
int rc;
socklen_t salen;
+ if (ENABLE_FEATURE_UNIX_LOCAL && sa->sa_family == AF_UNIX) {
+ struct sockaddr_un *sun = (struct sockaddr_un *)sa;
+ return xasprintf("local:%.*s",
+ (int) sizeof(sun->sun_path),
+ sun->sun_path);
+ }
+
salen = LSA_SIZEOF_SA;
#if ENABLE_FEATURE_IPV6
if (sa->sa_family == AF_INET)
Enable IPv6 support in busybox.
This adds IPv6 support in the networking applets.
+config FEATURE_UNIX_LOCAL
+ bool "Enable Unix domain socket support"
+ default n
+ help
+ Enable Unix domain socket support in all busybox networking
+ applets.
+
config FEATURE_PREFER_IPV4_ADDRESS
bool "Prefer IPv4 addresses from DNS queries"
default y
IF_NOT_NC_EXTRA (const) unsigned delay = 0;
IF_NOT_NC_EXTRA (const int execparam = 0;)
IF_NC_EXTRA (char **execparam = NULL;)
- len_and_sockaddr *lsa;
fd_set readfds, testfds;
int opt; /* must be signed (getopt returns -1) */
while ((opt = getopt(argc, argv,
"" IF_NC_SERVER("lp:") IF_NC_EXTRA("w:i:f:e:") )) > 0
) {
- if (ENABLE_NC_SERVER && opt=='l')
+ if (ENABLE_NC_SERVER && opt == 'l')
IF_NC_SERVER(do_listen++);
- else if (ENABLE_NC_SERVER && opt=='p')
+ else if (ENABLE_NC_SERVER && opt == 'p')
IF_NC_SERVER(lport = bb_lookup_port(optarg, "tcp", 0));
- else if (ENABLE_NC_EXTRA && opt=='w')
+ else if (ENABLE_NC_EXTRA && opt == 'w')
IF_NC_EXTRA( wsecs = xatou(optarg));
- else if (ENABLE_NC_EXTRA && opt=='i')
+ else if (ENABLE_NC_EXTRA && opt == 'i')
IF_NC_EXTRA( delay = xatou(optarg));
- else if (ENABLE_NC_EXTRA && opt=='f')
+ else if (ENABLE_NC_EXTRA && opt == 'f')
IF_NC_EXTRA( cfd = xopen(optarg, O_RDWR));
- else if (ENABLE_NC_EXTRA && opt=='e' && optind <= argc) {
+ else if (ENABLE_NC_EXTRA && opt == 'e' && optind <= argc) {
/* We cannot just 'break'. We should let getopt finish.
** Or else we won't be able to find where
** 'host' and 'port' params are
argc -= optind;
// -l and -f don't mix
if (do_listen && cfd) bb_show_usage();
- // Listen or file modes need zero arguments, client mode needs 2
- if (do_listen || cfd) {
+ // File mode needs need zero arguments, listen mode needs zero or one,
+ // client mode needs one or two
+ if (cfd) {
if (argc) bb_show_usage();
+ } else if (do_listen) {
+ if (argc > 1) bb_show_usage();
} else {
if (!argc || argc > 2) bb_show_usage();
}
if (!cfd) {
if (do_listen) {
- /* create_and_bind_stream_or_die(NULL, lport)
- * would've work wonderfully, but we need
- * to know lsa */
- sfd = xsocket_stream(&lsa);
- if (lport)
- set_nport(lsa, htons(lport));
- setsockopt_reuseaddr(sfd);
- xbind(sfd, &lsa->u.sa, lsa->len);
+ sfd = create_and_bind_stream_or_die(argv[0], lport);
xlisten(sfd, do_listen); /* can be > 1 */
+#if 0 /* nc-1.10 does not do this (without -v) */
/* If we didn't specify a port number,
* query and print it after listen() */
if (!lport) {
- getsockname(sfd, &lsa->u.sa, &lsa->len);
- lport = get_nport(&lsa->u.sa);
+ len_and_sockaddr lsa;
+ lsa.len = LSA_SIZEOF_SA;
+ getsockname(sfd, &lsa.u.sa, &lsa.len);
+ lport = get_nport(&lsa.u.sa);
fdprintf(2, "%d\n", ntohs(lport));
}
+#endif
close_on_exec_on(sfd);
- free(lsa);
accept_again:
cfd = accept(sfd, NULL, 0);
if (cfd < 0)
socklen_t x = sizeof(optbuf);
rr = getsockopt(netfd, IPPROTO_IP, IP_OPTIONS, optbuf, &x);
- if (rr < 0)
- bb_perror_msg("getsockopt failed");
- else if (x) { /* we've got options, lessee em... */
+ if (rr >= 0 && x) { /* we've got options, lessee em... */
bin2hex(bigbuf_net, optbuf, x);
bigbuf_net[2*x] = '\0';
fprintf(stderr, "IP options: %s\n", bigbuf_net);
mobygrams are kinda fun and exercise the reassembler. */
if (rr <= 0) { /* at end, or fukt, or ... */
FD_CLR(STDIN_FILENO, &ding1); /* disable and close stdin */
- close(0);
+ close(STDIN_FILENO);
+// Does it make sense to shutdown(net_fd, SHUT_WR)
+// to let other side know that we won't write anything anymore?
+// (and what about keeping compat if we do that?)
} else {
rzleft = rr;
zp = bigbuf_in;
setsockopt_reuseaddr(netfd);
if (o_udpmode)
socket_want_pktinfo(netfd);
- xbind(netfd, &ouraddr->u.sa, ouraddr->len);
+ if (!ENABLE_FEATURE_UNIX_LOCAL
+ || o_listen
+ || ouraddr->u.sa.sa_family != AF_UNIX
+ ) {
+ xbind(netfd, &ouraddr->u.sa, ouraddr->len);
+ }
#if 0
setsockopt(netfd, SOL_SOCKET, SO_RCVBUF, &o_rcvbuf, sizeof o_rcvbuf);
setsockopt(netfd, SOL_SOCKET, SO_SNDBUF, &o_sndbuf, sizeof o_sndbuf);