From vda at busybox.net Sun Apr 1 02:39:03 2007 From: vda at busybox.net (vda at busybox.net) Date: Sun, 1 Apr 2007 02:39:03 -0700 (PDT) Subject: svn commit: trunk/busybox: editors include ipsvd networking/udhcp Message-ID: <20070401093903.F19044800F@busybox.net> Author: vda Date: 2007-04-01 02:39:03 -0700 (Sun, 01 Apr 2007) New Revision: 18295 Log: Copyright, help text, whitespace cleanups Modified: trunk/busybox/editors/vi.c trunk/busybox/include/usage.h trunk/busybox/ipsvd/tcpsvd.c trunk/busybox/networking/udhcp/dumpleases.c Changeset: Modified: trunk/busybox/editors/vi.c =================================================================== --- trunk/busybox/editors/vi.c 2007-04-01 01:18:20 UTC (rev 18294) +++ trunk/busybox/editors/vi.c 2007-04-01 09:39:03 UTC (rev 18295) @@ -976,7 +976,7 @@ } #if ENABLE_FEATURE_VI_SETOPTS argp = args; - while (*argp) { + while (*argp) { if (strncasecmp(argp, "no", 2) == 0) i = 2; // ":set noautoindent" setops(argp, "autoindent ", i, "ai", VI_AUTOINDENT); Modified: trunk/busybox/include/usage.h =================================================================== --- trunk/busybox/include/usage.h 2007-04-01 01:18:20 UTC (rev 18294) +++ trunk/busybox/include/usage.h 2007-04-01 09:39:03 UTC (rev 18295) @@ -3326,9 +3326,27 @@ "1\n" #define tcpsvd_trivial_usage \ - "TODO" + "[-hpEvv] [-c n] [-C n:msg] [-b n] [-u user] [-l name] ip port prog..." +/* with not-implemented options: */ +/* "[-hpEvv] [-c n] [-C n:msg] [-b n] [-u user] [-l name] [-i dir|-x cdb] [ -t sec] ip port prog..." */ #define tcpsvd_full_usage \ - "TODO" + "tcpsvd creates TCP/IP socket, binds it to host:port\n" \ + "and listens on in for incoming connections. For each connection\n" \ + "it runs prog" \ + "\n" \ + "\nip IP to listen on. '0' = 'all'" \ + "\nport Port to listen on" \ + "\nprog [arg] Program to run for each connection" \ + "\n-l name Local hostname (else looks up local hostname in DNS)" \ + "\n-u user[:group] Change to user/group after bind" \ + "\n-c n Handle up to n connections simultaneously" \ + "\n-C n[:msg] Allow only up to n connections from the same IP" \ + "\n New connections from this IP address are closed" \ + "\n immediately. 'msg' is written to the peer before close" \ + "\n-h Look up peer's hostname in DNS" \ + "\n-b n Allow a backlog of approximately n TCP SYNs" \ + "\n-E Do not set up TCP-related environment variables" \ + "\n-v Verbose" #define tftp_trivial_usage \ "[OPTION]... HOST [PORT]" Modified: trunk/busybox/ipsvd/tcpsvd.c =================================================================== --- trunk/busybox/ipsvd/tcpsvd.c 2007-04-01 01:18:20 UTC (rev 18294) +++ trunk/busybox/ipsvd/tcpsvd.c 2007-04-01 09:39:03 UTC (rev 18295) @@ -1,16 +1,21 @@ -/* -# /usr/bin/tcpsvd -v 0 1234 true -tcpsvd: info: pid 24916 from 127.0.0.1 -tcpsvd: info: start 24916 localhost:127.0.0.1 ::127.0.0.1:47905 -tcpsvd: info: pid 24918 from 127.0.0.1 -tcpsvd: info: start 24918 localhost:127.0.0.1 ::127.0.0.1:47906 -# ./busybox tcpsvd -v 0 1234 true -tcpsvd: info: pid 24924 from 127.0.0.1 -tcpsvd: info: start 24924 localhost:1234:127.0.0.1:1234 ::127.0.0.1:47908 -tcpsvd: info: pid 24926 from 127.0.0.1 -tcpsvd: info: start 24926 localhost:1234:127.0.0.1:1234 ::127.0.0.1:47909 -*/ +/* Based on ipsvd utilities written by Gerrit Pape + * which are released into public domain by the author. + * Homepage: http://smarden.sunsite.dk/ipsvd/ + * + * Copyright (C) 2007 by Denis Vlasenko. + * + * Licensed under GPLv2, see file LICENSE in this tarball for details. + */ +/* Based on ipsvd ipsvd-0.12.1. This tcpsvd accepts all options + * which are supported by one from ipsvd-0.12.1, but not all are + * functional. See help text at the end of this file for details. + * + * Code inside "#ifdef SSLSVD" is for sslsvd and is currently unused. + * Code inside #if 0" is parts of original tcpsvd which are not implemented + * for busyboxed version. + */ + #include "busybox.h" #include "ipsvd_perhost.h" @@ -297,15 +302,15 @@ if (!max_per_host) remote_ip = xmalloc_sockaddr2dotted_noport(&sock_adr.sa, sizeof(sock_adr)); /* else it is already done */ - + remote_port = get_nport(&sock_adr.sa); remote_port = ntohs(remote_port); - + if (verbose) { pid = getpid(); printf("%s: info: pid %d from %s\n", applet_name, pid, remote_ip); } - + if (need_addresses && (option_mask32 & OPT_h)) { remote_hostname = xmalloc_sockaddr2host(&sock_adr.sa, sizeof(sock_adr)); if (!remote_hostname) { @@ -313,7 +318,7 @@ remote_hostname = (char*)""; } } - + sockadr_size = sizeof(sock_adr); /* Errors ignored (I'm not paranoid enough to imagine kernel * which doesn't know local ip) */ @@ -329,7 +334,7 @@ bb_error_msg_and_die("cannot look up local hostname for %s", local_ip); } } - + if (!(option_mask32 & OPT_E)) { /* setup ucspi env */ xsetenv("PROTO", "TCP"); @@ -346,7 +351,7 @@ if (cur_per_host > 0) xsetenv("TCPCONCURRENCY", utoa(cur_per_host)); } - + #if 0 if (instructs) { ac = ipsvd_check(iscdb, &inst, &match, (char*)instructs, @@ -356,11 +361,11 @@ } else ac = IPSVD_DEFAULT; #endif - + if (max_per_host && verbose) printf("%s: info: concurrency %u %s %u/%u\n", applet_name, pid, remote_ip, cur_per_host, max_per_host); - + if (verbose) { printf("%s: info: start %u %s:%s :%s:%s:%u\n", applet_name, pid, @@ -445,6 +450,8 @@ host either is a hostname, or a dotted-decimal IP address, or 0. If host is 0, tcpsvd accepts connections to any local IP address. + * busybox accepts IPv6 addresses and host:port pairs too + In this case second parameter is ignored port tcpsvd accepts connections to host:port. port may be a name from /etc/services or a number. @@ -453,14 +460,16 @@ tcpsvd normally runs prog, with file descriptor 0 reading from the network, and file descriptor 1 writing to the network. By default it also sets up TCP-related environment variables, - see tcp-environ(5) + see tcp-environ(5) -i dir read instructions for handling new connections from the instructions - directory dir. See ipsvd-instruct(5) for details. + directory dir. See ipsvd-instruct(5) for details. + * ignored by busyboxed version -x cdb read instructions for handling new connections from the constant database cdb. The constant database normally is created from an instructions - directory by running ipsvd-cdb(8). + directory by running ipsvd-cdb(8). + * ignored by busyboxed version -t sec timeout. This option only takes effect if the -i option is given. While checking the instructions directory, check the time of last access @@ -468,47 +477,50 @@ and remove the file if it wasn't accessed within the last sec seconds; tcpsvd does not discard or remove a file if the user's write permission is not set, for those files the timeout is disabled. Default is 0, - which means that the timeout is disabled. + which means that the timeout is disabled. + * ignored by busyboxed version -l name local hostname. Do not look up the local hostname in DNS, but use name as hostname. This option must be set if tcpsvd listens on port 53 - to avoid loops. + to avoid loops. -u user[:group] drop permissions. Switch user ID to user's UID, and group ID to user's primary GID after creating and binding to the socket. If user is followed by a colon and a group name, the group ID is switched to the GID of group - instead. All supplementary groups are removed. + instead. All supplementary groups are removed. -c n concurrency. Handle up to n connections simultaneously. Default is 30. If there are n connections active, tcpsvd defers acceptance of a new - connection until an active connection is closed. + connection until an active connection is closed. -C n[:msg] per host concurrency. Allow only up to n connections from the same IP - address simultaneously. If there are n active connections from one IP + address simultaneously. If there are n active connections from one IP address, new incoming connections from this IP address are closed - immediately. If n is followed by :msg, the message msg is written + immediately. If n is followed by :msg, the message msg is written to the client if possible, before closing the connection. By default msg is empty. See ipsvd-instruct(5) for supported escape sequences in msg. For each accepted connection, the current per host concurrency is available through the environment variable TCPCONCURRENCY. n and msg can be overwritten by ipsvd(7) instructions, see ipsvd-instruct(5). - By default tcpsvd doesn't keep track of connections. + By default tcpsvd doesn't keep track of connections. -h - Look up the client's hostname in DNS. + Look up the client's hostname in DNS. -p paranoid. After looking up the client's hostname in DNS, look up the IP addresses in DNS for that hostname, and forget about the hostname if none of the addresses match the client's IP address. You should set this option if you use hostname based instructions. The -p option - implies the -h option. + implies the -h option. + * ignored by busyboxed version -b n backlog. Allow a backlog of approximately n TCP SYNs. On some systems n - is silently limited. Default is 20. + is silently limited. Default is 20. -E - no special environment. Do not set up TCP-related environment variables. + no special environment. Do not set up TCP-related environment variables. -v - verbose. Print verbose messsages to standard output. + verbose. Print verbose messsages to standard output. -vv - more verbose. Print more verbose messages to standard output. + more verbose. Print more verbose messages to standard output. + * no difference between -v and -vv in busyboxed version */ Modified: trunk/busybox/networking/udhcp/dumpleases.c =================================================================== --- trunk/busybox/networking/udhcp/dumpleases.c 2007-04-01 01:18:20 UTC (rev 18294) +++ trunk/busybox/networking/udhcp/dumpleases.c 2007-04-01 09:39:03 UTC (rev 18295) @@ -23,14 +23,14 @@ OPT_r = 0x2, // -r OPT_f = 0x4, // -f }; -#if ENABLE_GETOPT_LONG +#if ENABLE_GETOPT_LONG static const struct option options[] = { { "absolute", no_argument, 0, 'a' }, { "remaining", no_argument, 0, 'r' }, { "file", required_argument, 0, 'f' }, { NULL, 0, 0, 0 } }; - + applet_long_options = options; #endif opt_complementary = "=0:?:a--r:r--a"; From vda at busybox.net Sun Apr 1 03:59:34 2007 From: vda at busybox.net (vda at busybox.net) Date: Sun, 1 Apr 2007 03:59:34 -0700 (PDT) Subject: svn commit: trunk/busybox/ipsvd Message-ID: <20070401105934.F39864800D@busybox.net> Author: vda Date: 2007-04-01 03:59:33 -0700 (Sun, 01 Apr 2007) New Revision: 18296 Log: tcpsvd: fix line buffering, add firewall query code Modified: trunk/busybox/ipsvd/ipsvd_perhost.c trunk/busybox/ipsvd/ipsvd_perhost.h trunk/busybox/ipsvd/tcpsvd.c Changeset: Modified: trunk/busybox/ipsvd/ipsvd_perhost.c =================================================================== --- trunk/busybox/ipsvd/ipsvd_perhost.c 2007-04-01 09:39:03 UTC (rev 18295) +++ trunk/busybox/ipsvd/ipsvd_perhost.c 2007-04-01 10:59:33 UTC (rev 18296) @@ -1,3 +1,12 @@ +/* Based on ipsvd utilities written by Gerrit Pape + * which are released into public domain by the author. + * Homepage: http://smarden.sunsite.dk/ipsvd/ + * + * Copyright (C) 2007 Denis Vlasenko. + * + * Licensed under GPLv2, see file LICENSE in this tarball for details. + */ + #include "busybox.h" #include "ipsvd_perhost.h" Modified: trunk/busybox/ipsvd/ipsvd_perhost.h =================================================================== --- trunk/busybox/ipsvd/ipsvd_perhost.h 2007-04-01 09:39:03 UTC (rev 18295) +++ trunk/busybox/ipsvd/ipsvd_perhost.h 2007-04-01 10:59:33 UTC (rev 18296) @@ -1,3 +1,12 @@ +/* Based on ipsvd utilities written by Gerrit Pape + * which are released into public domain by the author. + * Homepage: http://smarden.sunsite.dk/ipsvd/ + * + * Copyright (C) 2007 Denis Vlasenko. + * + * Licensed under GPLv2, see file LICENSE in this tarball for details. + */ + struct hcc { char ip[32 - sizeof(int)]; int pid; Modified: trunk/busybox/ipsvd/tcpsvd.c =================================================================== --- trunk/busybox/ipsvd/tcpsvd.c 2007-04-01 09:39:03 UTC (rev 18295) +++ trunk/busybox/ipsvd/tcpsvd.c 2007-04-01 10:59:33 UTC (rev 18296) @@ -2,7 +2,7 @@ * which are released into public domain by the author. * Homepage: http://smarden.sunsite.dk/ipsvd/ * - * Copyright (C) 2007 by Denis Vlasenko. + * Copyright (C) 2007 Denis Vlasenko. * * Licensed under GPLv2, see file LICENSE in this tarball for details. */ @@ -14,8 +14,17 @@ * Code inside "#ifdef SSLSVD" is for sslsvd and is currently unused. * Code inside #if 0" is parts of original tcpsvd which are not implemented * for busyboxed version. + * + * Output of verbose mode matches original (modulo bugs and + * unimplemented stuff). Unnatural splitting of IP and PORT + * is retained (personally I prefer one-value "IP:PORT" notation - + * it is a natural string representation of struct sockaddr_XX). + * + * TCPORIGDST{IP,PORT} is busybox-specific addition */ +#include +#include /* wants */ #include "busybox.h" #include "ipsvd_perhost.h" @@ -46,7 +55,7 @@ OPT_t = (1 << 10), OPT_v = (1 << 11), OPT_V = (1 << 12), - OPT_U = (1 << 13), + OPT_U = (1 << 13), /* from here: sslsvd only */ OPT_slash = (1 << 14), OPT_Z = (1 << 15), OPT_K = (1 << 16), @@ -104,7 +113,7 @@ const char *instructs; char *msg_per_host = NULL; unsigned len_per_host = len_per_host; /* gcc */ - int need_addresses; + int need_hostnames, need_remote_ip; int pid; int sock; int conn; @@ -171,7 +180,9 @@ if (!argv[0][0] || LONE_CHAR(argv[0], '0')) argv[0] = (char*)"0.0.0.0"; - need_addresses = verbose || !(option_mask32 & OPT_E); + setlinebuf(stdout); + need_hostnames = verbose || !(option_mask32 & OPT_E); + need_remote_ip = max_per_host || need_hostnames; #ifdef SSLSVD sslser = user; @@ -299,7 +310,7 @@ close(sock); - if (!max_per_host) + if (!max_per_host && need_remote_ip) remote_ip = xmalloc_sockaddr2dotted_noport(&sock_adr.sa, sizeof(sock_adr)); /* else it is already done */ @@ -311,7 +322,7 @@ printf("%s: info: pid %d from %s\n", applet_name, pid, remote_ip); } - if (need_addresses && (option_mask32 & OPT_h)) { + if (need_hostnames && (option_mask32 & OPT_h)) { remote_hostname = xmalloc_sockaddr2host(&sock_adr.sa, sizeof(sock_adr)); if (!remote_hostname) { bb_error_msg("warning: cannot look up hostname for %s", remote_ip); @@ -324,7 +335,7 @@ * which doesn't know local ip) */ getsockname(conn, &sock_adr.sa, &sockadr_size); - if (need_addresses) { + if (need_hostnames) { local_ip = xmalloc_sockaddr2dotted_noport(&sock_adr.sa, sockadr_size); local_port = get_nport(&sock_adr.sa); local_port = ntohs(local_port); @@ -337,6 +348,20 @@ if (!(option_mask32 & OPT_E)) { /* setup ucspi env */ + + /* Extract "original" destination addr:port + * from Linux firewall. Useful when you redirect + * an outbond connection to local handler, and it needs + * to know where it originally tried to connect */ + sockadr_size = sizeof(sock_adr); + if (getsockopt(conn, SOL_IP, SO_ORIGINAL_DST, &sock_adr.sa, &sockadr_size) == 0) { + char *ip = xmalloc_sockaddr2dotted_noport(&sock_adr.sa, sockadr_size); + port = get_nport(&sock_adr.sa); + port = ntohs(port); + xsetenv("TCPORIGDSTIP", ip); + xsetenv("TCPORIGDSTPORT", utoa(port)); + free(ip); + } xsetenv("PROTO", "TCP"); xsetenv("TCPLOCALIP", local_ip); xsetenv("TCPLOCALPORT", utoa(local_port)); @@ -431,7 +456,8 @@ } /* -tcpsvd [-hpEvv] [-c n] [-C n:msg] [-b n] [-u user] [-l name] [-i dir|-x cdb] [ -t sec] host port prog +tcpsvd [-hpEvv] [-c n] [-C n:msg] [-b n] [-u user] [-l name] + [-i dir|-x cdb] [ -t sec] host port prog tcpsvd creates a TCP/IP socket, binds it to the address host:port, and listens on the socket for incoming connections. From vda at busybox.net Sun Apr 1 12:10:37 2007 From: vda at busybox.net (vda at busybox.net) Date: Sun, 1 Apr 2007 12:10:37 -0700 (PDT) Subject: svn commit: trunk/busybox: include ipsvd Message-ID: <20070401191037.EC0844801C@busybox.net> Author: vda Date: 2007-04-01 12:10:36 -0700 (Sun, 01 Apr 2007) New Revision: 18297 Log: udpsvd: next part of ipsvd applets (not working yet) Modified: trunk/busybox/include/applets.h trunk/busybox/include/usage.h trunk/busybox/ipsvd/Config.in trunk/busybox/ipsvd/Kbuild trunk/busybox/ipsvd/tcpsvd.c Changeset: Modified: trunk/busybox/include/applets.h =================================================================== --- trunk/busybox/include/applets.h 2007-04-01 10:59:33 UTC (rev 18296) +++ trunk/busybox/include/applets.h 2007-04-01 19:10:36 UTC (rev 18297) @@ -311,6 +311,7 @@ //USE_TUNE2FS(APPLET(tune2fs, _BB_DIR_SBIN, _BB_SUID_NEVER)) USE_APP_UDHCPC(APPLET(udhcpc, _BB_DIR_SBIN, _BB_SUID_NEVER)) USE_APP_UDHCPD(APPLET(udhcpd, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) +USE_UDPSVD(APPLET(udpsvd, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) USE_UMOUNT(APPLET(umount, _BB_DIR_BIN, _BB_SUID_NEVER)) USE_UNAME(APPLET(uname, _BB_DIR_BIN, _BB_SUID_NEVER)) USE_UNCOMPRESS(APPLET(uncompress, _BB_DIR_BIN, _BB_SUID_NEVER)) Modified: trunk/busybox/include/usage.h =================================================================== --- trunk/busybox/include/usage.h 2007-04-01 10:59:33 UTC (rev 18296) +++ trunk/busybox/include/usage.h 2007-04-01 19:10:36 UTC (rev 18297) @@ -3348,6 +3348,11 @@ "\n-E Do not set up TCP-related environment variables" \ "\n-v Verbose" +#define udpsvd_trivial_usage \ + "TODO" +#define udpsvd_full_usage \ + "TODO" + #define tftp_trivial_usage \ "[OPTION]... HOST [PORT]" #define tftp_full_usage \ Modified: trunk/busybox/ipsvd/Config.in =================================================================== --- trunk/busybox/ipsvd/Config.in 2007-04-01 10:59:33 UTC (rev 18296) +++ trunk/busybox/ipsvd/Config.in 2007-04-01 19:10:36 UTC (rev 18297) @@ -9,6 +9,12 @@ bool "tcpsvd" default n help - tcpsvd listens on a port and runs a program for each new connection + tcpsvd listens on a tcp port and runs a program for each new connection +config UDPSVD + bool "udpsvd" + default n + help + udpsvd listens on a udp port and runs a program for each new connection + endmenu Modified: trunk/busybox/ipsvd/Kbuild =================================================================== --- trunk/busybox/ipsvd/Kbuild 2007-04-01 10:59:33 UTC (rev 18296) +++ trunk/busybox/ipsvd/Kbuild 2007-04-01 19:10:36 UTC (rev 18297) @@ -6,3 +6,4 @@ lib-y:= lib-$(CONFIG_TCPSVD) += tcpsvd.o ipsvd_perhost.o +lib-$(CONFIG_UDPSVD) += udpsvd.o Modified: trunk/busybox/ipsvd/tcpsvd.c =================================================================== --- trunk/busybox/ipsvd/tcpsvd.c 2007-04-01 10:59:33 UTC (rev 18296) +++ trunk/busybox/ipsvd/tcpsvd.c 2007-04-01 19:10:36 UTC (rev 18297) @@ -126,7 +126,6 @@ socklen_t sockadr_size; uint16_t local_port = local_port; uint16_t remote_port; - unsigned port; char *local_hostname = NULL; char *remote_hostname = (char*)""; /* "" used if no -h */ char *local_ip = local_ip; @@ -221,8 +220,8 @@ if (max_per_host) ipsvd_perhost_init(cmax); - port = bb_lookup_port(argv[1], "tcp", 0); - sock = create_and_bind_stream_or_die(argv[0], port); + local_port = bb_lookup_port(argv[1], "tcp", 0); + sock = create_and_bind_stream_or_die(argv[0], local_port); xlisten(sock, backlog); /* ndelay_off(sock); - it is the default I think? */ @@ -238,7 +237,7 @@ if (verbose) { /* we do it only for ":port" cosmetics... oh well */ - len_and_sockaddr *lsa = xhost2sockaddr(argv[0], port); + len_and_sockaddr *lsa = xhost2sockaddr(argv[0], local_port); char *addr = xmalloc_sockaddr2dotted(&lsa->sa, lsa->len); printf("%s: info: listening on %s", applet_name, addr); @@ -246,7 +245,7 @@ #ifndef SSLSVD if (option_mask32 & OPT_u) printf(", uid %u, gid %u", - (unsigned)ugid.uid, (unsigned)ugid.uid); + (unsigned)ugid.uid, (unsigned)ugid.gid); #endif puts(", starting"); } @@ -356,7 +355,7 @@ sockadr_size = sizeof(sock_adr); if (getsockopt(conn, SOL_IP, SO_ORIGINAL_DST, &sock_adr.sa, &sockadr_size) == 0) { char *ip = xmalloc_sockaddr2dotted_noport(&sock_adr.sa, sockadr_size); - port = get_nport(&sock_adr.sa); + unsigned port = get_nport(&sock_adr.sa); port = ntohs(port); xsetenv("TCPORIGDSTIP", ip); xsetenv("TCPORIGDSTPORT", utoa(port)); From vda at busybox.net Sun Apr 1 23:17:46 2007 From: vda at busybox.net (vda at busybox.net) Date: Sun, 1 Apr 2007 23:17:46 -0700 (PDT) Subject: svn commit: trunk/busybox/ipsvd Message-ID: <20070402061746.A1B9F48017@busybox.net> Author: vda Date: 2007-04-01 23:17:45 -0700 (Sun, 01 Apr 2007) New Revision: 18299 Log: udpsvd: forgotten 'svn add' Added: trunk/busybox/ipsvd/udpsvd.c Changeset: Added: trunk/busybox/ipsvd/udpsvd.c =================================================================== --- trunk/busybox/ipsvd/udpsvd.c (rev 0) +++ trunk/busybox/ipsvd/udpsvd.c 2007-04-02 06:17:45 UTC (rev 18299) @@ -0,0 +1,221 @@ +/* Based on ipsvd utilities written by Gerrit Pape + * which are released into public domain by the author. + * Homepage: http://smarden.sunsite.dk/ipsvd/ + * + * Copyright (C) 2007 Denis Vlasenko. + * + * Licensed under GPLv2, see file LICENSE in this tarball for details. + */ + +/* Based on ipsvd ipsvd-0.12.1. This tcpsvd accepts all options + * which are supported by one from ipsvd-0.12.1, but not all are + * functional. See help text at the end of this file for details. + * + * Code inside #if 0" is parts of original tcpsvd which are not implemented + * for busyboxed version. + * + * Output of verbose mode matches original (modulo bugs and + * unimplemented stuff). Unnatural splitting of IP and PORT + * is retained (personally I prefer one-value "IP:PORT" notation - + * it is a natural string representation of struct sockaddr_XX). + */ + +#include "busybox.h" + +unsigned verbose; + +static void sig_term_handler(int sig) +{ + if (verbose) + printf("udpsvd: info: sigterm received, exit\n"); + exit(0); +} + +int udpsvd_main(int argc, char **argv); +int udpsvd_main(int argc, char **argv) +{ + const char *instructs; + char *str_t, *user; + unsigned opt; +// unsigned lookuphost = 0; +// unsigned paranoid = 0; +// unsigned long timeout = 0; + + char *remote_hostname; + char *local_hostname; + char *remote_ip; + char *local_ip; + uint16_t local_port, remote_port; + union { + struct sockaddr sa; + struct sockaddr_in sin; + USE_FEATURE_IPV6(struct sockaddr_in6 sin6;) + } sock_adr; + socklen_t sockadr_size; + int sock; + int wstat; + unsigned pid; + struct bb_uidgid_t ugid; + + enum { + OPT_v = (1 << 0), + OPT_u = (1 << 1), + OPT_l = (1 << 2), + OPT_h = (1 << 3), + OPT_p = (1 << 4), + OPT_i = (1 << 5), + OPT_x = (1 << 6), + OPT_t = (1 << 7), + }; + + opt_complementary = "ph:vv"; + opt = getopt32(argc, argv, "vu:l:hpi:x:t:", + &user, &local_hostname, &instructs, &instructs, &str_t, &verbose); + //if (opt & OPT_x) iscdb =1; + //if (opt & OPT_t) timeout = xatou(str_t); + if (!(opt & OPT_h)) + remote_hostname = (char *)""; + if (opt & OPT_u) { + if (!get_uidgid(&ugid, user, 1)) + bb_error_msg_and_die("unknown user/group: %s", user); + } + argv += optind; + if (!argv[0][0] || LONE_CHAR(argv[0], '0')) + argv[0] = (char*)"0.0.0.0"; + + setlinebuf(stdout); + + signal(SIGTERM, sig_term_handler); + signal(SIGPIPE, SIG_IGN); + + local_port = bb_lookup_port(argv[1], "udp", 0); + sock = create_and_bind_dgram_or_die(argv[0], local_port); + + if (opt & OPT_u) { /* drop permissions */ + xsetgid(ugid.gid); + xsetuid(ugid.uid); + } + bb_sanitize_stdio(); /* fd# 1,2 must be opened */ + close(0); + + if (verbose) { + /* we do it only for ":port" cosmetics... oh well */ + len_and_sockaddr *lsa = xhost2sockaddr(argv[0], local_port); + char *addr = xmalloc_sockaddr2dotted(&lsa->sa, lsa->len); + printf("udpsvd: info: listening on %s", addr); + free(addr); + if (option_mask32 & OPT_u) + printf(", uid %u, gid %u", + (unsigned)ugid.uid, (unsigned)ugid.gid); + puts(", starting"); + } + + again: +/* io[0].fd = s; + io[0].events = IOPAUSE_READ; + io[0].revents = 0; + taia_now(&now); + taia_uint(&deadline, 3600); + taia_add(&deadline, &now, &deadline); + iopause(io, 1, &deadline, &now); + if (!(io[0].revents | IOPAUSE_READ)) + goto again; + io[0].revents = 0; +*/ + sockadr_size = sizeof(sock_adr); + if (recvfrom(sock, NULL, 0, MSG_PEEK, &sock_adr.sa, &sockadr_size) == -1) { + bb_perror_msg("recvfrom"); + goto again; + } + + while ((pid = fork()) < 0) { + bb_perror_msg("fork failed, sleeping"); + sleep(5); + } + if (pid > 0) { /* parent */ + while (wait_pid(&wstat, pid) == -1) + bb_perror_msg("error waiting for child"); + if (verbose) + printf("udpsvd: info: end %u\n", pid); + goto again; + } + + /* Child */ + +/* if (recvfrom(sock, 0, 0, MSG_PEEK, (struct sockaddr *)&sock_adr, &sockadr_size) == -1) + drop("unable to read from socket"); +*/ + remote_ip = xmalloc_sockaddr2dotted_noport(&sock_adr.sa, sockadr_size); + remote_port = get_nport(&sock_adr.sa); + remote_port = ntohs(remote_port); + if (verbose) { + printf("udpsvd: info: pid %u from %s\n", pid, remote_ip); + } + if (opt & OPT_h) { + remote_hostname = xmalloc_sockaddr2host(&sock_adr.sa, sizeof(sock_adr)); + if (!remote_hostname) { + bb_error_msg("warning: cannot look up hostname for %s", remote_ip); + remote_hostname = (char*)""; + } + } + +#if 0 + if (instructs) { + ac = ipsvd_check(iscdb, &inst, &match, (char*)instructs, + remote_ip, remote_hostname.s, timeout); + if (ac == -1) discard("unable to check inst", remote_ip); + if (ac == IPSVD_ERR) discard("unable to read", (char*)instructs); + } else + ac = IPSVD_DEFAULT; +#endif + + if (verbose) { +#if 0 + out("udpsvd: info: "); + switch(ac) { + case IPSVD_DENY: out("deny "); break; + case IPSVD_DEFAULT: case IPSVD_INSTRUCT: out("start "); break; + case IPSVD_EXEC: out("exec "); break; + } +#endif + printf("udpsvd: info: %u %s:%s :%s:%s:%u\n", + pid, local_hostname, local_ip, + remote_hostname, remote_ip, remote_port); +#if 0 + if (instructs) { + out(" "); + if (iscdb) { + out((char*)instructs); out("/"); + } + outfix(match.s); + if(inst.s && inst.len && (verbose > 1)) { + out(": "); outinst(&inst); + } + } +#endif + } + +#if 0 + if (ac == IPSVD_DENY) { + recv(s, 0, 0, 0); + _exit(100); + } + if (ac == IPSVD_EXEC) { + args[0] = "/bin/sh"; + args[1] = "-c"; + args[2] = inst.s; + args[3] = NULL; + run = args; + } else run = prog; +#endif + + xmove_fd(sock, 0); + dup2(0, 1); + + signal(SIGTERM, SIG_DFL); + signal(SIGPIPE, SIG_DFL); + argv += 2; + + BB_EXECVP(argv[0], argv); + bb_perror_msg_and_die("exec '%s'", argv[0]); +} From vda at busybox.net Mon Apr 2 05:37:30 2007 From: vda at busybox.net (vda at busybox.net) Date: Mon, 2 Apr 2007 05:37:30 -0700 (PDT) Subject: svn commit: trunk/busybox: coreutils include ipsvd libbb Message-ID: <20070402123730.582304801C@busybox.net> Author: vda Date: 2007-04-02 05:37:28 -0700 (Mon, 02 Apr 2007) New Revision: 18302 Log: test: comment out unused code udpsvd: fake it compile tcpsvd: more optimal memorizing of IP's for -C Modified: trunk/busybox/coreutils/test.c trunk/busybox/include/libbb.h trunk/busybox/ipsvd/ipsvd_perhost.c trunk/busybox/ipsvd/ipsvd_perhost.h trunk/busybox/ipsvd/tcpsvd.c trunk/busybox/ipsvd/udpsvd.c trunk/busybox/libbb/xconnect.c Changeset: Modified: trunk/busybox/coreutils/test.c =================================================================== --- trunk/busybox/coreutils/test.c 2007-04-02 12:06:00 UTC (rev 18301) +++ trunk/busybox/coreutils/test.c 2007-04-02 12:37:28 UTC (rev 18302) @@ -168,9 +168,11 @@ static arith_t primary(enum token n); static int filstat(char *nm, enum token mode); static arith_t getn(const char *s); +/* UNUSED static int newerf(const char *f1, const char *f2); static int olderf(const char *f1, const char *f2); static int equalf(const char *f1, const char *f2); +*/ static int test_eaccess(char *path, int mode); static int is_a_group_member(gid_t gid); static void initialize_group_array(void); @@ -490,6 +492,7 @@ return r; } +/* UNUSED static int newerf(const char *f1, const char *f2) { struct stat b1, b2; @@ -514,6 +517,7 @@ stat(f2, &b2) == 0 && b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino); } +*/ /* Do the same thing access(2) does, but use the effective uid and gid, and don't make the mistake of telling root that any file is Modified: trunk/busybox/include/libbb.h =================================================================== --- trunk/busybox/include/libbb.h 2007-04-02 12:06:00 UTC (rev 18301) +++ trunk/busybox/include/libbb.h 2007-04-02 12:37:28 UTC (rev 18302) @@ -324,11 +324,12 @@ /* Create stream socket, and allocated suitable lsa * (lsa of correct size and lsa->sa.sa_family (AF_INET/AF_INET6)) */ int xsocket_stream(len_and_sockaddr **lsap); -/* Create server TCP socket bound to bindaddr:port. bindaddr can be NULL, +/* Create server 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 */ int create_and_bind_stream_or_die(const char *bindaddr, int port); +int create_and_bind_dgram_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"). @@ -370,9 +371,9 @@ char* xmalloc_sockaddr2dotted(const struct sockaddr *sa, socklen_t salen); char* xmalloc_sockaddr2dotted_noport(const struct sockaddr *sa, socklen_t salen); // "old" (ipv4 only) API -// users: traceroute.c hostname.c +// users: traceroute.c hostname.c - use _list_ of all IPs struct hostent *xgethostbyname(const char *name); -// Also inetd.c and inetd.c are using gethostbyname(), +// Also mount.c and inetd.c are using gethostbyname(), // + inet_common.c has additional IPv4-only stuff Modified: trunk/busybox/ipsvd/ipsvd_perhost.c =================================================================== --- trunk/busybox/ipsvd/ipsvd_perhost.c 2007-04-02 12:06:00 UTC (rev 18301) +++ trunk/busybox/ipsvd/ipsvd_perhost.c 2007-04-02 12:37:28 UTC (rev 18302) @@ -22,26 +22,26 @@ cclen = c; } -unsigned ipsvd_perhost_add(const char *ip, unsigned maxconn, struct hcc **hccpp) +unsigned ipsvd_perhost_add(char *ip, unsigned maxconn, struct hcc **hccpp) { unsigned i; unsigned conn = 1; - int p = -1; + int freepos = -1; for (i = 0; i < cclen; ++i) { - if (cc[i].ip[0] == 0) { - if (p == -1) p = i; + if (!cc[i].ip) { + freepos = i; continue; } - if (strncmp(cc[i].ip, ip, sizeof(cc[i].ip)) == 0) { + if (strcmp(cc[i].ip, ip) == 0) { conn++; continue; } } - if (p == -1) return 0; + if (freepos == -1) return 0; if (conn <= maxconn) { - strcpy(cc[p].ip, ip); - *hccpp = &cc[p]; + cc[freepos].ip = ip; + *hccpp = &cc[freepos]; } return conn; } @@ -51,7 +51,8 @@ unsigned i; for (i = 0; i < cclen; ++i) { if (cc[i].pid == pid) { - cc[i].ip[0] = 0; + free(cc[i].ip); + cc[i].ip = NULL; cc[i].pid = 0; return; } Modified: trunk/busybox/ipsvd/ipsvd_perhost.h =================================================================== --- trunk/busybox/ipsvd/ipsvd_perhost.h 2007-04-02 12:06:00 UTC (rev 18301) +++ trunk/busybox/ipsvd/ipsvd_perhost.h 2007-04-02 12:37:28 UTC (rev 18302) @@ -8,12 +8,22 @@ */ struct hcc { - char ip[32 - sizeof(int)]; + char *ip; int pid; }; void ipsvd_perhost_init(unsigned); -unsigned ipsvd_perhost_add(const char *ip, unsigned maxconn, struct hcc **hccpp); + +/* Returns number of already opened connects to this ips, including this one. + * ip should be a malloc'ed ptr. + * If return value is <= maxconn, ip is inserted into the table + * and pointer to table entry if stored in *hccpp + * (useful for storing pid later). + * Else ip is NOT inserted (you must take care of it - free() etc) */ +unsigned ipsvd_perhost_add(char *ip, unsigned maxconn, struct hcc **hccpp); + +/* Finds and frees element with pid */ void ipsvd_perhost_remove(int pid); + //unsigned ipsvd_perhost_setpid(int pid); //void ipsvd_perhost_free(void); Modified: trunk/busybox/ipsvd/tcpsvd.c =================================================================== --- trunk/busybox/ipsvd/tcpsvd.c 2007-04-02 12:06:00 UTC (rev 18301) +++ trunk/busybox/ipsvd/tcpsvd.c 2007-04-02 12:37:28 UTC (rev 18302) @@ -128,8 +128,8 @@ uint16_t remote_port; char *local_hostname = NULL; char *remote_hostname = (char*)""; /* "" used if no -h */ - char *local_ip = local_ip; - char *remote_ip = NULL; + char *local_ip = local_ip; /* gcc */ + char *remote_ip = remote_ip; /* gcc */ //unsigned iscdb = 0; /* = option_mask32 & OPT_x (TODO) */ //unsigned long timeout = 0; #ifndef SSLSVD @@ -271,10 +271,10 @@ if (max_per_host) { /* we drop connection immediately if cur_per_host > max_per_host * (minimizing load under SYN flood) */ - free(remote_ip); remote_ip = xmalloc_sockaddr2dotted_noport(&sock_adr.sa, sockadr_size); cur_per_host = ipsvd_perhost_add(remote_ip, max_per_host, &hccp); if (cur_per_host > max_per_host) { + free(remote_ip); /* ipsvd_perhost_add detected that max is exceeded * (and did not store us in connection table) */ if (msg_per_host) { Modified: trunk/busybox/ipsvd/udpsvd.c =================================================================== --- trunk/busybox/ipsvd/udpsvd.c 2007-04-02 12:06:00 UTC (rev 18301) +++ trunk/busybox/ipsvd/udpsvd.c 2007-04-02 12:37:28 UTC (rev 18302) @@ -42,9 +42,9 @@ // unsigned long timeout = 0; char *remote_hostname; - char *local_hostname; + char *local_hostname = local_hostname; /* gcc */ char *remote_ip; - char *local_ip; + char *local_ip = local_ip; /* gcc */ uint16_t local_port, remote_port; union { struct sockaddr sa; @@ -145,6 +145,11 @@ /* if (recvfrom(sock, 0, 0, MSG_PEEK, (struct sockaddr *)&sock_adr, &sockadr_size) == -1) drop("unable to read from socket"); */ + if (verbose) { + local_ip = argv[0]; // TODO: recv_from_to! + local_hostname = (char*)"localhost"; + } + remote_ip = xmalloc_sockaddr2dotted_noport(&sock_adr.sa, sockadr_size); remote_port = get_nport(&sock_adr.sa); remote_port = ntohs(remote_port); Modified: trunk/busybox/libbb/xconnect.c =================================================================== --- trunk/busybox/libbb/xconnect.c 2007-04-02 12:06:00 UTC (rev 18301) +++ trunk/busybox/libbb/xconnect.c 2007-04-02 12:37:28 UTC (rev 18302) @@ -208,7 +208,7 @@ return str2sockaddr(host, port, AF_UNSPEC, AI_NUMERICHOST | DIE_ON_ERROR); } -int xsocket_stream(len_and_sockaddr **lsap) +static int xsocket_type(len_and_sockaddr **lsap, int sock_type) { len_and_sockaddr *lsa; int fd; @@ -216,14 +216,14 @@ int family = AF_INET; #if ENABLE_FEATURE_IPV6 - fd = socket(AF_INET6, SOCK_STREAM, 0); + fd = socket(AF_INET6, sock_type, 0); if (fd >= 0) { len = sizeof(struct sockaddr_in6); family = AF_INET6; } else #endif { - fd = xsocket(AF_INET, SOCK_STREAM, 0); + fd = xsocket(AF_INET, sock_type, 0); } lsa = xzalloc(offsetof(len_and_sockaddr, sa) + len); lsa->len = len; @@ -232,17 +232,22 @@ return fd; } -int create_and_bind_stream_or_die(const char *bindaddr, int port) +int xsocket_stream(len_and_sockaddr **lsap) { + return xsocket_type(lsap, SOCK_STREAM); +} + +static int create_and_bind_or_die(const char *bindaddr, int port, int sock_type) +{ int fd; len_and_sockaddr *lsa; if (bindaddr && bindaddr[0]) { lsa = xdotted2sockaddr(bindaddr, port); /* user specified bind addr dictates family */ - fd = xsocket(lsa->sa.sa_family, SOCK_STREAM, 0); + fd = xsocket(lsa->sa.sa_family, sock_type, 0); } else { - fd = xsocket_stream(&lsa); + fd = xsocket_type(&lsa, sock_type); set_nport(lsa, htons(port)); } setsockopt_reuseaddr(fd); @@ -251,6 +256,17 @@ return fd; } +int create_and_bind_stream_or_die(const char *bindaddr, int port) +{ + return create_and_bind_or_die(bindaddr, port, SOCK_STREAM); +} + +int create_and_bind_dgram_or_die(const char *bindaddr, int port) +{ + return create_and_bind_or_die(bindaddr, port, SOCK_DGRAM); +} + + int create_and_connect_stream_or_die(const char *peer, int port) { int fd; From aldot at busybox.net Mon Apr 2 09:38:13 2007 From: aldot at busybox.net (aldot at busybox.net) Date: Mon, 2 Apr 2007 09:38:13 -0700 (PDT) Subject: svn commit: trunk/busybox/coreutils Message-ID: <20070402163813.93B104801D@busybox.net> Author: aldot Date: 2007-04-02 09:38:13 -0700 (Mon, 02 Apr 2007) New Revision: 18304 Log: - remove args from bss, minor misc shrinkage while at it. text data bss dec hex filename 2577 0 4 2581 a15 expr.o 2522 0 0 2522 9da expr.o Modified: trunk/busybox/coreutils/expr.c Changeset: Modified: trunk/busybox/coreutils/expr.c =================================================================== --- trunk/busybox/coreutils/expr.c 2007-04-02 16:18:48 UTC (rev 18303) +++ trunk/busybox/coreutils/expr.c 2007-04-02 16:38:13 UTC (rev 18304) @@ -62,15 +62,18 @@ typedef struct valinfo VALUE; /* The arguments given to the program, minus the program name. */ -static char **args; +struct globals { + char **args; +}; +#define G (*(struct globals*)&bb_common_bufsiz1) static VALUE *docolon(VALUE * sv, VALUE * pv); static VALUE *eval(void); static VALUE *int_value(arith_t i); static VALUE *str_value(const char *s); -static int nextarg(const char *str); +static bool nextarg(const char *str); static int null(VALUE * v); -static int toarith(VALUE * v); +static bool toarith(VALUE * v); static void freev(VALUE * v); static void tostring(VALUE * v); @@ -83,10 +86,10 @@ bb_error_msg_and_die("too few arguments"); } - args = argv + 1; + G.args = argv + 1; v = eval(); - if (*args) + if (*G.args) bb_error_msg_and_die("syntax error"); if (v->type == integer) @@ -152,7 +155,7 @@ /* Coerce V to an integer value. Return 1 on success, 0 on failure. */ -static int toarith(VALUE * v) +static bool toarith(VALUE * v) { if (v->type == string) { arith_t i; @@ -173,11 +176,11 @@ /* Return nonzero if the next token matches STR exactly. STR must not be NULL. */ -static int nextarg(const char *str) +static bool nextarg(const char *str) { - if (*args == NULL) + if (*G.args == NULL) return 0; - return strcmp(*args, str) == 0; + return strcmp(*G.args, str) == 0; } /* The comparison operator handling functions. */ @@ -281,53 +284,57 @@ { VALUE *v; - if (!*args) + if (!*G.args) bb_error_msg_and_die("syntax error"); if (nextarg("(")) { - args++; + G.args++; v = eval(); if (!nextarg(")")) bb_error_msg_and_die("syntax error"); - args++; + G.args++; return v; } if (nextarg(")")) bb_error_msg_and_die("syntax error"); - return str_value(*args++); + return str_value(*G.args++); } /* Handle match, substr, index, length, and quote keywords. */ static VALUE *eval6(void) { - VALUE *l, *r, *v, *i1, *i2; + VALUE *l, *r, *v = NULL /* silence gcc */, *i1, *i2; + const char * const keywords[] = { + "quote", "length", "match", "index", "substr", NULL + }; - if (nextarg("quote")) { - args++; - if (!*args) + smalluint key = *G.args ? index_in_str_array(keywords, *G.args) + 1 : 0; + if (key == 0) /* not a keyword */ + return eval7(); + G.args++; /* We have a valid token, so get the next argument. */ + if (key == 1) { /* quote */ + if (!*G.args) bb_error_msg_and_die("syntax error"); - return str_value(*args++); - } else if (nextarg("length")) { - args++; + return str_value(*G.args++); + } + if (key == 2) { /* length */ r = eval6(); tostring(r); v = int_value(strlen(r->u.s)); freev(r); - return v; - } else if (nextarg("match")) { - args++; + } else l = eval6(); + + if (key == 3) { /* match */ r = eval6(); v = docolon(l, r); freev(l); freev(r); - return v; - } else if (nextarg("index")) { - args++; - l = eval6(); + } + if (key == 4) { /* index */ r = eval6(); tostring(l); tostring(r); @@ -336,10 +343,8 @@ v->u.i = 0; freev(l); freev(r); - return v; - } else if (nextarg("substr")) { - args++; - l = eval6(); + } + if (key == 5) { /* substr */ i1 = eval6(); i2 = eval6(); tostring(l); @@ -355,9 +360,9 @@ freev(l); freev(i1); freev(i2); - return v; - } else - return eval7(); + } + return v; + } /* Handle : operator (pattern matching). @@ -369,7 +374,7 @@ l = eval6(); while (nextarg(":")) { - args++; + G.args++; r = eval6(); v = docolon(l, r); freev(l); @@ -397,7 +402,7 @@ op = '%'; else return l; - args++; + G.args++; r = eval5(); val = arithmetic_common(l, r, op); freev(l); @@ -422,7 +427,7 @@ op = '-'; else return l; - args++; + G.args++; r = eval4(); val = arithmetic_common(l, r, op); freev(l); @@ -455,7 +460,7 @@ op = '>'; else return l; - args++; + G.args++; r = eval3(); toarith(l); toarith(r); @@ -474,7 +479,7 @@ l = eval2(); while (nextarg("&")) { - args++; + G.args++; r = eval2(); if (null(l) || null(r)) { freev(l); @@ -494,7 +499,7 @@ l = eval1(); while (nextarg("|")) { - args++; + G.args++; r = eval1(); if (null(l)) { freev(l); From aldot at busybox.net Mon Apr 2 09:41:24 2007 From: aldot at busybox.net (aldot at busybox.net) Date: Mon, 2 Apr 2007 09:41:24 -0700 (PDT) Subject: svn commit: trunk/busybox/coreutils Message-ID: <20070402164124.865DC4801C@busybox.net> Author: aldot Date: 2007-04-02 09:41:24 -0700 (Mon, 02 Apr 2007) New Revision: 18305 Log: - remove some unneeded forward declarations. No obj-code changes. Modified: trunk/busybox/coreutils/expr.c Changeset: Modified: trunk/busybox/coreutils/expr.c =================================================================== --- trunk/busybox/coreutils/expr.c 2007-04-02 16:38:13 UTC (rev 18304) +++ trunk/busybox/coreutils/expr.c 2007-04-02 16:41:24 UTC (rev 18305) @@ -67,39 +67,10 @@ }; #define G (*(struct globals*)&bb_common_bufsiz1) -static VALUE *docolon(VALUE * sv, VALUE * pv); +/* forward declarations */ static VALUE *eval(void); -static VALUE *int_value(arith_t i); -static VALUE *str_value(const char *s); -static bool nextarg(const char *str); -static int null(VALUE * v); -static bool toarith(VALUE * v); -static void freev(VALUE * v); -static void tostring(VALUE * v); -int expr_main(int argc, char **argv); -int expr_main(int argc, char **argv) -{ - VALUE *v; - if (argc == 1) { - bb_error_msg_and_die("too few arguments"); - } - - G.args = argv + 1; - - v = eval(); - if (*G.args) - bb_error_msg_and_die("syntax error"); - - if (v->type == integer) - printf("%" PF_REZ "d\n", PF_REZ_TYPE v->u.i); - else - puts(v->u.s); - - fflush_stdout_and_exit(null(v)); -} - /* Return a VALUE for I. */ static VALUE *int_value(arith_t i) @@ -509,3 +480,28 @@ } return l; } + +int expr_main(int argc, char **argv); +int expr_main(int argc, char **argv) +{ + VALUE *v; + + if (argc == 1) { + bb_error_msg_and_die("too few arguments"); + } + + G.args = argv + 1; + + v = eval(); + if (*G.args) + bb_error_msg_and_die("syntax error"); + + if (v->type == integer) + printf("%" PF_REZ "d\n", PF_REZ_TYPE v->u.i); + else + puts(v->u.s); + + fflush_stdout_and_exit(null(v)); +} + + From aldot at busybox.net Mon Apr 2 09:54:41 2007 From: aldot at busybox.net (aldot at busybox.net) Date: Mon, 2 Apr 2007 09:54:41 -0700 (PDT) Subject: svn commit: trunk/busybox/coreutils Message-ID: <20070402165441.AFD0E4801C@busybox.net> Author: aldot Date: 2007-04-02 09:54:41 -0700 (Mon, 02 Apr 2007) New Revision: 18306 Log: - use xregcomp. Untested. vda, isn't there a regfree missing here? text data bss dec hex filename 2522 0 0 2522 9da expr.o.r18305 2478 0 0 2478 9ae expr.o Modified: trunk/busybox/coreutils/expr.c Changeset: Modified: trunk/busybox/coreutils/expr.c =================================================================== --- trunk/busybox/coreutils/expr.c 2007-04-02 16:41:24 UTC (rev 18305) +++ trunk/busybox/coreutils/expr.c 2007-04-02 16:54:41 UTC (rev 18306) @@ -226,8 +226,7 @@ memset(&re_buffer, 0, sizeof(re_buffer)); memset(re_regs, 0, sizeof(*re_regs)); - if (regcomp(&re_buffer, pv->u.s, 0) != 0) - bb_error_msg_and_die("invalid regular expression"); + xregcomp(&re_buffer, pv->u.s, 0); /* expr uses an anchored pattern match, so check that there was a * match and that the match starts at offset 0. */ @@ -246,6 +245,7 @@ else v = int_value(0); } +//FIXME: sounds like here is a bit missing: regfree(&re_buffer); return v; } From aldot at busybox.net Mon Apr 2 10:01:22 2007 From: aldot at busybox.net (aldot at busybox.net) Date: Mon, 2 Apr 2007 10:01:22 -0700 (PDT) Subject: svn commit: trunk/busybox/coreutils Message-ID: <20070402170122.E4C854801F@busybox.net> Author: aldot Date: 2007-04-02 10:01:22 -0700 (Mon, 02 Apr 2007) New Revision: 18307 Log: - use bb_error_msg Modified: trunk/busybox/coreutils/expr.c Changeset: Modified: trunk/busybox/coreutils/expr.c =================================================================== --- trunk/busybox/coreutils/expr.c 2007-04-02 16:54:41 UTC (rev 18306) +++ trunk/busybox/coreutils/expr.c 2007-04-02 17:01:22 UTC (rev 18307) @@ -219,7 +219,7 @@ tostring(pv); if (pv->u.s[0] == '^') { - fprintf(stderr, "\ + bb_error_msg("\ warning: unportable BRE: `%s': using `^' as the first character\n\ of a basic regular expression is not portable; it is being ignored", pv->u.s); } From bugs at busybox.net Mon Apr 2 14:07:26 2007 From: bugs at busybox.net (bugs at busybox.net) Date: Mon, 2 Apr 2007 14:07:26 -0700 Subject: [BusyBox 0001299]: mdev can't create character devices Message-ID: <1fb43d4aaba8f71b7afb516718a8ba9a@bugs.busybox.net> The following issue has been SUBMITTED. ====================================================================== http://busybox.net/bugs/view.php?id=1299 ====================================================================== Reported By: Souf Assigned To: BusyBox ====================================================================== Project: BusyBox Issue ID: 1299 Category: Other Reproducibility: always Severity: major Priority: normal Status: assigned ====================================================================== Date Submitted: 04-02-2007 14:07 PDT Last Modified: 04-02-2007 14:07 PDT ====================================================================== Summary: mdev can't create character devices Description: I built an embedded system and I installed it on a mini PC (CPU: GeodeGX1), , when I load the sound driver (this driver is under development): modprobe snd-cs5530 mdev creates a block devices instead a character devices: ls -l /dev/snd/ brw-rw-rw- 1 root root 116, 5 Apr 2 22:29 controlC0 brw-rw-rw- 1 root root 116, 4 Apr 2 22:29 pcmC0D0c brw-rw-rw- 1 root root 116, 3 Apr 2 22:29 pcmC0D0p brw-rw-rw- 1 root root 116, 2 Apr 2 22:29 timer whereas the sound devices must be created as character devices. I believe that the problem comes from this line: type = (path[5]=='c') ? S_IFCHR : S_IFBLK; which must be like this: type = (path[5]=='b') ? S_IFBLK : S_IFCHR; ====================================================================== Issue History Date Modified Username Field Change ====================================================================== 04-02-07 14:07 Souf New Issue 04-02-07 14:07 Souf Status new => assigned 04-02-07 14:07 Souf Assigned To => BusyBox ====================================================================== From vda at busybox.net Mon Apr 2 18:13:05 2007 From: vda at busybox.net (vda at busybox.net) Date: Mon, 2 Apr 2007 18:13:05 -0700 (PDT) Subject: svn commit: trunk/busybox: include ipsvd Message-ID: <20070403011305.63B8B48021@busybox.net> Author: vda Date: 2007-04-02 18:13:04 -0700 (Mon, 02 Apr 2007) New Revision: 18311 Log: udpsvd: more work on it. works in limited testing. Added: trunk/busybox/ipsvd/udp_io.c Modified: trunk/busybox/include/libbb.h trunk/busybox/include/usage.h trunk/busybox/ipsvd/tcpsvd.c trunk/busybox/ipsvd/udpsvd.c Changeset: Modified: trunk/busybox/include/libbb.h =================================================================== --- trunk/busybox/include/libbb.h 2007-04-03 01:03:42 UTC (rev 18310) +++ trunk/busybox/include/libbb.h 2007-04-03 01:13:04 UTC (rev 18311) @@ -321,6 +321,17 @@ #endif }; } len_and_sockaddr; +enum { + LSA_SIZEOF_SA = sizeof( + union { + struct sockaddr sa; + struct sockaddr_in sin; +#if ENABLE_FEATURE_IPV6 + struct sockaddr_in6 sin6; +#endif + } + ) +}; /* Create stream socket, and allocated suitable lsa * (lsa of correct size and lsa->sa.sa_family (AF_INET/AF_INET6)) */ int xsocket_stream(len_and_sockaddr **lsap); Modified: trunk/busybox/include/usage.h =================================================================== --- trunk/busybox/include/usage.h 2007-04-03 01:03:42 UTC (rev 18310) +++ trunk/busybox/include/usage.h 2007-04-03 01:13:04 UTC (rev 18311) @@ -3326,32 +3326,41 @@ "1\n" #define tcpsvd_trivial_usage \ - "[-hpEvv] [-c n] [-C n:msg] [-b n] [-u user] [-l name] ip port prog..." + "[-hEv] [-c n] [-C n:msg] [-b n] [-u user] [-l name] ip port prog..." /* with not-implemented options: */ /* "[-hpEvv] [-c n] [-C n:msg] [-b n] [-u user] [-l name] [-i dir|-x cdb] [ -t sec] ip port prog..." */ #define tcpsvd_full_usage \ - "tcpsvd creates TCP/IP socket, binds it to host:port\n" \ - "and listens on in for incoming connections. For each connection\n" \ - "it runs prog" \ + "Creates TCP socket, binds it to host:port and listens on in\n" \ + "for incoming connections. For each connection it runs prog" \ "\n" \ - "\nip IP to listen on. '0' = 'all'" \ + "\nip IP to listen on. '0' = all" \ "\nport Port to listen on" \ - "\nprog [arg] Program to run for each connection" \ + "\nprog [arg] Program to run" \ "\n-l name Local hostname (else looks up local hostname in DNS)" \ "\n-u user[:group] Change to user/group after bind" \ "\n-c n Handle up to n connections simultaneously" \ "\n-C n[:msg] Allow only up to n connections from the same IP" \ "\n New connections from this IP address are closed" \ "\n immediately. 'msg' is written to the peer before close" \ - "\n-h Look up peer's hostname in DNS" \ + "\n-h Look up peer's hostname" \ "\n-b n Allow a backlog of approximately n TCP SYNs" \ "\n-E Do not set up TCP-related environment variables" \ "\n-v Verbose" #define udpsvd_trivial_usage \ - "TODO" + "[-hv] [-u user] [-l name] host port prog" #define udpsvd_full_usage \ - "TODO" + "Creates UDP socket, binds it to host:port and listens on in\n" \ + "for incoming packets. When packet arrives it runs prog.\n" \ + "When prog exits, it start to listen on the socket again" \ + "\n" \ + "\nip IP to listen on. '0' = all" \ + "\nport Port to listen on" \ + "\nprog [arg] Program to run" \ + "\n-l name Local hostname (else looks up local hostname in DNS)" \ + "\n-u user[:group] Change to user/group after bind" \ + "\n-h Look up peer's hostname" \ + "\n-v Verbose" #define tftp_trivial_usage \ "[OPTION]... HOST [PORT]" Modified: trunk/busybox/ipsvd/tcpsvd.c =================================================================== --- trunk/busybox/ipsvd/tcpsvd.c 2007-04-03 01:03:42 UTC (rev 18310) +++ trunk/busybox/ipsvd/tcpsvd.c 2007-04-03 01:13:04 UTC (rev 18311) @@ -179,7 +179,10 @@ if (!argv[0][0] || LONE_CHAR(argv[0], '0')) argv[0] = (char*)"0.0.0.0"; + /* stdout is used for logging, don't buffer */ setlinebuf(stdout); + bb_sanitize_stdio(); /* fd# 1,2 must be opened */ + need_hostnames = verbose || !(option_mask32 & OPT_E); need_remote_ip = max_per_host || need_hostnames; @@ -232,7 +235,6 @@ xsetuid(ugid.uid); } #endif - bb_sanitize_stdio(); /* fd# 1,2 must be opened */ close(0); if (verbose) { @@ -439,6 +441,7 @@ xmove_fd(conn, 0); dup2(0, 1); + signal(SIGTERM, SIG_DFL); signal(SIGPIPE, SIG_DFL); signal(SIGCHLD, SIG_DFL); Added: trunk/busybox/ipsvd/udp_io.c =================================================================== --- trunk/busybox/ipsvd/udp_io.c (rev 0) +++ trunk/busybox/ipsvd/udp_io.c 2007-04-03 01:13:04 UTC (rev 18311) @@ -0,0 +1,156 @@ +/* Thus far used only by udpsvd.c */ + +void socket_want_pktinfo(int fd); +ssize_t send_to_from(int fd, void *buf, size_t len, int flags, + const struct sockaddr *from, const struct sockaddr *to, + socklen_t tolen); +ssize_t recv_from_to(int fd, void *buf, size_t len, int flags, + struct sockaddr *from, struct sockaddr *to, + socklen_t sa_size); + +/* + * This asks kernel to let us know dst addr/port of incoming packets + * We don't check for errors here. Not supported == won't be used + */ +void +socket_want_pktinfo(int fd) +{ +#ifdef IP_PKTINFO + setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &const_int_1, sizeof(int)); +#endif +#ifdef IPV6_PKTINFO + setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &const_int_1, sizeof(int)); +#endif +} + + +ssize_t +send_to_from(int fd, void *buf, size_t len, int flags, + const struct sockaddr *from, const struct sockaddr *to, + socklen_t tolen) +{ +#ifndef IP_PKTINFO + return sendto(fd, buf, len, flags, to, tolen); +#else + struct iovec iov[1]; + struct msghdr msg; + char cbuf[LSA_SIZEOF_SA]; + /* actually, max(sizeof(in_pktinfo),sizeof(in6_pktinfo)) */ + struct cmsghdr* cmsgptr; + + if (from->sa_family != AF_INET +#if ENABLE_FEATURE_IPV6 + && from->sa_family != AF_INET6 +#endif + ) { + /* ANY local address */ + return sendto(fd, buf, len, flags, to, tolen); + } + + /* man recvmsg and man cmsg is needed to make sense of code below */ + + iov[0].iov_base = buf; + iov[0].iov_len = len; + + memset(cbuf, 0, sizeof(cbuf)); + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = (void *)(struct sockaddr *)to; /* or compiler will annoy us */ + msg.msg_namelen = tolen; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_control = cbuf; + msg.msg_controllen = sizeof(cbuf); + msg.msg_flags = flags; + + cmsgptr = CMSG_FIRSTHDR(&msg); + if (to->sa_family == AF_INET && from->sa_family == AF_INET) { + struct in_pktinfo *pktptr; + cmsgptr->cmsg_level = IPPROTO_IP; + cmsgptr->cmsg_type = IP_PKTINFO; + cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + pktptr = (struct in_pktinfo *)(CMSG_DATA(cmsgptr)); + /* pktptr->ipi_ifindex = 0; -- already done by memset(cbuf...) */ + pktptr->ipi_spec_dst = ((struct sockaddr_in*)from)->sin_addr; + } +#if ENABLE_FEATURE_IPV6 && defined(IP6_PKTINFO) + else if (to->sa_family == AF_INET6 && from->sa_family == AF_INET6) { + struct in6_pktinfo *pktptr; + cmsgptr->cmsg_level = IPPROTO_IPV6; + cmsgptr->cmsg_type = IP6_PKTINFO; + cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + pktptr = (struct in6_pktinfo *)(CMSG_DATA(cmsgptr)); + /* pktptr->ipi6_ifindex = 0; -- already done by memset(cbuf...) */ + pktptr->ipi6_addr = ((struct sockaddr_in6*)from)->sin6_addr; + } +#endif + return sendmsg(fd, &msg, flags); +#endif +} + +/* NB: this will never set port# in *to! */ +ssize_t +recv_from_to(int fd, void *buf, size_t len, int flags, + struct sockaddr *from, struct sockaddr *to, + socklen_t sa_size) +{ +#ifndef IP_PKTINFO + return recvfrom(fd, buf, len, flags, from, &sa_size); +#else + /* man recvmsg and man cmsg is needed to make sense of code below */ + struct iovec iov[1]; + union { + char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))]; + char cmsg6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; + } u; + struct cmsghdr *cmsgptr; + struct msghdr msg; + socklen_t recv_length; + + iov[0].iov_base = buf; + iov[0].iov_len = len; + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = (struct sockaddr *)from; + msg.msg_namelen = sa_size; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_control = &u; + msg.msg_controllen = sizeof(u); + + recv_length = recvmsg(fd, &msg, flags); + if (recv_length < 0) + return recv_length; + + /* Here we try to retrieve destination IP and memorize it */ + memset(to, 0, sa_size); + for (cmsgptr = CMSG_FIRSTHDR(&msg); + cmsgptr != NULL; + cmsgptr = CMSG_NXTHDR(&msg, cmsgptr) + ) { + if (cmsgptr->cmsg_level == IPPROTO_IP + && cmsgptr->cmsg_type == IP_PKTINFO + ) { +#define pktinfo(cmsgptr) ( (struct in_pktinfo*)(CMSG_DATA(cmsgptr)) ) + to->sa_family = AF_INET; + ((struct sockaddr_in*)to)->sin_addr = pktinfo(cmsgptr)->ipi_addr; + /* ((struct sockaddr_in*)to)->sin_port = 123; */ +#undef pktinfo + break; + } +#if ENABLE_FEATURE_IPV6 && defined(IP6_PKTINFO) + if (cmsgptr->cmsg_level == IPPROTO_IPV6 + && cmsgptr->cmsg_type == IP6_PKTINFO + ) { +#define pktinfo(cmsgptr) ( (struct in6_pktinfo*)(CMSG_DATA(cmsgptr)) ) + to->sa_family = AF_INET6; + ((struct sockaddr_in6*)to)->sin6_addr = pktinfo(cmsgptr)->ipi6_addr; + /* ((struct sockaddr_in6*)to)->sin6_port = 123; */ +#undef pktinfo + break; + } +#endif + } + return recv_length; +#endif +} Modified: trunk/busybox/ipsvd/udpsvd.c =================================================================== --- trunk/busybox/ipsvd/udpsvd.c 2007-04-03 01:03:42 UTC (rev 18310) +++ trunk/busybox/ipsvd/udpsvd.c 2007-04-03 01:13:04 UTC (rev 18311) @@ -22,12 +22,14 @@ #include "busybox.h" +#include "udp_io.c" + unsigned verbose; static void sig_term_handler(int sig) { if (verbose) - printf("udpsvd: info: sigterm received, exit\n"); + printf("%s: info: sigterm received, exit\n", applet_name); exit(0); } @@ -37,21 +39,14 @@ const char *instructs; char *str_t, *user; unsigned opt; -// unsigned lookuphost = 0; -// unsigned paranoid = 0; -// unsigned long timeout = 0; char *remote_hostname; - char *local_hostname = local_hostname; /* gcc */ + char *local_hostname = NULL; char *remote_ip; char *local_ip = local_ip; /* gcc */ uint16_t local_port, remote_port; - union { - struct sockaddr sa; - struct sockaddr_in sin; - USE_FEATURE_IPV6(struct sockaddr_in6 sin6;) - } sock_adr; - socklen_t sockadr_size; + len_and_sockaddr remote; + len_and_sockaddr *localp; int sock; int wstat; unsigned pid; @@ -68,7 +63,7 @@ OPT_t = (1 << 7), }; - opt_complementary = "ph:vv"; + opt_complementary = "-3:ph:vv"; opt = getopt32(argc, argv, "vu:l:hpi:x:t:", &user, &local_hostname, &instructs, &instructs, &str_t, &verbose); //if (opt & OPT_x) iscdb =1; @@ -83,26 +78,29 @@ if (!argv[0][0] || LONE_CHAR(argv[0], '0')) argv[0] = (char*)"0.0.0.0"; + /* stdout is used for logging, don't buffer */ setlinebuf(stdout); + bb_sanitize_stdio(); /* fd# 1,2 must be opened */ signal(SIGTERM, sig_term_handler); signal(SIGPIPE, SIG_IGN); local_port = bb_lookup_port(argv[1], "udp", 0); - sock = create_and_bind_dgram_or_die(argv[0], local_port); + localp = xhost2sockaddr(argv[0], local_port); + sock = xsocket(localp->sa.sa_family, SOCK_DGRAM, 0); + xmove_fd(sock, 0); /* fd# 0 is the open UDP socket */ + xbind(0, &localp->sa, localp->len); + socket_want_pktinfo(0); if (opt & OPT_u) { /* drop permissions */ xsetgid(ugid.gid); xsetuid(ugid.uid); } - bb_sanitize_stdio(); /* fd# 1,2 must be opened */ - close(0); if (verbose) { /* we do it only for ":port" cosmetics... oh well */ - len_and_sockaddr *lsa = xhost2sockaddr(argv[0], local_port); - char *addr = xmalloc_sockaddr2dotted(&lsa->sa, lsa->len); - printf("udpsvd: info: listening on %s", addr); + char *addr = xmalloc_sockaddr2dotted(&localp->sa, localp->len); + printf("%s: info: listening on %s", applet_name, addr); free(addr); if (option_mask32 & OPT_u) printf(", uid %u, gid %u", @@ -111,19 +109,8 @@ } again: -/* io[0].fd = s; - io[0].events = IOPAUSE_READ; - io[0].revents = 0; - taia_now(&now); - taia_uint(&deadline, 3600); - taia_add(&deadline, &now, &deadline); - iopause(io, 1, &deadline, &now); - if (!(io[0].revents | IOPAUSE_READ)) - goto again; - io[0].revents = 0; -*/ - sockadr_size = sizeof(sock_adr); - if (recvfrom(sock, NULL, 0, MSG_PEEK, &sock_adr.sa, &sockadr_size) == -1) { + /* if (recvfrom(0, NULL, 0, MSG_PEEK, &remote.sa, &localp->len) < 0) { */ + if (recv_from_to(0, NULL, 0, MSG_PEEK, &remote.sa, &localp->sa, localp->len) < 0) { bb_perror_msg("recvfrom"); goto again; } @@ -136,28 +123,38 @@ while (wait_pid(&wstat, pid) == -1) bb_perror_msg("error waiting for child"); if (verbose) - printf("udpsvd: info: end %u\n", pid); + printf("%s: info: end %u\n", applet_name, pid); goto again; } /* Child */ -/* if (recvfrom(sock, 0, 0, MSG_PEEK, (struct sockaddr *)&sock_adr, &sockadr_size) == -1) - drop("unable to read from socket"); -*/ +#if 0 + /* I'd like to make it so that local addr is fixed to localp->sa, + * but how? The below trick doesn't work... */ + close(0); + set_nport(localp, htons(local_port)); + xmove_fd(xsocket(localp->sa.sa_family, SOCK_DGRAM, 0), 0); + xbind(0, &localp->sa, localp->len); +#endif + if (verbose) { - local_ip = argv[0]; // TODO: recv_from_to! - local_hostname = (char*)"localhost"; + local_ip = xmalloc_sockaddr2dotted_noport(&localp->sa, localp->len); + if (!local_hostname) { + local_hostname = xmalloc_sockaddr2host_noport(&localp->sa, localp->len); + if (!local_hostname) + bb_error_msg_and_die("cannot look up local hostname for %s", local_ip); + } } - remote_ip = xmalloc_sockaddr2dotted_noport(&sock_adr.sa, sockadr_size); - remote_port = get_nport(&sock_adr.sa); + remote_ip = xmalloc_sockaddr2dotted_noport(&remote.sa, localp->len); + remote_port = get_nport(&remote.sa); remote_port = ntohs(remote_port); - if (verbose) { - printf("udpsvd: info: pid %u from %s\n", pid, remote_ip); - } + if (verbose) + printf("%s: info: pid %u from %s\n", applet_name, pid, remote_ip); + if (opt & OPT_h) { - remote_hostname = xmalloc_sockaddr2host(&sock_adr.sa, sizeof(sock_adr)); + remote_hostname = xmalloc_sockaddr2host(&remote.sa, localp->len); if (!remote_hostname) { bb_error_msg("warning: cannot look up hostname for %s", remote_ip); remote_hostname = (char*)""; @@ -176,15 +173,15 @@ if (verbose) { #if 0 - out("udpsvd: info: "); + out("%s: info: ", applet_name); switch(ac) { case IPSVD_DENY: out("deny "); break; case IPSVD_DEFAULT: case IPSVD_INSTRUCT: out("start "); break; case IPSVD_EXEC: out("exec "); break; } #endif - printf("udpsvd: info: %u %s:%s :%s:%s:%u\n", - pid, local_hostname, local_ip, + printf("%s: info: %u %s:%s :%s:%s:%u\n", + applet_name, pid, local_hostname, local_ip, remote_hostname, remote_ip, remote_port); #if 0 if (instructs) { @@ -202,7 +199,7 @@ #if 0 if (ac == IPSVD_DENY) { - recv(s, 0, 0, 0); + recv(0, 0, 0, 0); _exit(100); } if (ac == IPSVD_EXEC) { @@ -213,14 +210,98 @@ run = args; } else run = prog; #endif - - xmove_fd(sock, 0); + /* Make plain write(1) work for the child by supplying default + * destination address */ + xconnect(0, &remote.sa, localp->len); dup2(0, 1); signal(SIGTERM, SIG_DFL); signal(SIGPIPE, SIG_DFL); + argv += 2; - BB_EXECVP(argv[0], argv); bb_perror_msg_and_die("exec '%s'", argv[0]); } + +/* +udpsvd [-hpvv] [-u user] [-l name] [-i dir|-x cdb] [-t sec] host port prog + +udpsvd creates an UDP/IP socket, binds it to the address host:port, +and listens on the socket for incoming datagrams. + +If a datagram is available on the socket, udpsvd conditionally starts +a program, with standard input reading from the socket, and standard +output redirected to standard error, to handle this, and possibly +more datagrams. udpsvd does not start the program if another program +that it has started before still is running. If the program exits, +udpsvd again listens to the socket until a new datagram is available. +If there are still datagrams available on the socket, the program +is restarted immediately. + +udpsvd optionally checks for special intructions depending on +the IP address or hostname of the client sending the datagram which +not yet was handled by a running program, see ipsvd-instruct(5) +for details. + +Attention: +UDP is a connectionless protocol. Most programs that handle user datagrams, +such as talkd(8), keep running after receiving a datagram, and process +subsequent datagrams sent to the socket until a timeout is reached. +udpsvd only checks special instructions for a datagram that causes a startup +of the program; not if a program handling datagrams already is running. +It doesn't make much sense to restrict access through special instructions +when using such a program. + +On the other hand, it makes perfectly sense with programs like tftpd(8), +that fork to establish a separate connection to the client when receiving +the datagram. In general it's adequate to set up special instructions for +programs that support being run by tcpwrapper. +Options + +host + host either is a hostname, or a dotted-decimal IP address, or 0. + If host is 0, udpsvd accepts datagrams to any local IP address. +port + udpsvd accepts datagrams to host:port. port may be a name from + /etc/services or a number. +prog + prog consists of one or more arguments. udpsvd normally runs prog + to handle a datagram, and possibly more, that is sent to the socket, + if there is no program that was started before by udpsvd still running + and handling datagrams. +-i dir + read instructions for handling new connections from the instructions + directory dir. See ipsvd-instruct(5) for details. +-x cdb + read instructions for handling new connections from the constant + database cdb. The constant database normally is created from + an instructions directory by running ipsvd-cdb(8). +-t sec + timeout. This option only takes effect if the -i option is given. + While checking the instructions directory, check the time of last + access of the file that matches the clients address or hostname if any, + discard and remove the file if it wasn't accessed within the last + sec seconds; udpsvd does not discard or remove a file if the user's + write permission is not set, for those files the timeout is disabled. + Default is 0, which means that the timeout is disabled. +-l name + local hostname. Do not look up the local hostname in DNS, but use name + as hostname. By default udpsvd looks up the local hostname once at startup. +-u user[:group] + drop permissions. Switch user ID to user's UID, and group ID to user's + primary GID after creating and binding to the socket. If user + is followed by a colon and a group name, the group ID is switched + to the GID of group instead. All supplementary groups are removed. +-h + Look up the client's hostname in DNS. +-p + paranoid. After looking up the client's hostname in DNS, look up + the IP addresses in DNS for that hostname, and forget the hostname + if none of the addresses match the client's IP address. You should + set this option if you use hostname based instructions. The -p option + implies the -h option. +-v + verbose. Print verbose messages to standard output. +-vv + more verbose. Print more verbose messages to standard output. +*/ From vda at busybox.net Tue Apr 3 05:09:48 2007 From: vda at busybox.net (vda at busybox.net) Date: Tue, 3 Apr 2007 05:09:48 -0700 (PDT) Subject: svn commit: trunk/busybox/ipsvd Message-ID: <20070403120948.6FBBE4801E@busybox.net> Author: vda Date: 2007-04-03 05:09:46 -0700 (Tue, 03 Apr 2007) New Revision: 18312 Log: ipsvd: fixes and improvements after testing Added: trunk/busybox/ipsvd/tcpudp.c Removed: trunk/busybox/ipsvd/tcpsvd.c trunk/busybox/ipsvd/udpsvd.c Modified: trunk/busybox/ipsvd/Kbuild Changeset: Sorry, the patch is too large to include (1641 lines). Please use ViewCVS to see it! http://busybox.net/cgi-bin/viewcvs.cgi?view=rev&root=svn&rev=18312 From vda at busybox.net Tue Apr 3 16:23:11 2007 From: vda at busybox.net (vda at busybox.net) Date: Tue, 3 Apr 2007 16:23:11 -0700 (PDT) Subject: svn commit: trunk/busybox: include ipsvd Message-ID: <20070403232311.5BA1548088@busybox.net> Author: vda Date: 2007-04-03 16:23:10 -0700 (Tue, 03 Apr 2007) New Revision: 18316 Log: ipsvd: make udpsvd work similar to tcpsvd (multiple parallel children for several streams of udp packets tested to work) code size: -509 bytes Modified: trunk/busybox/include/applets.h trunk/busybox/include/usage.h trunk/busybox/ipsvd/tcpudp.c Changeset: Modified: trunk/busybox/include/applets.h =================================================================== --- trunk/busybox/include/applets.h 2007-04-03 15:36:16 UTC (rev 18315) +++ trunk/busybox/include/applets.h 2007-04-03 23:23:10 UTC (rev 18316) @@ -132,8 +132,8 @@ //USE_E2FSCK(APPLET_NOUSAGE(fsck.ext2, e2fsck, _BB_DIR_SBIN, _BB_SUID_NEVER)) //USE_E2FSCK(APPLET_NOUSAGE(fsck.ext3, e2fsck, _BB_DIR_SBIN, _BB_SUID_NEVER)) USE_FSCK_MINIX(APPLET_ODDNAME(fsck.minix, fsck_minix, _BB_DIR_SBIN, _BB_SUID_NEVER, fsck_minix)) -USE_FTPGET(APPLET_ODDNAME(ftpget, ftpgetput, _BB_DIR_USR_BIN, _BB_SUID_NEVER,ftpget)) -USE_FTPPUT(APPLET_ODDNAME(ftpput, ftpgetput, _BB_DIR_USR_BIN, _BB_SUID_NEVER,ftpput)) +USE_FTPGET(APPLET_ODDNAME(ftpget, ftpgetput, _BB_DIR_USR_BIN, _BB_SUID_NEVER, ftpget)) +USE_FTPPUT(APPLET_ODDNAME(ftpput, ftpgetput, _BB_DIR_USR_BIN, _BB_SUID_NEVER, ftpput)) USE_FUSER(APPLET(fuser, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) USE_GETENFORCE(APPLET(getenforce, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) USE_GETOPT(APPLET(getopt, _BB_DIR_BIN, _BB_SUID_NEVER)) @@ -293,7 +293,7 @@ USE_TAIL(APPLET(tail, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) USE_TAR(APPLET(tar, _BB_DIR_BIN, _BB_SUID_NEVER)) USE_TASKSET(APPLET(taskset, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) -USE_TCPSVD(APPLET(tcpsvd, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) +USE_TCPSVD(APPLET_ODDNAME(tcpsvd, tcpudpsvd, _BB_DIR_USR_BIN, _BB_SUID_NEVER, tcpsvd)) USE_TEE(APPLET(tee, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) USE_TELNET(APPLET(telnet, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) USE_TELNETD(APPLET(telnetd, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) @@ -311,7 +311,7 @@ //USE_TUNE2FS(APPLET(tune2fs, _BB_DIR_SBIN, _BB_SUID_NEVER)) USE_APP_UDHCPC(APPLET(udhcpc, _BB_DIR_SBIN, _BB_SUID_NEVER)) USE_APP_UDHCPD(APPLET(udhcpd, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) -USE_UDPSVD(APPLET(udpsvd, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) +USE_UDPSVD(APPLET_ODDNAME(udpsvd, tcpudpsvd, _BB_DIR_USR_BIN, _BB_SUID_NEVER, udpsvd)) USE_UMOUNT(APPLET(umount, _BB_DIR_BIN, _BB_SUID_NEVER)) USE_UNAME(APPLET(uname, _BB_DIR_BIN, _BB_SUID_NEVER)) USE_UNCOMPRESS(APPLET(uncompress, _BB_DIR_BIN, _BB_SUID_NEVER)) Modified: trunk/busybox/include/usage.h =================================================================== --- trunk/busybox/include/usage.h 2007-04-03 15:36:16 UTC (rev 18315) +++ trunk/busybox/include/usage.h 2007-04-03 23:23:10 UTC (rev 18316) @@ -3331,7 +3331,7 @@ /* "[-hpEvv] [-c n] [-C n:msg] [-b n] [-u user] [-l name] [-i dir|-x cdb] [ -t sec] ip port prog..." */ #define tcpsvd_full_usage \ "Creates TCP socket, binds it to host:port and listens on in\n" \ - "for incoming connections. For each connection it runs prog" \ + "for incoming connections. For each connection it runs prog." \ "\n" \ "\nip IP to listen on. '0' = all" \ "\nport Port to listen on" \ @@ -3339,27 +3339,29 @@ "\n-l name Local hostname (else looks up local hostname in DNS)" \ "\n-u user[:group] Change to user/group after bind" \ "\n-c n Handle up to n connections simultaneously" \ + "\n-b n Allow a backlog of approximately n TCP SYNs" \ "\n-C n[:msg] Allow only up to n connections from the same IP" \ "\n New connections from this IP address are closed" \ "\n immediately. 'msg' is written to the peer before close" \ "\n-h Look up peer's hostname" \ - "\n-b n Allow a backlog of approximately n TCP SYNs" \ "\n-E Do not set up TCP-related environment variables" \ "\n-v Verbose" #define udpsvd_trivial_usage \ - "[-hv] [-u user] [-l name] host port prog" + "[-hEv] [-u user] [-l name] host port prog" #define udpsvd_full_usage \ "Creates UDP socket, binds it to host:port and listens on in\n" \ - "for incoming packets. When packet arrives it runs prog.\n" \ - "When prog exits, it start to listen on the socket again" \ + "for incoming packets. For each packet it runs prog\n" \ + "(redirecting all further packets with same peer ip:port to it)." \ "\n" \ "\nip IP to listen on. '0' = all" \ "\nport Port to listen on" \ "\nprog [arg] Program to run" \ "\n-l name Local hostname (else looks up local hostname in DNS)" \ "\n-u user[:group] Change to user/group after bind" \ + "\n-c n Handle up to n connections simultaneously" \ "\n-h Look up peer's hostname" \ + "\n-E Do not set up TCP-related environment variables" \ "\n-v Verbose" #define tftp_trivial_usage \ Modified: trunk/busybox/ipsvd/tcpudp.c =================================================================== --- trunk/busybox/ipsvd/tcpudp.c 2007-04-03 15:36:16 UTC (rev 18315) +++ trunk/busybox/ipsvd/tcpudp.c 2007-04-03 23:23:10 UTC (rev 18316) @@ -7,13 +7,52 @@ * Licensed under GPLv2, see file LICENSE in this tarball for details. */ -/* TCP and UDP server are using a lot of same string constants - * We reuse them by keeping both in one source file */ +/* Based on ipsvd ipsvd-0.12.1. This tcpsvd accepts all options + * which are supported by one from ipsvd-0.12.1, but not all are + * functional. See help text at the end of this file for details. + * + * Code inside "#ifdef SSLSVD" is for sslsvd and is currently unused. + * + * Output of verbose mode matches original (modulo bugs and + * unimplemented stuff). Unnatural splitting of IP and PORT + * is retained (personally I prefer one-value "IP:PORT" notation - + * it is a natural string representation of struct sockaddr_XX). + * + * TCPORIGDST{IP,PORT} is busybox-specific addition + * + * udp server is hacked up by reusing TCP code. It has the following + * limitation inherent in Unix DGRAM sockets implementation: + * - local IP address is reptrieved (using recvmsg voodoo) but + * child's socket is not bound to it (bind cannot be called on + * already bound socket). Thus you still can get outgoing packets + * with wrong sorce IP... + * - don't know how to retrieve ORIGDST for udp. + */ +#include +#include /* wants */ + #include "busybox.h" +#include "udp_io.c" +#include "ipsvd_perhost.h" + +#ifdef SSLSVD +#include "matrixSsl.h" +#include "ssl_io.h" +#endif + static unsigned verbose; +static unsigned max_per_host; +static unsigned cur_per_host; +static unsigned cnum; +static unsigned cmax = 30; +static void xsetenv_proto(const char *proto, const char *n, const char *v) +{ + putenv(xasprintf("%s%s=%s", proto, n, v)); +} + static void sig_term_handler(int sig) { if (verbose) @@ -38,287 +77,6 @@ printf("%s: info: end %d %s %d\n", applet_name, pid, cause, e); } - -#if ENABLE_UDPSVD -/* Based on ipsvd ipsvd-0.12.1. This udpsvd accepts all options - * which are supported by one from ipsvd-0.12.1, but not all are - * functional. See help text at the end of this file for details. - * - * Output of verbose mode matches original (modulo bugs and - * unimplemented stuff). Unnatural splitting of IP and PORT - * is retained (personally I prefer one-value "IP:PORT" notation - - * it is a natural string representation of struct sockaddr_XX). - */ - -#include "udp_io.c" - -int udpsvd_main(int argc, char **argv); -int udpsvd_main(int argc, char **argv) -{ - const char *instructs; - char *str_t, *user; - unsigned opt; - - char *remote_hostname = (char*)""; /* used if no -h */ - char *local_hostname = NULL; - char *remote_ip; - char *local_ip;// = local_ip; /* gcc */ - uint16_t local_port, remote_port; - len_and_sockaddr remote; - len_and_sockaddr *localp; - int wstat; - unsigned pid; - struct bb_uidgid_t ugid; - - enum { - OPT_v = (1 << 0), - OPT_u = (1 << 1), - OPT_l = (1 << 2), - OPT_h = (1 << 3), - OPT_p = (1 << 4), - OPT_i = (1 << 5), - OPT_x = (1 << 6), - OPT_t = (1 << 7), - }; - - opt_complementary = "-3:ph:vv"; - opt = getopt32(argc, argv, "vu:l:hpi:x:t:", - &user, &local_hostname, &instructs, &instructs, &str_t, &verbose); - if (opt & OPT_u) { - if (!get_uidgid(&ugid, user, 1)) - bb_error_msg_and_die("unknown user/group: %s", user); - } - argv += optind; - if (!argv[0][0] || LONE_CHAR(argv[0], '0')) - argv[0] = (char*)"0.0.0.0"; - - /* stdout is used for logging, don't buffer */ - setlinebuf(stdout); - bb_sanitize_stdio(); /* fd# 1,2 must be opened */ - - signal(SIGTERM, sig_term_handler); - signal(SIGPIPE, SIG_IGN); - - local_port = bb_lookup_port(argv[1], "udp", 0); - localp = xhost2sockaddr(argv[0], local_port); - /* fd #0 is the open UDP socket */ - xmove_fd(xsocket(localp->sa.sa_family, SOCK_DGRAM, 0), 0); - setsockopt_reuseaddr(0); /* crucial */ - xbind(0, &localp->sa, localp->len); - socket_want_pktinfo(0); /* needed for recv_from_to to work */ - - if (opt & OPT_u) { /* drop permissions */ - xsetgid(ugid.gid); - xsetuid(ugid.uid); - } - - if (verbose) { - /* we do it only for ":port" cosmetics... oh well */ - char *addr = xmalloc_sockaddr2dotted(&localp->sa, localp->len); - - printf("%s: info: listening on %s", applet_name, addr); - free(addr); - if (option_mask32 & OPT_u) - printf(", uid %u, gid %u", - (unsigned)ugid.uid, (unsigned)ugid.gid); - puts(", starting"); - } - - again: - /* if (recvfrom(0, NULL, 0, MSG_PEEK, &remote.sa, &localp->len) < 0) { */ - if (recv_from_to(0, NULL, 0, MSG_PEEK, &remote.sa, &localp->sa, localp->len) < 0) { - bb_perror_msg("recvfrom"); - goto again; - } - - while ((pid = fork()) < 0) { - bb_perror_msg("fork failed, sleeping"); - sleep(5); - } - if (pid > 0) { /* parent */ - while (wait_pid(&wstat, pid) < 0) - bb_perror_msg("error waiting for child"); - if (verbose) - print_waitstat(pid, wstat); - goto again; - } - - /* Child */ - - if (verbose) { - remote_ip = xmalloc_sockaddr2dotted_noport(&remote.sa, localp->len); - local_ip = xmalloc_sockaddr2dotted_noport(&localp->sa, localp->len); - - pid = getpid(); - printf("%s: info: pid %u from %s\n", applet_name, pid, remote_ip); - - if (!local_hostname) { - local_hostname = xmalloc_sockaddr2host_noport(&localp->sa, localp->len); - if (!local_hostname) - bb_error_msg_and_die("cannot look up local hostname for %s", local_ip); - } - if (opt & OPT_h) { - remote_hostname = xmalloc_sockaddr2host(&remote.sa, localp->len); - if (!remote_hostname) { - bb_error_msg("warning: cannot look up hostname for %s", remote_ip); - remote_hostname = (char*)""; - } - } - - remote_port = get_nport(&remote.sa); - remote_port = ntohs(remote_port); - printf("%s: info: %u %s:%s :%s:%s:%u\n", - applet_name, pid, local_hostname, local_ip, - remote_hostname, remote_ip, remote_port); - } - - /* Doesn't work: - * we cannot replace fd #0 - we will lose pending packet - * which is already buffered for us! And we cannot use fd #1 - * instead - it will "intercept" all following packets, but child - * do not expect data coming *from fd #1*! */ -#if 0 - /* Make it so that local addr is fixed to localp->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); - setsockopt_reuseaddr(0); /* crucial */ - xbind(0, &localp->sa, localp->len); -#endif - - /* Make plain write to fd #1 work for the child by supplying default - * destination address. This also restricts incoming packets - * to ones coming from this remote IP. */ - xconnect(0, &remote.sa, localp->len); - dup2(0 ,1); - - signal(SIGTERM, SIG_DFL); - signal(SIGPIPE, SIG_DFL); - - argv += 2; - BB_EXECVP(argv[0], argv); - bb_perror_msg_and_die("exec '%s'", argv[0]); -} - - -/* -udpsvd [-hpvv] [-u user] [-l name] [-i dir|-x cdb] [-t sec] host port prog - -udpsvd creates an UDP/IP socket, binds it to the address host:port, -and listens on the socket for incoming datagrams. - -If a datagram is available on the socket, udpsvd conditionally starts -a program, with standard input reading from the socket, and standard -output redirected to standard error, to handle this, and possibly -more datagrams. udpsvd does not start the program if another program -that it has started before still is running. If the program exits, -udpsvd again listens to the socket until a new datagram is available. -If there are still datagrams available on the socket, the program -is restarted immediately. - -udpsvd optionally checks for special intructions depending on -the IP address or hostname of the client sending the datagram which -not yet was handled by a running program, see ipsvd-instruct(5) -for details. - -Attention: -UDP is a connectionless protocol. Most programs that handle user datagrams, -such as talkd(8), keep running after receiving a datagram, and process -subsequent datagrams sent to the socket until a timeout is reached. -udpsvd only checks special instructions for a datagram that causes a startup -of the program; not if a program handling datagrams already is running. -It doesn't make much sense to restrict access through special instructions -when using such a program. - -On the other hand, it makes perfectly sense with programs like tftpd(8), -that fork to establish a separate connection to the client when receiving -the datagram. In general it's adequate to set up special instructions for -programs that support being run by tcpwrapper. -Options - -host - host either is a hostname, or a dotted-decimal IP address, or 0. - If host is 0, udpsvd accepts datagrams to any local IP address. -port - udpsvd accepts datagrams to host:port. port may be a name from - /etc/services or a number. -prog - prog consists of one or more arguments. udpsvd normally runs prog - to handle a datagram, and possibly more, that is sent to the socket, - if there is no program that was started before by udpsvd still running - and handling datagrams. --i dir - read instructions for handling new connections from the instructions - directory dir. See ipsvd-instruct(5) for details. --x cdb - read instructions for handling new connections from the constant - database cdb. The constant database normally is created from - an instructions directory by running ipsvd-cdb(8). --t sec - timeout. This option only takes effect if the -i option is given. - While checking the instructions directory, check the time of last - access of the file that matches the clients address or hostname if any, - discard and remove the file if it wasn't accessed within the last - sec seconds; udpsvd does not discard or remove a file if the user's - write permission is not set, for those files the timeout is disabled. - Default is 0, which means that the timeout is disabled. --l name - local hostname. Do not look up the local hostname in DNS, but use name - as hostname. By default udpsvd looks up the local hostname once at startup. --u user[:group] - drop permissions. Switch user ID to user's UID, and group ID to user's - primary GID after creating and binding to the socket. If user - is followed by a colon and a group name, the group ID is switched - to the GID of group instead. All supplementary groups are removed. --h - Look up the client's hostname in DNS. --p - paranoid. After looking up the client's hostname in DNS, look up - the IP addresses in DNS for that hostname, and forget the hostname - if none of the addresses match the client's IP address. You should - set this option if you use hostname based instructions. The -p option - implies the -h option. --v - verbose. Print verbose messages to standard output. --vv - more verbose. Print more verbose messages to standard output. -*/ -#endif - - -#if ENABLE_TCPSVD -/* Based on ipsvd ipsvd-0.12.1. This tcpsvd accepts all options - * which are supported by one from ipsvd-0.12.1, but not all are - * functional. See help text at the end of this file for details. - * - * Code inside "#ifdef SSLSVD" is for sslsvd and is currently unused. - * - * Output of verbose mode matches original (modulo bugs and - * unimplemented stuff). Unnatural splitting of IP and PORT - * is retained (personally I prefer one-value "IP:PORT" notation - - * it is a natural string representation of struct sockaddr_XX). - * - * TCPORIGDST{IP,PORT} is busybox-specific addition - */ - -#include -#include /* wants */ -#include "ipsvd_perhost.h" - -#ifdef SSLSVD -#include "matrixSsl.h" -#include "ssl_io.h" -#endif - -static unsigned max_per_host; /* originally in ipsvd_check.c */ -static unsigned cur_per_host; -static unsigned cnum; -static unsigned cmax = 30; - /* Must match getopt32 in main! */ enum { OPT_c = (1 << 0), @@ -342,7 +100,9 @@ static void connection_status(void) { - printf("%s: info: status %u/%u\n", applet_name, cnum, cmax); + /* UDP and "only 1 client max" TCP don't need this */ + if (cmax > 1) + printf("%s: info: status %u/%u\n", applet_name, cnum, cmax); } static void sig_child_handler(int sig) @@ -362,8 +122,8 @@ connection_status(); } -int tcpsvd_main(int argc, char **argv); -int tcpsvd_main(int argc, char **argv) +int tcpudpsvd_main(int argc, char **argv); +int tcpudpsvd_main(int argc, char **argv) { char *str_c, *str_C, *str_b, *str_t; char *user; @@ -372,11 +132,13 @@ char *msg_per_host = NULL; unsigned len_per_host = len_per_host; /* gcc */ int need_hostnames, need_remote_ip; + int tcp; int pid; int sock; int conn; unsigned backlog = 20; len_and_sockaddr *lsa; + len_and_sockaddr local, remote; uint16_t local_port; uint16_t remote_port = remote_port; /* gcc */ char *local_hostname = NULL; @@ -386,6 +148,7 @@ #ifndef SSLSVD struct bb_uidgid_t ugid; #endif + tcp = (applet_name[0] == 't'); /* 3+ args, -i at most once, -p implies -h, -v is counter */ opt_complementary = "-3:?:i--i:ph:vv"; @@ -420,18 +183,22 @@ if (option_mask32 & OPT_b) backlog = xatou(str_b); #ifdef SSLSVD - if (option_mask32 & OPT_U) ssluser = (char*)optarg; break; - if (option_mask32 & OPT_slash) root = (char*)optarg; break; - if (option_mask32 & OPT_Z) cert = (char*)optarg; break; - if (option_mask32 & OPT_K) key = (char*)optarg; break; + if (option_mask32 & OPT_U) ssluser = optarg; + if (option_mask32 & OPT_slash) root = optarg; + if (option_mask32 & OPT_Z) cert = optarg; + if (option_mask32 & OPT_K) key = optarg; #endif argv += optind; if (!argv[0][0] || LONE_CHAR(argv[0], '0')) argv[0] = (char*)"0.0.0.0"; + /* Per-IP flood protection is not thought-out for UDP */ + if (!tcp) + max_per_host = 0; + /* stdout is used for logging, don't buffer */ setlinebuf(stdout); - bb_sanitize_stdio(); /* fd# 1,2 must be opened */ + bb_sanitize_stdio(); /* fd# 0,1,2 must be opened */ need_hostnames = verbose || !(option_mask32 & OPT_E); need_remote_ip = max_per_host || need_hostnames; @@ -473,12 +240,15 @@ if (max_per_host) ipsvd_perhost_init(cmax); - local_port = bb_lookup_port(argv[1], "tcp", 0); + local_port = bb_lookup_port(argv[1], tcp ? "tcp" : "udp", 0); lsa = xhost2sockaddr(argv[0], local_port); - sock = xsocket(lsa->sa.sa_family, SOCK_STREAM, 0); - setsockopt_reuseaddr(sock); /* desirable */ + sock = xsocket(lsa->sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0); + setsockopt_reuseaddr(sock); xbind(sock, &lsa->sa, lsa->len); - xlisten(sock, backlog); + if (tcp) + xlisten(sock, backlog); + else /* udp: needed for recv_from_to to work: */ + socket_want_pktinfo(sock); /* ndelay_off(sock); - it is the default I think? */ #ifndef SSLSVD @@ -503,7 +273,7 @@ puts(", starting"); } - /* The rest is a main accept() loop */ + /* Main accept() loop */ again: hccp = NULL; @@ -516,19 +286,23 @@ close(0); again2: sig_unblock(SIGCHLD); - conn = accept(sock, &lsa->sa, &lsa->len); + if (tcp) { + remote.len = lsa->len; + conn = accept(sock, &remote.sa, &remote.len); + } else + conn = recv_from_to(sock, NULL, 0, MSG_PEEK, &remote.sa, &local.sa, lsa->len); sig_block(SIGCHLD); if (conn < 0) { if (errno != EINTR) - bb_perror_msg("accept"); + bb_perror_msg(tcp ? "accept" : "recv"); goto again2; } - xmove_fd(conn, 0); + xmove_fd(tcp ? conn : sock, 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(&lsa->sa, lsa->len); + remote_ip = xmalloc_sockaddr2dotted_noport(&remote.sa, lsa->len); 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 @@ -543,17 +317,33 @@ } } - cnum++; - if (verbose) - connection_status(); + if (!tcp) { + /* Voodoo magic: making udp sockets each receive its own + * packets is not trivial */ + /* Make plain write 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, lsa->len); + /* Open new non-connected UDP socket for further clients */ + sock = xsocket(lsa->sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0); + setsockopt_reuseaddr(sock); + xbind(sock, &lsa->sa, lsa->len); + socket_want_pktinfo(sock); + } + pid = fork(); if (pid == -1) { bb_perror_msg("fork"); goto again; } + + if (pid != 0) { /* parent */ + cnum++; + if (verbose) + connection_status(); if (hccp) hccp->pid = pid; goto again; @@ -561,35 +351,38 @@ /* Child: prepare env, log, and exec prog */ - close(sock); /* listening socket */ - /* Find out local IP peer connected to. - * Errors ignored (I'm not paranoid enough to imagine kernel - * which doesn't know local IP). */ - getsockname(0, &lsa->sa, &lsa->len); + /* Closing tcp listening socket */ + if (tcp) + close(sock); if (need_remote_ip) { if (!max_per_host) - remote_ip = xmalloc_sockaddr2dotted_noport(&lsa->sa, lsa->len); + remote_ip = xmalloc_sockaddr2dotted_noport(&remote.sa, lsa->len); /* else it is already done */ - remote_port = get_nport(&lsa->sa); + remote_port = get_nport(&remote.sa); remote_port = ntohs(remote_port); } if (need_hostnames) { if (option_mask32 & OPT_h) { - remote_hostname = xmalloc_sockaddr2host(&lsa->sa, lsa->len); + remote_hostname = xmalloc_sockaddr2host(&remote.sa, lsa->len); if (!remote_hostname) { bb_error_msg("warning: cannot look up hostname for %s", remote_ip); remote_hostname = (char*)""; } } - local_ip = xmalloc_sockaddr2dotted_noport(&lsa->sa, lsa->len); - local_port = get_nport(&lsa->sa); + /* Find out local IP peer connected to. + * Errors ignored (I'm not paranoid enough to imagine kernel + * which doesn't know local IP). */ + if (tcp) + getsockname(0, &local.sa, &local.len); + local_ip = xmalloc_sockaddr2dotted_noport(&local.sa, lsa->len); + local_port = get_nport(&local.sa); local_port = ntohs(local_port); if (!local_hostname) { - local_hostname = xmalloc_sockaddr2host_noport(&lsa->sa, lsa->len); + local_hostname = xmalloc_sockaddr2host_noport(&local.sa, lsa->len); if (!local_hostname) - bb_error_msg_and_die("cannot look up local hostname for %s", local_ip); + bb_error_msg_and_die("warning: cannot look up hostname for %s"+9, local_ip); } } @@ -605,14 +398,16 @@ remote_hostname, remote_ip, (unsigned)remote_port); } +// TODO: stop splitiing port# from IP? if (!(option_mask32 & OPT_E)) { /* setup ucspi env */ + const char *proto = tcp ? "TCP" : "UDP"; /* Extract "original" destination addr:port * 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 (getsockopt(0, SOL_IP, SO_ORIGINAL_DST, &lsa->sa, &lsa->len) == 0) { + if (tcp && getsockopt(0, SOL_IP, SO_ORIGINAL_DST, &lsa->sa, &lsa->len) == 0) { char *ip = xmalloc_sockaddr2dotted_noport(&lsa->sa, lsa->len); unsigned port = get_nport(&lsa->sa); port = ntohs(port); @@ -620,18 +415,18 @@ xsetenv("TCPORIGDSTPORT", utoa(port)); free(ip); } - xsetenv("PROTO", "TCP"); - xsetenv("TCPLOCALIP", local_ip); - xsetenv("TCPLOCALPORT", utoa(local_port)); - xsetenv("TCPLOCALHOST", local_hostname); - xsetenv("TCPREMOTEIP", remote_ip); - xsetenv("TCPREMOTEPORT", utoa(remote_port)); + xsetenv("PROTO", proto); + xsetenv_proto(proto, "LOCALIP", local_ip); + xsetenv_proto(proto, "LOCALPORT", utoa(local_port)); + xsetenv_proto(proto, "LOCALHOST", local_hostname); + xsetenv_proto(proto, "REMOTEIP", remote_ip); + xsetenv_proto(proto, "REMOTEPORT", utoa(remote_port)); if (option_mask32 & OPT_h) { - xsetenv("TCPREMOTEHOST", remote_hostname); + xsetenv_proto(proto, "REMOTEHOST", remote_hostname); } - xsetenv("TCPREMOTEINFO", ""); + xsetenv_proto(proto, "REMOTEINFO", ""); /* additional */ - if (cur_per_host > 0) + if (cur_per_host > 0) /* can not be true for udp */ xsetenv("TCPCONCURRENCY", utoa(cur_per_host)); } @@ -747,4 +542,3 @@ more verbose. Print more verbose messages to standard output. * no difference between -v and -vv in busyboxed version */ -#endif From vda at busybox.net Wed Apr 4 03:16:15 2007 From: vda at busybox.net (vda at busybox.net) Date: Wed, 4 Apr 2007 03:16:15 -0700 (PDT) Subject: svn commit: trunk/busybox/ipsvd Message-ID: <20070404101615.78C2B48097@busybox.net> Author: vda Date: 2007-04-04 03:16:15 -0700 (Wed, 04 Apr 2007) New Revision: 18318 Log: ipsvd: use IP:PORT syntax for environment vars. Pros: 1. it's saner (matches internal libc sockaddr abstraction). 2. it's smaller. Cons: not compatible with smarden's ipsvd. Fix IPv6 define typos. Stop interpreting options in prog's args. Code size -162 bytes. Modified: trunk/busybox/ipsvd/tcpudp.c trunk/busybox/ipsvd/udp_io.c Changeset: Modified: trunk/busybox/ipsvd/tcpudp.c =================================================================== --- trunk/busybox/ipsvd/tcpudp.c 2007-04-03 23:50:10 UTC (rev 18317) +++ trunk/busybox/ipsvd/tcpudp.c 2007-04-04 10:16:15 UTC (rev 18318) @@ -22,9 +22,9 @@ * * udp server is hacked up by reusing TCP code. It has the following * limitation inherent in Unix DGRAM sockets implementation: - * - local IP address is reptrieved (using recvmsg voodoo) but + * - local IP address is retrieved (using recvmsg voodoo) but * child's socket is not bound to it (bind cannot be called on - * already bound socket). Thus you still can get outgoing packets + * already bound socket). Thus it still can emit outgoing packets * with wrong sorce IP... * - don't know how to retrieve ORIGDST for udp. */ @@ -100,7 +100,7 @@ static void connection_status(void) { - /* UDP and "only 1 client max" TCP don't need this */ + /* "only 1 client max" don't need this */ if (cmax > 1) printf("%s: info: status %u/%u\n", applet_name, cnum, cmax); } @@ -131,34 +131,35 @@ const char *instructs; char *msg_per_host = NULL; unsigned len_per_host = len_per_host; /* gcc */ - int need_hostnames, need_remote_ip; - int tcp; +#ifndef SSLSVD + struct bb_uidgid_t ugid; +#endif + bool need_hostnames, need_remote_ip, tcp; + uint16_t local_port; + char *local_hostname = NULL; + char *remote_hostname = (char*)""; /* "" used if no -h */ + char *local_addr = local_addr; /* gcc */ + char *remote_addr = remote_addr; /* gcc */ + char *remote_ip = remote_addr; /* gcc */ + len_and_sockaddr *lsa; + len_and_sockaddr local, remote; + socklen_t sa_len; int pid; int sock; int conn; unsigned backlog = 20; - len_and_sockaddr *lsa; - len_and_sockaddr local, remote; - uint16_t local_port; - uint16_t remote_port = remote_port; /* gcc */ - char *local_hostname = NULL; - char *remote_hostname = (char*)""; /* "" used if no -h */ - char *local_ip = local_ip; /* gcc */ - char *remote_ip = remote_ip; /* gcc */ -#ifndef SSLSVD - struct bb_uidgid_t ugid; -#endif + tcp = (applet_name[0] == 't'); /* 3+ args, -i at most once, -p implies -h, -v is counter */ opt_complementary = "-3:?:i--i:ph:vv"; #ifdef SSLSVD - getopt32(argc, argv, "c:C:i:x:u:l:Eb:hpt:vU:/:Z:K:", + getopt32(argc, argv, "+c:C:i:x:u:l:Eb:hpt:vU:/:Z:K:", &str_c, &str_C, &instructs, &instructs, &user, &local_hostname, &str_b, &str_t, &ssluser, &root, &cert, &key, &verbose ); #else - getopt32(argc, argv, "c:C:i:x:u:l:Eb:hpt:v", + getopt32(argc, argv, "+c:C:i:x:u:l:Eb:hpt:v", &str_c, &str_C, &instructs, &instructs, &user, &local_hostname, &str_b, &str_t, &verbose ); @@ -213,10 +214,8 @@ if (option_mask32 & OPT_u) if (!uidgid_get(&sslugid, ssluser, 1)) { if (errno) { - xfunc_exitcode = 100; bb_perror_msg_and_die("fatal: cannot get user/group: %s", ssluser); } - xfunc_exitcode = 111; bb_error_msg_and_die("fatal: unknown user/group '%s'", ssluser); } if (!cert) cert = "./cert.pem"; @@ -244,7 +243,8 @@ lsa = xhost2sockaddr(argv[0], local_port); sock = xsocket(lsa->sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0); setsockopt_reuseaddr(sock); - xbind(sock, &lsa->sa, lsa->len); + sa_len = lsa->len; /* I presume sockaddr len stays the same */ + xbind(sock, &lsa->sa, sa_len); if (tcp) xlisten(sock, backlog); else /* udp: needed for recv_from_to to work: */ @@ -260,9 +260,7 @@ #endif if (verbose) { - /* we do it only for ":port" cosmetics... oh well */ - char *addr = xmalloc_sockaddr2dotted(&lsa->sa, lsa->len); - + char *addr = xmalloc_sockaddr2dotted(&lsa->sa, sa_len); printf("%s: info: listening on %s", applet_name, addr); free(addr); #ifndef SSLSVD @@ -287,10 +285,14 @@ again2: sig_unblock(SIGCHLD); if (tcp) { - remote.len = lsa->len; + remote.len = sa_len; conn = accept(sock, &remote.sa, &remote.len); - } else - conn = recv_from_to(sock, NULL, 0, MSG_PEEK, &remote.sa, &local.sa, lsa->len); + } else { + /* In case we won't be able to recover local below. + * 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); + } sig_block(SIGCHLD); if (conn < 0) { if (errno != EINTR) @@ -302,7 +304,7 @@ 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, lsa->len); + remote_ip = xmalloc_sockaddr2dotted_noport(&remote.sa, sa_len); 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 @@ -319,16 +321,21 @@ if (!tcp) { /* Voodoo magic: making udp sockets each receive its own - * packets is not trivial */ + * packets is not trivial, and I still not sure + * I do it 100% right. + * 1) we have to do it before fork() + * 2) order is important - is it right now? */ - /* Make plain write work for this socket by supplying default + /* 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, lsa->len); + xconnect(0, &remote.sa, sa_len); + /* hole? at this point we have no wildcard udp socket... + * can this cause clients to get "port unreachable" icmp? */ /* Open new non-connected UDP socket for further clients */ sock = xsocket(lsa->sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0); setsockopt_reuseaddr(sock); - xbind(sock, &lsa->sa, lsa->len); + xbind(sock, &lsa->sa, sa_len); socket_want_pktinfo(sock); } @@ -355,50 +362,44 @@ if (tcp) close(sock); - if (need_remote_ip) { - if (!max_per_host) - remote_ip = xmalloc_sockaddr2dotted_noport(&remote.sa, lsa->len); - /* else it is already done */ - remote_port = get_nport(&remote.sa); - remote_port = ntohs(remote_port); - } + if (need_remote_ip) + remote_addr = xmalloc_sockaddr2dotted(&remote.sa, sa_len); if (need_hostnames) { if (option_mask32 & OPT_h) { - remote_hostname = xmalloc_sockaddr2host(&remote.sa, lsa->len); + remote_hostname = xmalloc_sockaddr2host_noport(&remote.sa, sa_len); if (!remote_hostname) { - bb_error_msg("warning: cannot look up hostname for %s", remote_ip); + bb_error_msg("warning: cannot look up hostname for %s", remote_addr); remote_hostname = (char*)""; } } /* Find out local IP peer connected to. * Errors ignored (I'm not paranoid enough to imagine kernel * which doesn't know local IP). */ - if (tcp) + if (tcp) { + local.len = sa_len; getsockname(0, &local.sa, &local.len); - local_ip = xmalloc_sockaddr2dotted_noport(&local.sa, lsa->len); - local_port = get_nport(&local.sa); - local_port = ntohs(local_port); + } + local_addr = xmalloc_sockaddr2dotted(&local.sa, sa_len); if (!local_hostname) { - local_hostname = xmalloc_sockaddr2host_noport(&local.sa, lsa->len); + local_hostname = xmalloc_sockaddr2host_noport(&local.sa, sa_len); if (!local_hostname) - bb_error_msg_and_die("warning: cannot look up hostname for %s"+9, local_ip); + bb_error_msg_and_die("warning: cannot look up hostname for %s"+9, local_addr); } } if (verbose) { pid = getpid(); - printf("%s: info: pid %u from %s\n", applet_name, pid, remote_ip); + printf("%s: info: pid %u from %s\n", applet_name, pid, remote_addr); if (max_per_host) printf("%s: info: concurrency %u %s %u/%u\n", applet_name, pid, remote_ip, cur_per_host, max_per_host); - printf("%s: info: start %u %s:%s :%s:%s:%u\n", + printf("%s: info: start %u %s:%s :%s:%s\n", applet_name, pid, - local_hostname, local_ip, - remote_hostname, remote_ip, (unsigned)remote_port); + local_hostname, local_addr, + remote_hostname, remote_addr); } -// TODO: stop splitiing port# from IP? if (!(option_mask32 & OPT_E)) { /* setup ucspi env */ const char *proto = tcp ? "TCP" : "UDP"; @@ -408,19 +409,14 @@ * 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 *ip = xmalloc_sockaddr2dotted_noport(&lsa->sa, lsa->len); - unsigned port = get_nport(&lsa->sa); - port = ntohs(port); - xsetenv("TCPORIGDSTIP", ip); - xsetenv("TCPORIGDSTPORT", utoa(port)); - free(ip); + char *addr = xmalloc_sockaddr2dotted(&lsa->sa, sa_len); + xsetenv("TCPORIGDSTADDR", addr); + free(addr); } xsetenv("PROTO", proto); - xsetenv_proto(proto, "LOCALIP", local_ip); - xsetenv_proto(proto, "LOCALPORT", utoa(local_port)); + xsetenv_proto(proto, "LOCALADDR", local_addr); xsetenv_proto(proto, "LOCALHOST", local_hostname); - xsetenv_proto(proto, "REMOTEIP", remote_ip); - xsetenv_proto(proto, "REMOTEPORT", utoa(remote_port)); + xsetenv_proto(proto, "REMOTEADDR", remote_addr); if (option_mask32 & OPT_h) { xsetenv_proto(proto, "REMOTEHOST", remote_hostname); } Modified: trunk/busybox/ipsvd/udp_io.c =================================================================== --- trunk/busybox/ipsvd/udp_io.c 2007-04-03 23:50:10 UTC (rev 18317) +++ trunk/busybox/ipsvd/udp_io.c 2007-04-04 10:16:15 UTC (rev 18318) @@ -18,12 +18,13 @@ #ifdef IP_PKTINFO setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &const_int_1, sizeof(int)); #endif -#ifdef IPV6_PKTINFO +#if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO) setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &const_int_1, sizeof(int)); #endif } +#ifdef UNUSED ssize_t send_to_from(int fd, void *buf, size_t len, int flags, const struct sockaddr *from, const struct sockaddr *to, @@ -34,8 +35,11 @@ #else struct iovec iov[1]; struct msghdr msg; - char cbuf[LSA_SIZEOF_SA]; - /* actually, max(sizeof(in_pktinfo),sizeof(in6_pktinfo)) */ + char cbuf[sizeof(struct in_pktinfo) +#if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO) + | sizeof(struct in6_pktinfo) /* (a|b) is poor man's max(a,b) */ +#endif + ]; struct cmsghdr* cmsgptr; if (from->sa_family != AF_INET @@ -73,11 +77,11 @@ /* pktptr->ipi_ifindex = 0; -- already done by memset(cbuf...) */ pktptr->ipi_spec_dst = ((struct sockaddr_in*)from)->sin_addr; } -#if ENABLE_FEATURE_IPV6 && defined(IP6_PKTINFO) +#if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO) else if (to->sa_family == AF_INET6 && from->sa_family == AF_INET6) { struct in6_pktinfo *pktptr; cmsgptr->cmsg_level = IPPROTO_IPV6; - cmsgptr->cmsg_type = IP6_PKTINFO; + cmsgptr->cmsg_type = IPV6_PKTINFO; cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); pktptr = (struct in6_pktinfo *)(CMSG_DATA(cmsgptr)); /* pktptr->ipi6_ifindex = 0; -- already done by memset(cbuf...) */ @@ -87,8 +91,12 @@ return sendmsg(fd, &msg, flags); #endif } +#endif /* UNUSED */ -/* NB: this will never set port# in *to! */ +/* NB: this will never set port# in 'to'! + * _Only_ IP/IPv6 address part of 'to' is _maybe_ modified. + * Typical usage is to preinit it with "default" value + * before calling recv_from_to(). */ ssize_t recv_from_to(int fd, void *buf, size_t len, int flags, struct sockaddr *from, struct sockaddr *to, @@ -123,7 +131,6 @@ return recv_length; /* Here we try to retrieve destination IP and memorize it */ - memset(to, 0, sa_size); for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr) @@ -138,9 +145,9 @@ #undef pktinfo break; } -#if ENABLE_FEATURE_IPV6 && defined(IP6_PKTINFO) +#if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO) if (cmsgptr->cmsg_level == IPPROTO_IPV6 - && cmsgptr->cmsg_type == IP6_PKTINFO + && cmsgptr->cmsg_type == IPV6_PKTINFO ) { #define pktinfo(cmsgptr) ( (struct in6_pktinfo*)(CMSG_DATA(cmsgptr)) ) to->sa_family = AF_INET6; From vda at busybox.net Wed Apr 4 04:02:56 2007 From: vda at busybox.net (vda at busybox.net) Date: Wed, 4 Apr 2007 04:02:56 -0700 (PDT) Subject: svn commit: trunk/busybox: include ipsvd Message-ID: <20070404110256.CCD8B4808B@busybox.net> Author: vda Date: 2007-04-04 04:02:55 -0700 (Wed, 04 Apr 2007) New Revision: 18319 Log: Add/improve comment, shorten some usage texts. No code changes. Modified: trunk/busybox/include/usage.h trunk/busybox/ipsvd/tcpudp.c trunk/busybox/ipsvd/udp_io.c Changeset: Modified: trunk/busybox/include/usage.h =================================================================== --- trunk/busybox/include/usage.h 2007-04-04 10:16:15 UTC (rev 18318) +++ trunk/busybox/include/usage.h 2007-04-04 11:02:55 UTC (rev 18319) @@ -37,7 +37,7 @@ "Read and optionally set system timebase parameters.\n" \ "See adjtimex(2)." \ "\n\nOptions:\n" \ - " -q Quiet mode - do not print\n" \ + " -q Quiet\n" \ " -o offset Time offset, microseconds\n" \ " -f frequency Frequency adjust, integer kernel units (65536 is 1ppm)\n" \ " (positive values make the system clock run fast)\n" \ @@ -53,7 +53,7 @@ " -p Extract to stdout\n" \ " -t List\n" \ " -x Extract\n" \ - " -v Verbosely list files processed" + " -v Verbose" #define arp_trivial_usage \ "\n" \ @@ -81,7 +81,7 @@ "Ping hosts by ARP requests/replies" \ "\n\nOptions:\n" \ " -f Quit on first ARP reply\n" \ - " -q Be quiet\n" \ + " -q Quiet\n" \ " -b Keep broadcasting, don't go unicast\n" \ " -D Duplicated address detection mode\n" \ " -U Unsolicited ARP mode, update your neighbours\n" \ @@ -383,7 +383,7 @@ "\n\nOptions:\n" \ " -l Write the byte numbers (decimal) and values (octal)\n" \ " for all differing bytes\n" \ - " -s Quiet mode - do not print" + " -s Quiet" #define comm_trivial_usage \ "[-123] FILE1 FILE2" @@ -777,7 +777,7 @@ " -y Assume 'yes' to all questions\n" \ " -c Check for bad blocks and add them to the badblock list\n" \ " -f Force checking even if filesystem is marked clean\n" \ - " -v Be verbose\n" \ + " -v Verbose\n" \ " -b superblock Use alternative superblock\n" \ " -B blocksize Force blocksize when looking for superblock\n" \ " -j journal Set location of the external journal\n" \ @@ -1131,7 +1131,7 @@ "\n -l List names of files that match" \ "\n -L List names of files that do not match" \ "\n -n Print line number with output lines" \ - "\n -q Be quiet. Returns 0 if PATTERN was found, 1 otherwise" \ + "\n -q Quiet. Returns 0 if PATTERN was found, 1 otherwise" \ "\n -v Select non-matching lines" \ "\n -s Suppress file open/read error messages" \ "\n -c Only print count of matching lines" \ @@ -1548,8 +1548,8 @@ "\n\nOptions:\n" \ " -f Force module to load into the wrong kernel version\n" \ " -k Make module autoclean-able\n" \ - " -v Verbose output\n" \ - " -q Quiet output\n" \ + " -v Verbose\n" \ + " -q Quiet\n" \ " -L Lock to prevent simultaneous loads of a module\n" \ USE_FEATURE_INSMOD_LOAD_MAP( \ " -m Output load map to stdout\n") \ @@ -2069,11 +2069,11 @@ " -N num Number of inodes to create\n" \ " -o os Set the 'creator os' field\n" \ " -O features Dir_index/filetype/has_journal/journal_dev/sparse_super\n" \ - " -q Quiet execution\n" \ + " -q Quiet\n" \ " -r rev Set filesystem revision\n" \ " -S Write superblock and group descriptors only\n" \ " -T fs-type Set usage type (news/largefile/largefile4)\n" \ - " -v Verbose execution" + " -v Verbose" #define mkfifo_trivial_usage \ "[OPTIONS] name" @@ -2144,10 +2144,10 @@ "Options:\n" \ " -k Make module autoclean-able\n" \ " -n Just show what would be done\n" \ - " -q Quiet output\n" \ + " -q Quiet\n" \ " -r Remove module (stacks) or do autoclean\n" \ " -s Report via syslog instead of stderr\n" \ - " -v Verbose output" + " -v Verbose" #define modprobe_notes_usage \ "modprobe can (un)load a stack of modules, passing each module options (when\n" \ "loading). modprobe uses a configuration file to determine what option(s) to\n" \ @@ -2269,7 +2269,7 @@ #define mountpoint_full_usage \ "mountpoint checks if the directory is a mountpoint" \ "\n\nOptions:\n" \ - " -q Be more quiet\n" \ + " -q Quiet\n" \ " -d Print major/minor device number of the filesystem\n" \ " -x Print major/minor device number of the blockdevice" #define mountpoint_example_usage \ @@ -2500,7 +2500,7 @@ " -c CNT Send only CNT pings\n" \ " -s SIZE Send SIZE data bytes in packets (default=56)\n" \ " -I iface/IP Use interface or IP address as source\n" \ - " -q Quiet mode, only displays output at start\n" \ + " -q Quiet, only displays output at start\n" \ " and when finished" #define ping6_trivial_usage \ "[OPTION]... host" @@ -2510,7 +2510,7 @@ " -c CNT Send only CNT pings\n" \ " -s SIZE Send SIZE data bytes in packets (default=56)\n" \ " -I iface/IP Use interface or IP address as source\n" \ - " -q Quiet mode, only displays output at start\n" \ + " -q Quiet, only displays output at start\n" \ " and when finished" #endif #define ping_example_usage \ @@ -2649,7 +2649,7 @@ " -p (Default: /proc/profile)\n" \ " -M Set the profiling multiplier to \n" \ " -i Print only info about the sampling step\n" \ - " -v Print verbose data\n" \ + " -v Verbose\n" \ " -a Print all symbols, even if count is 0\n" \ " -b Print individual histogram-bin counts\n" \ " -s Print individual counters within functions\n" \ @@ -2992,10 +2992,10 @@ "\n -m|--make-pidfile Create the -p file and enter pid in it" \ "\n -n|--name Stop processes with this name" \ "\n -p|--pidfile Save or load pid using a pid-file" \ - "\n -q|--quiet Be quiet" \ + "\n -q|--quiet Quiet" \ USE_FEATURE_START_STOP_DAEMON_FANCY( \ "\n -o|--oknodo Exit status 0 if nothing done" \ - "\n -v|--verbose Be verbose" \ + "\n -v|--verbose Verbose" \ "\n -N|--nicelevel Add N to process's nice level" \ ) \ "\n -s|--signal Signal to send (default TERM)" \ @@ -3238,7 +3238,7 @@ " exclude File to exclude\n" \ " X File with names to exclude\n") \ " C Change to directory DIR before operation\n" \ - " v Verbosely list files processed" + " v Verbose" #define tar_example_usage \ "$ zcat /tmp/tarball.tar.gz | tar -xf -\n" \ "$ tar -cf /tmp/tarball.tar /usr/local\n" @@ -3330,7 +3330,7 @@ /* with not-implemented options: */ /* "[-hpEvv] [-c n] [-C n:msg] [-b n] [-u user] [-l name] [-i dir|-x cdb] [ -t sec] ip port prog..." */ #define tcpsvd_full_usage \ - "Creates TCP socket, binds it to host:port and listens on in\n" \ + "Creates TCP socket, binds it to ip:port and listens on it\n" \ "for incoming connections. For each connection it runs prog." \ "\n" \ "\nip IP to listen on. '0' = all" \ @@ -3344,13 +3344,13 @@ "\n New connections from this IP address are closed" \ "\n immediately. 'msg' is written to the peer before close" \ "\n-h Look up peer's hostname" \ - "\n-E Do not set up TCP-related environment variables" \ + "\n-E Do not set up environment variables" \ "\n-v Verbose" #define udpsvd_trivial_usage \ - "[-hEv] [-u user] [-l name] host port prog" + "[-hEv] [-c n] [-u user] [-l name] ip port prog" #define udpsvd_full_usage \ - "Creates UDP socket, binds it to host:port and listens on in\n" \ + "Creates UDP socket, binds it to ip:port and listens on it\n" \ "for incoming packets. For each packet it runs prog\n" \ "(redirecting all further packets with same peer ip:port to it)." \ "\n" \ @@ -3361,7 +3361,7 @@ "\n-u user[:group] Change to user/group after bind" \ "\n-c n Handle up to n connections simultaneously" \ "\n-h Look up peer's hostname" \ - "\n-E Do not set up TCP-related environment variables" \ + "\n-E Do not set up environment variables" \ "\n-v Verbose" #define tftp_trivial_usage \ @@ -3386,7 +3386,7 @@ "Run the program COMMAND with arguments ARGS. When COMMAND finishes,\n" \ "COMMAND's resource usage information is displayed." \ "\n\nOptions:\n" \ - " -v Display verbose resource usage information" + " -v Verbose" #define top_trivial_usage \ "[-b] [-n count] [-d seconds]" @@ -3434,18 +3434,16 @@ " -d Set SO_DEBUG options to socket\n" \ " -n Print hop addresses numerically rather than symbolically\n" \ " -r Bypass the normal routing tables and send directly to a host\n" \ - " -v Verbose output\n" \ - " -m max_ttl Set the max time-to-live (max number of hops)\n" \ - " -p port# Set the base UDP port number used in probes\n" \ + " -v Verbose\n" \ + " -m max_ttl Max time-to-live (max number of hops)\n" \ + " -p port# Base UDP port number used in probes\n" \ " (default is 33434)\n" \ - " -q nqueries Set the number of probes per 'ttl' to nqueries\n" \ - " (default is 3)\n" \ - " -s src_addr Use the following IP address as the source address\n" \ - " -t tos Set the type-of-service in probe packets to the following value\n" \ - " (default 0)\n" \ - " -w wait Set the time (in seconds) to wait for a response to a probe\n" \ + " -q nqueries Number of probes per 'ttl' (default 3)\n" \ + " -s src_addr IP address to use as the source address\n" \ + " -t tos Type-of-service in probe packets (default 0)\n" \ + " -w wait Time in seconds to wait for a response to a probe\n" \ " (default 3 sec)\n" \ - " -g Specify a loose source route gateway (8 maximum)" + " -g Specify a loose source route gateway (8 max)" #define true_trivial_usage \ @@ -3566,7 +3564,7 @@ #define unix2dos_full_usage \ "Convert FILE from unix format to dos format. When no option\n" \ "is given, the input is converted to the opposite output format.\n" \ - "When no file is given, use stdin for input and stdout for output." \ + "When no file is given, use stdin/stdout." \ "\n\nOptions:\n" \ " -u Output will be in UNIX format\n" \ " -d Output will be in DOS format" @@ -3580,7 +3578,7 @@ " -n Never overwrite existing files (default)\n" \ " -o Overwrite files without prompting\n" \ " -p Send output to stdout\n" \ - " -q Be quiet\n" \ + " -q Quiet\n" \ " -x Exclude these files\n" \ " -d Extract files into this directory" @@ -3693,7 +3691,7 @@ "Retrieve files via HTTP or FTP" \ "\n\nOptions:\n" \ " -c Continue retrieval of aborted transfers\n" \ - " -q Quiet mode - do not print\n" \ + " -q Quiet\n" \ " -P Set directory prefix to DIR\n" \ " -O Save to filename ('-' for stdout)\n" \ " -U Adjust 'User-Agent' field\n" \ Modified: trunk/busybox/ipsvd/tcpudp.c =================================================================== --- trunk/busybox/ipsvd/tcpudp.c 2007-04-04 10:16:15 UTC (rev 18318) +++ trunk/busybox/ipsvd/tcpudp.c 2007-04-04 11:02:55 UTC (rev 18319) @@ -331,12 +331,31 @@ * to ones coming from this remote IP. */ xconnect(0, &remote.sa, sa_len); /* hole? at this point we have no wildcard udp socket... - * can this cause clients to get "port unreachable" icmp? */ + * 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); setsockopt_reuseaddr(sock); xbind(sock, &lsa->sa, sa_len); socket_want_pktinfo(sock); + + /* Doesn't work: + * we cannot replace fd #0 - we will lose pending packet + * which is already buffered for us! And we cannot use fd #1 + * instead - it will "intercept" all following packets, but child + * do not expect data coming *from fd #1*! */ +#if 0 + /* Make it so that local addr is fixed to localp->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); + setsockopt_reuseaddr(0); /* crucial */ + xbind(0, &localp->sa, localp->len); +#endif } pid = fork(); Modified: trunk/busybox/ipsvd/udp_io.c =================================================================== --- trunk/busybox/ipsvd/udp_io.c 2007-04-04 10:16:15 UTC (rev 18318) +++ trunk/busybox/ipsvd/udp_io.c 2007-04-04 11:02:55 UTC (rev 18319) @@ -95,7 +95,7 @@ /* NB: this will never set port# in 'to'! * _Only_ IP/IPv6 address part of 'to' is _maybe_ modified. - * Typical usage is to preinit it with "default" value + * Typical usage is to preinit 'to' with "default" value * before calling recv_from_to(). */ ssize_t recv_from_to(int fd, void *buf, size_t len, int flags, From aldot at busybox.net Wed Apr 4 06:58:34 2007 From: aldot at busybox.net (aldot at busybox.net) Date: Wed, 4 Apr 2007 06:58:34 -0700 (PDT) Subject: svn commit: trunk/busybox/coreutils Message-ID: <20070404135834.9511148084@busybox.net> Author: aldot Date: 2007-04-04 06:58:33 -0700 (Wed, 04 Apr 2007) New Revision: 18320 Log: - remove superfluous bss user (flags) and manually unswitch some areas: text data bss dec hex filename 4517 0 34 4551 11c7 stat.o.oorig 4300 0 30 4330 10ea stat.o Modified: trunk/busybox/coreutils/stat.c Changeset: Modified: trunk/busybox/coreutils/stat.c =================================================================== --- trunk/busybox/coreutils/stat.c 2007-04-04 11:02:55 UTC (rev 18319) +++ trunk/busybox/coreutils/stat.c 2007-04-04 13:58:33 UTC (rev 18320) @@ -16,12 +16,14 @@ #include "busybox.h" /* vars to control behavior */ -#define OPT_TERSE 2 -#define OPT_DEREFERENCE 4 -#define OPT_SELINUX 8 -static long flags; +#define OPT_FILESYS (1<<0) +#define OPT_TERSE (1<<1) +#define OPT_DEREFERENCE (1<<2) +#define OPT_SELINUX (1<<3) -static char const *file_type(struct stat const *st) +static char buf[sizeof("YYYY-MM-DD HH:MM:SS.000000000")]; + +static char const * file_type(struct stat const *st) { /* See POSIX 1003.1-2001 XCU Table 4-8 lines 17093-17107 * for some of these formats. @@ -53,7 +55,7 @@ return str; */ /* coreutils 6.3 compat: */ - static char buf[sizeof("YYYY-MM-DD HH:MM:SS.000000000")]; + strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S.000000000", localtime(&t)); return buf; } @@ -66,9 +68,9 @@ static char const *human_fstype(long f_type) { int i; - static const struct types { + const struct types { long type; - const char *fs; + const char * const fs; } humantypes[] = { { 0xADFF, "affs" }, { 0x1Cd1, "devpts" }, @@ -115,76 +117,58 @@ #ifdef CONFIG_FEATURE_STAT_FORMAT /* print statfs info */ -static void print_statfs(char *pformat, size_t buf_len, char m, - char const *filename, void const *data - USE_SELINUX(,security_context_t scontext) ) +static void print_statfs(char *pformat, const size_t buf_len, const char m, + const char * const filename, void const *data + USE_SELINUX(, security_context_t scontext)) { struct statfs const *statfsbuf = data; - - switch (m) { - case 'n': + if (m == 'n') { strncat(pformat, "s", buf_len); printf(pformat, filename); - break; - case 'i': + } else if (m == 'i') { strncat(pformat, "Lx", buf_len); printf(pformat, statfsbuf->f_fsid); - break; - case 'l': + } else if (m == 'l') { strncat(pformat, "lu", buf_len); printf(pformat, statfsbuf->f_namelen); - break; - case 't': + } else if (m == 't') { strncat(pformat, "lx", buf_len); - printf(pformat, (unsigned long int) (statfsbuf->f_type)); /* no equiv. */ - break; - case 'T': + printf(pformat, (unsigned long int) (statfsbuf->f_type)); /* no equiv */ + } else if (m == 'T') { strncat(pformat, "s", buf_len); printf(pformat, human_fstype(statfsbuf->f_type)); - break; - case 'b': + } else if (m == 'b') { strncat(pformat, "jd", buf_len); printf(pformat, (intmax_t) (statfsbuf->f_blocks)); - break; - case 'f': + } else if (m == 'f') { strncat(pformat, "jd", buf_len); printf(pformat, (intmax_t) (statfsbuf->f_bfree)); - break; - case 'a': + } else if (m == 'a') { strncat(pformat, "jd", buf_len); printf(pformat, (intmax_t) (statfsbuf->f_bavail)); - break; - case 'S': - case 's': + } else if (m == 's' || m == 'S') { strncat(pformat, "lu", buf_len); printf(pformat, (unsigned long int) (statfsbuf->f_bsize)); - break; - case 'c': + } else if (m == 'c') { strncat(pformat, "jd", buf_len); printf(pformat, (intmax_t) (statfsbuf->f_files)); - break; - case 'd': + } else if (m == 'd') { strncat(pformat, "jd", buf_len); printf(pformat, (intmax_t) (statfsbuf->f_ffree)); - break; #if ENABLE_SELINUX - case 'C': - if (flags & OPT_SELINUX) { - strncat(pformat, "s", buf_len); - printf(scontext); - } - break; + } else if (m == 'C' && (option_mask32 & OPT_SELINUX)) { + strncat(pformat, "s", buf_len); + printf(scontext); #endif - default: + } else { strncat(pformat, "c", buf_len); printf(pformat, m); - break; } } /* print stat info */ -static void print_stat(char *pformat, size_t buf_len, char m, - char const *filename, void const *data +static void print_stat(char *pformat, const size_t buf_len, const char m, + const char * const filename, void const *data USE_SELINUX(, security_context_t scontext)) { #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) @@ -192,12 +176,10 @@ struct passwd *pw_ent; struct group *gw_ent; - switch (m) { - case 'n': + if (m == 'n') { strncat(pformat, "s", buf_len); printf(pformat, filename); - break; - case 'N': + } else if (m == 'N') { strncat(pformat, "s", buf_len); if (S_ISLNK(statbuf->st_mode)) { char *linkname = xmalloc_readlink_or_warn(filename); @@ -212,119 +194,90 @@ } else { printf(pformat, filename); } - break; - case 'd': + } else if (m == 'd') { strncat(pformat, "ju", buf_len); printf(pformat, (uintmax_t) statbuf->st_dev); - break; - case 'D': + } else if (m == 'D') { strncat(pformat, "jx", buf_len); printf(pformat, (uintmax_t) statbuf->st_dev); - break; - case 'i': + } else if (m == 'i') { strncat(pformat, "ju", buf_len); printf(pformat, (uintmax_t) statbuf->st_ino); - break; - case 'a': + } else if (m == 'a') { strncat(pformat, "lo", buf_len); printf(pformat, (unsigned long int) (statbuf->st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO))); - break; - case 'A': + } else if (m == 'A') { strncat(pformat, "s", buf_len); printf(pformat, bb_mode_string(statbuf->st_mode)); - break; - case 'f': + } else if (m == 'f') { strncat(pformat, "lx", buf_len); printf(pformat, (unsigned long int) statbuf->st_mode); - break; - case 'F': + } else if (m == 'F') { strncat(pformat, "s", buf_len); printf(pformat, file_type(statbuf)); - break; - case 'h': + } else if (m == 'h') { strncat(pformat, "lu", buf_len); printf(pformat, (unsigned long int) statbuf->st_nlink); - break; - case 'u': + } else if (m == 'u') { strncat(pformat, "lu", buf_len); printf(pformat, (unsigned long int) statbuf->st_uid); - break; - case 'U': + } else if (m == 'U') { strncat(pformat, "s", buf_len); setpwent(); pw_ent = getpwuid(statbuf->st_uid); printf(pformat, (pw_ent != 0L) ? pw_ent->pw_name : "UNKNOWN"); - break; - case 'g': + } else if (m == 'g') { strncat(pformat, "lu", buf_len); printf(pformat, (unsigned long int) statbuf->st_gid); - break; - case 'G': + } else if (m == 'G') { strncat(pformat, "s", buf_len); setgrent(); gw_ent = getgrgid(statbuf->st_gid); printf(pformat, (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN"); - break; - case 't': + } else if (m == 't') { strncat(pformat, "lx", buf_len); printf(pformat, (unsigned long int) major(statbuf->st_rdev)); - break; - case 'T': + } else if (m == 'T') { strncat(pformat, "lx", buf_len); printf(pformat, (unsigned long int) minor(statbuf->st_rdev)); - break; - case 's': + } else if (m == 's') { strncat(pformat, "ju", buf_len); printf(pformat, (uintmax_t) (statbuf->st_size)); - break; - case 'B': + } else if (m == 'B') { strncat(pformat, "lu", buf_len); printf(pformat, (unsigned long int) 512); //ST_NBLOCKSIZE - break; - case 'b': + } else if (m == 'b') { strncat(pformat, "ju", buf_len); printf(pformat, (uintmax_t) statbuf->st_blocks); - break; - case 'o': + } else if (m == 'o') { strncat(pformat, "lu", buf_len); printf(pformat, (unsigned long int) statbuf->st_blksize); - break; - case 'x': + } else if (m == 'x') { strncat(pformat, "s", buf_len); printf(pformat, human_time(statbuf->st_atime)); - break; - case 'X': + } else if (m == 'X') { strncat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu", buf_len); printf(pformat, (unsigned long int) statbuf->st_atime); - break; - case 'y': + } else if (m == 'y') { strncat(pformat, "s", buf_len); printf(pformat, human_time(statbuf->st_mtime)); - break; - case 'Y': + } else if (m == 'Y') { strncat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu", buf_len); printf(pformat, (unsigned long int) statbuf->st_mtime); - break; - case 'z': + } else if (m == 'z') { strncat(pformat, "s", buf_len); printf(pformat, human_time(statbuf->st_ctime)); - break; - case 'Z': + } else if (m == 'Z') { strncat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu", buf_len); printf(pformat, (unsigned long int) statbuf->st_ctime); - break; #if ENABLE_SELINUX - case 'C': - if (flags & OPT_SELINUX) { - strncat(pformat, "s", buf_len); - printf(pformat, scontext); - } - break; +