Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/networking


Ignore:
Timestamp:
Jan 1, 2014, 12:47:38 AM (10 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.21.1
Location:
branches/3.2/mindi-busybox/networking
Files:
67 edited

Legend:

Unmodified
Added
Removed
  • branches/3.2/mindi-busybox/networking/Config.src

    r2725 r3232  
    5252    bool "arp"
    5353    default y
    54     depends on PLATFORM_LINUX
     54    select PLATFORM_LINUX
    5555    help
    5656      Manipulate the system ARP cache.
     
    5959    bool "arping"
    6060    default y
    61     depends on PLATFORM_LINUX
     61    select PLATFORM_LINUX
    6262    help
    6363      Ping hosts by ARP packets.
     
    6666    bool "brctl"
    6767    default y
    68     depends on PLATFORM_LINUX
     68    select PLATFORM_LINUX
    6969    help
    7070      Manage ethernet bridges.
     
    8383
    8484config FEATURE_BRCTL_SHOW
    85     bool "Support show, showmac and showstp"
     85    bool "Support show"
    8686    default y
    8787    depends on BRCTL && FEATURE_BRCTL_FANCY
    8888    help
    8989      Add support for option which prints the current config:
    90         showmacs, showstp, show
     90        show
    9191
    9292config DNSD
     
    9999    bool "ether-wake"
    100100    default y
    101     depends on PLATFORM_LINUX
     101    select PLATFORM_LINUX
    102102    help
    103103      Send a magic packet to wake up sleeping machines.
     
    200200      Utilizes password settings from /etc/httpd.conf for basic
    201201      authentication on a per url basis.
     202      Example for httpd.conf file:
     203      /adm:toor:PaSsWd
    202204
    203205config FEATURE_HTTPD_AUTH_MD5
     
    206208    depends on FEATURE_HTTPD_BASIC_AUTH
    207209    help
    208       Enables basic per URL authentication from /etc/httpd.conf
    209       using md5 passwords.
     210      Enables encrypted passwords, and wildcard user/passwords
     211      in httpd.conf file.
     212      User '*' means 'any system user name is ok',
     213      password of '*' means 'use system password for this user'
     214      Examples:
     215      /adm:toor:$1$P/eKnWXS$aI1aPGxT.dJD5SzqAKWrF0
     216      /adm:root:*
     217      /wiki:*:*
    210218
    211219config FEATURE_HTTPD_CGI
     
    224232      This option enables support for running scripts through an
    225233      interpreter. Turn this on if you want PHP scripts to work
    226       properly. You need to supply an additional line in your httpd
    227       config file:
     234      properly. You need to supply an additional line in your
     235      httpd.conf file:
    228236      *.php:/path/to/your/php
    229237
     
    282290    bool "ifconfig"
    283291    default y
    284     depends on PLATFORM_LINUX
     292    select PLATFORM_LINUX
    285293    help
    286294      Ifconfig is used to configure the kernel-resident network interfaces.
     
    330338    bool "ifenslave"
    331339    default y
    332     depends on PLATFORM_LINUX
     340    select PLATFORM_LINUX
    333341    help
    334342      Userspace application to bind several interfaces
     
    338346    bool "ifplugd"
    339347    default y
    340     depends on PLATFORM_LINUX
     348    select PLATFORM_LINUX
    341349    help
    342350      Network interface plug detection daemon.
     
    380388    bool "Use busybox ip applet"
    381389    default y
    382     depends on FEATURE_IFUPDOWN_IP && PLATFORM_LINUX
     390    depends on FEATURE_IFUPDOWN_IP
     391    select PLATFORM_LINUX
    383392    select IP
    384393    select FEATURE_IP_ADDRESS
     
    499508    bool "ip"
    500509    default y
    501     depends on PLATFORM_LINUX
     510    select PLATFORM_LINUX
    502511    help
    503512      The "ip" applet is a TCP/IP interface configuration and routing
     
    612621      Support long options for the ipcalc applet.
    613622
    614 config NAMEIF
    615     bool "nameif"
    616     default y
    617     depends on PLATFORM_LINUX
    618     select FEATURE_SYSLOG
    619     help
    620       nameif is used to rename network interface by its MAC address.
    621       Renamed interfaces MUST be in the down state.
    622       It is possible to use a file (default: /etc/mactab)
    623       with list of new interface names and MACs.
    624       Maximum interface name length: IFNAMSIZ = 16
    625       File fields are separated by space or tab.
    626       File format:
    627       # Comment
    628       new_interface_name    XX:XX:XX:XX:XX:XX
    629 
    630 config FEATURE_NAMEIF_EXTENDED
    631     bool "Extended nameif"
    632     default y
    633     depends on NAMEIF
    634     help
    635       This extends the nameif syntax to support the bus_info and driver
    636       checks. The syntax is compatible to the normal nameif.
    637       File format:
    638         new_interface_name  driver=asix bus=usb-0000:00:08.2-3
    639         new_interface_name  bus=usb-0000:00:08.2-3 00:80:C8:38:91:B5
    640         new_interface_name  mac=00:80:C8:38:91:B5
    641         new_interface_name  00:80:C8:38:91:B5
    642 
    643623config NETSTAT
    644624    bool "netstat"
    645625    default y
    646     depends on PLATFORM_LINUX
     626    select PLATFORM_LINUX
    647627    help
    648628      netstat prints information about the Linux networking subsystem.
     
    673653    bool "ntpd"
    674654    default y
    675     depends on PLATFORM_LINUX
     655    select PLATFORM_LINUX
    676656    help
    677657      The NTP client/server daemon.
     
    685665      ntpd will be usable only as a NTP client.
    686666
    687 config PING
    688     bool "ping"
    689     default y
    690     depends on PLATFORM_LINUX
    691     help
    692       ping uses the ICMP protocol's mandatory ECHO_REQUEST datagram to
    693       elicit an ICMP ECHO_RESPONSE from a host or gateway.
    694 
    695 config PING6
    696     bool "ping6"
    697     default y
    698     depends on FEATURE_IPV6 && PING
    699     help
    700       This will give you a ping that can talk IPv6.
    701 
    702 config FEATURE_FANCY_PING
    703     bool "Enable fancy ping output"
    704     default y
    705     depends on PING
    706     help
    707       Make the output from the ping applet include statistics, and at the
    708       same time provide full support for ICMP packets.
    709 
    710667config PSCAN
    711668    bool "pscan"
     
    717674    bool "route"
    718675    default y
    719     depends on PLATFORM_LINUX
     676    select PLATFORM_LINUX
    720677    help
    721678      Route displays or manipulates the kernel's IP routing tables.
     
    724681    bool "slattach"
    725682    default y
    726     depends on PLATFORM_LINUX
     683    select PLATFORM_LINUX
    727684    help
    728685      slattach is a small utility to attach network interfaces to serial
     
    911868    bool "traceroute"
    912869    default y
    913     depends on PLATFORM_LINUX
     870    select PLATFORM_LINUX
    914871    help
    915872      Utility to trace the route of IP packets.
     
    948905    bool "tunctl"
    949906    default y
    950     depends on PLATFORM_LINUX
     907    select PLATFORM_LINUX
    951908    help
    952909      tunctl creates or deletes tun devices.
     
    981938    bool "vconfig"
    982939    default y
    983     depends on PLATFORM_LINUX
     940    select PLATFORM_LINUX
    984941    help
    985942      Creates, removes, and configures VLAN interfaces
     
    989946    default y
    990947    help
    991       wget is a utility for non-interactive download of files from HTTP,
    992       HTTPS, and FTP servers.
     948      wget is a utility for non-interactive download of files from HTTP
     949      and FTP servers.
    993950
    994951config FEATURE_WGET_STATUSBAR
     
    1028985    bool "zcip"
    1029986    default y
    1030     depends on PLATFORM_LINUX
     987    select PLATFORM_LINUX
    1031988    select FEATURE_SYSLOG
    1032989    help
  • branches/3.2/mindi-busybox/networking/Kbuild.src

    r2725 r3232  
    3131lib-$(CONFIG_NSLOOKUP)     += nslookup.o
    3232lib-$(CONFIG_NTPD)         += ntpd.o
    33 lib-$(CONFIG_PING)         += ping.o
    34 lib-$(CONFIG_PING6)        += ping.o
    3533lib-$(CONFIG_PSCAN)        += pscan.o
    3634lib-$(CONFIG_ROUTE)        += route.o
  • branches/3.2/mindi-busybox/networking/arp.c

    r2725 r3232  
    1414 */
    1515
     16//usage:#define arp_trivial_usage
     17//usage:     "\n[-vn]   [-H HWTYPE] [-i IF] -a [HOSTNAME]"
     18//usage:     "\n[-v]            [-i IF] -d HOSTNAME [pub]"
     19//usage:     "\n[-v]    [-H HWTYPE] [-i IF] -s HOSTNAME HWADDR [temp]"
     20//usage:     "\n[-v]    [-H HWTYPE] [-i IF] -s HOSTNAME HWADDR [netmask MASK] pub"
     21//usage:     "\n[-v]    [-H HWTYPE] [-i IF] -Ds HOSTNAME IFACE [netmask MASK] pub"
     22//usage:#define arp_full_usage "\n\n"
     23//usage:       "Manipulate ARP cache\n"
     24//usage:       "\n  -a      Display (all) hosts"
     25//usage:       "\n  -s      Set new ARP entry"
     26//usage:       "\n  -d      Delete a specified entry"
     27//usage:       "\n  -v      Verbose"
     28//usage:       "\n  -n      Don't resolve names"
     29//usage:       "\n  -i IF       Network interface"
     30//usage:       "\n  -D      Read <hwaddr> from given device"
     31//usage:       "\n  -A,-p AF    Protocol family"
     32//usage:       "\n  -H HWTYPE   Hardware address type"
     33
    1634#include "libbb.h"
    1735#include "inet_common.h"
     
    197215/* Get the hardware address to a specified interface name */
    198216static void arp_getdevhw(char *ifname, struct sockaddr *sa,
    199                          const struct hwtype *hwt)
     217                        const struct hwtype *hwt)
    200218{
    201219    struct ifreq ifr;
     
    216234        }
    217235        bb_error_msg("device '%s' has HW address %s '%s'",
    218                      ifname, xhw->name,
    219                      xhw->print((unsigned char *) &ifr.ifr_hwaddr.sa_data));
     236                    ifname, xhw->name,
     237                    xhw->print((unsigned char *) &ifr.ifr_hwaddr.sa_data));
    220238    }
    221239}
     
    328346static void
    329347arp_disp(const char *name, char *ip, int type, int arp_flags,
    330          char *hwa, char *mask, char *dev)
     348        char *hwa, char *mask, char *dev)
    331349{
    332350    static const int arp_masks[] = {
     
    411429         * because fgets above reads limited amount of data */
    412430        num = sscanf(line, "%s 0x%x 0x%x %s %s %s\n",
    413                      ip, &type, &flags, hwa, mask, dev);
     431                    ip, &type, &flags, hwa, mask, dev);
    414432        if (num < 4)
    415433            break;
     
    444462    if (option_mask32 & ARP_OPT_v)
    445463        printf("Entries: %d\tSkipped: %d\tFound: %d\n",
    446                entries, entries - shown, shown);
     464                entries, entries - shown, shown);
    447465
    448466    if (!shown) {
     
    500518    if (hw->alen <= 0) {
    501519        bb_error_msg_and_die("%s: %s without ARP support",
    502                              hw->name, "hardware type");
     520                hw->name, "hardware type");
    503521    }
    504522
  • branches/3.2/mindi-busybox/networking/arping.c

    r2725 r3232  
    66 * Busybox port: Nick Fedchik <nick@fedchik.org.ua>
    77 */
     8
     9//usage:#define arping_trivial_usage
     10//usage:       "[-fqbDUA] [-c CNT] [-w TIMEOUT] [-I IFACE] [-s SRC_IP] DST_IP"
     11//usage:#define arping_full_usage "\n\n"
     12//usage:       "Send ARP requests/replies\n"
     13//usage:     "\n    -f      Quit on first ARP reply"
     14//usage:     "\n    -q      Quiet"
     15//usage:     "\n    -b      Keep broadcasting, don't go unicast"
     16//usage:     "\n    -D      Duplicated address detection mode"
     17//usage:     "\n    -U      Unsolicited ARP mode, update your neighbors"
     18//usage:     "\n    -A      ARP answer mode, update your neighbors"
     19//usage:     "\n    -c N        Stop after sending N ARP requests"
     20//usage:     "\n    -w TIMEOUT  Time to wait for ARP reply, seconds"
     21//usage:     "\n    -I IFACE    Interface to use (default eth0)"
     22//usage:     "\n    -s SRC_IP   Sender IP address"
     23//usage:     "\n    DST_IP      Target IP address"
    824
    925#include <arpa/inet.h>
  • branches/3.2/mindi-busybox/networking/brctl.c

    r2725 r3232  
    1313 * At the time of this writing this was considered a feature.
    1414 */
     15
     16//usage:#define brctl_trivial_usage
     17//usage:       "COMMAND [BRIDGE [INTERFACE]]"
     18//usage:#define brctl_full_usage "\n\n"
     19//usage:       "Manage ethernet bridges\n"
     20//usage:     "\nCommands:"
     21//usage:    IF_FEATURE_BRCTL_SHOW(
     22//usage:     "\n    show            Show a list of bridges"
     23//usage:    )
     24//usage:     "\n    addbr BRIDGE        Create BRIDGE"
     25//usage:     "\n    delbr BRIDGE        Delete BRIDGE"
     26//usage:     "\n    addif BRIDGE IFACE  Add IFACE to BRIDGE"
     27//usage:     "\n    delif BRIDGE IFACE  Delete IFACE from BRIDGE"
     28//usage:    IF_FEATURE_BRCTL_FANCY(
     29//usage:     "\n    setageing BRIDGE TIME       Set ageing time"
     30//usage:     "\n    setfd BRIDGE TIME       Set bridge forward delay"
     31//usage:     "\n    sethello BRIDGE TIME        Set hello time"
     32//usage:     "\n    setmaxage BRIDGE TIME       Set max message age"
     33//usage:     "\n    setpathcost BRIDGE COST     Set path cost"
     34//usage:     "\n    setportprio BRIDGE PRIO     Set port priority"
     35//usage:     "\n    setbridgeprio BRIDGE PRIO   Set bridge priority"
     36//usage:     "\n    stp BRIDGE [1/yes/on|0/no/off]  STP on/off"
     37//usage:    )
     38
    1539#include "libbb.h"
    1640#include <linux/sockios.h>
     
    4468
    4569/* FIXME: These 4 funcs are not really clean and could be improved */
    46 static ALWAYS_INLINE void strtotimeval(struct timeval *tv,
     70static ALWAYS_INLINE void bb_strtotimeval(struct timeval *tv,
    4771        const char *time_str)
    4872{
     
    81105{
    82106    struct timeval tv;
    83     strtotimeval(&tv, time_str);
     107    bb_strtotimeval(&tv, time_str);
    84108    return tv_to_jiffies(&tv);
    85109}
     
    106130        "setpathcost\0" "setportprio\0" "setbridgeprio\0"
    107131    )
    108     IF_FEATURE_BRCTL_SHOW("showmacs\0" "show\0");
     132    IF_FEATURE_BRCTL_SHOW("show\0");
    109133
    110134    enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif
    111135        IF_FEATURE_BRCTL_FANCY(,
    112            ARG_stp,
    113            ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage,
    114            ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio
     136            ARG_stp,
     137            ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage,
     138            ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio
    115139        )
    116         IF_FEATURE_BRCTL_SHOW(, ARG_showmacs, ARG_show)
     140        IF_FEATURE_BRCTL_SHOW(, ARG_show)
    117141    };
    118142
     
    262286                memset(ifidx, 0, sizeof ifidx);
    263287                arm_ioctl(args, BRCTL_GET_PORT_LIST, (unsigned long)ifidx,
    264                           MAX_PORTS);
     288                        MAX_PORTS);
    265289                xioctl(fd, SIOCDEVPRIVATE, &ifr);
    266290                for (i = 0; i < MAX_PORTS; i++) {
  • branches/3.2/mindi-busybox/networking/dnsd.c

    r2725 r3232  
    1717 * the first porting of oao' scdns to busybox also.
    1818 */
     19
     20//usage:#define dnsd_trivial_usage
     21//usage:       "[-dvs] [-c CONFFILE] [-t TTL_SEC] [-p PORT] [-i ADDR]"
     22//usage:#define dnsd_full_usage "\n\n"
     23//usage:       "Small static DNS server daemon\n"
     24//usage:     "\n    -c FILE Config file"
     25//usage:     "\n    -t SEC  TTL"
     26//usage:     "\n    -p PORT Listen on PORT"
     27//usage:     "\n    -i ADDR Listen on ADDR"
     28//usage:     "\n    -d  Daemonize"
     29//usage:     "\n    -v  Verbose"
     30//usage:     "\n    -s  Send successful replies only. Use this if you want"
     31//usage:     "\n        to use /etc/resolv.conf with two nameserver lines:"
     32//usage:     "\n            nameserver DNSD_SERVER"
     33//usage:     "\n            nameserver NORMAL_DNS_SERVER"
    1934
    2035#include "libbb.h"
  • branches/3.2/mindi-busybox/networking/ether-wake.c

    r2725 r3232  
    5050 *
    5151 *  The author may be reached as becker@scyld, or C/O
    52  *   Scyld Computing Corporation
    53  *   914 Bay Ridge Road, Suite 220
    54  *   Annapolis MD 21403
     52 *  Scyld Computing Corporation
     53 *  914 Bay Ridge Road, Suite 220
     54 *  Annapolis MD 21403
    5555 *
    5656 *   Notes:
     
    6565*/
    6666
    67 
     67//usage:#define ether_wake_trivial_usage
     68//usage:       "[-b] [-i iface] [-p aa:bb:cc:dd[:ee:ff]] MAC"
     69//usage:#define ether_wake_full_usage "\n\n"
     70//usage:       "Send a magic packet to wake up sleeping machines.\n"
     71//usage:       "MAC must be a station address (00:11:22:33:44:55) or\n"
     72//usage:       "a hostname with a known 'ethers' entry.\n"
     73//usage:     "\n    -b      Send wake-up packet to the broadcast address"
     74//usage:     "\n    -i iface    Interface to use (default eth0)"
     75//usage:     "\n    -p pass     Append four or six byte password PW to the packet"
     76
     77#include "libbb.h"
    6878#include <netpacket/packet.h>
    69 #include <net/ethernet.h>
    7079#include <netinet/ether.h>
    7180#include <linux/if.h>
    72 
    73 #include "libbb.h"
    7481
    7582/* Note: PF_INET, SOCK_DGRAM, IPPROTO_UDP would allow SIOCGIFHWADDR to
     
    107114 *    IP address string
    108115 *    MAC address string
    109 */
     116 */
    110117static void get_dest_addr(const char *hostid, struct ether_addr *eaddr)
    111118{
     
    232239            unsigned char *hwaddr = if_hwaddr.ifr_hwaddr.sa_data;
    233240            printf("The hardware address (SIOCGIFHWADDR) of %s is type %d  "
    234                    "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n\n", ifname,
    235                    if_hwaddr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],
    236                    hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
     241                "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n\n", ifname,
     242                if_hwaddr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],
     243                hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
    237244        }
    238245# endif
  • branches/3.2/mindi-busybox/networking/ftpd.c

    r2725 r3232  
    1212 * You have to run this daemon via inetd.
    1313 */
     14
     15//usage:#define ftpd_trivial_usage
     16//usage:       "[-wvS] [-t N] [-T N] [DIR]"
     17//usage:#define ftpd_full_usage "\n\n"
     18//usage:       "Anonymous FTP server\n"
     19//usage:       "\n"
     20//usage:       "ftpd should be used as an inetd service.\n"
     21//usage:       "ftpd's line for inetd.conf:\n"
     22//usage:       "    21 stream tcp nowait root ftpd ftpd /files/to/serve\n"
     23//usage:       "It also can be ran from tcpsvd:\n"
     24//usage:       "    tcpsvd -vE 0.0.0.0 21 ftpd /files/to/serve\n"
     25//usage:     "\n    -w  Allow upload"
     26//usage:     "\n    -v  Log errors to stderr. -vv: verbose log"
     27//usage:     "\n    -S  Log errors to syslog. -SS: verbose log"
     28//usage:     "\n    -t,-T   Idle and absolute timeouts"
     29//usage:     "\n    DIR Change root to this directory"
    1430
    1531#include "libbb.h"
     
    207223    *(uint32_t *) G.msg_err = status;
    208224    xwrite(STDOUT_FILENO, G.msg_err, sizeof("NNN " MSG_ERR) - 1);
    209     if (G.verbose > 1)
     225    if (G.verbose > 0)
    210226        verbose_log(G.msg_err);
    211227}
     
    417433    setsockopt_reuseaddr(fd);
    418434
    419     set_nport(G.local_addr, 0);
     435    set_nport(&G.local_addr->u.sa, 0);
    420436    xbind(fd, &G.local_addr->u.sa, G.local_addr->len);
    421437    xlisten(fd, 1);
     
    526542#else
    527543    G.port_addr = get_peer_lsa(STDIN_FILENO);
    528     set_nport(G.port_addr, htons(port));
     544    set_nport(&G.port_addr->u.sa, htons(port));
    529545#endif
    530546    WRITE_OK(FTP_PORTOK);
     
    806822        sprintf(buf, STR(FTP_STATFILE_OK)" %04u%02u%02u%02u%02u%02u\r\n",
    807823            broken_out.tm_year + 1900,
    808             broken_out.tm_mon,
     824            broken_out.tm_mon + 1,
    809825            broken_out.tm_mday,
    810826            broken_out.tm_hour,
     
    912928     || !S_ISREG(statbuf.st_mode)
    913929    ) {
     930        free(tempname);
    914931        WRITE_ERR(FTP_UPLOADFAIL);
    915932        if (local_file_fd >= 0)
     
    11641181
    11651182    if (argv[optind]) {
    1166         xchdir(argv[optind]);
    1167         chroot(".");
     1183        xchroot(argv[optind]);
    11681184    }
    11691185
  • branches/3.2/mindi-busybox/networking/ftpgetput.c

    r2725 r3232  
    1414 */
    1515
     16//usage:#define ftpget_trivial_usage
     17//usage:       "[OPTIONS] HOST [LOCAL_FILE] REMOTE_FILE"
     18//usage:#define ftpget_full_usage "\n\n"
     19//usage:       "Download a file via FTP\n"
     20//usage:    IF_FEATURE_FTPGETPUT_LONG_OPTIONS(
     21//usage:     "\n    -c,--continue       Continue previous transfer"
     22//usage:     "\n    -v,--verbose        Verbose"
     23//usage:     "\n    -u,--username USER  Username"
     24//usage:     "\n    -p,--password PASS  Password"
     25//usage:     "\n    -P,--port NUM       Port"
     26//usage:    )
     27//usage:    IF_NOT_FEATURE_FTPGETPUT_LONG_OPTIONS(
     28//usage:     "\n    -c  Continue previous transfer"
     29//usage:     "\n    -v  Verbose"
     30//usage:     "\n    -u USER Username"
     31//usage:     "\n    -p PASS Password"
     32//usage:     "\n    -P NUM  Port"
     33//usage:    )
     34//usage:
     35//usage:#define ftpput_trivial_usage
     36//usage:       "[OPTIONS] HOST [REMOTE_FILE] LOCAL_FILE"
     37//usage:#define ftpput_full_usage "\n\n"
     38//usage:       "Upload a file to a FTP server\n"
     39//usage:    IF_FEATURE_FTPGETPUT_LONG_OPTIONS(
     40//usage:     "\n    -v,--verbose        Verbose"
     41//usage:     "\n    -u,--username USER  Username"
     42//usage:     "\n    -p,--password PASS  Password"
     43//usage:     "\n    -P,--port NUM       Port"
     44//usage:    )
     45//usage:    IF_NOT_FEATURE_FTPGETPUT_LONG_OPTIONS(
     46//usage:     "\n    -v  Verbose"
     47//usage:     "\n    -u USER Username"
     48//usage:     "\n    -p PASS Password"
     49//usage:     "\n    -P NUM  Port number"
     50//usage:    )
     51
    1652#include "libbb.h"
    1753
     
    2359    int verbose_flag;
    2460    int do_continue;
    25     char buf[1]; /* actually [BUFSZ] */
     61    char buf[4]; /* actually [BUFSZ] */
    2662} FIX_ALIASING;
    2763#define G (*(struct globals*)&bb_common_bufsiz1)
     
    68104
    69105    do {
    70         strcpy(buf, "EOF");
     106        strcpy(buf, "EOF"); /* for ftp_die */
    71107        if (fgets(buf, BUFSZ - 2, control_stream) == NULL) {
    72108            ftp_die(NULL);
     
    152188    port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256;
    153189
    154     set_nport(lsa, htons(port_num));
     190    set_nport(&lsa->u.sa, htons(port_num));
    155191    return xconnect_stream(lsa);
    156192}
     
    279315int ftpgetput_main(int argc UNUSED_PARAM, char **argv)
    280316{
    281     unsigned opt;
    282317    const char *port = "ftp";
    283318    /* socket to ftp server */
     
    308343#endif
    309344    opt_complementary = "-2:vv:cc"; /* must have 2 to 3 params; -v and -c count */
    310     opt = getopt32(argv, "cvu:p:P:", &user, &password, &port,
     345    getopt32(argv, "cvu:p:P:", &user, &password, &port,
    311346                    &verbose_flag, &do_continue);
    312347    argv += optind;
  • branches/3.2/mindi-busybox/networking/hostname.c

    r2725 r3232  
    1010 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1111 */
     12
     13//usage:#define hostname_trivial_usage
     14//usage:       "[OPTIONS] [HOSTNAME | -F FILE]"
     15//usage:#define hostname_full_usage "\n\n"
     16//usage:       "Get or set hostname or DNS domain name\n"
     17//usage:     "\n    -s  Short"
     18//usage:     "\n    -i  Addresses for the hostname"
     19//usage:     "\n    -d  DNS domain name"
     20//usage:     "\n    -f  Fully qualified domain name"
     21//usage:     "\n    -F FILE Use FILE's content as hostname"
     22//usage:
     23//usage:#define hostname_example_usage
     24//usage:       "$ hostname\n"
     25//usage:       "sage\n"
     26//usage:
     27//usage:#define dnsdomainname_trivial_usage NOUSAGE_STR
     28//usage:#define dnsdomainname_full_usage ""
     29
    1230#include "libbb.h"
    1331
     
    136154                struct in_addr **h_addr_list = (struct in_addr **)hp->h_addr_list;
    137155                while (*h_addr_list) {
    138                     printf("%s ", inet_ntoa(**h_addr_list));
     156                    printf(h_addr_list[1] ? "%s " : "%s", inet_ntoa(**h_addr_list));
    139157                    h_addr_list++;
    140158                }
  • branches/3.2/mindi-busybox/networking/httpd.c

    r2725 r3232  
    2121 * The server changes directory to the location of the script and executes it
    2222 * after setting QUERY_STRING and other environment variables.
     23 *
     24 * If directory URL is given, no index.html is found and CGI support is enabled,
     25 * cgi-bin/index.cgi will be run. Directory to list is ../$QUERY_STRING.
     26 * See httpd_indexcgi.c for an example GCI code.
    2327 *
    2428 * Doc:
     
    5155 * /adm:admin:setup  # Require user admin, pwd setup on urls starting with /adm/
    5256 * /adm:toor:PaSsWd  # or user toor, pwd PaSsWd on urls starting with /adm/
     57 * /adm:root:*       # or user root, pwd from /etc/passwd on urls starting with /adm/
     58 * /wiki:*:*         # or any user from /etc/passwd with according pwd on urls starting with /wiki/
    5359 * .au:audio/basic   # additional mime type for audio.au files
    5460 * *.php:/path/php   # run xxx.php through an interpreter
     
    7278 *     A:*             # (optional line added for clarity)
    7379 *
    74  * If a sub directory contains a config file it is parsed and merged with
     80 * If a sub directory contains config file, it is parsed and merged with
    7581 * any existing settings as if it was appended to the original configuration.
    7682 *
     
    94100 /* TODO: use TCP_CORK, parse_config() */
    95101
     102//usage:#define httpd_trivial_usage
     103//usage:       "[-ifv[v]]"
     104//usage:       " [-c CONFFILE]"
     105//usage:       " [-p [IP:]PORT]"
     106//usage:    IF_FEATURE_HTTPD_SETUID(" [-u USER[:GRP]]")
     107//usage:    IF_FEATURE_HTTPD_BASIC_AUTH(" [-r REALM]")
     108//usage:       " [-h HOME]\n"
     109//usage:       "or httpd -d/-e" IF_FEATURE_HTTPD_AUTH_MD5("/-m") " STRING"
     110//usage:#define httpd_full_usage "\n\n"
     111//usage:       "Listen for incoming HTTP requests\n"
     112//usage:     "\n    -i      Inetd mode"
     113//usage:     "\n    -f      Don't daemonize"
     114//usage:     "\n    -v[v]       Verbose"
     115//usage:     "\n    -p [IP:]PORT    Bind to IP:PORT (default *:80)"
     116//usage:    IF_FEATURE_HTTPD_SETUID(
     117//usage:     "\n    -u USER[:GRP]   Set uid/gid after binding to port")
     118//usage:    IF_FEATURE_HTTPD_BASIC_AUTH(
     119//usage:     "\n    -r REALM    Authentication Realm for Basic Authentication")
     120//usage:     "\n    -h HOME     Home directory (default .)"
     121//usage:     "\n    -c FILE     Configuration file (default {/etc,HOME}/httpd.conf)"
     122//usage:    IF_FEATURE_HTTPD_AUTH_MD5(
     123//usage:     "\n    -m STRING   MD5 crypt STRING")
     124//usage:     "\n    -e STRING   HTML encode STRING"
     125//usage:     "\n    -d STRING   URL decode STRING"
     126
    96127#include "libbb.h"
     128#if ENABLE_PAM
     129/* PAM may include <locale.h>. We may need to undefine bbox's stub define: */
     130# undef setlocale
     131/* For some obscure reason, PAM is not in pam/xxx, but in security/xxx.
     132 * Apparently they like to confuse people. */
     133# include <security/pam_appl.h>
     134# include <security/pam_misc.h>
     135#endif
    97136#if ENABLE_FEATURE_HTTPD_USE_SENDFILE
    98137# include <sys/sendfile.h>
     
    310349#else
    311350enum {
    312     range_start = 0,
     351    range_start = -1,
    313352    range_end = MAXINT(off_t) - 1,
    314353    range_len = MAXINT(off_t),
     
    332371    SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
    333372    IF_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \
     373    IF_FEATURE_HTTPD_RANGES(range_start = -1;) \
    334374    bind_addr_or_port = "80"; \
    335375    index_page = index_html; \
     
    757797 config_error:
    758798        bb_error_msg("config error '%s' in '%s'", buf, filename);
    759      } /* while (fgets) */
    760 
    761      fclose(f);
     799    } /* while (fgets) */
     800
     801    fclose(f);
    762802}
    763803
     
    791831}
    792832#endif
    793 
    794 /*
    795  * Given a URL encoded string, convert it to plain ascii.
    796  * Since decoding always makes strings smaller, the decode is done in-place.
    797  * Thus, callers should xstrdup() the argument if they do not want the
    798  * argument modified.  The return is the original pointer, allowing this
    799  * function to be easily used as arguments to other functions.
    800  *
    801  * string    The first string to decode.
    802  * option_d  1 if called for httpd -d
    803  *
    804  * Returns a pointer to the decoded string (same as input).
    805  */
    806 static unsigned hex_to_bin(unsigned char c)
    807 {
    808     unsigned v;
    809 
    810     v = c - '0';
    811     if (v <= 9)
    812         return v;
    813     /* c | 0x20: letters to lower case, non-letters
    814      * to (potentially different) non-letters */
    815     v = (unsigned)(c | 0x20) - 'a';
    816     if (v <= 5)
    817         return v + 10;
    818     return ~0;
    819 /* For testing:
    820 void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); }
    821 int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f');
    822 t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; }
    823 */
    824 }
    825 static char *decodeString(char *orig, int option_d)
    826 {
    827     /* note that decoded string is always shorter than original */
    828     char *string = orig;
    829     char *ptr = string;
    830     char c;
    831 
    832     while ((c = *ptr++) != '\0') {
    833         unsigned v;
    834 
    835         if (option_d && c == '+') {
    836             *string++ = ' ';
    837             continue;
    838         }
    839         if (c != '%') {
    840             *string++ = c;
    841             continue;
    842         }
    843         v = hex_to_bin(ptr[0]);
    844         if (v > 15) {
    845  bad_hex:
    846             if (!option_d)
    847                 return NULL;
    848             *string++ = '%';
    849             continue;
    850         }
    851         v = (v * 16) | hex_to_bin(ptr[1]);
    852         if (v > 255)
    853             goto bad_hex;
    854         if (!option_d && (v == '/' || v == '\0')) {
    855             /* caller takes it as indication of invalid
    856              * (dangerous wrt exploits) chars */
    857             return orig + 1;
    858         }
    859         *string++ = v;
    860         ptr += 2;
    861     }
    862     *string = '\0';
    863     return orig;
    864 }
    865833
    866834#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
     
    10661034static void send_headers_and_exit(int responseNum)
    10671035{
     1036    IF_FEATURE_HTTPD_GZIP(content_gzip = 0;)
    10681037    send_headers(responseNum);
    10691038    log_and_exit();
     
    12981267 * Parameters:
    12991268 * const char *url              The requested URL (with leading /).
     1269 * const char *orig_uri         The original URI before rewriting (if any)
    13001270 * int post_len                 Length of the POST body.
    13011271 * const char *cookie           For set HTTP_COOKIE.
     
    13041274static void send_cgi_and_exit(
    13051275        const char *url,
     1276        const char *orig_uri,
    13061277        const char *request,
    13071278        int post_len,
     
    13101281static void send_cgi_and_exit(
    13111282        const char *url,
     1283        const char *orig_uri,
    13121284        const char *request,
    13131285        int post_len,
     
    13171289    struct fd_pair fromCgi;  /* CGI -> httpd pipe */
    13181290    struct fd_pair toCgi;    /* httpd -> CGI pipe */
    1319     char *script;
     1291    char *script, *last_slash;
    13201292    int pid;
    13211293
     
    13311303
    13321304    /* Check for [dirs/]script.cgi/PATH_INFO */
    1333     script = (char*)url;
     1305    last_slash = script = (char*)url;
    13341306    while ((script = strchr(script + 1, '/')) != NULL) {
     1307        int dir;
    13351308        *script = '\0';
    1336         if (!is_directory(url + 1, 1, NULL)) {
     1309        dir = is_directory(url + 1, /*followlinks:*/ 1);
     1310        *script = '/';
     1311        if (!dir) {
    13371312            /* not directory, found script.cgi/PATH_INFO */
    1338             *script = '/';
    13391313            break;
    13401314        }
    1341         *script = '/'; /* is directory, find next '/' */
     1315        /* is directory, find next '/' */
     1316        last_slash = script;
    13421317    }
    13431318    setenv1("PATH_INFO", script);   /* set to /PATH_INFO or "" */
    13441319    setenv1("REQUEST_METHOD", request);
    13451320    if (g_query) {
    1346         putenv(xasprintf("%s=%s?%s", "REQUEST_URI", url, g_query));
     1321        putenv(xasprintf("%s=%s?%s", "REQUEST_URI", orig_uri, g_query));
    13471322    } else {
    1348         setenv1("REQUEST_URI", url);
     1323        setenv1("REQUEST_URI", orig_uri);
    13491324    }
    13501325    if (script != NULL)
     
    14201395    }
    14211396
    1422     if (!pid) {
     1397    if (pid == 0) {
    14231398        /* Child process */
    14241399        char *argv[3];
     
    14361411
    14371412        /* Chdiring to script's dir */
    1438         script = strrchr(url, '/');
     1413        script = last_slash;
    14391414        if (script != url) { /* paranoia */
    14401415            *script = '\0';
    14411416            if (chdir(url + 1) != 0) {
    1442                 bb_perror_msg("chdir(%s)", url + 1);
     1417                bb_perror_msg("can't change directory to '%s'", url + 1);
    14431418                goto error_execing_cgi;
    14441419            }
     
    16161591     || content_gzip /* we are sending compressed page: can't do ranges */  ///why?
    16171592    ) {
    1618         range_start = 0;
     1593        range_start = -1;
    16191594    }
    16201595    range_len = MAXINT(off_t);
    1621     if (range_start) {
    1622         if (!range_end) {
     1596    if (range_start >= 0) {
     1597        if (!range_end || range_end > file_size - 1) {
    16231598            range_end = file_size - 1;
    16241599        }
     
    16271602        ) {
    16281603            lseek(fd, 0, SEEK_SET);
    1629             range_start = 0;
     1604            range_start = -1;
    16301605        } else {
    16311606            range_len = range_end - range_start + 1;
     
    16501625                goto fin;
    16511626            }
    1652             IF_FEATURE_HTTPD_RANGES(range_len -= sz;)
     1627            IF_FEATURE_HTTPD_RANGES(range_len -= count;)
    16531628            if (count == 0 || range_len == 0)
    16541629                log_and_exit();
     
    17011676
    17021677#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
     1678
     1679# if ENABLE_PAM
     1680struct pam_userinfo {
     1681    const char *name;
     1682    const char *pw;
     1683};
     1684
     1685static int pam_talker(int num_msg,
     1686        const struct pam_message **msg,
     1687        struct pam_response **resp,
     1688        void *appdata_ptr)
     1689{
     1690    int i;
     1691    struct pam_userinfo *userinfo = (struct pam_userinfo *) appdata_ptr;
     1692    struct pam_response *response;
     1693
     1694    if (!resp || !msg || !userinfo)
     1695        return PAM_CONV_ERR;
     1696
     1697    /* allocate memory to store response */
     1698    response = xzalloc(num_msg * sizeof(*response));
     1699
     1700    /* copy values */
     1701    for (i = 0; i < num_msg; i++) {
     1702        const char *s;
     1703
     1704        switch (msg[i]->msg_style) {
     1705        case PAM_PROMPT_ECHO_ON:
     1706            s = userinfo->name;
     1707            break;
     1708        case PAM_PROMPT_ECHO_OFF:
     1709            s = userinfo->pw;
     1710            break;
     1711        case PAM_ERROR_MSG:
     1712            case PAM_TEXT_INFO:
     1713                s = "";
     1714            break;
     1715        default:
     1716            free(response);
     1717            return PAM_CONV_ERR;
     1718        }
     1719        response[i].resp = xstrdup(s);
     1720        if (PAM_SUCCESS != 0)
     1721            response[i].resp_retcode = PAM_SUCCESS;
     1722    }
     1723    *resp = response;
     1724    return PAM_SUCCESS;
     1725}
     1726# endif
     1727
    17031728/*
    17041729 * Config file entries are of the form "/<path>:<user>:<passwd>".
     
    17101735 * Returns 1 if user_and_passwd is OK.
    17111736 */
    1712 static int check_user_passwd(const char *path, const char *user_and_passwd)
     1737static int check_user_passwd(const char *path, char *user_and_passwd)
    17131738{
    17141739    Htaccess *cur;
     
    17181743        const char *dir_prefix;
    17191744        size_t len;
     1745        int r;
    17201746
    17211747        dir_prefix = cur->before_colon;
     
    17331759        if (len != 1 /* dir_prefix "/" matches all, don't need to check */
    17341760         && (strncmp(dir_prefix, path, len) != 0
    1735             || (path[len] != '/' && path[len] != '\0'))
     1761            || (path[len] != '/' && path[len] != '\0')
     1762            )
    17361763        ) {
    17371764            continue;
     
    17421769
    17431770        if (ENABLE_FEATURE_HTTPD_AUTH_MD5) {
    1744             char *md5_passwd;
    1745 
    1746             md5_passwd = strchr(cur->after_colon, ':');
    1747             if (md5_passwd && md5_passwd[1] == '$' && md5_passwd[2] == '1'
    1748              && md5_passwd[3] == '$' && md5_passwd[4]
     1771            char *colon_after_user;
     1772            const char *passwd;
     1773# if ENABLE_FEATURE_SHADOWPASSWDS && !ENABLE_PAM
     1774            char sp_buf[256];
     1775# endif
     1776
     1777            colon_after_user = strchr(user_and_passwd, ':');
     1778            if (!colon_after_user)
     1779                goto bad_input;
     1780
     1781            /* compare "user:" */
     1782            if (cur->after_colon[0] != '*'
     1783             && strncmp(cur->after_colon, user_and_passwd,
     1784                    colon_after_user - user_and_passwd + 1) != 0
    17491785            ) {
     1786                continue;
     1787            }
     1788            /* this cfg entry is '*' or matches username from peer */
     1789
     1790            passwd = strchr(cur->after_colon, ':');
     1791            if (!passwd)
     1792                goto bad_input;
     1793            passwd++;
     1794            if (passwd[0] == '*') {
     1795# if ENABLE_PAM
     1796                struct pam_userinfo userinfo;
     1797                struct pam_conv conv_info = { &pam_talker, (void *) &userinfo };
     1798                pam_handle_t *pamh;
     1799
     1800                *colon_after_user = '\0';
     1801                userinfo.name = user_and_passwd;
     1802                userinfo.pw = colon_after_user + 1;
     1803                r = pam_start("httpd", user_and_passwd, &conv_info, &pamh) != PAM_SUCCESS;
     1804                if (r == 0) {
     1805                    r = pam_authenticate(pamh, PAM_DISALLOW_NULL_AUTHTOK) != PAM_SUCCESS
     1806                     || pam_acct_mgmt(pamh, PAM_DISALLOW_NULL_AUTHTOK)    != PAM_SUCCESS
     1807                    ;
     1808                    pam_end(pamh, PAM_SUCCESS);
     1809                }
     1810                *colon_after_user = ':';
     1811                goto end_check_passwd;
     1812# else
     1813#  if ENABLE_FEATURE_SHADOWPASSWDS
     1814                /* Using _r function to avoid pulling in static buffers */
     1815                struct spwd spw;
     1816#  endif
     1817                struct passwd *pw;
     1818
     1819                *colon_after_user = '\0';
     1820                pw = getpwnam(user_and_passwd);
     1821                *colon_after_user = ':';
     1822                if (!pw || !pw->pw_passwd)
     1823                    continue;
     1824                passwd = pw->pw_passwd;
     1825#  if ENABLE_FEATURE_SHADOWPASSWDS
     1826                if ((passwd[0] == 'x' || passwd[0] == '*') && !passwd[1]) {
     1827                    /* getspnam_r may return 0 yet set result to NULL.
     1828                     * At least glibc 2.4 does this. Be extra paranoid here. */
     1829                    struct spwd *result = NULL;
     1830                    r = getspnam_r(pw->pw_name, &spw, sp_buf, sizeof(sp_buf), &result);
     1831                    if (r == 0 && result)
     1832                        passwd = result->sp_pwdp;
     1833                }
     1834#  endif
     1835                /* In this case, passwd is ALWAYS encrypted:
     1836                 * it came from /etc/passwd or /etc/shadow!
     1837                 */
     1838                goto check_encrypted;
     1839# endif /* ENABLE_PAM */
     1840            }
     1841            /* Else: passwd is from httpd.conf, it is either plaintext or encrypted */
     1842
     1843            if (passwd[0] == '$' && isdigit(passwd[1])) {
    17501844                char *encrypted;
    1751                 int r, user_len_p1;
    1752 
    1753                 md5_passwd++;
    1754                 user_len_p1 = md5_passwd - cur->after_colon;
    1755                 /* comparing "user:" */
    1756                 if (strncmp(cur->after_colon, user_and_passwd, user_len_p1) != 0) {
    1757                     continue;
    1758                 }
    1759 
     1845# if !ENABLE_PAM
     1846 check_encrypted:
     1847# endif
     1848                /* encrypt pwd from peer and check match with local one */
    17601849                encrypted = pw_encrypt(
    1761                     user_and_passwd + user_len_p1 /* cleartext pwd from user */,
    1762                     md5_passwd /*salt */, 1 /* cleanup */);
    1763                 r = strcmp(encrypted, md5_passwd);
     1850                    /* pwd (from peer): */  colon_after_user + 1,
     1851                    /* salt: */ passwd,
     1852                    /* cleanup: */ 0
     1853                );
     1854                r = strcmp(encrypted, passwd);
    17641855                free(encrypted);
    1765                 if (r == 0)
    1766                     goto set_remoteuser_var; /* Ok */
    1767                 continue;
    1768             }
    1769         }
    1770 
     1856            } else {
     1857                /* local passwd is from httpd.conf and it's plaintext */
     1858                r = strcmp(colon_after_user + 1, passwd);
     1859            }
     1860            goto end_check_passwd;
     1861        }
     1862 bad_input:
    17711863        /* Comparing plaintext "user:pass" in one go */
    1772         if (strcmp(cur->after_colon, user_and_passwd) == 0) {
    1773  set_remoteuser_var:
     1864        r = strcmp(cur->after_colon, user_and_passwd);
     1865 end_check_passwd:
     1866        if (r == 0) {
    17741867            remoteuser = xstrndup(user_and_passwd,
    1775                     strchrnul(user_and_passwd, ':') - user_and_passwd);
     1868                strchrnul(user_and_passwd, ':') - user_and_passwd
     1869            );
    17761870            return 1; /* Ok */
    17771871        }
     
    19122006
    19132007    /* Extract url args if present */
    1914     g_query = NULL;
     2008    /* g_query = NULL; - already is */
    19152009    tptr = strchr(urlcopy, '?');
    19162010    if (tptr) {
     
    19202014
    19212015    /* Decode URL escape sequences */
    1922     tptr = decodeString(urlcopy, 0);
     2016    tptr = percent_decode_in_place(urlcopy, /*strict:*/ 1);
    19232017    if (tptr == NULL)
    19242018        send_headers_and_exit(HTTP_BAD_REQUEST);
     
    19322026     * but don't strdup, retain trailing slash, protect root */
    19332027    urlp = tptr = urlcopy;
    1934     do {
     2028    for (;;) {
    19352029        if (*urlp == '/') {
    19362030            /* skip duplicate (or initial) slash */
    19372031            if (*tptr == '/') {
    1938                 continue;
     2032                goto next_char;
    19392033            }
    19402034            if (*tptr == '.') {
    1941                 /* skip extra "/./" */
    1942                 if (tptr[1] == '/' || !tptr[1]) {
    1943                     continue;
     2035                if (tptr[1] == '.' && (tptr[2] == '/' || tptr[2] == '\0')) {
     2036                    /* "..": be careful */
     2037                    /* protect root */
     2038                    if (urlp == urlcopy)
     2039                        send_headers_and_exit(HTTP_BAD_REQUEST);
     2040                    /* omit previous dir */
     2041                    while (*--urlp != '/')
     2042                        continue;
     2043                    /* skip to "./" or ".<NUL>" */
     2044                    tptr++;
    19442045                }
    1945                 /* "..": be careful */
    1946                 if (tptr[1] == '.' && (tptr[2] == '/' || !tptr[2])) {
    1947                     ++tptr;
    1948                     if (urlp == urlcopy) /* protect root */
    1949                         send_headers_and_exit(HTTP_BAD_REQUEST);
    1950                     while (*--urlp != '/') /* omit previous dir */;
    1951                         continue;
     2046                if (tptr[1] == '/' || tptr[1] == '\0') {
     2047                    /* skip extra "/./" */
     2048                    goto next_char;
    19522049                }
    19532050            }
    19542051        }
    19552052        *++urlp = *tptr;
    1956     } while (*++tptr);
    1957     *++urlp = '\0';       /* terminate after last character */
     2053        if (*urlp == '\0')
     2054            break;
     2055 next_char:
     2056        tptr++;
     2057    }
    19582058
    19592059    /* If URL is a directory, add '/' */
    19602060    if (urlp[-1] != '/') {
    1961         if (is_directory(urlcopy + 1, 1, NULL)) {
     2061        if (is_directory(urlcopy + 1, /*followlinks:*/ 1)) {
    19622062            found_moved_temporarily = urlcopy;
    19632063        }
     
    19732073        /* have path1/path2 */
    19742074        *tptr = '\0';
    1975         if (is_directory(urlcopy + 1, 1, NULL)) {
     2075        if (is_directory(urlcopy + 1, /*followlinks:*/ 1)) {
    19762076            /* may have subdir config */
    19772077            parse_conf(urlcopy + 1, SUBDIR_PARSE);
     
    20722172                    range_start = BB_STRTOOFF(s, &s, 10);
    20732173                    if (s[0] != '-' || range_start < 0) {
    2074                         range_start = 0;
     2174                        range_start = -1;
    20752175                    } else if (s[1]) {
    20762176                        range_end = BB_STRTOOFF(s+1, NULL, 10);
    20772177                        if (errno || range_end < range_start)
    2078                             range_start = 0;
     2178                            range_start = -1;
    20792179                    }
    20802180                }
     
    21102210
    21112211#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
    2112     /* Case: no "Authorization:" was seen, but page does require passwd.
     2212    /* Case: no "Authorization:" was seen, but page might require passwd.
    21132213     * Check that with dummy user:pass */
    21142214    if (authorized < 0)
    2115         authorized = check_user_passwd(urlcopy, ":");
     2215        authorized = check_user_passwd(urlcopy, (char *) "");
    21162216    if (!authorized)
    21172217        send_headers_and_exit(HTTP_UNAUTHORIZED);
     
    21592259            send_headers_and_exit(HTTP_FORBIDDEN);
    21602260        }
    2161         send_cgi_and_exit(urlcopy, prequest, length, cookie, content_type);
    2162     }
    2163 #endif
    2164 
    2165     if (urlp[-1] == '/')
     2261        send_cgi_and_exit(urlcopy, urlcopy, prequest, length, cookie, content_type);
     2262    }
     2263#endif
     2264
     2265    if (urlp[-1] == '/') {
     2266        /* When index_page string is appended to <dir>/ URL, it overwrites
     2267         * the query string. If we fall back to call /cgi-bin/index.cgi,
     2268         * query string would be lost and not available to the CGI.
     2269         * Work around it by making a deep copy.
     2270         */
     2271        if (ENABLE_FEATURE_HTTPD_CGI)
     2272            g_query = xstrdup(g_query); /* ok for NULL too */
    21662273        strcpy(urlp, index_page);
     2274    }
    21672275    if (stat(tptr, &sb) == 0) {
    21682276#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
     
    21722280            for (cur = script_i; cur; cur = cur->next) {
    21732281                if (strcmp(cur->before_colon + 1, suffix) == 0) {
    2174                     send_cgi_and_exit(urlcopy, prequest, length, cookie, content_type);
     2282                    send_cgi_and_exit(urlcopy, urlcopy, prequest, length, cookie, content_type);
    21752283                }
    21762284            }
     
    21852293         * Try cgi-bin/index.cgi */
    21862294        if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) {
    2187             urlp[0] = '\0';
    2188             g_query = urlcopy;
    2189             send_cgi_and_exit("/cgi-bin/index.cgi", prequest, length, cookie, content_type);
     2295            urlp[0] = '\0'; /* remove index_page */
     2296            send_cgi_and_exit("/cgi-bin/index.cgi", urlcopy, prequest, length, cookie, content_type);
    21902297        }
    21912298    }
     
    22862393            re_exec(argv_copy);
    22872394        }
     2395        argv_copy[0][0] &= 0x7f;
    22882396        /* parent, or vfork failed */
    22892397        close(n);
     
    23792487        );
    23802488    if (opt & OPT_DECODE_URL) {
    2381         fputs(decodeString(url_for_decode, 1), stdout);
     2489        fputs(percent_decode_in_place(url_for_decode, /*strict:*/ 0), stdout);
    23822490        return 0;
    23832491    }
     
    23942502        salt[1] = '1';
    23952503        salt[2] = '$';
    2396         crypt_make_salt(salt + 3, 4, 0);
    2397         puts(pw_encrypt(pass, salt, 1));
     2504        crypt_make_salt(salt + 3, 4);
     2505        puts(pw_encrypt(pass, salt, /*cleanup:*/ 0));
    23982506        return 0;
    23992507    }
  • branches/3.2/mindi-busybox/networking/httpd_indexcgi.c

    r2725 r3232  
    3636 */
    3737
     38#define _GNU_SOURCE 1  /* for strchrnul */
    3839#include <sys/types.h>
    3940#include <sys/stat.h>
     
    222223    int odd;
    223224    DIR *dirp;
    224     char *QUERY_STRING;
    225 
    226     QUERY_STRING = getenv("QUERY_STRING");
    227     if (!QUERY_STRING
    228      || QUERY_STRING[0] != '/'
    229      || strstr(QUERY_STRING, "//")
    230      || strstr(QUERY_STRING, "/../")
    231      || strcmp(strrchr(QUERY_STRING, '/'), "/..") == 0
     225    char *location;
     226
     227    location = getenv("REQUEST_URI");
     228    if (!location)
     229        return 1;
     230
     231    /* drop URL arguments if any */
     232    strchrnul(location, '?')[0] = '\0';
     233
     234    if (location[0] != '/'
     235     || strstr(location, "//")
     236     || strstr(location, "/../")
     237     || strcmp(strrchr(location, '/'), "/..") == 0
    232238    ) {
    233239        return 1;
     
    235241
    236242    if (chdir("..")
    237      || (QUERY_STRING[1] && chdir(QUERY_STRING + 1))
     243     || (location[1] && chdir(location + 1))
    238244    ) {
    239245        return 1;
     
    272278        "<html><head><title>Index of ");
    273279    /* Guard against directories with &, > etc */
    274     fmt_html(QUERY_STRING);
     280    fmt_html(location);
    275281    fmt_str(
    276282        "</title>\n"
     
    279285        "<body>" "\n"
    280286        "<h1>Index of ");
    281     fmt_html(QUERY_STRING);
     287    fmt_html(location);
    282288    fmt_str(
    283289        "</h1>" "\n"
  • branches/3.2/mindi-busybox/networking/httpd_ssi.c

    r2725 r3232  
    5353static char* skip_whitespace(char *s)
    5454{
    55         while (*s == ' ' || *s == '\t') ++s;
     55    while (*s == ' ' || *s == '\t') ++s;
    5656
    57         return s;
     57    return s;
    5858}
    5959
     
    134134
    135135        /* Print everything after directive */
    136             if (end) {
     136        if (end) {
    137137            fputs(end, stdout);
    138138            free(end);
  • branches/3.2/mindi-busybox/networking/ifconfig.c

    r2725 r3232  
    2727 */
    2828
     29//usage:#define ifconfig_trivial_usage
     30//usage:    IF_FEATURE_IFCONFIG_STATUS("[-a]") " interface [address]"
     31//usage:#define ifconfig_full_usage "\n\n"
     32//usage:       "Configure a network interface\n"
     33//usage:     "\n"
     34//usage:    IF_FEATURE_IPV6(
     35//usage:       "    [add ADDRESS[/PREFIXLEN]]\n")
     36//usage:    IF_FEATURE_IPV6(
     37//usage:       "    [del ADDRESS[/PREFIXLEN]]\n")
     38//usage:       "    [[-]broadcast [ADDRESS]] [[-]pointopoint [ADDRESS]]\n"
     39//usage:       "    [netmask ADDRESS] [dstaddr ADDRESS]\n"
     40//usage:    IF_FEATURE_IFCONFIG_SLIP(
     41//usage:       "    [outfill NN] [keepalive NN]\n")
     42//usage:       "    " IF_FEATURE_IFCONFIG_HW("[hw ether" IF_FEATURE_HWIB("|infiniband")" ADDRESS] ") "[metric NN] [mtu NN]\n"
     43//usage:       "    [[-]trailers] [[-]arp] [[-]allmulti]\n"
     44//usage:       "    [multicast] [[-]promisc] [txqueuelen NN] [[-]dynamic]\n"
     45//usage:    IF_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ(
     46//usage:       "    [mem_start NN] [io_addr NN] [irq NN]\n")
     47//usage:       "    [up|down] ..."
     48
     49#include "libbb.h"
     50#include "inet_common.h"
    2951#include <net/if.h>
    3052#include <net/if_arp.h>
    3153#include <netinet/in.h>
    32 #if defined(__GLIBC__) && __GLIBC__ >=2 && __GLIBC_MINOR__ >= 1
    33 #include <netpacket/packet.h>
    34 #include <net/ethernet.h>
    35 #else
    36 #include <sys/types.h>
    37 #include <netinet/if_ether.h>
    38 #endif
    39 #include "libbb.h"
    40 #include "inet_common.h"
     54#ifdef HAVE_NET_ETHERNET_H
     55# include <net/ethernet.h>
     56#endif
    4157
    4258#if ENABLE_FEATURE_IFCONFIG_SLIP
     
    159175
    160176
    161 /*
    162  * Set up the tables.  Warning!  They must have corresponding order!
    163  */
    164 
    165177struct arg1opt {
    166178    const char *name;
     
    182194
    183195#define ifreq_offsetof(x)  offsetof(struct ifreq, x)
     196
     197/*
     198 * Set up the tables.  Warning!  They must have corresponding order!
     199 */
    184200
    185201static const struct arg1opt Arg1Opt[] = {
     
    205221    { "SIFMAP",     SIOCSIFMAP,     ifreq_offsetof(ifr_map.irq) },
    206222#endif
    207     /* Last entry if for unmatched (possibly hostname) arg. */
    208223#if ENABLE_FEATURE_IPV6
    209224    { "SIFADDR",    SIOCSIFADDR,    ifreq_offsetof(ifr_addr) }, /* IPv6 version ignores the offset */
    210225    { "DIFADDR",    SIOCDIFADDR,    ifreq_offsetof(ifr_addr) }, /* IPv6 version ignores the offset */
    211226#endif
     227    /* Last entry is for unmatched (assumed to be hostname/address) arg. */
    212228    { "SIFADDR",    SIOCSIFADDR,    ifreq_offsetof(ifr_addr) },
    213229};
     
    250266};
    251267
    252 /*
    253  * A couple of prototypes.
    254  */
    255268#if ENABLE_FEATURE_IFCONFIG_HW
    256 static int in_ether(const char *bufp, struct sockaddr *sap);
    257 #endif
    258 
    259 /*
    260  * Our main function.
    261  */
     269/* Input an Ethernet address and convert to binary. */
     270static int in_ether(const char *bufp, struct sockaddr *sap)
     271{
     272    char *ptr;
     273    int i, j;
     274    unsigned char val;
     275    unsigned char c;
     276
     277    sap->sa_family = ARPHRD_ETHER;
     278    ptr = (char *) sap->sa_data;
     279
     280    i = 0;
     281    do {
     282        j = val = 0;
     283
     284        /* We might get a semicolon here - not required. */
     285        if (i && (*bufp == ':')) {
     286            bufp++;
     287        }
     288
     289        do {
     290            c = *bufp;
     291            if (((unsigned char)(c - '0')) <= 9) {
     292                c -= '0';
     293            } else if ((unsigned char)((c|0x20) - 'a') <= 5) {
     294                c = (unsigned char)((c|0x20) - 'a') + 10;
     295            } else if (j && (c == ':' || c == 0)) {
     296                break;
     297            } else {
     298                return -1;
     299            }
     300            ++bufp;
     301            val <<= 4;
     302            val += c;
     303        } while (++j < 2);
     304        *ptr++ = val;
     305    } while (++i < ETH_ALEN);
     306
     307    return *bufp; /* Error if we don't end at end of string. */
     308}
     309#endif
     310
    262311int ifconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    263312int ifconfig_main(int argc UNUSED_PARAM, char **argv)
     
    315364
    316365    /* Process the remaining arguments. */
    317     while (*++argv != (char *) NULL) {
     366    while (*++argv != NULL) {
    318367        p = *argv;
    319368        mask = N_MASK;
     
    341390        if (mask & ARG_MASK) {
    342391            mask = op->arg_flags;
    343             a1op = Arg1Opt + (op - OptArray);
    344392            if (mask & A_NETMASK & did_flags)
    345393                bb_show_usage();
     394            a1op = Arg1Opt + (op - OptArray);
    346395            if (*++argv == NULL) {
    347396                if (mask & A_ARG_REQ)
     
    356405                    if (mask & A_CAST_RESOLVE) {
    357406#endif
    358 #if ENABLE_FEATURE_IPV6
    359                         char *prefix;
    360                         int prefix_len = 0;
    361 #endif
    362                         /*safe_strncpy(host, *argv, (sizeof host));*/
    363407                        host = *argv;
    364 #if ENABLE_FEATURE_IPV6
    365                         prefix = strchr(host, '/');
    366                         if (prefix) {
    367                             prefix_len = xatou_range(prefix + 1, 0, 128);
    368                             *prefix = '\0';
    369                         }
    370 #endif
     408                        if (strcmp(host, "inet") == 0)
     409                            continue; /* compat stuff */
    371410                        sai.sin_family = AF_INET;
    372411                        sai.sin_port = 0;
     
    376415                        }
    377416#if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS
    378                         else if ((host[0] == '+' && !host[1]) && (mask & A_BROADCAST)
     417                        else if ((host[0] == '+' && !host[1])
     418                         && (mask & A_BROADCAST)
    379419                         && (did_flags & (A_NETMASK|A_HOSTNAME)) == (A_NETMASK|A_HOSTNAME)
    380420                        ) {
     
    385425                        else {
    386426                            len_and_sockaddr *lsa;
    387                             if (strcmp(host, "inet") == 0)
    388                                 continue; /* compat stuff */
     427#if ENABLE_FEATURE_IPV6
     428                            char *prefix;
     429                            int prefix_len = 0;
     430                            prefix = strchr(host, '/');
     431                            if (prefix) {
     432                                prefix_len = xatou_range(prefix + 1, 0, 128);
     433                                *prefix = '\0';
     434                            }
     435 resolve:
     436#endif
    389437                            lsa = xhost2sockaddr(host, 0);
    390438#if ENABLE_FEATURE_IPV6
     439                            if (lsa->u.sa.sa_family != AF_INET6 && prefix) {
     440/* TODO: we do not support "ifconfig eth0 up 1.2.3.4/17".
     441 * For now, just make it fail instead of silently ignoring "/17" part:
     442 */
     443                                *prefix = '/';
     444                                goto resolve;
     445                            }
    391446                            if (lsa->u.sa.sa_family == AF_INET6) {
    392447                                int sockfd6;
    393448                                struct in6_ifreq ifr6;
    394449
    395                                 memcpy((char *) &ifr6.ifr6_addr,
    396                                         (char *) &(lsa->u.sin6.sin6_addr),
    397                                         sizeof(struct in6_addr));
    398 
    399                                 /* Create a channel to the NET kernel. */
    400450                                sockfd6 = xsocket(AF_INET6, SOCK_DGRAM, 0);
    401                                 xioctl(sockfd6, SIOGIFINDEX, &ifr);
     451                                xioctl(sockfd6, SIOCGIFINDEX, &ifr);
    402452                                ifr6.ifr6_ifindex = ifr.ifr_ifindex;
    403453                                ifr6.ifr6_prefixlen = prefix_len;
     454                                memcpy(&ifr6.ifr6_addr,
     455                                        &lsa->u.sin6.sin6_addr,
     456                                        sizeof(struct in6_addr));
    404457                                ioctl_or_perror_and_die(sockfd6, a1op->selector, &ifr6, "SIOC%s", a1op->name);
    405458                                if (ENABLE_FEATURE_CLEAN_UP)
     
    422475                    } else {    /* A_CAST_HOST_COPY_IN_ETHER */
    423476                        /* This is the "hw" arg case. */
    424                         smalluint hw_class= index_in_substrings("ether\0"
     477                        smalluint hw_class = index_in_substrings("ether\0"
    425478                                IF_FEATURE_HWIB("infiniband\0"), *argv) + 1;
    426479                        if (!hw_class || !*++argv)
    427480                            bb_show_usage();
    428                         /*safe_strncpy(host, *argv, sizeof(host));*/
    429481                        host = *argv;
    430482                        if (hw_class == 1 ? in_ether(host, &sa) : in_ib(host, &sa))
     
    433485                    }
    434486#endif
    435                     memcpy( (((char *)&ifr) + a1op->ifr_offset),
    436                            p, sizeof(struct sockaddr));
     487                    memcpy( ((char *)&ifr) + a1op->ifr_offset,
     488                        p, sizeof(struct sockaddr));
    437489                } else {
    438490                    /* FIXME: error check?? */
     
    443495                        xioctl(sockfd, SIOCGIFMAP, &ifr);
    444496                        if ((mask & A_MAP_UCHAR) == A_MAP_UCHAR)
    445                             *((unsigned char *) p) = i;
     497                            *(unsigned char *) p = i;
    446498                        else if (mask & A_MAP_USHORT)
    447                             *((unsigned short *) p) = i;
     499                            *(unsigned short *) p = i;
    448500                        else
    449                             *((unsigned long *) p) = i;
     501                            *(unsigned long *) p = i;
    450502                    } else
    451503#endif
    452504                    if (mask & A_CAST_CHAR_PTR)
    453                         *((caddr_t *) p) = (caddr_t) i;
     505                        *(caddr_t *) p = (caddr_t) i;
    454506                    else    /* A_CAST_INT */
    455                         *((int *) p) = i;
     507                        *(int *) p = i;
    456508                }
    457509
     
    479531                continue;
    480532            mask = N_SET;
    481         }
     533        } /* if (mask & ARG_MASK) */
    482534
    483535        xioctl(sockfd, SIOCGIFFLAGS, &ifr);
     
    494546    return 0;
    495547}
    496 
    497 #if ENABLE_FEATURE_IFCONFIG_HW
    498 /* Input an Ethernet address and convert to binary. */
    499 static int in_ether(const char *bufp, struct sockaddr *sap)
    500 {
    501     char *ptr;
    502     int i, j;
    503     unsigned char val;
    504     unsigned char c;
    505 
    506     sap->sa_family = ARPHRD_ETHER;
    507     ptr = (char *) sap->sa_data;
    508 
    509     i = 0;
    510     do {
    511         j = val = 0;
    512 
    513         /* We might get a semicolon here - not required. */
    514         if (i && (*bufp == ':')) {
    515             bufp++;
    516         }
    517 
    518         do {
    519             c = *bufp;
    520             if (((unsigned char)(c - '0')) <= 9) {
    521                 c -= '0';
    522             } else if (((unsigned char)((c|0x20) - 'a')) <= 5) {
    523                 c = (c|0x20) - ('a'-10);
    524             } else if (j && (c == ':' || c == 0)) {
    525                 break;
    526             } else {
    527                 return -1;
    528             }
    529             ++bufp;
    530             val <<= 4;
    531             val += c;
    532         } while (++j < 2);
    533         *ptr++ = val;
    534     } while (++i < ETH_ALEN);
    535 
    536     return *bufp; /* Error if we don't end at end of string. */
    537 }
    538 #endif
  • branches/3.2/mindi-busybox/networking/ifenslave.c

    r2725 r3232  
    9898 *         set version to 1.1.0
    9999 */
     100
     101//usage:#define ifenslave_trivial_usage
     102//usage:       "[-cdf] MASTER_IFACE SLAVE_IFACE..."
     103//usage:#define ifenslave_full_usage "\n\n"
     104//usage:       "Configure network interfaces for parallel routing\n"
     105//usage:     "\n    -c,--change-active  Change active slave"
     106//usage:     "\n    -d,--detach     Remove slave interface from bonding device"
     107//usage:     "\n    -f,--force      Force, even if interface is not Ethernet"
     108/* //usage:  "\n    -r,--receive-slave  Create a receive-only slave" */
     109//usage:
     110//usage:#define ifenslave_example_usage
     111//usage:       "To create a bond device, simply follow these three steps:\n"
     112//usage:       "- ensure that the required drivers are properly loaded:\n"
     113//usage:       "  # modprobe bonding ; modprobe <3c59x|eepro100|pcnet32|tulip|...>\n"
     114//usage:       "- assign an IP address to the bond device:\n"
     115//usage:       "  # ifconfig bond0 <addr> netmask <mask> broadcast <bcast>\n"
     116//usage:       "- attach all the interfaces you need to the bond device:\n"
     117//usage:       "  # ifenslave bond0 eth0 eth1 eth2\n"
     118//usage:       "  If bond0 didn't have a MAC address, it will take eth0's. Then, all\n"
     119//usage:       "  interfaces attached AFTER this assignment will get the same MAC addr.\n\n"
     120//usage:       "  To detach a dead interface without setting the bond device down:\n"
     121//usage:       "  # ifenslave -d bond0 eth1\n\n"
     122//usage:       "  To set the bond device down and automatically release all the slaves:\n"
     123//usage:       "  # ifconfig bond0 down\n\n"
     124//usage:       "  To change active slave:\n"
     125//usage:       "  # ifenslave -c bond0 eth0\n"
    100126
    101127#include "libbb.h"
     
    245271            ifr.ifr_addr.sa_family = AF_INET;
    246272            memset(ifr.ifr_addr.sa_data, 0,
    247                    sizeof(ifr.ifr_addr.sa_data));
     273                sizeof(ifr.ifr_addr.sa_data));
    248274        }
    249275
     
    521547    /* Neither -c[hange] nor -d[etach] -> it's "enslave" then;
    522548     * and -f[orce] is not there too. Check that it's ethernet. */
    523     if (!(opt & (OPT_d|OPT_c|OPT_f)) {
     549    if (!(opt & (OPT_d|OPT_c|OPT_f))) {
    524550        /* The family '1' is ARPHRD_ETHER for ethernet. */
    525551        if (master.hwaddr.ifr_hwaddr.sa_family != 1) {
  • branches/3.2/mindi-busybox/networking/ifplugd.c

    r2725 r3232  
    77 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
     9
     10//usage:#define ifplugd_trivial_usage
     11//usage:       "[OPTIONS]"
     12//usage:#define ifplugd_full_usage "\n\n"
     13//usage:       "Network interface plug detection daemon\n"
     14//usage:     "\n    -n      Don't daemonize"
     15//usage:     "\n    -s      Don't log to syslog"
     16//usage:     "\n    -i IFACE    Interface"
     17//usage:     "\n    -f/-F       Treat link detection error as link down/link up"
     18//usage:     "\n            (otherwise exit on error)"
     19//usage:     "\n    -a      Don't up interface at each link probe"
     20//usage:     "\n    -M      Monitor creation/destruction of interface"
     21//usage:     "\n            (otherwise it must exist)"
     22//usage:     "\n    -r PROG     Script to run"
     23//usage:     "\n    -x ARG      Extra argument for script"
     24//usage:     "\n    -I      Don't exit on nonzero exit code from script"
     25//usage:     "\n    -p      Don't run \"up\" script on startup"
     26//usage:     "\n    -q      Don't run \"down\" script on exit"
     27//usage:     "\n    -l      Always run script on startup"
     28//usage:     "\n    -t SECS     Poll time in seconds"
     29//usage:     "\n    -u SECS     Delay before running script after link up"
     30//usage:     "\n    -d SECS     Delay after link down"
     31//usage:     "\n    -m MODE     API mode (mii, priv, ethtool, wlan, iff, auto)"
     32//usage:     "\n    -k      Kill running daemon"
     33
    934#include "libbb.h"
    1035
     
    1338#include <linux/mii.h>
    1439#include <linux/ethtool.h>
    15 #include <net/ethernet.h>
     40#ifdef HAVE_NET_ETHERNET_H
     41# include <net/ethernet.h>
     42#endif
    1643#include <linux/netlink.h>
    1744#include <linux/rtnetlink.h>
     
    132159static smallint detect_link_mii(void)
    133160{
    134     struct ifreq ifreq;
    135     struct mii_ioctl_data *mii = (void *)&ifreq.ifr_data;
    136 
    137     set_ifreq_to_ifname(&ifreq);
    138 
    139     if (network_ioctl(SIOCGMIIPHY, &ifreq, "SIOCGMIIPHY") < 0) {
     161    /* char buffer instead of bona-fide struct avoids aliasing warning */
     162    char buf[sizeof(struct ifreq)];
     163    struct ifreq *const ifreq = (void *)buf;
     164
     165    struct mii_ioctl_data *mii = (void *)&ifreq->ifr_data;
     166
     167    set_ifreq_to_ifname(ifreq);
     168
     169    if (network_ioctl(SIOCGMIIPHY, ifreq, "SIOCGMIIPHY") < 0) {
    140170        return IFSTATUS_ERR;
    141171    }
     
    143173    mii->reg_num = 1;
    144174
    145     if (network_ioctl(SIOCGMIIREG, &ifreq, "SIOCGMIIREG") < 0) {
     175    if (network_ioctl(SIOCGMIIREG, ifreq, "SIOCGMIIREG") < 0) {
    146176        return IFSTATUS_ERR;
    147177    }
     
    152182static smallint detect_link_priv(void)
    153183{
    154     struct ifreq ifreq;
    155     struct mii_ioctl_data *mii = (void *)&ifreq.ifr_data;
    156 
    157     set_ifreq_to_ifname(&ifreq);
    158 
    159     if (network_ioctl(SIOCDEVPRIVATE, &ifreq, "SIOCDEVPRIVATE") < 0) {
     184    /* char buffer instead of bona-fide struct avoids aliasing warning */
     185    char buf[sizeof(struct ifreq)];
     186    struct ifreq *const ifreq = (void *)buf;
     187
     188    struct mii_ioctl_data *mii = (void *)&ifreq->ifr_data;
     189
     190    set_ifreq_to_ifname(ifreq);
     191
     192    if (network_ioctl(SIOCDEVPRIVATE, ifreq, "SIOCDEVPRIVATE") < 0) {
    160193        return IFSTATUS_ERR;
    161194    }
     
    163196    mii->reg_num = 1;
    164197
    165     if (network_ioctl(SIOCDEVPRIVATE+1, &ifreq, "SIOCDEVPRIVATE+1") < 0) {
     198    if (network_ioctl(SIOCDEVPRIVATE+1, ifreq, "SIOCDEVPRIVATE+1") < 0) {
    166199        return IFSTATUS_ERR;
    167200    }
     
    519552
    520553#if ENABLE_FEATURE_PIDFILE
    521     pidfile_name = xasprintf(_PATH_VARRUN"ifplugd.%s.pid", G.iface);
     554    pidfile_name = xasprintf(CONFIG_PID_FILE_PATH "/ifplugd.%s.pid", G.iface);
    522555    pid_from_pidfile = read_pid(pidfile_name);
    523556
  • branches/3.2/mindi-busybox/networking/ifupdown.c

    r2725 r3232  
    1818 */
    1919
     20//usage:#define ifup_trivial_usage
     21//usage:       "[-an"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] [-i FILE] IFACE..."
     22//usage:#define ifup_full_usage "\n\n"
     23//usage:       "    -a  De/configure all interfaces automatically"
     24//usage:     "\n    -i FILE Use FILE for interface definitions"
     25//usage:     "\n    -n  Print out what would happen, but don't do it"
     26//usage:    IF_FEATURE_IFUPDOWN_MAPPING(
     27//usage:     "\n        (note: doesn't disable mappings)"
     28//usage:     "\n    -m  Don't run any mappings"
     29//usage:    )
     30//usage:     "\n    -v  Print out what would happen before doing it"
     31//usage:     "\n    -f  Force de/configuration"
     32//usage:
     33//usage:#define ifdown_trivial_usage
     34//usage:       "[-an"IF_FEATURE_IFUPDOWN_MAPPING("m")"vf] [-i FILE] IFACE..."
     35//usage:#define ifdown_full_usage "\n\n"
     36//usage:       "    -a  De/configure all interfaces automatically"
     37//usage:     "\n    -i FILE Use FILE for interface definitions"
     38//usage:     "\n    -n  Print out what would happen, but don't do it"
     39//usage:    IF_FEATURE_IFUPDOWN_MAPPING(
     40//usage:     "\n        (note: doesn't disable mappings)"
     41//usage:     "\n    -m  Don't run any mappings"
     42//usage:    )
     43//usage:     "\n    -v  Print out what would happen before doing it"
     44//usage:     "\n    -f  Force de/configuration"
     45
    2046#include "libbb.h"
    2147/* After libbb.h, since it needs sys/types.h on some systems */
     
    2450
    2551#define MAX_OPT_DEPTH 10
    26 #define EUNBALBRACK 10001
    27 #define EUNDEFVAR   10002
    28 #define EUNBALPER   10000
    2952
    3053#if ENABLE_FEATURE_IFUPDOWN_MAPPING
     
    6285    char *script;
    6386
    64     int max_mappings;
    6587    int n_mappings;
    6688    char **mapping;
     
    7799
    78100    char *iface;
    79     int max_options;
    80101    int n_options;
    81102    struct variable_t *option;
     
    107128    char **my_environ;
    108129    const char *startup_PATH;
     130    char *shell;
    109131} FIX_ALIASING;
    110132#define G (*(struct globals*)&bb_common_bufsiz1)
    111133#define INIT_G() do { } while (0)
     134
     135
     136static const char keywords_up_down[] ALIGN1 =
     137    "up\0"
     138    "down\0"
     139    "pre-up\0"
     140    "post-down\0"
     141;
    112142
    113143
     
    201231{
    202232    size_t old_pos[MAX_OPT_DEPTH] = { 0 };
    203     int okay[MAX_OPT_DEPTH] = { 1 };
     233    smallint okay[MAX_OPT_DEPTH] = { 1 };
    204234    int opt_depth = 1;
    205235    char *result = NULL;
     
    212242            break;
    213243        case '\\':
    214             if (command[1]) {
    215                 addstr(&result, command + 1, 1);
    216                 command += 2;
    217             } else {
    218                 addstr(&result, command, 1);
     244            if (command[1])
    219245                command++;
    220             }
     246            addstr(&result, command, 1);
     247            command++;
    221248            break;
    222249        case '[':
     
    227254                command += 2;
    228255            } else {
    229                 addstr(&result, "[", 1);
     256                addstr(&result, command, 1);
    230257                command++;
    231258            }
     
    239266                command += 2;
    240267            } else {
    241                 addstr(&result, "]", 1);
     268                addstr(&result, command, 1);
    242269                command++;
    243270            }
     
    251278                nextpercent = strchr(command, '%');
    252279                if (!nextpercent) {
    253                     errno = EUNBALPER;
     280                    /* Unterminated %var% */
    254281                    free(result);
    255282                    return NULL;
     
    296323
    297324    if (opt_depth > 1) {
    298         errno = EUNBALBRACK;
     325        /* Unbalanced bracket */
    299326        free(result);
    300327        return NULL;
     
    302329
    303330    if (!okay[0]) {
    304         errno = EUNDEFVAR;
     331        /* Undefined variable and we aren't in a bracket */
    305332        free(result);
    306333        return NULL;
     
    369396    result += execute("ip link set[[ mtu %mtu%]][[ addr %hwaddress%]] %iface% up", ifd, exec);
    370397    /* Was: "[[ ip ....%gateway% ]]". Removed extra spaces w/o checking */
    371     result += execute("[[ip route add ::/0 via %gateway%]]", ifd, exec);
     398    result += execute("[[ip route add ::/0 via %gateway%]][[ prio %metric%]]", ifd, exec);
    372399# else
    373400    result = execute("ifconfig %iface%[[ media %media%]][[ hw %hwaddress%]][[ mtu %mtu%]] up", ifd, exec);
    374401    result += execute("ifconfig %iface% add %address%/%netmask%", ifd, exec);
    375     result += execute("[[route -A inet6 add ::/0 gw %gateway%]]", ifd, exec);
     402    result += execute("[[route -A inet6 add ::/0 gw %gateway%[[ metric %metric%]]]]", ifd, exec);
    376403# endif
    377404    return ((result == 3) ? 3 : 0);
     
    456483            "dev %iface%[[ peer %pointopoint%]][[ label %label%]]", ifd, exec);
    457484    result += execute("ip link set[[ mtu %mtu%]][[ addr %hwaddress%]] %iface% up", ifd, exec);
    458     result += execute("[[ip route add default via %gateway% dev %iface%]]", ifd, exec);
     485    result += execute("[[ip route add default via %gateway% dev %iface%[[ prio %metric%]]]]", ifd, exec);
    459486    return ((result == 3) ? 3 : 0);
    460487# else
     
    466493                "[[ broadcast %broadcast%]][[ pointopoint %pointopoint%]] ",
    467494                ifd, exec);
    468     result += execute("[[route add default gw %gateway% %iface%]]", ifd, exec);
     495    result += execute("[[route add default gw %gateway%[[ metric %metric%]] %iface%]]", ifd, exec);
    469496    return ((result == 3) ? 3 : 0);
    470497# endif
     
    777804                currmap->match[currmap->n_matches++] = xstrdup(first_word);
    778805            }
    779             /*currmap->max_mappings = 0; - done by xzalloc */
    780806            /*currmap->n_mappings = 0;*/
    781807            /*currmap->mapping = NULL;*/
     
    862888                    bb_error_msg_and_die("option with empty value \"%s\"", buf);
    863889
    864                 if (strcmp(first_word, "up") != 0
    865                  && strcmp(first_word, "down") != 0
    866                  && strcmp(first_word, "pre-up") != 0
    867                  && strcmp(first_word, "post-down") != 0
    868                 ) {
     890                if (strcmp(first_word, "post-up") == 0)
     891                    first_word += 5; /* "up" */
     892                else if (strcmp(first_word, "pre-down") == 0)
     893                    first_word += 4; /* "down" */
     894
     895                /* If not one of "up", "down",... words... */
     896                if (index_in_strings(keywords_up_down, first_word) < 0) {
    869897                    int i;
    870898                    for (i = 0; i < currif->n_options; i++) {
     
    873901                    }
    874902                }
    875                 if (currif->n_options >= currif->max_options) {
    876                     currif->max_options += 10;
    877                     currif->option = xrealloc(currif->option,
    878                         sizeof(*currif->option) * currif->max_options);
    879                 }
    880903                debug_noise("\t%s=%s\n", first_word, rest_of_line);
     904                currif->option = xrealloc_vector(currif->option, 4, currif->n_options);
    881905                currif->option[currif->n_options].name = xstrdup(first_word);
    882906                currif->option[currif->n_options].value = xstrdup(rest_of_line);
     
    890914                    currmap->script = xstrdup(next_word(&rest_of_line));
    891915                } else if (strcmp(first_word, "map") == 0) {
    892                     if (currmap->n_mappings >= currmap->max_mappings) {
    893                         currmap->max_mappings = currmap->max_mappings * 2 + 1;
    894                         currmap->mapping = xrealloc(currmap->mapping,
    895                             sizeof(char *) * currmap->max_mappings);
    896                     }
     916                    currmap->mapping = xrealloc_vector(currmap->mapping, 2, currmap->n_mappings);
    897917                    currmap->mapping[currmap->n_mappings] = xstrdup(next_word(&rest_of_line));
    898918                    currmap->n_mappings++;
     
    941961}
    942962
    943 static void set_environ(struct interface_defn_t *iface, const char *mode)
     963static void set_environ(struct interface_defn_t *iface, const char *mode, const char *opt)
    944964{
    945965    int i;
     
    954974
    955975    /* note: last element will stay NULL: */
    956     G.my_environ = xzalloc(sizeof(char *) * (iface->n_options + 6));
     976    G.my_environ = xzalloc(sizeof(char *) * (iface->n_options + 7));
    957977    pp = G.my_environ;
    958978
    959979    for (i = 0; i < iface->n_options; i++) {
    960         if (strcmp(iface->option[i].name, "up") == 0
    961          || strcmp(iface->option[i].name, "down") == 0
    962          || strcmp(iface->option[i].name, "pre-up") == 0
    963          || strcmp(iface->option[i].name, "post-down") == 0
    964         ) {
     980        if (index_in_strings(keywords_up_down, iface->option[i].name) >= 0) {
    965981            continue;
    966982        }
     
    972988    *pp++ = setlocalenv("%s=%s", "METHOD", iface->method->name);
    973989    *pp++ = setlocalenv("%s=%s", "MODE", mode);
     990    *pp++ = setlocalenv("%s=%s", "PHASE", opt);
    974991    if (G.startup_PATH)
    975992        *pp++ = setlocalenv("%s=%s", "PATH", G.startup_PATH);
     
    9871004        fflush_all();
    9881005        child = vfork();
    989         switch (child) {
    990         case -1: /* failure */
     1006        if (child < 0) /* failure */
    9911007            return 0;
    992         case 0: /* child */
    993             execle(DEFAULT_SHELL, DEFAULT_SHELL, "-c", str, (char *) NULL, G.my_environ);
     1008        if (child == 0) { /* child */
     1009            execle(G.shell, G.shell, "-c", str, (char *) NULL, G.my_environ);
    9941010            _exit(127);
    9951011        }
     
    10271043{
    10281044    if (!iface->method->up(iface, check)) return -1;
    1029     set_environ(iface, "start");
     1045    set_environ(iface, "start", "pre-up");
    10301046    if (!execute_all(iface, "pre-up")) return 0;
    10311047    if (!iface->method->up(iface, doit)) return 0;
     1048    set_environ(iface, "start", "post-up");
    10321049    if (!execute_all(iface, "up")) return 0;
    10331050    return 1;
     
    10361053static int iface_down(struct interface_defn_t *iface)
    10371054{
    1038     if (!iface->method->down(iface,check)) return -1;
    1039     set_environ(iface, "stop");
     1055    if (!iface->method->down(iface, check)) return -1;
     1056    set_environ(iface, "stop", "pre-down");
    10401057    if (!execute_all(iface, "down")) return 0;
    10411058    if (!iface->method->down(iface, doit)) return 0;
     1059    set_environ(iface, "stop", "post-down");
    10421060    if (!execute_all(iface, "post-down")) return 0;
    10431061    return 1;
     
    11661184
    11671185    G.startup_PATH = getenv("PATH");
     1186    G.shell = xstrdup(get_shell_name());
    11681187
    11691188    cmds = iface_down;
     
    12211240                if (iface_state) {
    12221241                    bb_error_msg("interface %s already configured", iface);
    1223                     continue;
     1242                    goto next;
    12241243                }
    12251244            } else {
     
    12271246                if (!iface_state) {
    12281247                    bb_error_msg("interface %s not configured", iface);
    1229                     continue;
     1248                    goto next;
    12301249                }
    12311250            }
     
    12911310            llist_t *iface_state = find_iface_state(state_list, iface);
    12921311
    1293             if (cmds == iface_up) {
    1294                 char * const newiface = xasprintf("%s=%s", iface, liface);
    1295                 if (iface_state == NULL) {
     1312            if (cmds == iface_up && !any_failures) {
     1313                char *newiface = xasprintf("%s=%s", iface, liface);
     1314                if (!iface_state) {
    12961315                    llist_add_to_end(&state_list, newiface);
    12971316                } else {
     
    13171336            llist_free(state_list, free);
    13181337        }
     1338 next:
     1339        free(iface);
     1340        free(liface);
    13191341    }
    13201342
  • branches/3.2/mindi-busybox/networking/inetd.c

    r2725 r3232  
    155155 */
    156156
     157//usage:#define inetd_trivial_usage
     158//usage:       "[-fe] [-q N] [-R N] [CONFFILE]"
     159//usage:#define inetd_full_usage "\n\n"
     160//usage:       "Listen for network connections and launch programs\n"
     161//usage:     "\n    -f  Run in foreground"
     162//usage:     "\n    -e  Log to stderr"
     163//usage:     "\n    -q N    Socket listen queue (default: 128)"
     164//usage:     "\n    -R N    Pause services after N connects/min"
     165//usage:     "\n        (default: 0 - disabled)"
     166
    157167#include <syslog.h>
     168#include <sys/resource.h> /* setrlimit */
     169#include <sys/socket.h> /* un.h may need this */
    158170#include <sys/un.h>
    159171
     
    161173
    162174#if ENABLE_FEATURE_INETD_RPC
    163 #include <rpc/rpc.h>
    164 #include <rpc/pmap_clnt.h>
     175# if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__)
     176#  error "You need to build uClibc with UCLIBC_HAS_RPC for NFS support"
     177# endif
     178# include <rpc/rpc.h>
     179# include <rpc/pmap_clnt.h>
    165180#endif
    166181
     
    171186#define ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN 0
    172187#endif
    173 
    174 #define _PATH_INETDPID  "/var/run/inetd.pid"
    175188
    176189#define CNT_INTERVAL    60      /* servers in CNT_INTERVAL sec. */
     
    345358} while (0)
    346359
     360#if 1
     361# define dbg(...) ((void)0)
     362#else
     363# define dbg(...) \
     364do { \
     365    int dbg_fd = open("inetd_debug.log", O_WRONLY | O_CREAT | O_APPEND, 0666); \
     366    if (dbg_fd >= 0) { \
     367        fdprintf(dbg_fd, "%d: ", getpid()); \
     368        fdprintf(dbg_fd, __VA_ARGS__); \
     369        close(dbg_fd); \
     370    } \
     371} while (0)
     372#endif
     373
    347374static void maybe_close(int fd)
    348375{
    349     if (fd >= 0)
     376    if (fd >= 0) {
    350377        close(fd);
     378        dbg("closed fd:%d\n", fd);
     379    }
    351380}
    352381
     
    452481    if (fd >= 0) {
    453482        FD_CLR(fd, &allsock);
     483        dbg("stopped listening on fd:%d\n", fd);
    454484        maxsock = -1;
     485        dbg("maxsock:%d\n", maxsock);
    455486    }
    456487}
     
    460491    if (fd >= 0) {
    461492        FD_SET(fd, &allsock);
     493        dbg("started listening on fd:%d\n", fd);
    462494        if (maxsock >= 0 && fd > maxsock) {
    463495            prev_maxsock = maxsock = fd;
     496            dbg("maxsock:%d\n", maxsock);
    464497            if ((rlim_t)fd > rlim_ofile_cur - FD_MARGIN)
    465498                bump_nofile();
     
    480513        fd++;
    481514    }
     515    dbg("recalculated maxsock:%d\n", maxsock);
    482516    prev_maxsock = maxsock;
    483517    if ((rlim_t)maxsock > rlim_ofile_cur - FD_MARGIN)
     
    502536        /* zero out the port for all RPC services; let bind()
    503537         * find one. */
    504         set_nport(sep->se_lsa, 0);
     538        set_nport(&sep->se_lsa->u.sa, 0);
    505539
    506540        /* for RPC services, attempt to use a reserved port
     
    537571        return;
    538572    }
    539     if (sep->se_socktype == SOCK_STREAM)
     573
     574    if (sep->se_socktype == SOCK_STREAM) {
    540575        listen(fd, global_queuelen);
     576        dbg("new sep->se_fd:%d (stream)\n", fd);
     577    } else {
     578        dbg("new sep->se_fd:%d (!stream)\n", fd);
     579    }
    541580
    542581    add_fd_to_set(fd);
     
    960999            if (LONE_CHAR(sep->se_local_hostname, '*')) {
    9611000                lsa = xzalloc_lsa(sep->se_family);
    962                 set_nport(lsa, port);
     1001                set_nport(&lsa->u.sa, port);
    9631002            } else {
    9641003                lsa = host_and_af2sockaddr(sep->se_local_hostname,
     
    10001039    block_CHLD_HUP_ALRM(&omask);
    10011040    sepp = &serv_list;
    1002     while ((sep = *sepp)) {
     1041    while ((sep = *sepp) != NULL) {
    10031042        if (sep->se_checked) {
    10041043            sepp = &sep->se_next;
     
    10921131            close(sep->se_fd);
    10931132    }
    1094     remove_pidfile(_PATH_INETDPID);
     1133    remove_pidfile(CONFIG_PID_FILE_PATH "/inetd.pid");
    10951134    exit(EXIT_SUCCESS);
    10961135}
     
    11411180    }
    11421181
    1143     write_pidfile(_PATH_INETDPID);
     1182    write_pidfile(CONFIG_PID_FILE_PATH "/inetd.pid");
    11441183
    11451184    /* never fails under Linux (except if you pass it bad arguments) */
     
    11541193    sigaddset(&sa.sa_mask, SIGCHLD);
    11551194    sigaddset(&sa.sa_mask, SIGHUP);
     1195//FIXME: explain why no SA_RESTART
     1196//FIXME: retry_network_setup is unsafe to run in signal handler (many reasons)!
    11561197    sa.sa_handler = retry_network_setup;
    11571198    sigaction_set(SIGALRM, &sa);
     1199//FIXME: reread_config_file is unsafe to run in signal handler(many reasons)!
    11581200    sa.sa_handler = reread_config_file;
    11591201    sigaction_set(SIGHUP, &sa);
     1202//FIXME: reap_child is unsafe to run in signal handler (uses stdio)!
    11601203    sa.sa_handler = reap_child;
    11611204    sigaction_set(SIGCHLD, &sa);
     1205//FIXME: clean_up_and_exit is unsafe to run in signal handler (uses stdio)!
    11621206    sa.sa_handler = clean_up_and_exit;
    11631207    sigaction_set(SIGTERM, &sa);
     
    11891233            continue;
    11901234        }
     1235        dbg("ready_fd_cnt:%d\n", ready_fd_cnt);
    11911236
    11921237        for (sep = serv_list; ready_fd_cnt && sep; sep = sep->se_next) {
     
    11941239                continue;
    11951240
     1241            dbg("ready fd:%d\n", sep->se_fd);
    11961242            ready_fd_cnt--;
    11971243            ctrl = sep->se_fd;
     
    12011247                if (sep->se_socktype == SOCK_STREAM) {
    12021248                    ctrl = accepted_fd = accept(sep->se_fd, NULL, NULL);
     1249                    dbg("accepted_fd:%d\n", accepted_fd);
    12031250                    if (ctrl < 0) {
    12041251                        if (errno != EINTR)
     
    12211268 * Parent must create and use new socket instead. */
    12221269                    new_udp_fd = socket(sep->se_family, SOCK_DGRAM, 0);
     1270                    dbg("new_udp_fd:%d\n", new_udp_fd);
    12231271                    if (new_udp_fd < 0) { /* error: eat packet, forget about it */
    12241272 udp_err:
     
    12271275                    }
    12281276                    setsockopt_reuseaddr(new_udp_fd);
    1229                     /* TODO: better do bind after vfork in parent,
     1277                    /* TODO: better do bind after fork in parent,
    12301278                     * so that we don't have two wildcard bound sockets
    12311279                     * even for a brief moment? */
    12321280                    if (bind(new_udp_fd, &sep->se_lsa->u.sa, sep->se_lsa->len) < 0) {
     1281                        dbg("bind(new_udp_fd) failed\n");
    12331282                        close(new_udp_fd);
    12341283                        goto udp_err;
    12351284                    }
     1285                    dbg("bind(new_udp_fd) succeeded\n");
    12361286                }
    12371287            }
     
    12611311                            rearm_alarm(); /* will revive it in RETRYTIME sec */
    12621312                            restore_sigmask(&omask);
     1313                            maybe_close(new_udp_fd);
    12631314                            maybe_close(accepted_fd);
    12641315                            continue; /* -> check next fd in fd set */
     
    12811332                    sleep(1);
    12821333                    restore_sigmask(&omask);
     1334                    maybe_close(new_udp_fd);
    12831335                    maybe_close(accepted_fd);
    12841336                    continue; /* -> check next fd in fd set */
     
    12871339                    pid--; /* -1: "we did fork and we are child" */
    12881340            }
    1289             /* if pid == 0 here, we never forked */
     1341            /* if pid == 0 here, we didn't fork */
    12901342
    12911343            if (pid > 0) { /* parent */
    12921344                if (sep->se_wait) {
    1293                     /* tcp wait: we passed listening socket to child,
     1345                    /* wait: we passed socket to child,
    12941346                     * will wait for child to terminate */
    12951347                    sep->se_wait = pid;
     
    13001352                     * we created and will use new, unconnected one */
    13011353                    xmove_fd(new_udp_fd, sep->se_fd);
     1354                    dbg("moved new_udp_fd:%d to sep->se_fd:%d\n", new_udp_fd, sep->se_fd);
    13021355                }
    13031356                restore_sigmask(&omask);
     
    13061359            }
    13071360
    1308             /* we are either child or didn't vfork at all */
     1361            /* we are either child or didn't fork at all */
    13091362#ifdef INETD_BUILTINS_ENABLED
    13101363            if (sep->se_builtin) {
    1311                 if (pid) { /* "pid" is -1: we did vfork */
     1364                if (pid) { /* "pid" is -1: we did fork */
    13121365                    close(sep->se_fd); /* listening socket */
     1366                    dbg("closed sep->se_fd:%d\n", sep->se_fd);
    13131367                    logmode = LOGMODE_NONE; /* make xwrite etc silent */
    13141368                }
     
    13181372                else
    13191373                    sep->se_builtin->bi_dgram_fn(ctrl, sep);
    1320                 if (pid) /* we did vfork */
     1374                if (pid) /* we did fork */
    13211375                    _exit(EXIT_FAILURE);
    13221376                maybe_close(accepted_fd);
     
    13281382            /* "nowait" udp */
    13291383            if (new_udp_fd >= 0) {
    1330                 len_and_sockaddr *lsa = xzalloc_lsa(sep->se_family);
     1384                len_and_sockaddr *lsa;
     1385                int r;
     1386
     1387                close(new_udp_fd);
     1388                dbg("closed new_udp_fd:%d\n", new_udp_fd);
     1389                lsa = xzalloc_lsa(sep->se_family);
    13311390                /* peek at the packet and remember peer addr */
    1332                 int r = recvfrom(ctrl, NULL, 0, MSG_PEEK|MSG_DONTWAIT,
     1391                r = recvfrom(ctrl, NULL, 0, MSG_PEEK|MSG_DONTWAIT,
    13331392                    &lsa->u.sa, &lsa->len);
    13341393                if (r < 0)
     
    13381397                 * and bare write()/send() will work on it */
    13391398                connect(ctrl, &lsa->u.sa, lsa->len);
     1399                dbg("connected ctrl:%d to remote peer\n", ctrl);
    13401400                free(lsa);
    13411401            }
     
    13551415                goto do_exit1;
    13561416            }
    1357             if (pwd->pw_uid) {
     1417            if (pwd->pw_uid != 0) {
    13581418                if (sep->se_group)
    13591419                    pwd->pw_gid = grp->gr_gid;
     
    13741434            xmove_fd(ctrl, STDIN_FILENO);
    13751435            xdup2(STDIN_FILENO, STDOUT_FILENO);
     1436            dbg("moved ctrl:%d to fd 0,1[,2]\n", ctrl);
    13761437            /* manpages of inetd I managed to find either say
    13771438             * that stderr is also redirected to the network,
     
    13861447            sigaction_set(SIGPIPE, &saved_pipe_handler);
    13871448            restore_sigmask(&omask);
     1449            dbg("execing:'%s'\n", sep->se_program);
    13881450            BB_EXECVP(sep->se_program, sep->se_argv);
    13891451            bb_perror_msg("can't execute '%s'", sep->se_program);
  • branches/3.2/mindi-busybox/networking/interface.c

    r2725 r3232  
    2828 *                     - gettext instead of catgets for i18n
    2929 *          10/1998  - Andi Kleen. Use interface list primitives.
    30  *      20001008 - Bernd Eckenfels, Patch from RH for setting mtu
     30 *          20001008 - Bernd Eckenfels, Patch from RH for setting mtu
    3131 *          (default AF was wrong)
    3232 */
     33
     34#include "libbb.h"
     35#include "inet_common.h"
    3336#include <net/if.h>
    3437#include <net/if_arp.h>
    35 #if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined(_NEWLIB_VERSION)
     38#ifdef HAVE_NET_ETHERNET_H
    3639# include <net/ethernet.h>
    37 #else
    38 # include <linux/if_ether.h>
    39 #endif
    40 #include "libbb.h"
    41 #include "inet_common.h"
     40#endif
    4241
    4342#if ENABLE_FEATURE_HWIB
     
    952951            sap.sin6_family = AF_INET6;
    953952            printf("          inet6 addr: %s/%d",
    954                    INET6_sprint((struct sockaddr *) &sap, 1),
    955                    plen);
     953                INET6_sprint((struct sockaddr *) &sap, 1),
     954                plen);
    956955            printf(" Scope:");
    957956            switch (scope & IPV6_ADDR_SCOPE_MASK) {
     
    10211020    if (ptr->has_ip) {
    10221021        printf("          %s addr:%s ", ap->name,
    1023                ap->sprint(&ptr->addr, 1));
     1022            ap->sprint(&ptr->addr, 1));
    10241023        if (ptr->flags & IFF_POINTOPOINT) {
    10251024            printf(" P-t-P:%s ", ap->sprint(&ptr->dstaddr, 1));
     
    11041103
    11051104        printf("RX packets:%llu errors:%lu dropped:%lu overruns:%lu frame:%lu\n",
    1106                ptr->stats.rx_packets, ptr->stats.rx_errors,
    1107                ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors,
    1108                ptr->stats.rx_frame_errors);
     1105            ptr->stats.rx_packets, ptr->stats.rx_errors,
     1106            ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors,
     1107            ptr->stats.rx_frame_errors);
    11091108        if (can_compress)
    11101109            printf("             compressed:%lu\n",
    1111                    ptr->stats.rx_compressed);
     1110                ptr->stats.rx_compressed);
    11121111        printf("          ");
    11131112        printf("TX packets:%llu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n",
    1114                ptr->stats.tx_packets, ptr->stats.tx_errors,
    1115                ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors,
    1116                ptr->stats.tx_carrier_errors);
     1113            ptr->stats.tx_packets, ptr->stats.tx_errors,
     1114            ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors,
     1115            ptr->stats.tx_carrier_errors);
    11171116        printf("          collisions:%lu ", ptr->stats.collisions);
    11181117        if (can_compress)
     
    11311130        if (ptr->map.irq)
    11321131            printf("Interrupt:%d ", ptr->map.irq);
    1133         if (ptr->map.base_addr >= 0x100)    /* Only print devices using it for
    1134                                                I/O maps */
     1132        if (ptr->map.base_addr >= 0x100) /* Only print devices using it for I/O maps */
    11351133            printf("Base address:0x%lx ",
    1136                    (unsigned long) ptr->map.base_addr);
     1134                (unsigned long) ptr->map.base_addr);
    11371135        if (ptr->map.mem_start) {
    11381136            printf("Memory:%lx-%lx ", ptr->map.mem_start,
    1139                    ptr->map.mem_end);
     1137                ptr->map.mem_end);
    11401138        }
    11411139        if (ptr->map.dma)
     
    11701168#ifdef UNUSED
    11711169static int for_all_interfaces(int (*doit) (struct interface *, void *),
    1172                               void *cookie)
     1170                            void *cookie)
    11731171{
    11741172    struct interface *ife;
  • branches/3.2/mindi-busybox/networking/ip.c

    r2725 r3232  
    99 * Bernhard Reutner-Fischer rewrote to use index_in_substr_array
    1010 */
     11
     12/* would need to make the " | " optional depending on more than one selected: */
     13//usage:#define ip_trivial_usage
     14//usage:       "[OPTIONS] {"
     15//usage:    IF_FEATURE_IP_ADDRESS("address | ")
     16//usage:    IF_FEATURE_IP_ROUTE("route | ")
     17//usage:    IF_FEATURE_IP_LINK("link | ")
     18//usage:    IF_FEATURE_IP_TUNNEL("tunnel | ")
     19//usage:    IF_FEATURE_IP_RULE("rule")
     20//usage:       "} {COMMAND}"
     21//usage:#define ip_full_usage "\n\n"
     22//usage:       "ip [OPTIONS] OBJECT {COMMAND}\n"
     23//usage:       "where OBJECT := {"
     24//usage:    IF_FEATURE_IP_ADDRESS("address | ")
     25//usage:    IF_FEATURE_IP_ROUTE("route | ")
     26//usage:    IF_FEATURE_IP_LINK("link | ")
     27//usage:    IF_FEATURE_IP_TUNNEL("tunnel | ")
     28//usage:    IF_FEATURE_IP_RULE("rule")
     29//usage:       "}\n"
     30//usage:       "OPTIONS := { -f[amily] { inet | inet6 | link } | -o[neline] }"
     31//usage:
     32//usage:#define ipaddr_trivial_usage
     33//usage:       "{ {add|del} IFADDR dev STRING | {show|flush}\n"
     34//usage:       "        [dev STRING] [to PREFIX] }"
     35//usage:#define ipaddr_full_usage "\n\n"
     36//usage:       "ipaddr {add|delete} IFADDR dev STRING\n"
     37//usage:       "ipaddr {show|flush} [dev STRING] [scope SCOPE-ID]\n"
     38//usage:       "    [to PREFIX] [label PATTERN]\n"
     39//usage:       "    IFADDR := PREFIX | ADDR peer PREFIX\n"
     40//usage:       "    [broadcast ADDR] [anycast ADDR]\n"
     41//usage:       "    [label STRING] [scope SCOPE-ID]\n"
     42//usage:       "    SCOPE-ID := [host | link | global | NUMBER]"
     43//usage:
     44//usage:#define iplink_trivial_usage
     45//usage:       "{ set DEVICE { up | down | arp { on | off } | show [DEVICE] }"
     46//usage:#define iplink_full_usage "\n\n"
     47//usage:       "iplink set DEVICE { up | down | arp | multicast { on | off } |\n"
     48//usage:       "            dynamic { on | off } |\n"
     49//usage:       "            mtu MTU }\n"
     50//usage:       "iplink show [DEVICE]"
     51//usage:
     52//usage:#define iproute_trivial_usage
     53//usage:       "{ list | flush | add | del | change | append |\n"
     54//usage:       "        replace | test } ROUTE"
     55//usage:#define iproute_full_usage "\n\n"
     56//usage:       "iproute { list | flush } SELECTOR\n"
     57//usage:       "iproute get ADDRESS [from ADDRESS iif STRING]\n"
     58//usage:       "    [oif STRING] [tos TOS]\n"
     59//usage:       "iproute { add | del | change | append | replace | test } ROUTE\n"
     60//usage:       "    SELECTOR := [root PREFIX] [match PREFIX] [proto RTPROTO]\n"
     61//usage:       "    ROUTE := [TYPE] PREFIX [tos TOS] [proto RTPROTO] [metric METRIC]"
     62//usage:
     63//usage:#define iprule_trivial_usage
     64//usage:       "{[list | add | del] RULE}"
     65//usage:#define iprule_full_usage "\n\n"
     66//usage:       "iprule [list | add | del] SELECTOR ACTION\n"
     67//usage:       "    SELECTOR := [from PREFIX] [to PREFIX] [tos TOS] [fwmark FWMARK]\n"
     68//usage:       "            [dev STRING] [pref NUMBER]\n"
     69//usage:       "    ACTION := [table TABLE_ID] [nat ADDRESS]\n"
     70//usage:       "            [prohibit | reject | unreachable]\n"
     71//usage:       "            [realms [SRCREALM/]DSTREALM]\n"
     72//usage:       "    TABLE_ID := [local | main | default | NUMBER]"
     73//usage:
     74//usage:#define iptunnel_trivial_usage
     75//usage:       "{ add | change | del | show } [NAME]\n"
     76//usage:       "    [mode { ipip | gre | sit }]\n"
     77//usage:       "    [remote ADDR] [local ADDR] [ttl TTL]"
     78//usage:#define iptunnel_full_usage "\n\n"
     79//usage:       "iptunnel { add | change | del | show } [NAME]\n"
     80//usage:       "    [mode { ipip | gre | sit }] [remote ADDR] [local ADDR]\n"
     81//usage:       "    [[i|o]seq] [[i|o]key KEY] [[i|o]csum]\n"
     82//usage:       "    [ttl TTL] [tos TOS] [[no]pmtudisc] [dev PHYS_DEV]"
    1183
    1284#include "libbb.h"
  • branches/3.2/mindi-busybox/networking/ipcalc.c

    r2725 r3232  
    1212 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1313 */
     14
     15//usage:#define ipcalc_trivial_usage
     16//usage:       "[OPTIONS] ADDRESS[[/]NETMASK] [NETMASK]"
     17//usage:#define ipcalc_full_usage "\n\n"
     18//usage:       "Calculate IP network settings from a IP address\n"
     19//usage:    IF_FEATURE_IPCALC_LONG_OPTIONS(
     20//usage:     "\n    -b,--broadcast  Display calculated broadcast address"
     21//usage:     "\n    -n,--network    Display calculated network address"
     22//usage:     "\n    -m,--netmask    Display default netmask for IP"
     23//usage:    IF_FEATURE_IPCALC_FANCY(
     24//usage:     "\n    -p,--prefix Display the prefix for IP/NETMASK"
     25//usage:     "\n    -h,--hostname   Display first resolved host name"
     26//usage:     "\n    -s,--silent Don't ever display error messages"
     27//usage:    )
     28//usage:    )
     29//usage:    IF_NOT_FEATURE_IPCALC_LONG_OPTIONS(
     30//usage:     "\n    -b  Display calculated broadcast address"
     31//usage:     "\n    -n  Display calculated network address"
     32//usage:     "\n    -m  Display default netmask for IP"
     33//usage:    IF_FEATURE_IPCALC_FANCY(
     34//usage:     "\n    -p  Display the prefix for IP/NETMASK"
     35//usage:     "\n    -h  Display first resolved host name"
     36//usage:     "\n    -s  Don't ever display error messages"
     37//usage:    )
     38//usage:    )
     39
    1440#include "libbb.h"
    1541/* After libbb.h, because on some systems it needs other includes */
  • branches/3.2/mindi-busybox/networking/isrv_identd.c

    r2725 r3232  
    77 * Licensed under GPLv2, see file LICENSE in this source tree.
    88 */
     9
     10//usage:#define fakeidentd_trivial_usage
     11//usage:       "[-fiw] [-b ADDR] [STRING]"
     12//usage:#define fakeidentd_full_usage "\n\n"
     13//usage:       "Provide fake ident (auth) service\n"
     14//usage:     "\n    -f  Run in foreground"
     15//usage:     "\n    -i  Inetd mode"
     16//usage:     "\n    -w  Inetd 'wait' mode"
     17//usage:     "\n    -b ADDR Bind to specified address"
     18//usage:     "\n    STRING  Ident answer string (default: nobody)"
    919
    1020#include "libbb.h"
  • branches/3.2/mindi-busybox/networking/libiproute/ipaddress.c

    r2725 r3232  
    163163    }
    164164#endif
     165/* IFLA_OPERSTATE was added to kernel with the same commit as IFF_DORMANT */
     166#ifdef IFF_DORMANT
    165167    if (tb[IFLA_OPERSTATE]) {
    166168        static const char operstate_labels[] ALIGN1 =
     
    170172                    *(uint8_t *)RTA_DATA(tb[IFLA_OPERSTATE])));
    171173    }
     174#endif
    172175    if (G_filter.showqueue)
    173176        print_queuelen((char*)RTA_DATA(tb[IFLA_IFNAME]));
     
    312315        printf("brd %s ",
    313316            rt_addr_n2a(ifa->ifa_family,
    314                     RTA_DATA(rta_tb[IFA_BROADCAST]),
    315                     abuf, sizeof(abuf)));
     317                    RTA_DATA(rta_tb[IFA_BROADCAST]),
     318                    abuf, sizeof(abuf))
     319        );
    316320    }
    317321    if (rta_tb[IFA_ANYCAST]) {
    318322        printf("any %s ",
    319323            rt_addr_n2a(ifa->ifa_family,
    320                     RTA_DATA(rta_tb[IFA_ANYCAST]),
    321                     abuf, sizeof(abuf)));
     324                    RTA_DATA(rta_tb[IFA_ANYCAST]),
     325                    abuf, sizeof(abuf))
     326        );
    322327    }
    323328    printf("scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1));
  • branches/3.2/mindi-busybox/networking/libiproute/iplink.c

    r2725 r3232  
    88#include <net/if_packet.h>
    99#include <netpacket/packet.h>
    10 #include <net/ethernet.h>
     10#include <netinet/if_ether.h>
    1111
    1212#include "ip_common.h"  /* #include "libbb.h" is inside */
  • branches/3.2/mindi-busybox/networking/libiproute/iproute.c

    r2725 r3232  
    3232    //int typemask; - unused
    3333    //int tos, tosmask; - unused
    34     int iif, iifmask;
    35     int oif, oifmask;
     34    int iif;
     35    int oif;
    3636    //int realm, realmmask; - unused
    3737    //inet_prefix rprefsrc; - read-only
     
    8383    struct rtmsg *r = NLMSG_DATA(n);
    8484    int len = n->nlmsg_len;
    85     struct rtattr * tb[RTA_MAX+1];
     85    struct rtattr *tb[RTA_MAX+1];
    8686    char abuf[256];
    8787    inet_prefix dst;
     
    160160
    161161    memset(tb, 0, sizeof(tb));
     162    memset(&src, 0, sizeof(src));
     163    memset(&dst, 0, sizeof(dst));
    162164    parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
     165
     166    if (tb[RTA_SRC]) {
     167        src.bitlen = r->rtm_src_len;
     168        src.bytelen = (r->rtm_family == AF_INET6 ? 16 : 4);
     169        memcpy(src.data, RTA_DATA(tb[RTA_SRC]), src.bytelen);
     170    }
     171    if (tb[RTA_DST]) {
     172        dst.bitlen = r->rtm_dst_len;
     173        dst.bytelen = (r->rtm_family == AF_INET6 ? 16 : 4);
     174        memcpy(dst.data, RTA_DATA(tb[RTA_DST]), dst.bytelen);
     175    }
    163176
    164177    if (G_filter.rdst.family
     
    183196        return 0;
    184197    }
    185     if (G_filter.flushb
    186      && r->rtm_family == AF_INET6
    187      && r->rtm_dst_len == 0
    188      && r->rtm_type == RTN_UNREACHABLE
    189      && tb[RTA_PRIORITY]
    190      && *(int*)RTA_DATA(tb[RTA_PRIORITY]) == -1
    191     ) {
    192         return 0;
     198    if (G_filter.oif != 0) {
     199        if (!tb[RTA_OIF])
     200            return 0;
     201        if (G_filter.oif != *(int*)RTA_DATA(tb[RTA_OIF]))
     202            return 0;
    193203    }
    194204
    195205    if (G_filter.flushb) {
    196206        struct nlmsghdr *fn;
     207
     208        /* We are creating route flush commands */
     209
     210        if (r->rtm_family == AF_INET6
     211         && r->rtm_dst_len == 0
     212         && r->rtm_type == RTN_UNREACHABLE
     213         && tb[RTA_PRIORITY]
     214         && *(int*)RTA_DATA(tb[RTA_PRIORITY]) == -1
     215        ) {
     216            return 0;
     217        }
     218
    197219        if (NLMSG_ALIGN(G_filter.flushp) + n->nlmsg_len > G_filter.flushe) {
    198220            if (flush_update())
    199221                bb_error_msg_and_die("flush");
    200222        }
    201         fn = (struct nlmsghdr*)(G_filter.flushb + NLMSG_ALIGN(G_filter.flushp));
     223        fn = (void*)(G_filter.flushb + NLMSG_ALIGN(G_filter.flushp));
    202224        memcpy(fn, n, n->nlmsg_len);
    203225        fn->nlmsg_type = RTM_DELROUTE;
     
    208230        return 0;
    209231    }
     232
     233    /* We are printing routes */
    210234
    211235    if (n->nlmsg_type == RTM_DELROUTE) {
     
    258282                    abuf, sizeof(abuf)));
    259283    }
    260     if (tb[RTA_OIF] && G_filter.oifmask != -1) {
     284    if (tb[RTA_OIF]) {
    261285        printf("dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF])));
    262286    }
     287
     288    /* Todo: parse & show "proto kernel", "scope link" here */
    263289
    264290    if (tb[RTA_PREFSRC] && /*G_filter.rprefsrc.bitlen - always 0*/ 0 != host_len) {
     
    293319        }
    294320    }
    295     if (tb[RTA_IIF] && G_filter.iifmask != -1) {
     321    if (tb[RTA_IIF] && G_filter.iif == 0) {
    296322        printf(" iif %s", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_IIF])));
    297323    }
     
    414440            }
    415441            if ((**argv < '0' || **argv > '9')
    416              && rtnl_rtntype_a2n(&type, *argv) == 0) {
     442             && rtnl_rtntype_a2n(&type, *argv) == 0
     443            ) {
    417444                NEXT_ARG();
    418445                req.r.rtm_type = type;
     
    663690            idx = xll_name_to_index(id);
    664691            G_filter.iif = idx;
    665             G_filter.iifmask = -1;
    666692        }
    667693        if (od) {
    668694            idx = xll_name_to_index(od);
    669695            G_filter.oif = idx;
    670             G_filter.oifmask = -1;
    671696        }
    672697    }
  • branches/3.2/mindi-busybox/networking/libiproute/iprule.c

    r2725 r3232  
    7474        if (r->rtm_src_len != host_len) {
    7575            printf("%s/%u", rt_addr_n2a(r->rtm_family,
    76                              RTA_DATA(tb[RTA_SRC]),
    77                              abuf, sizeof(abuf)),
     76                            RTA_DATA(tb[RTA_SRC]),
     77                            abuf, sizeof(abuf)),
    7878                r->rtm_src_len
    79                 );
     79            );
    8080        } else {
    8181            fputs(format_host(r->rtm_family,
    82                                RTA_PAYLOAD(tb[RTA_SRC]),
    83                                RTA_DATA(tb[RTA_SRC]),
    84                                abuf, sizeof(abuf)), stdout);
     82                        RTA_PAYLOAD(tb[RTA_SRC]),
     83                        RTA_DATA(tb[RTA_SRC]),
     84                        abuf, sizeof(abuf)),
     85                stdout
     86            );
    8587        }
    8688    } else if (r->rtm_src_len) {
  • branches/3.2/mindi-busybox/networking/libiproute/iptunnel.c

    r2725 r3232  
    439439        if (p->iph.tos & ~1)
    440440            printf("%c%s ", p->iph.tos & 1 ? '/' : ' ',
    441                    rtnl_dsfield_n2a(p->iph.tos & ~1, b1));
     441                rtnl_dsfield_n2a(p->iph.tos & ~1, b1));
    442442    }
    443443    if (!(p->iph.frag_off & htons(IP_DF)))
  • branches/3.2/mindi-busybox/networking/libiproute/libnetlink.c

    r2725 r3232  
    5656}
    5757
     58//TODO: pass rth->fd instead of full rth?
    5859int FAST_FUNC rtnl_send(struct rtnl_handle *rth, char *buf, int len)
    5960{
     
    393394            tb[rta->rta_type] = rta;
    394395        }
    395         rta = RTA_NEXT(rta,len);
     396        rta = RTA_NEXT(rta, len);
    396397    }
    397398    if (len) {
  • branches/3.2/mindi-busybox/networking/libiproute/ll_proto.c

    r2725 r3232  
    1313#include "utils.h"
    1414
    15 #if defined(__GLIBC__) && __GLIBC__ >=2 && __GLIBC_MINOR__ >= 1
    16 #include <net/ethernet.h>
    17 #else
    18 #include <linux/if_ether.h>
    19 #endif
     15#include <netinet/if_ether.h>
    2016
    21 #if !ENABLE_WERROR
    22 #warning de-bloat
    23 #endif
    24 /* Before re-enabling this, please (1) conditionalize exotic protocols
    25  * on CONFIG_something, and (2) decouple strings and numbers
    26  * (use llproto_ids[] = n,n,n..; and llproto_names[] = "loop\0" "pup\0" ...;)
    27  */
     17/* Please conditionalize exotic protocols on CONFIG_something */
    2818
    29 #define __PF(f,n) { ETH_P_##f, #n },
    30 static struct {
    31     int id;
    32     const char *name;
    33 } llproto_names[] = {
     19static const uint16_t llproto_ids[] = {
     20#define __PF(f,n) ETH_P_##f,
    3421__PF(LOOP,loop)
    3522__PF(PUP,pup)
     
    9178#endif
    9279
    93 { 0x8100, "802.1Q" },
    94 { ETH_P_IP, "ipv4" },
     800x8100,
     81ETH_P_IP
    9582};
     83#undef __PF
     84
     85/* Keep declarations above and below in sync! */
     86
     87static const char llproto_names[] =
     88#define __PF(f,n) #n "\0"
     89__PF(LOOP,loop)
     90__PF(PUP,pup)
     91#ifdef ETH_P_PUPAT
     92__PF(PUPAT,pupat)
     93#endif
     94__PF(IP,ip)
     95__PF(X25,x25)
     96__PF(ARP,arp)
     97__PF(BPQ,bpq)
     98#ifdef ETH_P_IEEEPUP
     99__PF(IEEEPUP,ieeepup)
     100#endif
     101#ifdef ETH_P_IEEEPUPAT
     102__PF(IEEEPUPAT,ieeepupat)
     103#endif
     104__PF(DEC,dec)
     105__PF(DNA_DL,dna_dl)
     106__PF(DNA_RC,dna_rc)
     107__PF(DNA_RT,dna_rt)
     108__PF(LAT,lat)
     109__PF(DIAG,diag)
     110__PF(CUST,cust)
     111__PF(SCA,sca)
     112__PF(RARP,rarp)
     113__PF(ATALK,atalk)
     114__PF(AARP,aarp)
     115__PF(IPX,ipx)
     116__PF(IPV6,ipv6)
     117#ifdef ETH_P_PPP_DISC
     118__PF(PPP_DISC,ppp_disc)
     119#endif
     120#ifdef ETH_P_PPP_SES
     121__PF(PPP_SES,ppp_ses)
     122#endif
     123#ifdef ETH_P_ATMMPOA
     124__PF(ATMMPOA,atmmpoa)
     125#endif
     126#ifdef ETH_P_ATMFATE
     127__PF(ATMFATE,atmfate)
     128#endif
     129
     130__PF(802_3,802_3)
     131__PF(AX25,ax25)
     132__PF(ALL,all)
     133__PF(802_2,802_2)
     134__PF(SNAP,snap)
     135__PF(DDCMP,ddcmp)
     136__PF(WAN_PPP,wan_ppp)
     137__PF(PPP_MP,ppp_mp)
     138__PF(LOCALTALK,localtalk)
     139__PF(PPPTALK,ppptalk)
     140__PF(TR_802_2,tr_802_2)
     141__PF(MOBITEX,mobitex)
     142__PF(CONTROL,control)
     143__PF(IRDA,irda)
     144#ifdef ETH_P_ECONET
     145__PF(ECONET,econet)
     146#endif
     147
     148"802.1Q" "\0"
     149"ipv4" "\0"
     150;
    96151#undef __PF
    97152
     
    101156    unsigned i;
    102157    id = ntohs(id);
    103     for (i = 0; i < ARRAY_SIZE(llproto_names); i++) {
    104          if (llproto_names[i].id == id)
    105             return llproto_names[i].name;
     158    for (i = 0; i < ARRAY_SIZE(llproto_ids); i++) {
     159        if (llproto_ids[i] == id)
     160            return nth_string(llproto_names, i);
    106161    }
    107     snprintf(buf, len, "[%d]", id);
     162    snprintf(buf, len, "[%u]", id);
    108163    return buf;
    109164}
     
    112167{
    113168    unsigned i;
    114     for (i = 0; i < ARRAY_SIZE(llproto_names); i++) {
    115          if (strcasecmp(llproto_names[i].name, buf) == 0) {
    116              i = llproto_names[i].id;
    117              goto good;
    118          }
     169    const char *name = llproto_names;
     170    for (i = 0; i < ARRAY_SIZE(llproto_ids); i++) {
     171        if (strcasecmp(name, buf) == 0) {
     172            i = llproto_ids[i];
     173            goto good;
     174        }
     175        name += strlen(name) + 1;
    119176    }
     177    errno = 0;
    120178    i = bb_strtou(buf, NULL, 0);
    121179    if (errno || i > 0xffff)
  • branches/3.2/mindi-busybox/networking/libiproute/ll_types.c

    r2725 r3232  
    88 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
    99 */
     10#include <sys/socket.h> /* linux/if_arp.h needs it on some systems */
    1011#include <arpa/inet.h>
    1112#include <linux/if_arp.h>
  • branches/3.2/mindi-busybox/networking/libiproute/utils.c

    r2725 r3232  
    8484    }
    8585
    86     addr->family = AF_INET;
    8786    if (family != AF_UNSPEC && family != AF_INET)
    8887        return -1;
     88
     89    /* Try to parse it as IPv4 */
     90    addr->family = AF_INET;
     91#if 0 /* Doesn't handle e.g. "10.10", for example, "ip r l root 10.10/16" */
    8992    if (inet_pton(AF_INET, name, addr->data) <= 0)
    9093        return -1;
     94#else
     95    {
     96        unsigned i = 0;
     97        unsigned n = 0;
     98        const char *cp = name - 1;
     99        while (*++cp) {
     100            if ((unsigned char)(*cp - '0') <= 9) {
     101                n = 10 * n + (unsigned char)(*cp - '0');
     102                if (n >= 256)
     103                    return -1;
     104                ((uint8_t*)addr->data)[i] = n;
     105                continue;
     106            }
     107            if (*cp == '.' && ++i <= 3) {
     108                n = 0;
     109                continue;
     110            }
     111            return -1;
     112        }
     113    }
     114#endif
    91115    addr->bytelen = 4;
    92116    addr->bitlen = -1;
     117
    93118    return 0;
    94119}
    95120
    96 static int get_prefix_1(inet_prefix *dst, char *arg, int family)
    97 {
    98     int err;
    99     unsigned plen;
     121static void get_prefix_1(inet_prefix *dst, char *arg, int family)
     122{
    100123    char *slash;
    101124
     
    109132        /*dst->bytelen = 0; - done by memset */
    110133        /*dst->bitlen = 0;*/
    111         return 0;
     134        return;
    112135    }
    113136
     
    115138    if (slash)
    116139        *slash = '\0';
    117     err = get_addr_1(dst, arg, family);
    118     if (err == 0) {
     140
     141    if (get_addr_1(dst, arg, family) == 0) {
    119142        dst->bitlen = (dst->family == AF_INET6) ? 128 : 32;
    120143        if (slash) {
     144            unsigned plen;
    121145            inet_prefix netmask_pfx;
    122146
     
    124148            plen = bb_strtou(slash + 1, NULL, 0);
    125149            if ((errno || plen > dst->bitlen)
    126              && (get_addr_1(&netmask_pfx, slash + 1, family)))
    127                 err = -1;
    128             else if (netmask_pfx.family == AF_INET) {
     150             && get_addr_1(&netmask_pfx, slash + 1, family) != 0
     151            ) {
     152                goto bad;
     153            }
     154            if (netmask_pfx.family == AF_INET) {
    129155                /* fill in prefix length of dotted quad */
    130156                uint32_t mask = ntohl(netmask_pfx.data[0]);
     
    132158
    133159                /* a valid netmask must be 2^n - 1 */
    134                 if (!(host & (host + 1))) {
    135                     for (plen = 0; mask; mask <<= 1)
    136                         ++plen;
    137                     if (plen <= dst->bitlen) {
    138                         dst->bitlen = plen;
    139                         /* dst->flags |= PREFIXLEN_SPECIFIED; */
    140                     } else
    141                         err = -1;
    142                 } else
    143                     err = -1;
    144             } else {
    145                 /* plain prefix */
    146                 dst->bitlen = plen;
    147             }
    148         }
    149     }
     160                if (host & (host + 1))
     161                    goto bad;
     162
     163                for (plen = 0; mask; mask <<= 1)
     164                    ++plen;
     165                if (plen > dst->bitlen)
     166                    goto bad;
     167                /* dst->flags |= PREFIXLEN_SPECIFIED; */
     168            }
     169            dst->bitlen = plen;
     170        }
     171    }
     172
    150173    if (slash)
    151174        *slash = '/';
    152     return err;
     175    return;
     176 bad:
     177    bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "inet", "prefix", arg);
    153178}
    154179
     
    164189}
    165190
    166 int get_prefix(inet_prefix *dst, char *arg, int family)
     191void get_prefix(inet_prefix *dst, char *arg, int family)
    167192{
    168193    if (family == AF_PACKET) {
    169194        bb_error_msg_and_die("\"%s\" may be inet %s, but it is not allowed in this context", arg, "prefix");
    170195    }
    171     if (get_prefix_1(dst, arg, family)) {
    172         bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "inet", "prefix", arg);
    173     }
    174     return 0;
     196    get_prefix_1(dst, arg, family);
    175197}
    176198
     
    205227}
    206228
    207 int inet_addr_match(inet_prefix *a, inet_prefix *b, int bits)
    208 {
    209     uint32_t *a1 = a->data;
    210     uint32_t *a2 = b->data;
     229int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits)
     230{
     231    const uint32_t *a1 = a->data;
     232    const uint32_t *a2 = b->data;
    211233    int words = bits >> 5;
    212234
  • branches/3.2/mindi-busybox/networking/libiproute/utils.h

    r2725 r3232  
    5959extern uint32_t get_addr32(char *name);
    6060extern int get_addr_1(inet_prefix *dst, char *arg, int family);
    61 /*extern int get_prefix_1(inet_prefix *dst, char *arg, int family);*/
     61/*extern void get_prefix_1(inet_prefix *dst, char *arg, int family);*/
    6262extern int get_addr(inet_prefix *dst, char *arg, int family);
    63 extern int get_prefix(inet_prefix *dst, char *arg, int family);
     63extern void get_prefix(inet_prefix *dst, char *arg, int family);
    6464
    6565extern unsigned get_unsigned(char *arg, const char *errmsg);
     
    7878void duparg(const char *, const char *) NORETURN;
    7979void duparg2(const char *, const char *) NORETURN;
    80 int inet_addr_match(inet_prefix *a, inet_prefix *b, int bits);
     80int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits);
    8181
    8282const char *dnet_ntop(int af, const void *addr, char *str, size_t len);
  • branches/3.2/mindi-busybox/networking/nameif.c

    r2725 r3232  
    1111 */
    1212
     13//config:config NAMEIF
     14//config:   bool "nameif"
     15//config:   default y
     16//config:   select PLATFORM_LINUX
     17//config:   select FEATURE_SYSLOG
     18//config:   help
     19//config:     nameif is used to rename network interface by its MAC address.
     20//config:     Renamed interfaces MUST be in the down state.
     21//config:     It is possible to use a file (default: /etc/mactab)
     22//config:     with list of new interface names and MACs.
     23//config:     Maximum interface name length: IFNAMSIZ = 16
     24//config:     File fields are separated by space or tab.
     25//config:     File format:
     26//config:     # Comment
     27//config:     new_interface_name    XX:XX:XX:XX:XX:XX
     28//config:
     29//config:config FEATURE_NAMEIF_EXTENDED
     30//config:   bool "Extended nameif"
     31//config:   default y
     32//config:   depends on NAMEIF
     33//config:   help
     34//config:     This extends the nameif syntax to support the bus_info, driver,
     35//config:     phyaddr selectors. The syntax is compatible to the normal nameif.
     36//config:     File format:
     37//config:       new_interface_name  driver=asix bus=usb-0000:00:08.2-3
     38//config:       new_interface_name  bus=usb-0000:00:08.2-3 00:80:C8:38:91:B5
     39//config:       new_interface_name  phy_address=2 00:80:C8:38:91:B5
     40//config:       new_interface_name  mac=00:80:C8:38:91:B5
     41//config:       new_interface_name  00:80:C8:38:91:B5
     42
     43//usage:#define nameif_trivial_usage
     44//usage:    IF_NOT_FEATURE_NAMEIF_EXTENDED(
     45//usage:        "[-s] [-c FILE] [IFNAME HWADDR]..."
     46//usage:    )
     47//usage:    IF_FEATURE_NAMEIF_EXTENDED(
     48//usage:        "[-s] [-c FILE] [IFNAME SELECTOR]..."
     49//usage:    )
     50//usage:#define nameif_full_usage "\n\n"
     51//usage:    "Rename network interface while it in the down state."
     52//usage:    IF_NOT_FEATURE_NAMEIF_EXTENDED(
     53//usage:     "\nThe device with address HWADDR is renamed to IFACE."
     54//usage:    )
     55//usage:    IF_FEATURE_NAMEIF_EXTENDED(
     56//usage:     "\nThe device matched by SELECTOR is renamed to IFACE."
     57//usage:     "\nSELECTOR can be a combination of:"
     58//usage:     "\n    driver=STRING"
     59//usage:     "\n    bus=STRING"
     60//usage:     "\n    phy_address=NUM"
     61//usage:     "\n    [mac=]XX:XX:XX:XX:XX:XX"
     62//usage:    )
     63//usage:     "\n"
     64//usage:     "\n    -c FILE Configuration file (default: /etc/mactab)"
     65//usage:     "\n    -s  Log to syslog"
     66//usage:
     67//usage:#define nameif_example_usage
     68//usage:       "$ nameif -s dmz0 00:A0:C9:8C:F6:3F\n"
     69//usage:       " or\n"
     70//usage:       "$ nameif -c /etc/my_mactab_file\n"
     71
    1372#include "libbb.h"
    1473#include <syslog.h>
     
    3998    char *bus_info;
    4099    char *driver;
     100    int32_t phy_address;
    41101#endif
    42102} ethtable_t;
     
    60120    uint32_t regdump_len;  /* Size of data from ETHTOOL_GREGS (bytes) */
    61121};
     122
     123struct ethtool_cmd {
     124    uint32_t   cmd;
     125    uint32_t   supported;      /* Features this interface supports */
     126    uint32_t   advertising;    /* Features this interface advertises */
     127    uint16_t   speed;          /* The forced speed, 10Mb, 100Mb, gigabit */
     128    uint8_t    duplex;         /* Duplex, half or full */
     129    uint8_t    port;           /* Which connector port */
     130    uint8_t    phy_address;
     131    uint8_t    transceiver;    /* Which transceiver to use */
     132    uint8_t    autoneg;        /* Enable or disable autonegotiation */
     133    uint32_t   maxtxpkt;       /* Tx pkts before generating tx int */
     134    uint32_t   maxrxpkt;       /* Rx pkts before generating rx int */
     135    uint16_t   speed_hi;
     136    uint16_t   reserved2;
     137    uint32_t   reserved[3];
     138};
     139
     140#define ETHTOOL_GSET      0x00000001 /* Get settings. */
    62141#define ETHTOOL_GDRVINFO  0x00000003 /* Get driver info. */
    63142#endif
     
    75154        selector = skip_whitespace(selector);
    76155#if ENABLE_FEATURE_NAMEIF_EXTENDED
     156        ch->phy_address = -1;
    77157        if (*selector == '\0')
    78158            break;
     
    88168            ch->driver = xstrdup(selector + 7);
    89169            found_selector++;
     170        } else if (strncmp(selector, "phyaddr=", 8) == 0) {
     171            ch->phy_address = xatoi_positive(selector + 8);
     172            found_selector++;
    90173        } else {
    91174#endif
     
    134217
    135218int nameif_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    136 int nameif_main(int argc, char **argv)
     219int nameif_main(int argc UNUSED_PARAM, char **argv)
    137220{
    138221    ethtable_t *clist = NULL;
     
    149232        logmode |= LOGMODE_SYSLOG;
    150233    }
    151     argc -= optind;
    152234    argv += optind;
    153235
    154     if (argc & 1)
    155         bb_show_usage();
    156 
    157     if (argc) {
    158         while (*argv) {
    159             char *ifname = xstrdup(*argv++);
    160             prepend_new_eth_table(&clist, ifname, *argv++);
    161         }
     236    if (argv[0]) {
     237        do {
     238            if (!argv[1])
     239                bb_show_usage();
     240            prepend_new_eth_table(&clist, argv[0], argv[1]);
     241            argv += 2;
     242        } while (*argv);
    162243    } else {
    163244        parser = config_open(fname);
     
    174255#if  ENABLE_FEATURE_NAMEIF_EXTENDED
    175256        struct ethtool_drvinfo drvinfo;
    176 #endif
    177         if (parser->lineno < 2)
     257        struct ethtool_cmd eth_settings;
     258#endif
     259        if (parser->lineno <= 2)
    178260            continue; /* Skip the first two lines */
    179261
     
    183265
    184266#if ENABLE_FEATURE_NAMEIF_EXTENDED
     267        /* Check for phy address */
     268        memset(&eth_settings, 0, sizeof(eth_settings));
     269        eth_settings.cmd = ETHTOOL_GSET;
     270        ifr.ifr_data = (caddr_t) &eth_settings;
     271        ioctl(ctl_sk, SIOCETHTOOL, &ifr);
     272
    185273        /* Check for driver etc. */
    186         memset(&drvinfo, 0, sizeof(struct ethtool_drvinfo));
     274        memset(&drvinfo, 0, sizeof(drvinfo));
    187275        drvinfo.cmd = ETHTOOL_GDRVINFO;
    188276        ifr.ifr_data = (caddr_t) &drvinfo;
     
    198286                continue;
    199287            if (ch->driver && strcmp(ch->driver, drvinfo.driver) != 0)
     288                continue;
     289            if (ch->phy_address != -1 && ch->phy_address != eth_settings.phy_address)
    200290                continue;
    201291#endif
  • branches/3.2/mindi-busybox/networking/nbd-client.c

    r2725 r3232  
    88#include <linux/fs.h>
    99
    10 //applet:IF_NBDCLIENT(APPLET_ODDNAME(nbd-client, nbdclient, _BB_DIR_USR_SBIN, _BB_SUID_DROP, nbdclient))
     10//applet:IF_NBDCLIENT(APPLET_ODDNAME(nbd-client, nbdclient, BB_DIR_USR_SBIN, BB_SUID_DROP, nbdclient))
    1111
    1212//kbuild:lib-$(CONFIG_NBDCLIENT) += nbd-client.o
  • branches/3.2/mindi-busybox/networking/nc.c

    r2725 r3232  
    5050//usage:
    5151//usage:#if ENABLE_NC_SERVER || ENABLE_NC_EXTRA
    52 //usage:#define NC_OPTIONS_STR "\n\nOptions:"
     52//usage:#define NC_OPTIONS_STR "\n"
    5353//usage:#else
    5454//usage:#define NC_OPTIONS_STR
     
    121121        ** it cannot handle "... -e PROG -prog-opt" */
    122122        while ((opt = getopt(argc, argv,
    123                 "" IF_NC_SERVER("lp:") IF_NC_EXTRA("w:i:f:e:") )) > 0
     123            "" IF_NC_SERVER("lp:") IF_NC_EXTRA("w:i:f:e:") )) > 0
    124124        ) {
    125125            if (ENABLE_NC_SERVER && opt == 'l')
  • branches/3.2/mindi-busybox/networking/nc_bloaty.c

    r2725 r3232  
    6161//usage:    )
    6262//usage:#define nc_full_usage "\n\n"
    63 //usage:       "Options:"
    64 //usage:     "\n    -e PROG Run PROG after connect (must be last)"
     63//usage:       "    -e PROG Run PROG after connect (must be last)"
    6564//usage:    IF_NC_SERVER(
    6665//usage:     "\n    -l  Listen mode, for inbound connects"
     
    117116    unsigned wrote_net;          /* total net bytes */
    118117#endif
     118    char *proggie0saved;
    119119    /* ouraddr is never NULL and goes through three states as we progress:
    120120     1 - local address before bind (IP/port possibly zero)
     
    129129    jmp_buf jbuf;                /* timer crud */
    130130
    131     /* will malloc up the following globals: */
    132131    fd_set ding1;                /* for select loop */
    133132    fd_set ding2;
     
    161160/* Must match getopt32 call! */
    162161enum {
    163     OPT_h = (1 << 0),
    164     OPT_n = (1 << 1),
    165     OPT_p = (1 << 2),
    166     OPT_s = (1 << 3),
    167     OPT_u = (1 << 4),
    168     OPT_v = (1 << 5),
    169     OPT_w = (1 << 6),
    170     OPT_l = (1 << 7) * ENABLE_NC_SERVER,
    171     OPT_i = (1 << (7+ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
    172     OPT_o = (1 << (8+ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
    173     OPT_z = (1 << (9+ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
     162    OPT_n = (1 << 0),
     163    OPT_p = (1 << 1),
     164    OPT_s = (1 << 2),
     165    OPT_u = (1 << 3),
     166    OPT_v = (1 << 4),
     167    OPT_w = (1 << 5),
     168    OPT_l = (1 << 6) * ENABLE_NC_SERVER,
     169    OPT_i = (1 << (6+ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
     170    OPT_o = (1 << (7+ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
     171    OPT_z = (1 << (8+ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
    174172};
    175173
     
    265263static int doexec(char **proggie)
    266264{
     265    if (G.proggie0saved)
     266        proggie[0] = G.proggie0saved;
    267267    xmove_fd(netfd, 0);
    268268    dup2(0, 1);
    269269    /* dup2(0, 2); - do we *really* want this? NO!
    270270     * exec'ed prog can do it yourself, if needed */
    271     execvp(proggie[0], proggie);
    272     bb_perror_msg_and_die("can't execute '%s'", proggie[0]);
     271    BB_EXECVP_or_die(proggie);
    273272}
    274273
     
    388387                    /* "nc -nl -p LPORT RHOST" (w/o RPORT!):
    389388                     * we should accept any remote port */
    390                     set_nport(&remend, 0); /* blot out remote port# */
     389                    set_nport(&remend.u.sa, 0); /* blot out remote port# */
    391390                }
    392391                r = memcmp(&remend.u.sa, &themaddr->u.sa, remend.len);
    393                 set_nport(&remend, sv_port); /* restore */
     392                set_nport(&remend.u.sa, sv_port); /* restore */
    394393                if (r != 0) {
    395394                    /* nc 1.10 bails out instead, and its error message
     
    431430        rr = getsockopt(netfd, IPPROTO_IP, IP_OPTIONS, optbuf, &x);
    432431        if (rr >= 0 && x) {    /* we've got options, lessee em... */
    433             bin2hex(bigbuf_net, optbuf, x);
    434             bigbuf_net[2*x] = '\0';
     432            *bin2hex(bigbuf_net, optbuf, x) = '\0';
    435433            fprintf(stderr, "IP options: %s\n", bigbuf_net);
    436434        }
     
    488486        o_wait = 5;                     /* enough that we'll notice?? */
    489487        rr = xsocket(ouraddr->u.sa.sa_family, SOCK_STREAM, 0);
    490         set_nport(themaddr, htons(SLEAZE_PORT));
     488        set_nport(&themaddr->u.sa, htons(SLEAZE_PORT));
    491489        connect_w_timeout(rr);
    492490        /* don't need to restore themaddr's port, it's not used anymore */
     
    730728    char *str_p, *str_s;
    731729    IF_NC_EXTRA(char *str_i, *str_o;)
    732     char *themdotted = themdotted; /* gcc */
     730    char *themdotted = themdotted; /* for compiler */
    733731    char **proggie;
    734732    int x;
     
    758756            goto e_found;
    759757        }
     758        /* -<other_opts>e PROG [ARGS] ? */
     759        /* (aboriginal linux uses this form) */
     760        if (proggie[0][0] == '-') {
     761            char *optpos = *proggie + 1;
     762            /* Skip all valid opts w/o params */
     763            optpos = optpos + strspn(optpos, "nuv"IF_NC_SERVER("l")IF_NC_EXTRA("z"));
     764            if (*optpos == 'e' && !optpos[1]) {
     765                *optpos = '\0';
     766                proggie++;
     767                G.proggie0saved = *proggie;
     768                *proggie = NULL; /* terminate argv for getopt32 */
     769                goto e_found;
     770            }
     771        }
    760772    }
    761773    proggie = NULL;
     
    764776    // -g -G -t -r deleted, unimplemented -a deleted too
    765777    opt_complementary = "?2:vv:w+"; /* max 2 params; -v is a counter; -w N */
    766     getopt32(argv, "hnp:s:uvw:" IF_NC_SERVER("l")
     778    getopt32(argv, "np:s:uvw:" IF_NC_SERVER("l")
    767779            IF_NC_EXTRA("i:o:z"),
    768780            &str_p, &str_s, &o_wait
     
    815827                x);
    816828        if (o_lport)
    817             set_nport(ouraddr, htons(o_lport));
     829            set_nport(&ouraddr->u.sa, htons(o_lport));
    818830    }
    819831    xmove_fd(x, netfd);
  • branches/3.2/mindi-busybox/networking/netstat.c

    r2725 r3232  
    2222//usage:#define netstat_full_usage "\n\n"
    2323//usage:       "Display networking information\n"
    24 //usage:     "\nOptions:"
    2524//usage:    IF_ROUTE(
    2625//usage:     "\n    -r  Routing table"
     
    189188        if (pn->inode == inode) {
    190189            /* Some warning should be appropriate here
    191                as we got multiple processes for one i-node */
     190             * as we got multiple processes for one i-node */
    192191            return;
    193192        }
  • branches/3.2/mindi-busybox/networking/nslookup.c

    r2725 r3232  
    1111 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1212 */
     13
     14//usage:#define nslookup_trivial_usage
     15//usage:       "[HOST] [SERVER]"
     16//usage:#define nslookup_full_usage "\n\n"
     17//usage:       "Query the nameserver for the IP address of the given HOST\n"
     18//usage:       "optionally using a specified DNS server"
     19//usage:
     20//usage:#define nslookup_example_usage
     21//usage:       "$ nslookup localhost\n"
     22//usage:       "Server:     default\n"
     23//usage:       "Address:    default\n"
     24//usage:       "\n"
     25//usage:       "Name:       debian\n"
     26//usage:       "Address:    127.0.0.1\n"
    1327
    1428#include <resolv.h>
     
    6781    rc = getaddrinfo(hostname, NULL /*service*/, &hint, &result);
    6882
    69     if (!rc) {
     83    if (rc == 0) {
    7084        struct addrinfo *cur = result;
    7185        unsigned cnt = 0;
     
    95109#endif
    96110    }
    97     if (ENABLE_FEATURE_CLEAN_UP)
     111    if (ENABLE_FEATURE_CLEAN_UP && result)
    98112        freeaddrinfo(result);
    99113    return (rc != 0);
  • branches/3.2/mindi-busybox/networking/ntpd.c

    r2725 r3232  
    2828 ***********************************************************************
    2929 */
     30
     31//usage:#define ntpd_trivial_usage
     32//usage:    "[-dnqNw"IF_FEATURE_NTPD_SERVER("l")"] [-S PROG] [-p PEER]..."
     33//usage:#define ntpd_full_usage "\n\n"
     34//usage:       "NTP client/server\n"
     35//usage:     "\n    -d  Verbose"
     36//usage:     "\n    -n  Do not daemonize"
     37//usage:     "\n    -q  Quit after clock is set"
     38//usage:     "\n    -N  Run at high priority"
     39//usage:     "\n    -w  Do not set time (only query peers), implies -n"
     40//usage:    IF_FEATURE_NTPD_SERVER(
     41//usage:     "\n    -l  Run as server on port 123"
     42//usage:    )
     43//usage:     "\n    -S PROG Run PROG after stepping time, stratum change, and every 11 mins"
     44//usage:     "\n    -p PEER Obtain time from PEER (may be repeated)"
     45
    3046#include "libbb.h"
    3147#include <math.h>
    3248#include <netinet/ip.h> /* For IPTOS_LOWDELAY definition */
     49#include <sys/resource.h> /* setpriority */
    3350#include <sys/timex.h>
    3451#ifndef IPTOS_LOWDELAY
     
    92109#define BURSTPOLL       0       /* initial poll */
    93110#define MINPOLL         5       /* minimum poll interval. std ntpd uses 6 (6: 64 sec) */
    94 #define BIGPOLL         10      /* drop to lower poll at any trouble (10: 17 min) */
     111/* If offset > discipline_jitter * POLLADJ_GATE, and poll interval is >= 2^BIGPOLL,
     112 * then it is decreased _at once_. (If < 2^BIGPOLL, it will be decreased _eventually_).
     113 */
     114#define BIGPOLL         10      /* 2^10 sec ~= 17 min */
    95115#define MAXPOLL         12      /* maximum poll interval (12: 1.1h, 17: 36.4h). std ntpd uses 17 */
    96116/* Actively lower poll when we see such big offsets.
    97117 * With STEP_THRESHOLD = 0.125, it means we try to sync more aggressively
    98  * if offset increases over 0.03 sec */
    99 #define POLLDOWN_OFFSET (STEP_THRESHOLD / 4)
     118 * if offset increases over ~0.04 sec */
     119#define POLLDOWN_OFFSET (STEP_THRESHOLD / 3)
    100120#define MINDISP         0.01    /* minimum dispersion (sec) */
    101121#define MAXDISP         16      /* maximum dispersion (sec) */
     
    109129/* Poll-adjust threshold.
    110130 * When we see that offset is small enough compared to discipline jitter,
    111  * we grow a counter: += MINPOLL. When it goes over POLLADJ_LIMIT,
     131 * we grow a counter: += MINPOLL. When counter goes over POLLADJ_LIMIT,
    112132 * we poll_exp++. If offset isn't small, counter -= poll_exp*2,
    113  * and when it goes below -POLLADJ_LIMIT, we poll_exp--
    114  * (bumped from 30 to 36 since otherwise I often see poll_exp going *2* steps down)
     133 * and when it goes below -POLLADJ_LIMIT, we poll_exp--.
     134 * (Bumped from 30 to 40 since otherwise I often see poll_exp going *2* steps down)
    115135 */
    116 #define POLLADJ_LIMIT   36
    117 /* If offset < POLLADJ_GATE * discipline_jitter, then we can increase
     136#define POLLADJ_LIMIT   40
     137/* If offset < discipline_jitter * POLLADJ_GATE, then we decide to increase
    118138 * poll interval (we think we can't improve timekeeping
    119139 * by staying at smaller poll).
    120140 */
    121141#define POLLADJ_GATE    4
     142#define TIMECONST_HACK_GATE 2
    122143/* Compromise Allan intercept (sec). doc uses 1500, std ntpd uses 512 */
    123144#define ALLAN           512
     
    193214
    194215typedef struct {
     216    double d_offset;
    195217    double d_recv_time;
    196     double d_offset;
    197218    double d_dispersion;
    198219} datapoint_t;
     
    201222    len_and_sockaddr *p_lsa;
    202223    char             *p_dotted;
    203     /* when to send new query (if p_fd == -1)
    204      * or when receive times out (if p_fd >= 0): */
    205224    int              p_fd;
    206225    int              datapoint_idx;
     
    209228    uint8_t          lastpkt_stratum;
    210229    uint8_t          reachable_bits;
     230        /* when to send new query (if p_fd == -1)
     231         * or when receive times out (if p_fd >= 0): */
    211232    double           next_action_time;
    212233    double           p_xmttime;
     
    239260    OPT_S = (1 << 6),
    240261    OPT_l = (1 << 7) * ENABLE_FEATURE_NTPD_SERVER,
     262    /* We hijack some bits for other purposes */
     263    OPT_qq = (1 << 31),
    241264};
    242265
     
    255278#if ENABLE_FEATURE_NTPD_SERVER
    256279    int      listen_fd;
     280# define G_listen_fd (G.listen_fd)
     281#else
     282# define G_listen_fd (-1)
    257283#endif
    258284    unsigned verbose;
    259285    unsigned peer_cnt;
    260286    /* refid: 32-bit code identifying the particular server or reference clock
    261      *  in stratum 0 packets this is a four-character ASCII string,
    262      *  called the kiss code, used for debugging and monitoring
    263      *  in stratum 1 packets this is a four-character ASCII string
    264      *  assigned to the reference clock by IANA. Example: "GPS "
    265      *  in stratum 2+ packets, it's IPv4 address or 4 first bytes of MD5 hash of IPv6
     287     * in stratum 0 packets this is a four-character ASCII string,
     288     * called the kiss code, used for debugging and monitoring
     289     * in stratum 1 packets this is a four-character ASCII string
     290     * assigned to the reference clock by IANA. Example: "GPS "
     291     * in stratum 2+ packets, it's IPv4 address or 4 first bytes
     292     * of MD5 hash of IPv6
    266293     */
    267294    uint32_t refid;
     
    272299     * system clock hardware representation is to the nanosecond.
    273300     *
    274      * Delays, jitters of various kinds are clamper down to precision.
     301     * Delays, jitters of various kinds are clamped down to precision.
    275302     *
    276303     * If precision_sec is too large, discipline_jitter gets clamped to it
    277      * and if offset is much smaller than discipline_jitter, poll interval
    278      * grows even though we really can benefit from staying at smaller one,
    279      * collecting non-lagged datapoits and correcting the offset.
     304     * and if offset is smaller than discipline_jitter * POLLADJ_GATE, poll
     305     * interval grows even though we really can benefit from staying at
     306     * smaller one, collecting non-lagged datapoits and correcting offset.
    280307     * (Lagged datapoits exist when poll_exp is large but we still have
    281308     * systematic offset error - the time distance between datapoints
    282      * is significat and older datapoints have smaller offsets.
     309     * is significant and older datapoints have smaller offsets.
    283310     * This makes our offset estimation a bit smaller than reality)
    284311     * Due to this effect, setting G_precision_sec close to
     
    286313     * too big and we will step. I observed it with -6.
    287314     *
    288      * OTOH, setting precision too small would result in futile attempts
    289      * to syncronize to the unachievable precision.
     315     * OTOH, setting precision_sec far too small would result in futile
     316     * attempts to syncronize to an unachievable precision.
    290317     *
    291318     * -6 is 1/64 sec, -7 is 1/128 sec and so on.
    292      */
    293 #define G_precision_exp  -8
    294 #define G_precision_sec  (1.0 / (1 << (- G_precision_exp)))
     319     * -8 is 1/256 ~= 0.003906 (worked well for me --vda)
     320     * -9 is 1/512 ~= 0.001953 (let's try this for some time)
     321     */
     322#define G_precision_exp  -9
     323    /*
     324     * G_precision_exp is used only for construction outgoing packets.
     325     * It's ok to set G_precision_sec to a slightly different value
     326     * (One which is "nicer looking" in logs).
     327     * Exact value would be (1.0 / (1 << (- G_precision_exp))):
     328     */
     329#define G_precision_sec  0.002
    295330    uint8_t  stratum;
    296331    /* Bool. After set to 1, never goes back to 0: */
     
    310345    double   last_update_recv_time; // s.t
    311346    double   discipline_jitter;     // c.jitter
     347    /* Since we only compare it with ints, can simplify code
     348     * by not making this variable floating point:
     349     */
     350    unsigned offset_to_jitter_ratio;
    312351    //double   cluster_offset;        // s.offset
    313352    //double   cluster_jitter;        // s.jitter
     
    483522{
    484523    int i, idx;
     524    double sum, wavg;
     525    datapoint_t *fdp;
     526
     527#if 0
     528/* Simulations have shown that use of *averaged* offset for p->filter_offset
     529 * is in fact worse than simply using last received one: with large poll intervals
     530 * (>= 2048) averaging code uses offset values which are outdated by hours,
     531 * and time/frequency correction goes totally wrong when fed essentially bogus offsets.
     532 */
    485533    int got_newest;
    486     double minoff, maxoff, wavg, sum, w;
     534    double minoff, maxoff, w;
    487535    double x = x; /* for compiler */
    488536    double oldest_off = oldest_off;
     
    491539    double newest_age = newest_age;
    492540
    493     minoff = maxoff = p->filter_datapoint[0].d_offset;
     541    fdp = p->filter_datapoint;
     542
     543    minoff = maxoff = fdp[0].d_offset;
    494544    for (i = 1; i < NUM_DATAPOINTS; i++) {
    495         if (minoff > p->filter_datapoint[i].d_offset)
    496             minoff = p->filter_datapoint[i].d_offset;
    497         if (maxoff < p->filter_datapoint[i].d_offset)
    498             maxoff = p->filter_datapoint[i].d_offset;
    499     }
    500 
    501     idx = p->datapoint_idx; /* most recent datapoint */
     545        if (minoff > fdp[i].d_offset)
     546            minoff = fdp[i].d_offset;
     547        if (maxoff < fdp[i].d_offset)
     548            maxoff = fdp[i].d_offset;
     549    }
     550
     551    idx = p->datapoint_idx; /* most recent datapoint's index */
    502552    /* Average offset:
    503553     * Drop two outliers and take weighted average of the rest:
     
    521571            bb_error_msg("datapoint[%d]: off:%f disp:%f(%f) age:%f%s",
    522572                i,
    523                 p->filter_datapoint[idx].d_offset,
    524                 p->filter_datapoint[idx].d_dispersion, dispersion(&p->filter_datapoint[idx]),
    525                 G.cur_time - p->filter_datapoint[idx].d_recv_time,
    526                 (minoff == p->filter_datapoint[idx].d_offset || maxoff == p->filter_datapoint[idx].d_offset)
     573                fdp[idx].d_offset,
     574                fdp[idx].d_dispersion, dispersion(&fdp[idx]),
     575                G.cur_time - fdp[idx].d_recv_time,
     576                (minoff == fdp[idx].d_offset || maxoff == fdp[idx].d_offset)
    527577                    ? " (outlier by offset)" : ""
    528578            );
    529579        }
    530580
    531         sum += dispersion(&p->filter_datapoint[idx]) / (2 << i);
    532 
    533         if (minoff == p->filter_datapoint[idx].d_offset) {
     581        sum += dispersion(&fdp[idx]) / (2 << i);
     582
     583        if (minoff == fdp[idx].d_offset) {
    534584            minoff -= 1; /* so that we don't match it ever again */
    535585        } else
    536         if (maxoff == p->filter_datapoint[idx].d_offset) {
     586        if (maxoff == fdp[idx].d_offset) {
    537587            maxoff += 1;
    538588        } else {
    539             oldest_off = p->filter_datapoint[idx].d_offset;
    540             oldest_age = G.cur_time - p->filter_datapoint[idx].d_recv_time;
     589            oldest_off = fdp[idx].d_offset;
     590            oldest_age = G.cur_time - fdp[idx].d_recv_time;
    541591            if (!got_newest) {
    542592                got_newest = 1;
     
    570620    }
    571621    p->filter_offset = wavg;
     622
     623#else
     624
     625    fdp = p->filter_datapoint;
     626    idx = p->datapoint_idx; /* most recent datapoint's index */
     627
     628    /* filter_offset: simply use the most recent value */
     629    p->filter_offset = fdp[idx].d_offset;
     630
     631    /*                     n-1
     632     *                     ---    dispersion(i)
     633     * filter_dispersion =  \     -------------
     634     *                      /       (i+1)
     635     *                     ---     2
     636     *                     i=0
     637     */
     638    wavg = 0;
     639    sum = 0;
     640    for (i = 0; i < NUM_DATAPOINTS; i++) {
     641        sum += dispersion(&fdp[idx]) / (2 << i);
     642        wavg += fdp[idx].d_offset;
     643        idx = (idx - 1) & (NUM_DATAPOINTS - 1);
     644    }
     645    wavg /= NUM_DATAPOINTS;
     646    p->filter_dispersion = sum;
     647#endif
    572648
    573649    /*                  +-----                 -----+ ^ 1/2
     
    584660    sum = 0;
    585661    for (i = 0; i < NUM_DATAPOINTS; i++) {
    586         sum += SQUARE(wavg - p->filter_datapoint[i].d_offset);
     662        sum += SQUARE(wavg - fdp[i].d_offset);
    587663    }
    588664    sum = SQRT(sum / NUM_DATAPOINTS);
    589665    p->filter_jitter = sum > G_precision_sec ? sum : G_precision_sec;
    590666
    591     VERB3 bb_error_msg("filter offset:%f(corr:%e) disp:%f jitter:%f",
    592             p->filter_offset, x,
     667    VERB3 bb_error_msg("filter offset:%+f disp:%f jitter:%f",
     668            p->filter_offset,
    593669            p->filter_dispersion,
    594670            p->filter_jitter);
     
    605681            p->filter_datapoint[i].d_recv_time += offset;
    606682            if (p->filter_datapoint[i].d_offset != 0) {
    607                 p->filter_datapoint[i].d_offset += offset;
     683                p->filter_datapoint[i].d_offset -= offset;
     684                //bb_error_msg("p->filter_datapoint[%d].d_offset %f -> %f",
     685                //  i,
     686                //  p->filter_datapoint[i].d_offset + offset,
     687                //  p->filter_datapoint[i].d_offset);
    608688            }
    609689        } else {
     
    702782    }
    703783
     784    /* Emit message _before_ attempted send. Think of a very short
     785     * roundtrip networks: we need to go back to recv loop ASAP,
     786     * to reduce delay. Printing messages after send works against that.
     787     */
     788    VERB1 bb_error_msg("sending query to %s", p->p_dotted);
     789
    704790    /*
    705791     * Send out a random 64-bit number as our transmit time.  The NTP
     
    729815
    730816    p->reachable_bits <<= 1;
    731     VERB1 bb_error_msg("sent query to %s", p->p_dotted);
    732817    set_next(p, RESPONSE_INTERVAL);
    733818}
     
    791876    llist_t *item;
    792877    double dtime;
    793     struct timeval tv;
    794     char buf[80];
     878    struct timeval tvc, tvn;
     879    char buf[sizeof("yyyy-mm-dd hh:mm:ss") + /*paranoia:*/ 4];
    795880    time_t tval;
    796881
    797     gettimeofday(&tv, NULL); /* never fails */
    798     dtime = offset + tv.tv_sec;
    799     dtime += 1.0e-6 * tv.tv_usec;
    800     d_to_tv(dtime, &tv);
    801 
    802     if (settimeofday(&tv, NULL) == -1)
     882    gettimeofday(&tvc, NULL); /* never fails */
     883    dtime = tvc.tv_sec + (1.0e-6 * tvc.tv_usec) + offset;
     884    d_to_tv(dtime, &tvn);
     885    if (settimeofday(&tvn, NULL) == -1)
    803886        bb_perror_msg_and_die("settimeofday");
    804887
    805     tval = tv.tv_sec;
    806     strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y", localtime(&tval));
    807 
    808     bb_error_msg("setting clock to %s (offset %fs)", buf, offset);
     888    VERB2 {
     889        tval = tvc.tv_sec;
     890        strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&tval));
     891        bb_error_msg("current time is %s.%06u", buf, (unsigned)tvc.tv_usec);
     892    }
     893    tval = tvn.tv_sec;
     894    strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&tval));
     895    bb_error_msg("setting time to %s.%06u (offset %+fs)", buf, (unsigned)tvn.tv_usec, offset);
    809896
    810897    /* Correct various fields which contain time-relative values: */
     898
     899    /* Globals: */
     900    G.cur_time += offset;
     901    G.last_update_recv_time += offset;
     902    G.last_script_run += offset;
    811903
    812904    /* p->lastpkt_recv_time, p->next_action_time and such: */
     
    814906        peer_t *pp = (peer_t *) item->data;
    815907        reset_peer_stats(pp, offset);
    816         //bb_error_msg("offset:%f pp->next_action_time:%f -> %f",
     908        //bb_error_msg("offset:%+f pp->next_action_time:%f -> %f",
    817909        //  offset, pp->next_action_time, pp->next_action_time + offset);
    818910        pp->next_action_time += offset;
    819     }
    820     /* Globals: */
    821     G.cur_time += offset;
    822     G.last_update_recv_time += offset;
    823     G.last_script_run += offset;
     911        if (pp->p_fd >= 0) {
     912            /* We wait for reply from this peer too.
     913             * But due to step we are doing, reply's data is no longer
     914             * useful (in fact, it'll be bogus). Stop waiting for it.
     915             */
     916            close(pp->p_fd);
     917            pp->p_fd = -1;
     918            set_next(pp, RETRY_INTERVAL);
     919        }
     920    }
    824921}
    825922
     
    883980//  if (p->refid == p->dstaddr || p->refid == s.refid)
    884981//      return 0;
    885         return 1;
     982    return 1;
    886983}
    887984static peer_t*
     
    11501247    G.last_update_peer = p;
    11511248 keep_old:
    1152     VERB3 bb_error_msg("selected peer %s filter_offset:%f age:%f",
     1249    VERB3 bb_error_msg("selected peer %s filter_offset:%+f age:%f",
    11531250            p->p_dotted,
    11541251            p->filter_offset,
     
    12411338        case STATE_SYNC:
    12421339            /* The first outlyer: ignore it, switch to SPIK state */
    1243             VERB3 bb_error_msg("offset:%f - spike detected", offset);
     1340            VERB3 bb_error_msg("offset:%+f - spike detected", offset);
    12441341            G.discipline_state = STATE_SPIK;
    12451342            return -1; /* "decrease poll interval" */
     
    12781375         * intervals.
    12791376         */
    1280         VERB3 bb_error_msg("stepping time by %f; poll_exp=MINPOLL", offset);
     1377        VERB3 bb_error_msg("stepping time by %+f; poll_exp=MINPOLL", offset);
    12811378        step_time(offset);
    12821379        if (option_mask32 & OPT_q) {
     
    12971394        }
    12981395#endif
    1299         set_new_values(STATE_SYNC, /*offset:*/ 0, recv_time);
     1396        abs_offset = offset = 0;
     1397        set_new_values(STATE_SYNC, offset, recv_time);
    13001398
    13011399    } else { /* abs_offset <= STEP_THRESHOLD */
    13021400
    13031401        if (G.poll_exp < MINPOLL && G.initial_poll_complete) {
    1304             VERB3 bb_error_msg("small offset:%f, disabling burst mode", offset);
     1402            VERB3 bb_error_msg("small offset:%+f, disabling burst mode", offset);
    13051403            G.polladj_count = 0;
    13061404            G.poll_exp = MINPOLL;
     
    13111409         */
    13121410        etemp = SQUARE(G.discipline_jitter);
    1313         dtemp = SQUARE(MAXD(fabs(offset - G.last_update_offset), G_precision_sec));
     1411        dtemp = SQUARE(offset - G.last_update_offset);
    13141412        G.discipline_jitter = SQRT(etemp + (dtemp - etemp) / AVG);
    1315         VERB3 bb_error_msg("discipline jitter=%f", G.discipline_jitter);
    13161413
    13171414        switch (G.discipline_state) {
     
    13901487    }
    13911488
     1489    if (G.discipline_jitter < G_precision_sec)
     1490        G.discipline_jitter = G_precision_sec;
     1491    G.offset_to_jitter_ratio = abs_offset / G.discipline_jitter;
     1492
    13921493    G.reftime = G.cur_time;
    13931494    G.ntp_status = p->lastpkt_status;
     
    14011502    /* We are in STATE_SYNC now, but did not do adjtimex yet.
    14021503     * (Any other state does not reach this, they all return earlier)
    1403      * By this time, freq_drift and G.last_update_offset are set
     1504     * By this time, freq_drift and offset are set
    14041505     * to values suitable for adjtimex.
    14051506     */
     
    14271528        if (adjtimex(&tmx) < 0)
    14281529            bb_perror_msg_and_die("adjtimex");
    1429         VERB3 bb_error_msg("p adjtimex freq:%ld offset:%ld constant:%ld status:0x%x",
    1430                 tmx.freq, tmx.offset, tmx.constant, tmx.status);
     1530        bb_error_msg("p adjtimex freq:%ld offset:%+ld status:0x%x tc:%ld",
     1531                tmx.freq, tmx.offset, tmx.status, tmx.constant);
    14311532    }
    14321533
     
    14401541    /* 65536 is one ppm */
    14411542    tmx.freq = G.discipline_freq_drift * 65536e6;
    1442     tmx.offset = G.last_update_offset * 1000000; /* usec */
    14431543#endif
    14441544    tmx.modes = ADJ_OFFSET | ADJ_STATUS | ADJ_TIMECONST;// | ADJ_MAXERROR | ADJ_ESTERROR;
    1445     tmx.offset = (G.last_update_offset * 1000000); /* usec */
    1446             /* + (G.last_update_offset < 0 ? -0.5 : 0.5) - too small to bother */
     1545    tmx.offset = (offset * 1000000); /* usec */
    14471546    tmx.status = STA_PLL;
    14481547    if (G.ntp_status & LI_PLUSSEC)
     
    14501549    if (G.ntp_status & LI_MINUSSEC)
    14511550        tmx.status |= STA_DEL;
     1551
    14521552    tmx.constant = G.poll_exp - 4;
    1453     //tmx.esterror = (u_int32)(clock_jitter * 1e6);
    1454     //tmx.maxerror = (u_int32)((sys_rootdelay / 2 + sys_rootdisp) * 1e6);
     1553    /* EXPERIMENTAL.
     1554     * The below if statement should be unnecessary, but...
     1555     * It looks like Linux kernel's PLL is far too gentle in changing
     1556     * tmx.freq in response to clock offset. Offset keeps growing
     1557     * and eventually we fall back to smaller poll intervals.
     1558     * We can make correction more agressive (about x2) by supplying
     1559     * PLL time constant which is one less than the real one.
     1560     * To be on a safe side, let's do it only if offset is significantly
     1561     * larger than jitter.
     1562     */
     1563    if (tmx.constant > 0 && G.offset_to_jitter_ratio >= TIMECONST_HACK_GATE)
     1564        tmx.constant--;
     1565
     1566    //tmx.esterror = (uint32_t)(clock_jitter * 1e6);
     1567    //tmx.maxerror = (uint32_t)((sys_rootdelay / 2 + sys_rootdisp) * 1e6);
    14551568    rc = adjtimex(&tmx);
    14561569    if (rc < 0)
     
    14591572     * Not sure why. Perhaps it is normal.
    14601573     */
    1461     VERB3 bb_error_msg("adjtimex:%d freq:%ld offset:%ld constant:%ld status:0x%x",
    1462                 rc, tmx.freq, tmx.offset, tmx.constant, tmx.status);
    1463 #if 0
    1464     VERB3 {
    1465         /* always gives the same output as above msg */
    1466         memset(&tmx, 0, sizeof(tmx));
    1467         if (adjtimex(&tmx) < 0)
    1468             bb_perror_msg_and_die("adjtimex");
    1469         VERB3 bb_error_msg("c adjtimex freq:%ld offset:%ld constant:%ld status:0x%x",
    1470                 tmx.freq, tmx.offset, tmx.constant, tmx.status);
    1471     }
    1472 #endif
     1574    VERB3 bb_error_msg("adjtimex:%d freq:%ld offset:%+ld status:0x%x",
     1575                rc, tmx.freq, tmx.offset, tmx.status);
    14731576    G.kernel_freq_drift = tmx.freq / 65536;
    1474     VERB2 bb_error_msg("update peer:%s, offset:%f, clock drift:%ld ppm",
    1475             p->p_dotted, G.last_update_offset, G.kernel_freq_drift);
     1577    VERB2 bb_error_msg("update from:%s offset:%+f jitter:%f clock drift:%+.3fppm tc:%d",
     1578            p->p_dotted, offset, G.discipline_jitter, (double)tmx.freq / 65536, (int)tmx.constant);
    14761579
    14771580    return 1; /* "ok to increase poll interval" */
     
    15321635//TODO: always do this?
    15331636            interval = retry_interval();
    1534             goto set_next_and_close_sock;
     1637            goto set_next_and_ret;
    15351638        }
    15361639        xfunc_die();
     
    15391642    if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) {
    15401643        bb_error_msg("malformed packet received from %s", p->p_dotted);
    1541         goto bail;
     1644        return;
    15421645    }
    15431646
     
    15451648     || msg.m_orgtime.fractionl != p->p_xmt_msg.m_xmttime.fractionl
    15461649    ) {
    1547         goto bail;
    1548     }
     1650        /* Somebody else's packet */
     1651        return;
     1652    }
     1653
     1654    /* We do not expect any more packets from this peer for now.
     1655     * Closing the socket informs kernel about it.
     1656     * We open a new socket when we send a new query.
     1657     */
     1658    close(p->p_fd);
     1659    p->p_fd = -1;
    15491660
    15501661    if ((msg.m_status & LI_ALARM) == LI_ALARM
     
    15561667// "RATE" - peer is overloaded, reduce polling freq
    15571668        interval = poll_interval(0);
    1558         bb_error_msg("reply from %s: not synced, next query in %us", p->p_dotted, interval);
    1559         goto set_next_and_close_sock;
     1669        bb_error_msg("reply from %s: peer is unsynced, next query in %us", p->p_dotted, interval);
     1670        goto set_next_and_ret;
    15601671    }
    15611672
     
    16091720        /* 1st datapoint ever - replicate offset in every element */
    16101721        int i;
    1611         for (i = 1; i < NUM_DATAPOINTS; i++) {
     1722        for (i = 0; i < NUM_DATAPOINTS; i++) {
    16121723            p->filter_datapoint[i].d_offset = datapoint->d_offset;
    16131724        }
     
    16161727    p->reachable_bits |= 1;
    16171728    if ((MAX_VERBOSE && G.verbose) || (option_mask32 & OPT_w)) {
    1618         bb_error_msg("reply from %s: reach 0x%02x offset %f delay %f status 0x%02x strat %d refid 0x%08x rootdelay %f",
     1729        bb_error_msg("reply from %s: offset:%+f delay:%f status:0x%02x strat:%d refid:0x%08x rootdelay:%f reach:0x%02x",
    16191730            p->p_dotted,
    1620             p->reachable_bits,
    16211731            datapoint->d_offset,
    16221732            p->lastpkt_delay,
     
    16241734            p->lastpkt_stratum,
    16251735            p->lastpkt_refid,
    1626             p->lastpkt_rootdelay
     1736            p->lastpkt_rootdelay,
     1737            p->reachable_bits
    16271738            /* not shown: m_ppoll, m_precision_exp, m_rootdisp,
    16281739             * m_reftime, m_orgtime, m_rectime, m_xmttime
     
    16431754             */
    16441755            if (fabs(q->filter_offset) >= POLLDOWN_OFFSET) {
    1645                 VERB3 bb_error_msg("offset:%f > POLLDOWN_OFFSET", q->filter_offset);
     1756                VERB3 bb_error_msg("offset:%+f > POLLDOWN_OFFSET", q->filter_offset);
    16461757                goto poll_down;
    16471758            }
     
    16571768         * helps calm the dance. Works best using burst mode.
    16581769         */
    1659         VERB4 if (rc > 0) {
    1660             bb_error_msg("offset:%f POLLADJ_GATE*discipline_jitter:%f poll:%s",
    1661                 q->filter_offset, POLLADJ_GATE * G.discipline_jitter,
    1662                 fabs(q->filter_offset) < POLLADJ_GATE * G.discipline_jitter
    1663                     ? "grows" : "falls"
    1664             );
    1665         }
    1666         if (rc > 0 && fabs(q->filter_offset) < POLLADJ_GATE * G.discipline_jitter) {
     1770        if (rc > 0 && G.offset_to_jitter_ratio <= POLLADJ_GATE) {
    16671771            /* was += G.poll_exp but it is a bit
    16681772             * too optimistic for my taste at high poll_exp's */
     
    17101814    interval = poll_interval(0);
    17111815
    1712  set_next_and_close_sock:
     1816 set_next_and_ret:
    17131817    set_next(p, interval);
    1714     /* We do not expect any more packets from this peer for now.
    1715      * Closing the socket informs kernel about it.
    1716      * We open a new socket when we send a new query.
    1717      */
    1718     close(p->p_fd);
    1719     p->p_fd = -1;
    1720  bail:
    1721     return;
    17221818}
    17231819
     
    17271823{
    17281824    ssize_t          size;
    1729     uint8_t          version;
     1825    //uint8_t          version;
    17301826    len_and_sockaddr *to;
    17311827    struct sockaddr  *from;
     
    17341830    l_fixedpt_t      query_xmttime;
    17351831
    1736     to = get_sock_lsa(G.listen_fd);
     1832    to = get_sock_lsa(G_listen_fd);
    17371833    from = xzalloc(to->len);
    17381834
    1739     size = recv_from_to(G.listen_fd, &msg, sizeof(msg), MSG_DONTWAIT, from, &to->u.sa, to->len);
     1835    size = recv_from_to(G_listen_fd, &msg, sizeof(msg), MSG_DONTWAIT, from, &to->u.sa, to->len);
    17401836    if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) {
    17411837        char *addr;
     
    17561852    /* Build a reply packet */
    17571853    memset(&msg, 0, sizeof(msg));
    1758     msg.m_status = G.stratum < MAXSTRAT ? G.ntp_status : LI_ALARM;
     1854    msg.m_status = G.stratum < MAXSTRAT ? (G.ntp_status & LI_MASK) : LI_ALARM;
    17591855    msg.m_status |= (query_status & VERSION_MASK);
    17601856    msg.m_status |= ((query_status & MODE_MASK) == MODE_CLIENT) ?
    1761              MODE_SERVER : MODE_SYM_PAS;
     1857            MODE_SERVER : MODE_SYM_PAS;
    17621858    msg.m_stratum = G.stratum;
    17631859    msg.m_ppoll = G.poll_exp;
     
    17751871//simple code does not do this, fix simple code!
    17761872    msg.m_rootdisp = d_to_sfp(G.rootdisp);
    1777     version = (query_status & VERSION_MASK); /* ... >> VERSION_SHIFT - done below instead */
     1873    //version = (query_status & VERSION_MASK); /* ... >> VERSION_SHIFT - done below instead */
    17781874    msg.m_refid = G.refid; // (version > (3 << VERSION_SHIFT)) ? G.refid : G.refid3;
    17791875
    17801876    /* We reply from the local address packet was sent to,
    17811877     * this makes to/from look swapped here: */
    1782     do_sendto(G.listen_fd,
     1878    do_sendto(G_listen_fd,
    17831879        /*from:*/ &to->u.sa, /*to:*/ from, /*addrlen:*/ to->len,
    17841880        &msg, size);
     
    19192015    }
    19202016#if ENABLE_FEATURE_NTPD_SERVER
    1921     G.listen_fd = -1;
     2017    G_listen_fd = -1;
    19222018    if (opts & OPT_l) {
    1923         G.listen_fd = create_and_bind_dgram_or_die(NULL, 123);
    1924         socket_want_pktinfo(G.listen_fd);
    1925         setsockopt(G.listen_fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY));
     2019        G_listen_fd = create_and_bind_dgram_or_die(NULL, 123);
     2020        socket_want_pktinfo(G_listen_fd);
     2021        setsockopt(G_listen_fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY));
    19262022    }
    19272023#endif
     
    19312027
    19322028    /* If network is up, syncronization occurs in ~10 seconds.
    1933      * We give "ntpd -q" a full minute to finish, then we exit.
     2029     * We give "ntpd -q" 10 seconds to get first reply,
     2030     * then another 50 seconds to finish syncing.
    19342031     *
    19352032     * I tested ntpd 4.2.6p1 and apparently it never exits
     
    19382035     * after a reasonably small period of polling, or fail.
    19392036     */
    1940     if (opts & OPT_q)
    1941         alarm(60);
     2037    if (opts & OPT_q) {
     2038        option_mask32 |= OPT_qq;
     2039        alarm(10);
     2040    }
    19422041
    19432042    bb_signals(0
     
    19822081    cnt = G.peer_cnt * (INITIAL_SAMPLES + 1);
    19832082
     2083    write_pidfile(CONFIG_PID_FILE_PATH "/ntpd.pid");
     2084
    19842085    while (!bb_got_signal) {
    19852086        llist_t *item;
     
    19942095        i = 0;
    19952096#if ENABLE_FEATURE_NTPD_SERVER
    1996         if (G.listen_fd != -1) {
    1997             pfd[0].fd = G.listen_fd;
     2097        if (G_listen_fd != -1) {
     2098            pfd[0].fd = G_listen_fd;
    19982099            pfd[0].events = POLLIN;
    19992100            i++;
     
    20402141
    20412142        /* Here we may block */
    2042         VERB2 bb_error_msg("poll %us, sockets:%u, poll interval:%us", timeout, i, 1 << G.poll_exp);
     2143        VERB2 {
     2144            if (i > (ENABLE_FEATURE_NTPD_SERVER && G_listen_fd != -1)) {
     2145                /* We wait for at least one reply.
     2146                 * Poll for it, without wasting time for message.
     2147                 * Since replies often come under 1 second, this also
     2148                 * reduces clutter in logs.
     2149                 */
     2150                nfds = poll(pfd, i, 1000);
     2151                if (nfds != 0)
     2152                    goto did_poll;
     2153                if (--timeout <= 0)
     2154                    goto did_poll;
     2155            }
     2156            bb_error_msg("poll:%us sockets:%u interval:%us", timeout, i, 1 << G.poll_exp);
     2157        }
    20432158        nfds = poll(pfd, i, timeout * 1000);
     2159 did_poll:
    20442160        gettime1900d(); /* sets G.cur_time */
    20452161        if (nfds <= 0) {
     
    20662182        for (; nfds != 0 && j < i; j++) {
    20672183            if (pfd[j].revents /* & (POLLIN|POLLERR)*/) {
     2184                /*
     2185                 * At init, alarm was set to 10 sec.
     2186                 * Now we did get a reply.
     2187                 * Increase timeout to 50 seconds to finish syncing.
     2188                 */
     2189                if (option_mask32 & OPT_qq) {
     2190                    option_mask32 &= ~OPT_qq;
     2191                    alarm(50);
     2192                }
    20682193                nfds--;
    20692194                recv_and_process_peer_pkt(idx2peer[j]);
     
    20732198    } /* while (!bb_got_signal) */
    20742199
     2200    remove_pidfile(CONFIG_PID_FILE_PATH "/ntpd.pid");
    20752201    kill_myself_with_sig(bb_got_signal);
    20762202}
     
    22032329                if (!(pll_status & STA_PPSTIME))
    22042330                    report_event(EVNT_KERN,
    2205                         NULL, "PPS enabled");
     2331                        NULL, "PPS enabled");
    22062332                ntv.status |= STA_PPSTIME | STA_PPSFREQ;
    22072333            } else {
    22082334                if (pll_status & STA_PPSTIME)
    22092335                    report_event(EVNT_KERN,
    2210                         NULL, "PPS disabled");
    2211                 ntv.status &= ~(STA_PPSTIME |
    2212                     STA_PPSFREQ);
     2336                        NULL, "PPS disabled");
     2337                ntv.status &= ~(STA_PPSTIME | STA_PPSFREQ);
    22132338            }
    22142339            if (sys_leap == LEAP_ADDSECOND)
     
    22262351            if (!(ntv.status & STA_PPSSIGNAL))
    22272352                report_event(EVNT_KERN, NULL,
    2228                     "PPS no signal");
     2353                        "PPS no signal");
    22292354        }
    22302355        pll_status = ntv.status;
  • branches/3.2/mindi-busybox/networking/ntpd_simple.c

    r2725 r3232  
    88#include "libbb.h"
    99#include <netinet/ip.h> /* For IPTOS_LOWDELAY definition */
     10#include <sys/resource.h> /* setpriority */
    1011#ifndef IPTOS_LOWDELAY
    1112# define IPTOS_LOWDELAY 0x10
     
    710711    msg.m_status |= (query_status & VERSION_MASK);
    711712    msg.m_status |= ((query_status & MODE_MASK) == MODE_CLIENT) ?
    712              MODE_SERVER : MODE_SYM_PAS;
     713            MODE_SERVER : MODE_SYM_PAS;
    713714    msg.m_stratum = G.stratum;
    714715    msg.m_ppoll = query_ppoll;
  • branches/3.2/mindi-busybox/networking/ping.c

    r2725 r3232  
    2929#include <netinet/ip_icmp.h>
    3030#include "libbb.h"
     31
     32#ifdef __BIONIC__
     33/* should be in netinet/ip_icmp.h */
     34# define ICMP_DEST_UNREACH    3  /* Destination Unreachable  */
     35# define ICMP_SOURCE_QUENCH   4  /* Source Quench    */
     36# define ICMP_REDIRECT        5  /* Redirect (change route)  */
     37# define ICMP_ECHO            8  /* Echo Request      */
     38# define ICMP_TIME_EXCEEDED  11  /* Time Exceeded    */
     39# define ICMP_PARAMETERPROB  12  /* Parameter Problem    */
     40# define ICMP_TIMESTAMP      13  /* Timestamp Request    */
     41# define ICMP_TIMESTAMPREPLY 14  /* Timestamp Reply    */
     42# define ICMP_INFO_REQUEST   15  /* Information Request    */
     43# define ICMP_INFO_REPLY     16  /* Information Reply    */
     44# define ICMP_ADDRESS        17  /* Address Mask Request    */
     45# define ICMP_ADDRESSREPLY   18  /* Address Mask Reply    */
     46#endif
     47
     48//config:config PING
     49//config:   bool "ping"
     50//config:   default y
     51//config:   select PLATFORM_LINUX
     52//config:   help
     53//config:     ping uses the ICMP protocol's mandatory ECHO_REQUEST datagram to
     54//config:     elicit an ICMP ECHO_RESPONSE from a host or gateway.
     55//config:
     56//config:config PING6
     57//config:   bool "ping6"
     58//config:   default y
     59//config:   depends on FEATURE_IPV6 && PING
     60//config:   help
     61//config:     This will give you a ping that can talk IPv6.
     62//config:
     63//config:config FEATURE_FANCY_PING
     64//config:   bool "Enable fancy ping output"
     65//config:   default y
     66//config:   depends on PING
     67//config:   help
     68//config:     Make the output from the ping applet include statistics, and at the
     69//config:     same time provide full support for ICMP packets.
     70
     71/* Needs socket(AF_INET, SOCK_RAW, IPPROTO_ICMP), therefore BB_SUID_MAYBE: */
     72//applet:IF_PING(APPLET(ping, BB_DIR_BIN, BB_SUID_MAYBE))
     73//applet:IF_PING6(APPLET(ping6, BB_DIR_BIN, BB_SUID_MAYBE))
     74
     75//kbuild:lib-$(CONFIG_PING)  += ping.o
     76//kbuild:lib-$(CONFIG_PING6) += ping.o
     77
     78//usage:#if !ENABLE_FEATURE_FANCY_PING
     79//usage:# define ping_trivial_usage
     80//usage:       "HOST"
     81//usage:# define ping_full_usage "\n\n"
     82//usage:       "Send ICMP ECHO_REQUEST packets to network hosts"
     83//usage:# define ping6_trivial_usage
     84//usage:       "HOST"
     85//usage:# define ping6_full_usage "\n\n"
     86//usage:       "Send ICMP ECHO_REQUEST packets to network hosts"
     87//usage:#else
     88//usage:# define ping_trivial_usage
     89//usage:       "[OPTIONS] HOST"
     90//usage:# define ping_full_usage "\n\n"
     91//usage:       "Send ICMP ECHO_REQUEST packets to network hosts\n"
     92//usage:     "\n    -4,-6       Force IP or IPv6 name resolution"
     93//usage:     "\n    -c CNT      Send only CNT pings"
     94//usage:     "\n    -s SIZE     Send SIZE data bytes in packets (default:56)"
     95//usage:     "\n    -t TTL      Set TTL"
     96//usage:     "\n    -I IFACE/IP Use interface or IP address as source"
     97//usage:     "\n    -W SEC      Seconds to wait for the first response (default:10)"
     98//usage:     "\n            (after all -c CNT packets are sent)"
     99//usage:     "\n    -w SEC      Seconds until ping exits (default:infinite)"
     100//usage:     "\n            (can exit earlier with -c CNT)"
     101//usage:     "\n    -q      Quiet, only displays output at start"
     102//usage:     "\n            and when finished"
     103//usage:
     104//usage:# define ping6_trivial_usage
     105//usage:       "[OPTIONS] HOST"
     106//usage:# define ping6_full_usage "\n\n"
     107//usage:       "Send ICMP ECHO_REQUEST packets to network hosts\n"
     108//usage:     "\n    -c CNT      Send only CNT pings"
     109//usage:     "\n    -s SIZE     Send SIZE data bytes in packets (default:56)"
     110//usage:     "\n    -I IFACE/IP Use interface or IP address as source"
     111//usage:     "\n    -q      Quiet, only displays output at start"
     112//usage:     "\n            and when finished"
     113//usage:
     114//usage:#endif
     115//usage:
     116//usage:#define ping_example_usage
     117//usage:       "$ ping localhost\n"
     118//usage:       "PING slag (127.0.0.1): 56 data bytes\n"
     119//usage:       "64 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=20.1 ms\n"
     120//usage:       "\n"
     121//usage:       "--- debian ping statistics ---\n"
     122//usage:       "1 packets transmitted, 1 packets received, 0% packet loss\n"
     123//usage:       "round-trip min/avg/max = 20.1/20.1/20.1 ms\n"
     124//usage:#define ping6_example_usage
     125//usage:       "$ ping6 ip6-localhost\n"
     126//usage:       "PING ip6-localhost (::1): 56 data bytes\n"
     127//usage:       "64 bytes from ::1: icmp6_seq=0 ttl=64 time=20.1 ms\n"
     128//usage:       "\n"
     129//usage:       "--- ip6-localhost ping statistics ---\n"
     130//usage:       "1 packets transmitted, 1 packets received, 0% packet loss\n"
     131//usage:       "round-trip min/avg/max = 20.1/20.1/20.1 ms\n"
    31132
    32133#if ENABLE_PING6
     
    49150};
    50151
    51 /* Common routines */
    52 
    53 static int in_cksum(unsigned short *buf, int sz)
    54 {
    55     int nleft = sz;
    56     int sum = 0;
    57     unsigned short *w = buf;
    58     unsigned short ans = 0;
    59 
    60     while (nleft > 1) {
    61         sum += *w++;
    62         nleft -= 2;
    63     }
    64 
    65     if (nleft == 1) {
    66         *(unsigned char *) (&ans) = *(unsigned char *) w;
    67         sum += ans;
    68     }
    69 
    70     sum = (sum >> 16) + (sum & 0xFFFF);
    71     sum += (sum >> 16);
    72     ans = ~sum;
    73     return ans;
    74 }
    75 
    76152#if !ENABLE_FEATURE_FANCY_PING
    77153
     
    101177    memset(pkt, 0, sizeof(G.packet));
    102178    pkt->icmp_type = ICMP_ECHO;
    103     pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(G.packet));
     179    pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, sizeof(G.packet));
    104180
    105181    xsendto(pingsock, G.packet, DEFDATALEN + ICMP_MINLEN, &lsa->u.sa, lsa->len);
     
    224300/* Full(er) version */
    225301
    226 #define OPT_STRING ("qvc:s:w:W:I:4" IF_PING6("6"))
     302#define OPT_STRING ("qvc:s:t:w:W:I:4" IF_PING6("6"))
    227303enum {
    228304    OPT_QUIET = 1 << 0,
     
    230306    OPT_c = 1 << 2,
    231307    OPT_s = 1 << 3,
    232     OPT_w = 1 << 4,
    233     OPT_W = 1 << 5,
    234     OPT_I = 1 << 6,
    235     OPT_IPV4 = 1 << 7,
    236     OPT_IPV6 = (1 << 8) * ENABLE_PING6,
     308    OPT_t = 1 << 4,
     309    OPT_w = 1 << 5,
     310    OPT_W = 1 << 6,
     311    OPT_I = 1 << 7,
     312    OPT_IPV4 = 1 << 8,
     313    OPT_IPV6 = (1 << 9) * ENABLE_PING6,
    237314};
    238315
     
    245322    unsigned datalen;
    246323    unsigned pingcount; /* must be int-sized */
     324    unsigned opt_ttl;
    247325    unsigned long ntransmitted, nreceived, nrepeats;
    248326    uint16_t myid;
     
    276354#define nrepeats     (G.nrepeats    )
    277355#define pingcount    (G.pingcount   )
     356#define opt_ttl      (G.opt_ttl     )
    278357#define myid         (G.myid        )
    279358#define tmin         (G.tmin        )
     
    330409}
    331410
    332 static void sendping_tail(void (*sp)(int), const void *pkt, int size_pkt)
     411static void sendping_tail(void (*sp)(int), int size_pkt)
    333412{
    334413    int sz;
     
    337416    ntransmitted++;
    338417
     418    size_pkt += datalen;
     419
    339420    /* sizeof(pingaddr) can be larger than real sa size, but I think
    340421     * it doesn't matter */
    341     sz = xsendto(pingsock, pkt, size_pkt, &pingaddr.sa, sizeof(pingaddr));
     422    sz = xsendto(pingsock, G.snd_packet, size_pkt, &pingaddr.sa, sizeof(pingaddr));
    342423    if (sz != size_pkt)
    343424        bb_error_msg_and_die(bb_msg_write_error);
     
    388469        *(uint32_t*)&pkt->icmp_dun = monotonic_us();
    389470
    390     pkt->icmp_cksum = in_cksum((unsigned short *) pkt, datalen + ICMP_MINLEN);
    391 
    392     sendping_tail(sendping4, pkt, datalen + ICMP_MINLEN);
     471    pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, datalen + ICMP_MINLEN);
     472
     473    sendping_tail(sendping4, ICMP_MINLEN);
    393474}
    394475#if ENABLE_PING6
     
    407488        *(uint32_t*)(&pkt->icmp6_data8[4]) = monotonic_us();
    408489
    409     //TODO? pkt->icmp_cksum = in_cksum(...);
    410 
    411     sendping_tail(sendping6, pkt, datalen + sizeof(struct icmp6_hdr));
     490    //TODO? pkt->icmp_cksum = inet_cksum(...);
     491
     492    sendping_tail(sendping6, sizeof(struct icmp6_hdr));
    412493}
    413494#endif
     
    533614}
    534615#if ENABLE_PING6
    535 static void unpack6(char *packet, int sz, /*struct sockaddr_in6 *from,*/ int hoplimit)
     616static void unpack6(char *packet, int sz, struct sockaddr_in6 *from, int hoplimit)
    536617{
    537618    struct icmp6_hdr *icmppkt;
     
    553634            tp = (uint32_t *) &icmppkt->icmp6_data8[4];
    554635        unpack_tail(sz, tp,
    555             inet_ntop(AF_INET6, &pingaddr.sin6.sin6_addr,
     636            inet_ntop(AF_INET6, &from->sin6_addr,
    556637                    buf, sizeof(buf)),
    557638            recv_seq, hoplimit);
     
    586667    sockopt = (datalen * 2) + 7 * 1024; /* giving it a bit of extra room */
    587668    setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt));
     669
     670    if (opt_ttl != 0) {
     671        setsockopt(pingsock, IPPROTO_IP, IP_TTL, &opt_ttl, sizeof(opt_ttl));
     672        /* above doesnt affect packets sent to bcast IP, so... */
     673        setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, &opt_ttl, sizeof(opt_ttl));
     674    }
    588675
    589676    signal(SIGINT, print_stats_and_exit);
     
    638725        }
    639726        if (setsockopt(pingsock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
    640                        sizeof(filt)) < 0)
     727                    sizeof(filt)) < 0)
    641728            bb_error_msg_and_die("setsockopt(ICMP6_FILTER)");
    642729    }
     
    697784            }
    698785        }
    699         unpack6(G.rcv_packet, c, /*&from,*/ hoplimit);
     786        unpack6(G.rcv_packet, c, &from, hoplimit);
    700787        if (pingcount && nreceived >= pingcount)
    701788            break;
     
    736823    INIT_G();
    737824
    738     /* exactly one argument needed; -v and -q don't mix; -c NUM, -w NUM, -W NUM */
    739     opt_complementary = "=1:q--v:v--q:c+:w+:W+";
    740     opt |= getopt32(argv, OPT_STRING, &pingcount, &str_s, &deadline, &timeout, &str_I);
     825    /* exactly one argument needed; -v and -q don't mix; -c NUM, -t NUM, -w NUM, -W NUM */
     826    opt_complementary = "=1:q--v:v--q:c+:t+:w+:W+";
     827    opt |= getopt32(argv, OPT_STRING, &pingcount, &str_s, &opt_ttl, &deadline, &timeout, &str_I);
    741828    if (opt & OPT_s)
    742829        datalen = xatou16(str_s); // -s
  • branches/3.2/mindi-busybox/networking/pscan.c

    r2725 r3232  
    66 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    77 */
     8
     9//usage:#define pscan_trivial_usage
     10//usage:       "[-cb] [-p MIN_PORT] [-P MAX_PORT] [-t TIMEOUT] [-T MIN_RTT] HOST"
     11//usage:#define pscan_full_usage "\n\n"
     12//usage:       "Scan a host, print all open ports\n"
     13//usage:     "\n    -c  Show closed ports too"
     14//usage:     "\n    -b  Show blocked ports too"
     15//usage:     "\n    -p  Scan from this port (default 1)"
     16//usage:     "\n    -P  Scan up to this port (default 1024)"
     17//usage:     "\n    -t  Timeout (default 5000 ms)"
     18//usage:     "\n    -T  Minimum rtt (default 5 ms, increase for congested hosts)"
    819
    920#include "libbb.h"
     
    7788
    7889        /* The SOCK_STREAM socket type is implemented on the TCP/IP protocol. */
    79         set_nport(lsap, htons(port));
     90        set_nport(&lsap->u.sa, htons(port));
    8091        s = xsocket(lsap->u.sa.sa_family, SOCK_STREAM, 0);
    8192        /* We need unblocking socket so we don't need to wait for ETIMEOUT. */
  • branches/3.2/mindi-busybox/networking/route.c

    r2725 r3232  
    2626 */
    2727
     28//usage:#define route_trivial_usage
     29//usage:       "[{add|del|delete}]"
     30//usage:#define route_full_usage "\n\n"
     31//usage:       "Edit kernel routing tables\n"
     32//usage:     "\n    -n  Don't resolve names"
     33//usage:     "\n    -e  Display other/more information"
     34//usage:     "\n    -A inet" IF_FEATURE_IPV6("{6}") "   Select address family"
     35
    2836#include <net/route.h>
    2937#include <net/if.h>
     
    154162static NOINLINE void INET_setroute(int action, char **args)
    155163{
    156     struct rtentry rt;
     164    /* char buffer instead of bona-fide struct avoids aliasing warning */
     165    char rt_buf[sizeof(struct rtentry)];
     166    struct rtentry *const rt = (void *)rt_buf;
     167
    157168    const char *netmask = NULL;
    158169    int skfd, isnet, xflag;
     
    167178
    168179    /* Clean out the RTREQ structure. */
    169     memset(&rt, 0, sizeof(rt));
     180    memset(rt, 0, sizeof(*rt));
    170181
    171182    {
     
    179190
    180191            prefix_len = xatoul_range(prefix+1, 0, 32);
    181             mask_in_addr(rt) = htonl( ~(0xffffffffUL >> prefix_len));
     192            mask_in_addr(*rt) = htonl( ~(0xffffffffUL >> prefix_len));
    182193            *prefix = '\0';
    183194#if HAVE_NEW_ADDRT
    184             rt.rt_genmask.sa_family = AF_INET;
     195            rt->rt_genmask.sa_family = AF_INET;
    185196#endif
    186197        } else {
     
    189200        }
    190201        /* Prefer hostname lookup is -host flag (xflag==1) was given. */
    191         isnet = INET_resolve(target, (struct sockaddr_in *) &rt.rt_dst,
     202        isnet = INET_resolve(target, (struct sockaddr_in *) &rt->rt_dst,
    192203                             (xflag & HOST_FLAG));
    193204        if (isnet < 0) {
     
    205216
    206217    /* Fill in the other fields. */
    207     rt.rt_flags = ((isnet) ? RTF_UP : (RTF_UP | RTF_HOST));
     218    rt->rt_flags = ((isnet) ? RTF_UP : (RTF_UP | RTF_HOST));
    208219
    209220    while (*args) {
     
    212223
    213224        if (k & KW_IPVx_FLAG_ONLY) {
    214             rt.rt_flags |= flags_ipvx[k & 3];
     225            rt->rt_flags |= flags_ipvx[k & 3];
    215226            continue;
    216227        }
     
    218229#if HAVE_NEW_ADDRT
    219230        if (k == KW_IPVx_METRIC) {
    220             rt.rt_metric = xatoul(args_m1) + 1;
     231            rt->rt_metric = xatoul(args_m1) + 1;
    221232            continue;
    222233        }
     
    226237            struct sockaddr mask;
    227238
    228             if (mask_in_addr(rt)) {
     239            if (mask_in_addr(*rt)) {
    229240                bb_show_usage();
    230241            }
     
    235246                bb_error_msg_and_die("resolving %s", netmask);
    236247            }
    237             rt.rt_genmask = full_mask(mask);
     248            rt->rt_genmask = full_mask(mask);
    238249            continue;
    239250        }
    240251
    241252        if (k == KW_IPVx_GATEWAY) {
    242             if (rt.rt_flags & RTF_GATEWAY) {
     253            if (rt->rt_flags & RTF_GATEWAY) {
    243254                bb_show_usage();
    244255            }
    245256
    246257            isnet = INET_resolve(args_m1,
    247                                  (struct sockaddr_in *) &rt.rt_gateway, 1);
    248             rt.rt_flags |= RTF_GATEWAY;
     258                        (struct sockaddr_in *) &rt->rt_gateway, 1);
     259            rt->rt_flags |= RTF_GATEWAY;
    249260
    250261            if (isnet) {
     
    258269
    259270        if (k == KW_IPVx_MSS) { /* Check valid MSS bounds. */
    260             rt.rt_flags |= RTF_MSS;
    261             rt.rt_mss = xatoul_range(args_m1, 64, 32768);
     271            rt->rt_flags |= RTF_MSS;
     272            rt->rt_mss = xatoul_range(args_m1, 64, 32768);
    262273            continue;
    263274        }
    264275
    265276        if (k == KW_IPVx_WINDOW) {  /* Check valid window bounds. */
    266             rt.rt_flags |= RTF_WINDOW;
    267             rt.rt_window = xatoul_range(args_m1, 128, INT_MAX);
     277            rt->rt_flags |= RTF_WINDOW;
     278            rt->rt_window = xatoul_range(args_m1, 128, INT_MAX);
    268279            continue;
    269280        }
     
    271282#ifdef RTF_IRTT
    272283        if (k == KW_IPVx_IRTT) {
    273             rt.rt_flags |= RTF_IRTT;
    274             rt.rt_irtt = xatoul(args_m1);
    275             rt.rt_irtt *= (sysconf(_SC_CLK_TCK) / 100); /* FIXME */
     284            rt->rt_flags |= RTF_IRTT;
     285            rt->rt_irtt = xatoul(args_m1);
     286            rt->rt_irtt *= (sysconf(_SC_CLK_TCK) / 100);    /* FIXME */
    276287#if 0                   /* FIXME: do we need to check anything of this? */
    277             if (rt.rt_irtt < 1 || rt.rt_irtt > (120 * HZ)) {
     288            if (rt->rt_irtt < 1 || rt->rt_irtt > (120 * HZ)) {
    278289                bb_error_msg_and_die("bad irtt");
    279290            }
     
    285296        /* Device is special in that it can be the last arg specified
    286297         * and doesn't requre the dev/device keyword in that case. */
    287         if (!rt.rt_dev && ((k == KW_IPVx_DEVICE) || (!k && !*++args))) {
     298        if (!rt->rt_dev && ((k == KW_IPVx_DEVICE) || (!k && !*++args))) {
    288299            /* Don't use args_m1 here since args may have changed! */
    289             rt.rt_dev = args[-1];
     300            rt->rt_dev = args[-1];
    290301            continue;
    291302        }
     
    296307
    297308#ifdef RTF_REJECT
    298     if ((rt.rt_flags & RTF_REJECT) && !rt.rt_dev) {
    299         rt.rt_dev = (char*)"lo";
     309    if ((rt->rt_flags & RTF_REJECT) && !rt->rt_dev) {
     310        rt->rt_dev = (char*)"lo";
    300311    }
    301312#endif
    302313
    303314    /* sanity checks.. */
    304     if (mask_in_addr(rt)) {
    305         uint32_t mask = mask_in_addr(rt);
     315    if (mask_in_addr(*rt)) {
     316        uint32_t mask = mask_in_addr(*rt);
    306317
    307318        mask = ~ntohl(mask);
    308         if ((rt.rt_flags & RTF_HOST) && mask != 0xffffffff) {
     319        if ((rt->rt_flags & RTF_HOST) && mask != 0xffffffff) {
    309320            bb_error_msg_and_die("netmask %.8x and host route conflict",
    310321                                 (unsigned int) mask);
     
    313324            bb_error_msg_and_die("bogus netmask %s", netmask);
    314325        }
    315         mask = ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr;
    316         if (mask & ~(uint32_t)mask_in_addr(rt)) {
     326        mask = ((struct sockaddr_in *) &rt->rt_dst)->sin_addr.s_addr;
     327        if (mask & ~(uint32_t)mask_in_addr(*rt)) {
    317328            bb_error_msg_and_die("netmask and route address conflict");
    318329        }
     
    320331
    321332    /* Fill out netmask if still unset */
    322     if ((action == RTACTION_ADD) && (rt.rt_flags & RTF_HOST)) {
    323         mask_in_addr(rt) = 0xffffffff;
     333    if ((action == RTACTION_ADD) && (rt->rt_flags & RTF_HOST)) {
     334        mask_in_addr(*rt) = 0xffffffff;
    324335    }
    325336
     
    328339
    329340    if (action == RTACTION_ADD)
    330         xioctl(skfd, SIOCADDRT, &rt);
     341        xioctl(skfd, SIOCADDRT, rt);
    331342    else
    332         xioctl(skfd, SIOCDELRT, &rt);
     343        xioctl(skfd, SIOCDELRT, rt);
    333344
    334345    if (ENABLE_FEATURE_CLEAN_UP) close(skfd);
     
    399410            }
    400411            memcpy(&rt.rtmsg_gateway, sa6.sin6_addr.s6_addr,
    401                    sizeof(struct in6_addr));
     412                    sizeof(struct in6_addr));
    402413            rt.rtmsg_flags |= RTF_GATEWAY;
    403414            continue;
     
    425436        memset(&ifr, 0, sizeof(ifr));
    426437        strncpy_IFNAMSIZ(ifr.ifr_name, devname);
    427         xioctl(skfd, SIOGIFINDEX, &ifr);
     438        xioctl(skfd, SIOCGIFINDEX, &ifr);
    428439        rt.rtmsg_ifindex = ifr.ifr_ifindex;
    429440    }
     
    488499
    489500    printf("Kernel IP routing table\n"
    490            "Destination     Gateway         Genmask         Flags %s Iface\n",
     501        "Destination     Gateway         Genmask         Flags %s Iface\n",
    491502            netstatfmt ? "  MSS Window  irtt" : "Metric Ref    Use");
    492503
    493504    if (fscanf(fp, "%*[^\n]\n") < 0) { /* Skip the first line. */
    494         goto ERROR;        /* Empty or missing line, or read error. */
     505        goto ERROR;                /* Empty or missing line, or read error. */
    495506    }
    496507    while (1) {
    497508        int r;
    498509        r = fscanf(fp, "%63s%lx%lx%X%d%d%d%lx%d%d%d\n",
    499                    devname, &d, &g, &flgs, &ref, &use, &metric, &m,
    500                    &mtu, &win, &ir);
     510                devname, &d, &g, &flgs, &ref, &use, &metric, &m,
     511                &mtu, &win, &ir);
    501512        if (r != 11) {
    502513            if ((r < 0) && feof(fp)) { /* EOF with no (nonspace) chars read. */
     
    535546        }
    536547    }
     548    fclose(fp);
    537549}
    538550
     
    556568
    557569    printf("Kernel IPv6 routing table\n%-44s%-40s"
    558               "Flags Metric Ref    Use Iface\n",
    559               "Destination", "Next Hop");
     570            "Flags Metric Ref    Use Iface\n",
     571            "Destination", "Next Hop");
    560572
    561573    while (1) {
     
    602614
    603615        r = 0;
    604         do {
     616        while (1) {
    605617            inet_pton(AF_INET6, addr6x + r,
    606618                      (struct sockaddr *) &snaddr6.sin6_addr);
    607619            snaddr6.sin6_family = AF_INET6;
    608620            naddr6 = INET6_rresolve((struct sockaddr_in6 *) &snaddr6,
    609                            0x0fff /* Apparently, upstream never resolves. */
    610                            );
     621                        0x0fff /* Apparently, upstream never resolves. */
     622                        );
    611623
    612624            if (!r) {           /* 1st pass */
     
    621633                break;
    622634            }
    623         } while (1);
    624     }
     635        }
     636    }
     637    fclose(fp);
    625638}
    626639
  • branches/3.2/mindi-busybox/networking/slattach.c

    r2725 r3232  
    1313 * - The -F options allows disabling of RTS/CTS flow control.
    1414 */
     15
     16//usage:#define slattach_trivial_usage
     17//usage:       "[-cehmLF] [-s SPEED] [-p PROTOCOL] DEVICE"
     18//usage:#define slattach_full_usage "\n\n"
     19//usage:       "Attach network interface(s) to serial line(s)\n"
     20//usage:     "\n    -p PROT Set protocol (slip, cslip, slip6, clisp6 or adaptive)"
     21//usage:     "\n    -s SPD  Set line speed"
     22//usage:     "\n    -e  Exit after initializing device"
     23//usage:     "\n    -h  Exit when the carrier is lost"
     24//usage:     "\n    -c PROG Run PROG when the line is hung up"
     25//usage:     "\n    -m  Do NOT initialize the line in raw 8 bits mode"
     26//usage:     "\n    -L  Enable 3-wire operation"
     27//usage:     "\n    -F  Disable RTS/CTS flow control"
    1528
    1629#include "libbb.h"
  • branches/3.2/mindi-busybox/networking/tc.c

    r2725 r3232  
    77 * Bernhard Reutner-Fischer adjusted for busybox
    88 */
     9
     10//usage:#define tc_trivial_usage
     11/* //usage: "[OPTIONS] OBJECT CMD [dev STRING]" */
     12//usage:    "OBJECT CMD [dev STRING]"
     13//usage:#define tc_full_usage "\n\n"
     14//usage:    "OBJECT: {qdisc|class|filter}\n"
     15//usage:    "CMD: {add|del|change|replace|show}\n"
     16//usage:    "\n"
     17//usage:    "qdisc [ handle QHANDLE ] [ root |"IF_FEATURE_TC_INGRESS(" ingress |")" parent CLASSID ]\n"
     18/* //usage: "[ estimator INTERVAL TIME_CONSTANT ]\n" */
     19//usage:    "   [ [ QDISC_KIND ] [ help | OPTIONS ] ]\n"
     20//usage:    "   QDISC_KIND := { [p|b]fifo | tbf | prio | cbq | red | etc. }\n"
     21//usage:    "qdisc show [ dev STRING ]"IF_FEATURE_TC_INGRESS(" [ingress]")"\n"
     22//usage:    "class [ classid CLASSID ] [ root | parent CLASSID ]\n"
     23//usage:    "   [ [ QDISC_KIND ] [ help | OPTIONS ] ]\n"
     24//usage:    "class show [ dev STRING ] [ root | parent CLASSID ]\n"
     25//usage:    "filter [ pref PRIO ] [ protocol PROTO ]\n"
     26/* //usage: "\t[ estimator INTERVAL TIME_CONSTANT ]\n" */
     27//usage:    "   [ root | classid CLASSID ] [ handle FILTERID ]\n"
     28//usage:    "   [ [ FILTER_TYPE ] [ help | OPTIONS ] ]\n"
     29//usage:    "filter show [ dev STRING ] [ root | parent CLASSID ]"
    930
    1031#include "libbb.h"
     
    3859struct globals {
    3960    int filter_ifindex;
    40     __u32 filter_qdisc;
    41     __u32 filter_parent;
    42     __u32 filter_prio;
    43     __u32 filter_proto;
     61    uint32_t filter_qdisc;
     62    uint32_t filter_parent;
     63    uint32_t filter_prio;
     64    uint32_t filter_proto;
    4465} FIX_ALIASING;
    4566#define G (*(struct globals*)&bb_common_bufsiz1)
     67struct BUG_G_too_big {
     68        char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
     69};
    4670#define filter_ifindex (G.filter_ifindex)
    4771#define filter_qdisc (G.filter_qdisc)
     
    4973#define filter_prio (G.filter_prio)
    5074#define filter_proto (G.filter_proto)
    51 
    52 void BUG_tc_globals_too_big(void);
    53 #define INIT_G() do { \
    54     if (sizeof(G) > COMMON_BUFSIZE) \
    55         BUG_tc_globals_too_big(); \
    56 } while (0)
     75#define INIT_G() do { } while (0)
    5776
    5877/* Allocates a buffer containing the name of a class id.
     
    7695
    7796/* Get a qdisc handle.  Return 0 on success, !0 otherwise.  */
    78 static int get_qdisc_handle(__u32 *h, const char *str) {
    79     __u32 maj;
     97static int get_qdisc_handle(uint32_t *h, const char *str) {
     98    uint32_t maj;
    8099    char *p;
    81100
     
    95114
    96115/* Get class ID.  Return 0 on success, !0 otherwise.  */
    97 static int get_tc_classid(__u32 *h, const char *str) {
    98     __u32 maj, min;
     116static int get_tc_classid(uint32_t *h, const char *str) {
     117    uint32_t maj, min;
    99118    char *p;
    100119
     
    373392    else if (msg->tcm_parent) {
    374393        classid = print_tc_classid(filter_qdisc ?
    375                                    TC_H_MIN(msg->tcm_parent) : msg->tcm_parent);
     394                TC_H_MIN(msg->tcm_parent) : msg->tcm_parent);
    376395        printf("parent %s ", classid);
    377396        if (ENABLE_FEATURE_CLEAN_UP)
     
    495514                filter_parent = TC_H_ROOT;
    496515        } else if (arg == ARG_parent) {
    497             __u32 handle;
     516            uint32_t handle;
    498517            if (msg.tcm_parent)
    499518                duparg(*argv, "parent");
     
    508527            /* reject LONG_MIN || LONG_MAX */
    509528            /* TODO: for fw
    510                if ((slash = strchr(handle, '/')) != NULL)
     529            slash = strchr(handle, '/');
     530            if (slash != NULL)
    511531                   *slash = '\0';
    512532             */
    513533            msg.tcm_handle = get_u32(*argv, "handle");
    514             /* if (slash) {if (get_u32(__u32 &mask, slash+1, NULL)) inv mask; addattr32(n, MAX_MSG, TCA_FW_MASK, mask); */
     534            /* if (slash) {if (get_u32(uint32_t &mask, slash+1, NULL)) inv mask; addattr32(n, MAX_MSG, TCA_FW_MASK, mask); */
    515535        } else if (arg == ARG_classid && obj == OBJ_class && cmd == CMD_change){
    516536        } else if (arg == ARG_pref || arg == ARG_prio) { /* filter::list */
  • branches/3.2/mindi-busybox/networking/tcpudp.c

    r2725 r3232  
    3030 */
    3131
     32//usage:#define tcpsvd_trivial_usage
     33//usage:       "[-hEv] [-c N] [-C N[:MSG]] [-b N] [-u USER] [-l NAME] IP PORT PROG"
     34/* with not-implemented options: */
     35/* //usage:    "[-hpEvv] [-c N] [-C N[:MSG]] [-b N] [-u USER] [-l NAME] [-i DIR|-x CDB] [-t SEC] IP PORT PROG" */
     36//usage:#define tcpsvd_full_usage "\n\n"
     37//usage:       "Create TCP socket, bind to IP:PORT and listen\n"
     38//usage:       "for incoming connection. Run PROG for each connection.\n"
     39//usage:     "\n    IP      IP to listen on, 0 = all"
     40//usage:     "\n    PORT        Port to listen on"
     41//usage:     "\n    PROG ARGS   Program to run"
     42//usage:     "\n    -l NAME     Local hostname (else looks up local hostname in DNS)"
     43//usage:     "\n    -u USER[:GRP]   Change to user/group after bind"
     44//usage:     "\n    -c N        Handle up to N connections simultaneously"
     45//usage:     "\n    -b N        Allow a backlog of approximately N TCP SYNs"
     46//usage:     "\n    -C N[:MSG]  Allow only up to N connections from the same IP"
     47//usage:     "\n            New connections from this IP address are closed"
     48//usage:     "\n            immediately. MSG is written to the peer before close"
     49//usage:     "\n    -h      Look up peer's hostname"
     50//usage:     "\n    -E      Don't set up environment variables"
     51//usage:     "\n    -v      Verbose"
     52//usage:
     53//usage:#define udpsvd_trivial_usage
     54//usage:       "[-hEv] [-c N] [-u USER] [-l NAME] IP PORT PROG"
     55//usage:#define udpsvd_full_usage "\n\n"
     56//usage:       "Create UDP socket, bind to IP:PORT and wait\n"
     57//usage:       "for incoming packets. Run PROG for each packet,\n"
     58//usage:       "redirecting all further packets with same peer ip:port to it.\n"
     59//usage:     "\n    IP      IP to listen on, 0 = all"
     60//usage:     "\n    PORT        Port to listen on"
     61//usage:     "\n    PROG ARGS   Program to run"
     62//usage:     "\n    -l NAME     Local hostname (else looks up local hostname in DNS)"
     63//usage:     "\n    -u USER[:GRP]   Change to user/group after bind"
     64//usage:     "\n    -c N        Handle up to N connections simultaneously"
     65//usage:     "\n    -h      Look up peer's hostname"
     66//usage:     "\n    -E      Don't set up environment variables"
     67//usage:     "\n    -v      Verbose"
     68
    3269#include "libbb.h"
    3370
     
    388425         * (otherwise we can move socket to fd #0 only if bind succeeds) */
    389426        close(0);
    390         set_nport(localp, htons(local_port));
     427        set_nport(&localp->u.sa, htons(local_port));
    391428        xmove_fd(xsocket(localp->u.sa.sa_family, SOCK_DGRAM, 0), 0);
    392429        setsockopt_reuseaddr(0); /* crucial */
  • branches/3.2/mindi-busybox/networking/telnet.c

    r2725 r3232  
    2222 */
    2323
     24//usage:#if ENABLE_FEATURE_TELNET_AUTOLOGIN
     25//usage:#define telnet_trivial_usage
     26//usage:       "[-a] [-l USER] HOST [PORT]"
     27//usage:#define telnet_full_usage "\n\n"
     28//usage:       "Connect to telnet server\n"
     29//usage:     "\n    -a  Automatic login with $USER variable"
     30//usage:     "\n    -l USER Automatic login as USER"
     31//usage:
     32//usage:#else
     33//usage:#define telnet_trivial_usage
     34//usage:       "HOST [PORT]"
     35//usage:#define telnet_full_usage "\n\n"
     36//usage:       "Connect to telnet server"
     37//usage:#endif
     38
    2439#include <arpa/telnet.h>
    2540#include <netinet/in.h>
    2641#include "libbb.h"
    2742
     43#ifdef __BIONIC__
     44/* should be in arpa/telnet.h */
     45# define IAC         255  /* interpret as command: */
     46# define DONT        254  /* you are not to use option */
     47# define DO          253  /* please, you use option */
     48# define WONT        252  /* I won't use option */
     49# define WILL        251  /* I will use option */
     50# define SB          250  /* interpret as subnegotiation */
     51# define SE          240  /* end sub negotiation */
     52# define TELOPT_ECHO   1  /* echo */
     53# define TELOPT_SGA    3  /* suppress go ahead */
     54# define TELOPT_TTYPE 24  /* terminal type */
     55# define TELOPT_NAWS  31  /* window size */
     56#endif
     57
    2858#ifdef DOTRACE
    29 #define TRACE(x, y) do { if (x) printf y; } while (0)
     59# define TRACE(x, y) do { if (x) printf y; } while (0)
    3060#else
    31 #define TRACE(x, y)
     61# define TRACE(x, y)
    3262#endif
    3363
     
    157187static void handle_net_output(int len)
    158188{
    159     /* here we could do smart tricks how to handle 0xFF:s in output
    160      * stream like writing twice every sequence of FF:s (thus doing
    161      * many write()s. But I think interactive telnet application does
    162      * not need to be 100% 8-bit clean, so changing every 0xff:s to
    163      * 0x7f:s
    164      *
    165      * 2002-mar-21, Przemyslaw Czerpak (druzus@polbox.com)
    166      * I don't agree.
    167      * first - I cannot use programs like sz/rz
    168      * second - the 0x0D is sent as one character and if the next
    169      *  char is 0x0A then it's eaten by a server side.
    170      * third - why do you have to make 'many write()s'?
    171      *  I don't understand.
    172      * So I implemented it. It's really useful for me. I hope that
    173      * other people will find it interesting too.
    174      */
    175189    byte outbuf[2 * DATABUFSIZE];
    176     byte *p = (byte*)G.buf;
    177     int j = 0;
    178 
    179     for (; len > 0; len--, p++) {
    180         byte c = *p;
     190    byte *dst = outbuf;
     191    byte *src = (byte*)G.buf;
     192    byte *end = src + len;
     193
     194    while (src < end) {
     195        byte c = *src++;
    181196        if (c == 0x1d) {
    182197            con_escape();
    183198            return;
    184199        }
    185         outbuf[j++] = c;
     200        *dst = c;
    186201        if (c == IAC)
    187             outbuf[j++] = c; /* IAC -> IAC IAC */
    188         else if (c == '\r')
    189             outbuf[j++] = '\0'; /* CR -> CR NUL */
    190     }
    191     if (j > 0)
    192         full_write(netfd, outbuf, j);
     202            *++dst = c; /* IAC -> IAC IAC */
     203        else
     204        if (c == '\r' || c == '\n') {
     205            /* Enter key sends '\r' in raw mode and '\n' in cooked one.
     206             *
     207             * See RFC 1123 3.3.1 Telnet End-of-Line Convention.
     208             * Using CR LF instead of other allowed possibilities
     209             * like CR NUL - easier to talk to HTTP/SMTP servers.
     210             */
     211            *dst = '\r'; /* Enter -> CR LF */
     212            *++dst = '\n';
     213        }
     214        dst++;
     215    }
     216    if (dst - outbuf != 0)
     217        full_write(netfd, outbuf, dst - outbuf);
    193218}
    194219
     
    369394#endif
    370395
    371 static char const escapecharis[] ALIGN1 = "\r\nEscape character is ";
    372 
    373396static void setConMode(void)
    374397{
     
    376399        if (G.charmode == CHM_TRY) {
    377400            G.charmode = CHM_ON;
    378             printf("\r\nEntering character mode%s'^]'.\r\n", escapecharis);
     401            printf("\r\nEntering %s mode"
     402                "\r\nEscape character is '^%c'.\r\n", "character", ']');
    379403            rawmode();
    380404        }
     
    382406        if (G.charmode != CHM_OFF) {
    383407            G.charmode = CHM_OFF;
    384             printf("\r\nEntering line mode%s'^C'.\r\n", escapecharis);
     408            printf("\r\nEntering %s mode"
     409                "\r\nEscape character is '^%c'.\r\n", "line", 'C');
    385410            cookmode();
    386411        }
  • branches/3.2/mindi-busybox/networking/telnetd.c

    r2725 r3232  
    2121 * Set process group corrections, initial busybox port
    2222 */
     23
     24//usage:#define telnetd_trivial_usage
     25//usage:       "[OPTIONS]"
     26//usage:#define telnetd_full_usage "\n\n"
     27//usage:       "Handle incoming telnet connections"
     28//usage:    IF_NOT_FEATURE_TELNETD_STANDALONE(" via inetd") "\n"
     29//usage:     "\n    -l LOGIN    Exec LOGIN on connect"
     30//usage:     "\n    -f ISSUE_FILE   Display ISSUE_FILE instead of /etc/issue"
     31//usage:     "\n    -K      Close connection as soon as login exits"
     32//usage:     "\n            (normally wait until all programs close slave pty)"
     33//usage:    IF_FEATURE_TELNETD_STANDALONE(
     34//usage:     "\n    -p PORT     Port to listen on"
     35//usage:     "\n    -b ADDR[:PORT]  Address to bind to"
     36//usage:     "\n    -F      Run in foreground"
     37//usage:     "\n    -i      Inetd mode"
     38//usage:    IF_FEATURE_TELNETD_INETD_WAIT(
     39//usage:     "\n    -w SEC      Inetd 'wait' mode, linger time SEC"
     40//usage:     "\n    -S      Log to syslog (implied by -i or without -F and -w)"
     41//usage:    )
     42//usage:    )
     43
    2344#define DEBUG 0
    2445
     
    3152#endif
    3253#include <arpa/telnet.h>
    33 
    34 #if ENABLE_FEATURE_UTMP
    35 # include <utmp.h> /* LOGIN_PROCESS */
    36 #endif
    3754
    3855
     
    109126             * Many client implementations send \r\n when
    110127             * the user hits the CarriageReturn key.
     128             * See RFC 1123 3.3.1 Telnet End-of-Line Convention.
    111129             */
    112130            if (c == '\r' && ptr < end && (*ptr == '\n' || *ptr == '\0'))
     
    315333    bb_signals((1 << SIGCHLD) + (1 << SIGPIPE), SIG_DFL);
    316334
     335    pid = getpid();
     336
    317337    if (ENABLE_FEATURE_UTMP) {
    318338        len_and_sockaddr *lsa = get_peer_lsa(sock);
     
    336356    xdup2(0, 1);
    337357    xdup2(0, 2);
    338     pid = getpid();
    339358    tcsetpgrp(0, pid); /* switch this tty's process group to us */
    340359
  • branches/3.2/mindi-busybox/networking/tftp.c

    r2725 r3232  
    1919 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    2020 */
     21
     22//usage:#define tftp_trivial_usage
     23//usage:       "[OPTIONS] HOST [PORT]"
     24//usage:#define tftp_full_usage "\n\n"
     25//usage:       "Transfer a file from/to tftp server\n"
     26//usage:     "\n    -l FILE Local FILE"
     27//usage:     "\n    -r FILE Remote FILE"
     28//usage:    IF_FEATURE_TFTP_GET(
     29//usage:     "\n    -g  Get file"
     30//usage:    )
     31//usage:    IF_FEATURE_TFTP_PUT(
     32//usage:     "\n    -p  Put file"
     33//usage:    )
     34//usage:    IF_FEATURE_TFTP_BLOCKSIZE(
     35//usage:     "\n    -b SIZE Transfer blocks of SIZE octets"
     36//usage:    )
     37//usage:
     38//usage:#define tftpd_trivial_usage
     39//usage:       "[-cr] [-u USER] [DIR]"
     40//usage:#define tftpd_full_usage "\n\n"
     41//usage:       "Transfer a file on tftp client's request\n"
     42//usage:       "\n"
     43//usage:       "tftpd should be used as an inetd service.\n"
     44//usage:       "tftpd's line for inetd.conf:\n"
     45//usage:       "    69 dgram udp nowait root tftpd tftpd -l /files/to/serve\n"
     46//usage:       "It also can be ran from udpsvd:\n"
     47//usage:       "    udpsvd -vE 0.0.0.0 69 tftpd /files/to/serve\n"
     48//usage:     "\n    -r  Prohibit upload"
     49//usage:     "\n    -c  Allow file creation via upload"
     50//usage:     "\n    -u  Access files as USER"
     51//usage:     "\n    -l  Log to syslog (inetd mode requires this)"
     52
    2153#include "libbb.h"
     54#include <syslog.h>
    2255
    2356#if ENABLE_FEATURE_TFTP_GET || ENABLE_FEATURE_TFTP_PUT
     
    6093    TFTPD_OPT_c = (1 << 9) * ENABLE_TFTPD,
    6194    TFTPD_OPT_u = (1 << 10) * ENABLE_TFTPD,
     95    TFTPD_OPT_l = (1 << 11) * ENABLE_TFTPD,
    6296};
    6397
     
    83117    /* u16 TFTP_ERROR; u16 reason; both network-endian, then error text: */
    84118    uint8_t error_pkt[4 + 32];
    85     char *user_opt;
     119    struct passwd *pw;
    86120    /* used in tftpd_main(), a bit big for stack: */
    87121    char block_buf[TFTP_BLKSIZE_DEFAULT];
     
    97131    char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
    98132};
    99 #define block_buf        (G.block_buf   )
    100 #define user_opt         (G.user_opt    )
    101 #define error_pkt        (G.error_pkt   )
    102133#define INIT_G() do { } while (0)
    103134
    104 #define error_pkt_reason (error_pkt[3])
    105 #define error_pkt_str    (error_pkt + 4)
     135#define G_error_pkt_reason (G.error_pkt[3])
     136#define G_error_pkt_str    ((char*)(G.error_pkt + 4))
    106137
    107138#if ENABLE_FEATURE_TFTP_PROGRESS_BAR
    108139static void tftp_progress_update(void)
    109140{
    110     bb_progress_update(&G.pmt, G.file, 0, G.pos, G.size);
     141    bb_progress_update(&G.pmt, 0, G.pos, G.size);
    111142}
    112143static void tftp_progress_init(void)
    113144{
    114     bb_progress_init(&G.pmt);
     145    bb_progress_init(&G.pmt, G.file);
    115146    tftp_progress_update();
    116147}
    117148static void tftp_progress_done(void)
    118149{
    119     if (G.pmt.inited) {
     150    if (is_bb_progress_inited(&G.pmt)) {
    120151        tftp_progress_update();
    121152        bb_putchar_stderr('\n');
    122         G.pmt.inited = 0;
     153        bb_progress_free(&G.pmt);
    123154    }
    124155}
     
    239270
    240271        /* Is there an error already? Send pkt and bail out */
    241         if (error_pkt_reason || error_pkt_str[0])
     272        if (G_error_pkt_reason || G_error_pkt_str[0])
    242273            goto send_err_pkt;
    243274
    244         if (user_opt) {
    245             struct passwd *pw = xgetpwnam(user_opt);
    246             change_identity(pw); /* initgroups, setgid, setuid */
     275        if (G.pw) {
     276            change_identity(G.pw); /* initgroups, setgid, setuid */
    247277        }
    248278    }
     
    296326        local_fd = open(local_file, open_mode, 0666);
    297327        if (local_fd < 0) {
    298             error_pkt_reason = ERR_NOFILE;
    299             strcpy((char*)error_pkt_str, "can't open file");
     328            G_error_pkt_reason = ERR_NOFILE;
     329            strcpy(G_error_pkt_str, "can't open file");
    300330            goto send_err_pkt;
    301331        }
     
    423453            }
    424454            cp += len;
     455            IF_FEATURE_TFTP_PROGRESS_BAR(G.pos += len;)
    425456        }
    426457 send_pkt:
     
    444475
    445476#if ENABLE_FEATURE_TFTP_PROGRESS_BAR
    446         if (ENABLE_TFTP && remote_file) /* tftp */
    447             G.pos = (block_nr - 1) * (uoff_t)blksize;
    448         if (G.pmt.inited)
     477        if (is_bb_progress_inited(&G.pmt))
    449478            tftp_progress_update();
    450479#endif
     
    543572                    blksize = tftp_blksize_check(res, blksize);
    544573                    if (blksize < 0) {
    545                         error_pkt_reason = ERR_BAD_OPT;
     574                        G_error_pkt_reason = ERR_BAD_OPT;
    546575                        goto send_err_pkt;
    547576                    }
     
    582611                int sz = full_write(local_fd, &rbuf[4], len - 4);
    583612                if (sz != len - 4) {
    584                     strcpy((char*)error_pkt_str, bb_msg_write_error);
    585                     error_pkt_reason = ERR_WRITE;
     613                    strcpy(G_error_pkt_str, bb_msg_write_error);
     614                    G_error_pkt_reason = ERR_WRITE;
    586615                    goto send_err_pkt;
    587616                }
     
    589618                    finished = 1;
    590619                }
     620                IF_FEATURE_TFTP_PROGRESS_BAR(G.pos += sz;)
    591621                continue; /* send ACK */
    592622            }
     
    631661
    632662 send_read_err_pkt:
    633     strcpy((char*)error_pkt_str, bb_msg_read_error);
     663    strcpy(G_error_pkt_str, bb_msg_read_error);
    634664 send_err_pkt:
    635     if (error_pkt_str[0])
    636         bb_error_msg("%s", (char*)error_pkt_str);
    637     error_pkt[1] = TFTP_ERROR;
    638     xsendto(socket_fd, error_pkt, 4 + 1 + strlen((char*)error_pkt_str),
     665    if (G_error_pkt_str[0])
     666        bb_error_msg("%s", G_error_pkt_str);
     667    G.error_pkt[1] = TFTP_ERROR;
     668    xsendto(socket_fd, G.error_pkt, 4 + 1 + strlen(G_error_pkt_str),
    639669            &peer_lsa->u.sa, peer_lsa->len);
    640670    return EXIT_FAILURE;
     
    728758    len_and_sockaddr *our_lsa;
    729759    len_and_sockaddr *peer_lsa;
    730     char *local_file, *mode;
     760    char *local_file, *mode, *user_opt;
    731761    const char *error_msg;
    732762    int opt, result, opcode;
     
    750780
    751781    /* Shifting to not collide with TFTP_OPTs */
    752     opt = option_mask32 = TFTPD_OPT | (getopt32(argv, "rcu:", &user_opt) << 8);
     782    opt = option_mask32 = TFTPD_OPT | (getopt32(argv, "rcu:l", &user_opt) << 8);
    753783    argv += optind;
    754     if (argv[0])
    755         xchdir(argv[0]);
    756 
    757     result = recv_from_to(STDIN_FILENO, block_buf, sizeof(block_buf),
     784    if (opt & TFTPD_OPT_l) {
     785        openlog(applet_name, LOG_PID, LOG_DAEMON);
     786        logmode = LOGMODE_SYSLOG;
     787    }
     788    if (opt & TFTPD_OPT_u) {
     789        /* Must be before xchroot */
     790        G.pw = xgetpwnam(user_opt);
     791    }
     792    if (argv[0]) {
     793        xchroot(argv[0]);
     794    }
     795
     796    result = recv_from_to(STDIN_FILENO, G.block_buf, sizeof(G.block_buf),
    758797            0 /* flags */,
    759798            &peer_lsa->u.sa, &our_lsa->u.sa, our_lsa->len);
    760799
    761800    error_msg = "malformed packet";
    762     opcode = ntohs(*(uint16_t*)block_buf);
    763     if (result < 4 || result >= sizeof(block_buf)
    764      || block_buf[result-1] != '\0'
     801    opcode = ntohs(*(uint16_t*)G.block_buf);
     802    if (result < 4 || result >= sizeof(G.block_buf)
     803     || G.block_buf[result-1] != '\0'
    765804     || (IF_FEATURE_TFTP_PUT(opcode != TFTP_RRQ) /* not download */
    766805         IF_GETPUT(&&)
     
    770809        goto err;
    771810    }
    772     local_file = block_buf + 2;
     811    local_file = G.block_buf + 2;
    773812    if (local_file[0] == '.' || strstr(local_file, "/.")) {
    774813        error_msg = "dot in file name";
     
    776815    }
    777816    mode = local_file + strlen(local_file) + 1;
    778     if (mode >= block_buf + result || strcmp(mode, "octet") != 0) {
     817    /* RFC 1350 says mode string is case independent */
     818    if (mode >= G.block_buf + result || strcasecmp(mode, "octet") != 0) {
    779819        goto err;
    780820    }
     
    783823        char *res;
    784824        char *opt_str = mode + sizeof("octet");
    785         int opt_len = block_buf + result - opt_str;
     825        int opt_len = G.block_buf + result - opt_str;
    786826        if (opt_len > 0) {
    787827            res = tftp_get_option("blksize", opt_str, opt_len);
     
    789829                blksize = tftp_blksize_check(res, 65564);
    790830                if (blksize < 0) {
    791                     error_pkt_reason = ERR_BAD_OPT;
     831                    G_error_pkt_reason = ERR_BAD_OPT;
    792832                    /* will just send error pkt */
    793833                    goto do_proto;
     
    807847        if (opt & TFTPD_OPT_r) {
    808848            /* This would mean "disk full" - not true */
    809             /*error_pkt_reason = ERR_WRITE;*/
     849            /*G_error_pkt_reason = ERR_WRITE;*/
    810850            error_msg = bb_msg_write_error;
    811851            goto err;
     
    816856    }
    817857
    818     /* NB: if error_pkt_str or error_pkt_reason is set up,
     858    /* NB: if G_error_pkt_str or G_error_pkt_reason is set up,
    819859     * tftp_protocol() just sends one error pkt and returns */
    820860
     
    831871    return result;
    832872 err:
    833     strcpy((char*)error_pkt_str, error_msg);
     873    strcpy(G_error_pkt_str, error_msg);
    834874    goto do_proto;
    835875}
  • branches/3.2/mindi-busybox/networking/traceroute.c

    r2725 r3232  
    211211 */
    212212
     213//usage:#define traceroute_trivial_usage
     214//usage:       "[-"IF_TRACEROUTE6("46")"FIldnrv] [-f 1ST_TTL] [-m MAXTTL] [-p PORT] [-q PROBES]\n"
     215//usage:       "    [-s SRC_IP] [-t TOS] [-w WAIT_SEC] [-g GATEWAY] [-i IFACE]\n"
     216//usage:       "    [-z PAUSE_MSEC] HOST [BYTES]"
     217//usage:#define traceroute_full_usage "\n\n"
     218//usage:       "Trace the route to HOST\n"
     219//usage:    IF_TRACEROUTE6(
     220//usage:     "\n    -4,-6   Force IP or IPv6 name resolution"
     221//usage:    )
     222//usage:     "\n    -F  Set the don't fragment bit"
     223//usage:     "\n    -I  Use ICMP ECHO instead of UDP datagrams"
     224//usage:     "\n    -l  Display the TTL value of the returned packet"
     225//usage:     "\n    -d  Set SO_DEBUG options to socket"
     226//usage:     "\n    -n  Print numeric addresses"
     227//usage:     "\n    -r  Bypass routing tables, send directly to HOST"
     228//usage:     "\n    -v  Verbose"
     229//usage:     "\n    -m  Max time-to-live (max number of hops)"
     230//usage:     "\n    -p  Base UDP port number used in probes"
     231//usage:     "\n        (default 33434)"
     232//usage:     "\n    -q  Number of probes per TTL (default 3)"
     233//usage:     "\n    -s  IP address to use as the source address"
     234//usage:     "\n    -t  Type-of-service in probe packets (default 0)"
     235//usage:     "\n    -w  Time in seconds to wait for a response (default 3)"
     236//usage:     "\n    -g  Loose source route gateway (8 max)"
     237//usage:
     238//usage:#define traceroute6_trivial_usage
     239//usage:       "[-dnrv] [-m MAXTTL] [-p PORT] [-q PROBES]\n"
     240//usage:       "    [-s SRC_IP] [-t TOS] [-w WAIT_SEC] [-i IFACE]\n"
     241//usage:       "    HOST [BYTES]"
     242//usage:#define traceroute6_full_usage "\n\n"
     243//usage:       "Trace the route to HOST\n"
     244//usage:     "\n    -d  Set SO_DEBUG options to socket"
     245//usage:     "\n    -n  Print numeric addresses"
     246//usage:     "\n    -r  Bypass routing tables, send directly to HOST"
     247//usage:     "\n    -v  Verbose"
     248//usage:     "\n    -m  Max time-to-live (max number of hops)"
     249//usage:     "\n    -p  Base UDP port number used in probes"
     250//usage:     "\n        (default is 33434)"
     251//usage:     "\n    -q  Number of probes per TTL (default 3)"
     252//usage:     "\n    -s  IP address to use as the source address"
     253//usage:     "\n    -t  Type-of-service in probe packets (default 0)"
     254//usage:     "\n    -w  Time in seconds to wait for a response (default 3)"
     255
    213256#define TRACEROUTE_SO_DEBUG 0
    214257
     
    248291
    249292
    250 #define OPT_STRING "FIlnrdvxt:i:m:p:q:s:w:z:f:" \
    251             IF_FEATURE_TRACEROUTE_SOURCE_ROUTE("g:") \
    252             "4" IF_TRACEROUTE6("6")
     293#define OPT_STRING \
     294    "FIlnrdvxt:i:m:p:q:s:w:z:f:" \
     295    IF_FEATURE_TRACEROUTE_SOURCE_ROUTE("g:") \
     296    "4" IF_TRACEROUTE6("6")
    253297enum {
    254298    OPT_DONT_FRAGMNT = (1 << 0),    /* F */
     
    354398
    355399static int
    356 wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to)
     400wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timestamp_us, int *left_ms)
    357401{
    358402    struct pollfd pfd[1];
     
    361405    pfd[0].fd = rcvsock;
    362406    pfd[0].events = POLLIN;
    363     if (safe_poll(pfd, 1, waittime * 1000) > 0) {
     407    if (*left_ms >= 0 && safe_poll(pfd, 1, *left_ms) > 0) {
     408        unsigned t;
     409
    364410        read_len = recv_from_to(rcvsock,
    365411                recv_pkt, sizeof(recv_pkt),
    366                 /*flags:*/ 0,
     412                /*flags:*/ MSG_DONTWAIT,
    367413                &from_lsa->u.sa, to, from_lsa->len);
     414        t = monotonic_us();
     415        *left_ms -= (t - *timestamp_us) / 1000;
     416        *timestamp_us = t;
    368417    }
    369418
    370419    return read_len;
    371 }
    372 
    373 /*
    374  * Checksum routine for Internet Protocol family headers (C Version)
    375  */
    376 static uint16_t
    377 in_cksum(uint16_t *addr, int len)
    378 {
    379     int nleft = len;
    380     uint16_t *w = addr;
    381     uint16_t answer;
    382     int sum = 0;
    383 
    384     /*
    385      * Our algorithm is simple, using a 32 bit accumulator (sum),
    386      * we add sequential 16 bit words to it, and at the end, fold
    387      * back all the carry bits from the top 16 bits into the lower
    388      * 16 bits.
    389      */
    390     while (nleft > 1) {
    391         sum += *w++;
    392         nleft -= 2;
    393     }
    394 
    395     /* mop up an odd byte, if necessary */
    396     if (nleft == 1)
    397         sum += *(unsigned char *)w;
    398 
    399     /* add back carry outs from top 16 bits to low 16 bits */
    400     sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
    401     sum += (sum >> 16);                     /* add carry */
    402     answer = ~sum;                          /* truncate to 16 bits */
    403     return answer;
    404420}
    405421
     
    430446            /* Always calculate checksum for icmp packets */
    431447            outicmp->icmp_cksum = 0;
    432             outicmp->icmp_cksum = in_cksum((uint16_t *)outicmp,
     448            outicmp->icmp_cksum = inet_cksum((uint16_t *)outicmp,
    433449                        packlen - (sizeof(*outip) + optlen));
    434450            if (outicmp->icmp_cksum == 0)
     
    483499            out = outdata;
    484500            len -= sizeof(*outudp);
    485             set_nport(dest_lsa, htons(port + seq));
     501            set_nport(&dest_lsa->u.sa, htons(port + seq));
    486502        }
    487503    }
     
    686702
    687703        read_len -= sizeof(struct icmp6_hdr);
    688         for (i = 0; i < read_len ; i++) {
     704        for (i = 0; i < read_len; i++) {
    689705            if (i % 16 == 0)
    690706                printf("%04x:", i);
     
    752768#endif
    753769        {
    754             read_len -= ((struct ip*)recv_pkt)->ip_hl << 2;
     770            struct ip *ip4packet = (struct ip*)recv_pkt;
     771            read_len -= ip4packet->ip_hl << 2;
    755772        }
    756773        printf(" %d bytes to %s", read_len, ina);
     
    774791common_traceroute_main(int op, char **argv)
    775792{
    776     int i;
    777793    int minpacket;
    778794    int tos = 0;
     
    928944        if (lsrr > 0) {
    929945            unsigned char optlist[MAX_IPOPTLEN];
     946            unsigned size;
    930947
    931948            /* final hop */
     
    937954            /* loose source route option */
    938955            optlist[1] = IPOPT_LSRR;
    939             i = lsrr * sizeof(gwlist[0]);
    940             optlist[2] = i + 3;
     956            size = lsrr * sizeof(gwlist[0]);
     957            optlist[2] = size + 3;
    941958            /* pointer to LSRR addresses */
    942959            optlist[3] = IPOPT_MINOFF;
    943             memcpy(optlist + 4, gwlist, i);
     960            memcpy(optlist + 4, gwlist, size);
    944961
    945962            if (setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS,
    946                     (char *)optlist, i + sizeof(gwlist[0])) < 0) {
     963                    (char *)optlist, size + sizeof(gwlist[0])) < 0) {
    947964                bb_perror_msg_and_die("IP_OPTIONS");
    948965            }
     
    10181035        if (op & OPT_DEVICE)
    10191036            setsockopt_bindtodevice(probe_fd, device);
    1020         set_nport(dest_lsa, htons(1025));
     1037        set_nport(&dest_lsa->u.sa, htons(1025));
    10211038        /* dummy connect. makes kernel pick source IP (and port) */
    10221039        xconnect(probe_fd, &dest_lsa->u.sa, dest_lsa->len);
    1023         set_nport(dest_lsa, htons(port));
     1040        set_nport(&dest_lsa->u.sa, htons(port));
    10241041
    10251042        /* read IP and port */
     
    10311048
    10321049        /* bind our sockets to this IP (but not port) */
    1033         set_nport(source_lsa, 0);
     1050        set_nport(&source_lsa->u.sa, 0);
    10341051        xbind(sndsock, &source_lsa->u.sa, source_lsa->len);
    10351052        xbind(rcvsock, &source_lsa->u.sa, source_lsa->len);
     
    10581075        int gotlastaddr = 0; /* flags */
    10591076        int got_there = 0;
    1060         int first = 1;
    10611077
    10621078        printf("%2d", ttl);
     
    10651081            unsigned t1;
    10661082            unsigned t2;
     1083            int left_ms;
    10671084            struct ip *ip;
    10681085
    1069             if (!first && pausemsecs > 0)
     1086            fflush_all();
     1087            if (probe != 0 && pausemsecs > 0)
    10701088                usleep(pausemsecs * 1000);
    1071             fflush_all();
    1072 
    1073             t1 = monotonic_us();
     1089
    10741090            send_probe(++seq, ttl);
    1075 
    1076             first = 0;
    1077             while ((read_len = wait_for_reply(from_lsa, to)) != 0) {
    1078                 t2 = monotonic_us();
    1079                 i = packet_ok(read_len, from_lsa, to, seq);
     1091            t2 = t1 = monotonic_us();
     1092
     1093            left_ms = waittime * 1000;
     1094            while ((read_len = wait_for_reply(from_lsa, to, &t2, &left_ms)) != 0) {
     1095                int icmp_code;
     1096
     1097                /* Recv'ed a packet, or read error */
     1098                /* t2 = monotonic_us() - set by wait_for_reply */
     1099
     1100                if (read_len < 0)
     1101                    continue;
     1102                icmp_code = packet_ok(read_len, from_lsa, to, seq);
    10801103                /* Skip short packet */
    1081                 if (i == 0)
     1104                if (icmp_code == 0)
    10821105                    continue;
    10831106
     
    10981121
    10991122                /* time exceeded in transit */
    1100                 if (i == -1)
    1101                     break;
    1102                 i--;
    1103                 switch (i) {
     1123                if (icmp_code == -1)
     1124                    break;
     1125                icmp_code--;
     1126                switch (icmp_code) {
    11041127#if ENABLE_TRACEROUTE6
    11051128                case ICMP6_DST_UNREACH_NOPORT << 8:
     
    11741197                    break;
    11751198                default:
    1176                     printf(" !<%d>", i);
     1199                    printf(" !<%d>", icmp_code);
    11771200                    ++unreachable;
    11781201                    break;
    11791202                }
    11801203                break;
    1181             }
     1204            } /* while (wait and read a packet) */
     1205
    11821206            /* there was no packet at all? */
    11831207            if (read_len == 0)
    11841208                printf("  *");
    1185         }
     1209        } /* for (nprobes) */
     1210
    11861211        bb_putchar('\n');
    11871212        if (got_there
  • branches/3.2/mindi-busybox/networking/tunctl.c

    r2725 r3232  
    1010 * Licensed under GPLv2, see file LICENSE in this source tree.
    1111 */
     12
     13//usage:#define tunctl_trivial_usage
     14//usage:       "[-f device] ([-t name] | -d name)" IF_FEATURE_TUNCTL_UG(" [-u owner] [-g group] [-b]")
     15//usage:#define tunctl_full_usage "\n\n"
     16//usage:       "Create or delete tun interfaces\n"
     17//usage:     "\n    -f name     tun device (/dev/net/tun)"
     18//usage:     "\n    -t name     Create iface 'name'"
     19//usage:     "\n    -d name     Delete iface 'name'"
     20//usage:    IF_FEATURE_TUNCTL_UG(
     21//usage:     "\n    -u owner    Set iface owner"
     22//usage:     "\n    -g group    Set iface group"
     23//usage:     "\n    -b      Brief output"
     24//usage:    )
     25//usage:
     26//usage:#define tunctl_example_usage
     27//usage:       "# tunctl\n"
     28//usage:       "# tunctl -d tun0\n"
     29
    1230#include <netinet/in.h>
    1331#include <net/if.h>
  • branches/3.2/mindi-busybox/networking/udhcp/Config.src

    r2725 r3232  
    99    bool "udhcp server (udhcpd)"
    1010    default y
    11     depends on PLATFORM_LINUX
     11    select PLATFORM_LINUX
    1212    help
    1313      udhcpd is a DHCP server geared primarily toward embedded systems,
     
    4040      time a new lease has been accepted, thus eliminating the need
    4141      to send SIGUSR1 for the initial writing or updating. Any timed
    42       rewriting remains undisturbed
     42      rewriting remains undisturbed.
     43
     44config FEATURE_UDHCPD_BASE_IP_ON_MAC
     45    bool "Select IP address based on client MAC"
     46    default n
     47    depends on UDHCPD
     48    help
     49      If selected, udhcpd will base its selection of IP address to offer
     50      on the client's hardware address. Otherwise udhcpd uses the next
     51      consecutive free address.
     52
     53      This reduces the frequency of IP address changes for clients
     54      which let their lease expire, and makes consecutive DHCPOFFERS
     55      for the same client to (almost always) contain the same
     56      IP address.
    4357
    4458config DHCPD_LEASES_FILE
     
    5367    bool "udhcp client (udhcpc)"
    5468    default y
    55     depends on PLATFORM_LINUX
     69    select PLATFORM_LINUX
    5670    help
    5771      udhcpc is a DHCP client geared primarily toward embedded systems,
     
    7387config FEATURE_UDHCP_PORT
    7488    bool "Enable '-P port' option for udhcpd and udhcpc"
    75     default y
     89    default n
    7690    depends on UDHCPD || UDHCPC
    7791    help
     
    99113      search lists via option 119, specified in RFC 3397,
    100114      and SIP servers option 120, specified in RFC 3361.
     115
     116config FEATURE_UDHCP_8021Q
     117    bool "Support for 802.1Q VLAN parameters"
     118    default y
     119    depends on UDHCPD || UDHCPC
     120    help
     121      If selected, both client and server will support passing of VLAN
     122      ID and priority via options 132 and 133 as per 802.1Q.
    101123
    102124config UDHCPC_DEFAULT_SCRIPT
  • branches/3.2/mindi-busybox/networking/udhcp/arpping.c

    r2725 r3232  
    119119            }
    120120        }
    121         timeout_ms -= (unsigned)monotonic_ms() - prevTime;
    122     } while (timeout_ms > 0);
     121        timeout_ms -= (unsigned)monotonic_ms() - prevTime + 1;
     122
     123        /* We used to check "timeout_ms > 0", but
     124         * this is more under/overflow-resistant
     125         * (people did see overflows here when system time jumps):
     126         */
     127    } while ((unsigned)timeout_ms <= 2000);
    123128
    124129 ret:
  • branches/3.2/mindi-busybox/networking/udhcp/common.c

    r2725 r3232  
    3030//  { OPTION_IP | OPTION_LIST                 , 0x08 }, /* DHCP_COOKIE_SERVER */
    3131    { OPTION_IP | OPTION_LIST                 , 0x09 }, /* DHCP_LPR_SERVER    */
    32     { OPTION_STRING               | OPTION_REQ, 0x0c }, /* DHCP_HOST_NAME     */
     32    { OPTION_STRING_HOST          | OPTION_REQ, 0x0c }, /* DHCP_HOST_NAME     */
    3333    { OPTION_U16                              , 0x0d }, /* DHCP_BOOT_SIZE     */
    34     { OPTION_STRING               | OPTION_REQ, 0x0f }, /* DHCP_DOMAIN_NAME   */
     34    { OPTION_STRING_HOST          | OPTION_REQ, 0x0f }, /* DHCP_DOMAIN_NAME   */
    3535    { OPTION_IP                               , 0x10 }, /* DHCP_SWAP_SERVER   */
    3636    { OPTION_STRING                           , 0x11 }, /* DHCP_ROOT_PATH     */
    3737    { OPTION_U8                               , 0x17 }, /* DHCP_IP_TTL        */
    3838    { OPTION_U16                              , 0x1a }, /* DHCP_MTU           */
     39//TODO: why do we request DHCP_BROADCAST? Can't we assume that
     40//in the unlikely case it is different from typical N.N.255.255,
     41//server would let us know anyway?
    3942    { OPTION_IP                   | OPTION_REQ, 0x1c }, /* DHCP_BROADCAST     */
    4043    { OPTION_IP_PAIR | OPTION_LIST            , 0x21 }, /* DHCP_ROUTES        */
    41     { OPTION_STRING                           , 0x28 }, /* DHCP_NIS_DOMAIN    */
     44    { OPTION_STRING_HOST                      , 0x28 }, /* DHCP_NIS_DOMAIN    */
    4245    { OPTION_IP | OPTION_LIST                 , 0x29 }, /* DHCP_NIS_SERVER    */
    4346    { OPTION_IP | OPTION_LIST     | OPTION_REQ, 0x2a }, /* DHCP_NTP_SERVER    */
     
    4750    { OPTION_STRING                           , 0x38 }, /* DHCP_ERR_MESSAGE   */
    4851//TODO: must be combined with 'sname' and 'file' handling:
    49     { OPTION_STRING                           , 0x42 }, /* DHCP_TFTP_SERVER_NAME */
     52    { OPTION_STRING_HOST                      , 0x42 }, /* DHCP_TFTP_SERVER_NAME */
    5053    { OPTION_STRING                           , 0x43 }, /* DHCP_BOOT_FILE     */
    5154//TODO: not a string, but a set of LASCII strings:
     
    5558    { OPTION_SIP_SERVERS                      , 0x78 }, /* DHCP_SIP_SERVERS   */
    5659#endif
    57     { OPTION_STATIC_ROUTES                    , 0x79 }, /* DHCP_STATIC_ROUTES */
    58     { OPTION_STATIC_ROUTES                    , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */
     60    { OPTION_STATIC_ROUTES | OPTION_LIST      , 0x79 }, /* DHCP_STATIC_ROUTES */
     61#if ENABLE_FEATURE_UDHCP_8021Q
     62    { OPTION_U16                              , 0x84 }, /* DHCP_VLAN_ID       */
     63    { OPTION_U8                               , 0x85 }, /* DHCP_VLAN_PRIORITY */
     64#endif
     65    { OPTION_6RD                              , 0xd4 }, /* DHCP_6RD           */
     66    { OPTION_STATIC_ROUTES | OPTION_LIST      , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */
    5967    { OPTION_STRING                           , 0xfc }, /* DHCP_WPAD          */
    6068
     
    116124    "sipsrv" "\0"      /* DHCP_SIP_SERVERS    */
    117125#endif
    118 // doesn't work in udhcpd.conf since OPTION_STATIC_ROUTES
    119 // is not handled yet by "string->option" conversion code:
    120126    "staticroutes" "\0"/* DHCP_STATIC_ROUTES  */
     127#if ENABLE_FEATURE_UDHCP_8021Q
     128    "vlanid" "\0"      /* DHCP_VLAN_ID        */
     129    "vlanpriority" "\0"/* DHCP_VLAN_PRIORITY  */
     130#endif
     131    "ip6rd" "\0"       /* DHCP_6RD            */
    121132    "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */
    122133    "wpad" "\0"        /* DHCP_WPAD           */
     
    136147//  [OPTION_BOOLEAN] = 1,
    137148    [OPTION_STRING] =  1,  /* ignored by udhcp_str2optset */
     149    [OPTION_STRING_HOST] = 1,  /* ignored by udhcp_str2optset */
    138150#if ENABLE_FEATURE_UDHCP_RFC3397
    139151    [OPTION_DNS_STRING] = 1,  /* ignored by both udhcp_str2optset and xmalloc_optname_optval */
     
    147159    /* Just like OPTION_STRING, we use minimum length here */
    148160    [OPTION_STATIC_ROUTES] = 5,
     161    [OPTION_6RD] =    22,  /* ignored by udhcp_str2optset */
    149162};
    150163
     
    324337    if (!lsa)
    325338        return 0;
    326     *(uint32_t*)arg = lsa->u.sin.sin_addr.s_addr;
     339    /* arg maybe unaligned */
     340    move_to_unaligned32((uint32_t*)arg, lsa->u.sin.sin_addr.s_addr);
    327341    free(lsa);
    328342    return 1;
     
    404418
    405419            existing->data = xrealloc(existing->data, OPT_DATA + 1 + old_len + length);
    406             if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING) {
     420            if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING
     421             || (optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING_HOST
     422            ) {
    407423                /* add space separator between STRING options in a list */
    408424                existing->data[OPT_DATA + old_len] = ' ';
     
    421437{
    422438    struct option_set **opt_list = arg;
    423     char *opt, *val, *endptr;
     439    char *opt, *val;
    424440    char *str;
    425441    const struct dhcp_optflag *optflag;
     
    427443    unsigned optcode;
    428444    int retval, length;
    429     char buffer[8] ALIGNED(4);
     445    /* IP_PAIR needs 8 bytes, STATIC_ROUTES needs 9 max */
     446    char buffer[9] ALIGNED(4);
    430447    uint16_t *result_u16 = (uint16_t *) buffer;
    431448    uint32_t *result_u32 = (uint32_t *) buffer;
     
    468485            break;
    469486        case OPTION_STRING:
     487        case OPTION_STRING_HOST:
    470488#if ENABLE_FEATURE_UDHCP_RFC3397
    471489        case OPTION_DNS_STRING:
     
    484502//      }
    485503        case OPTION_U8:
    486             buffer[0] = strtoul(val, &endptr, 0);
    487             retval = (endptr[0] == '\0');
     504            buffer[0] = bb_strtou32(val, NULL, 0);
     505            retval = (errno == 0);
    488506            break;
    489507        /* htonX are macros in older libc's, using temp var
     
    491509        /* TODO: use bb_strtoX? */
    492510        case OPTION_U16: {
    493             unsigned long tmp = strtoul(val, &endptr, 0);
     511            uint32_t tmp = bb_strtou32(val, NULL, 0);
    494512            *result_u16 = htons(tmp);
    495             retval = (endptr[0] == '\0' /*&& tmp < 0x10000*/);
     513            retval = (errno == 0 /*&& tmp < 0x10000*/);
    496514            break;
    497515        }
    498516//      case OPTION_S16: {
    499 //          long tmp = strtol(val, &endptr, 0);
     517//          long tmp = bb_strtoi32(val, NULL, 0);
    500518//          *result_u16 = htons(tmp);
    501 //          retval = (endptr[0] == '\0');
     519//          retval = (errno == 0);
    502520//          break;
    503521//      }
    504522        case OPTION_U32: {
    505             unsigned long tmp = strtoul(val, &endptr, 0);
     523            uint32_t tmp = bb_strtou32(val, NULL, 0);
    506524            *result_u32 = htonl(tmp);
    507             retval = (endptr[0] == '\0');
     525            retval = (errno == 0);
    508526            break;
    509527        }
    510528        case OPTION_S32: {
    511             long tmp = strtol(val, &endptr, 0);
     529            int32_t tmp = bb_strtoi32(val, NULL, 0);
    512530            *result_u32 = htonl(tmp);
    513             retval = (endptr[0] == '\0');
     531            retval = (errno == 0);
     532            break;
     533        }
     534        case OPTION_STATIC_ROUTES: {
     535            /* Input: "a.b.c.d/m" */
     536            /* Output: mask(1 byte),pfx(0-4 bytes),gw(4 bytes) */
     537            unsigned mask;
     538            char *slash = strchr(val, '/');
     539            if (slash) {
     540                *slash = '\0';
     541                retval = udhcp_str2nip(val, buffer + 1);
     542                buffer[0] = mask = bb_strtou(slash + 1, NULL, 10);
     543                val = strtok(NULL, ", \t/-");
     544                if (!val || mask > 32 || errno)
     545                    retval = 0;
     546                if (retval) {
     547                    length = ((mask + 7) >> 3) + 5;
     548                    retval = udhcp_str2nip(val, buffer + (length - 4));
     549                }
     550            }
    514551            break;
    515552        }
     
    522559        if (retval)
    523560            attach_option(opt_list, optflag, opt, length);
    524     } while (retval && optflag->flags & OPTION_LIST);
     561    } while (retval && (optflag->flags & OPTION_LIST));
    525562
    526563    return retval;
    527564}
     565
     566/* note: ip is a pointer to an IPv6 in network order, possibly misaliged */
     567int FAST_FUNC sprint_nip6(char *dest, /*const char *pre,*/ const uint8_t *ip)
     568{
     569    char hexstrbuf[16 * 2];
     570    bin2hex(hexstrbuf, (void*)ip, 16);
     571    return sprintf(dest, /* "%s" */
     572        "%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s",
     573        /* pre, */
     574        hexstrbuf + 0 * 4,
     575        hexstrbuf + 1 * 4,
     576        hexstrbuf + 2 * 4,
     577        hexstrbuf + 3 * 4,
     578        hexstrbuf + 4 * 4,
     579        hexstrbuf + 5 * 4,
     580        hexstrbuf + 6 * 4,
     581        hexstrbuf + 7 * 4
     582    );
     583}
  • branches/3.2/mindi-busybox/networking/udhcp/common.h

    r2725 r3232  
    1515PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
    1616
    17 extern const uint8_t MAC_BCAST_ADDR[6]; /* six all-ones */
     17extern const uint8_t MAC_BCAST_ADDR[6] ALIGN2; /* six all-ones */
    1818
    1919
     
    8181    OPTION_IP_PAIR,
    8282    OPTION_STRING,
     83    /* Opts of STRING_HOST type will be sanitized before they are passed
     84     * to udhcpc script's environment: */
     85    OPTION_STRING_HOST,
    8386//  OPTION_BOOLEAN,
    8487    OPTION_U8,
     
    8992    OPTION_BIN,
    9093    OPTION_STATIC_ROUTES,
     94    OPTION_6RD,
    9195#if ENABLE_FEATURE_UDHCP_RFC3397
    9296    OPTION_DNS_STRING,  /* RFC1035 compressed domain name list */
     
    104108 * http://www.iana.org/assignments/bootp-dhcp-parameters/
    105109 * Commented out options are handled by common option machinery,
    106  * uncommented ones have spacial cases (grep for them to see).
     110 * uncommented ones have special cases (grep for them to see).
    107111 */
    108112#define DHCP_PADDING            0x00
     
    146150//#define DHCP_SIP_SERVERS      0x78 /* RFC 3361. flag byte, then: 0: domain names, 1: IP addrs */
    147151//#define DHCP_STATIC_ROUTES    0x79 /* RFC 3442. (mask,ip,router) tuples */
     152#define DHCP_VLAN_ID            0x84 /* 802.1P VLAN ID */
     153#define DHCP_VLAN_PRIORITY      0x85 /* 802.1Q VLAN priority */
    148154//#define DHCP_MS_STATIC_ROUTES 0xf9 /* Microsoft's pre-RFC 3442 code for 0x79? */
    149155//#define DHCP_WPAD             0xfc /* MSIE's Web Proxy Autodiscovery Protocol */
     
    182188
    183189extern const struct dhcp_optflag dhcp_optflags[];
    184 extern const char dhcp_option_strings[];
    185 extern const uint8_t dhcp_option_lengths[];
     190extern const char dhcp_option_strings[] ALIGN1;
     191extern const uint8_t dhcp_option_lengths[] ALIGN1;
    186192
    187193unsigned FAST_FUNC udhcp_option_idx(const char *name);
     
    247253
    248254#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
     255# define IF_UDHCP_VERBOSE(...) __VA_ARGS__
    249256extern unsigned dhcp_verbose;
    250257# define log1(...) do { if (dhcp_verbose >= 1) bb_info_msg(__VA_ARGS__); } while (0)
     
    262269# endif
    263270#else
     271# define IF_UDHCP_VERBOSE(...)
    264272# define udhcp_dump_packet(...) ((void)0)
    265273# define log1(...) ((void)0)
     
    275283/* 2nd param is "struct option_set**" */
    276284int FAST_FUNC udhcp_str2optset(const char *str, void *arg);
    277 
    278 uint16_t udhcp_checksum(void *addr, int count) FAST_FUNC;
    279285
    280286void udhcp_init_header(struct dhcp_packet *packet, char type) FAST_FUNC;
     
    306312        const char *interface) FAST_FUNC;
    307313
     314/* note: ip is a pointer to an IPv6 in network order, possibly misaliged */
     315int sprint_nip6(char *dest, /*const char *pre,*/ const uint8_t *ip) FAST_FUNC;
     316
    308317POP_SAVED_FUNCTION_VISIBILITY
    309318
  • branches/3.2/mindi-busybox/networking/udhcp/dhcpc.c

    r2725 r3232  
    2626#include "dhcpc.h"
    2727
    28 #include <asm/types.h>
    29 #if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined(_NEWLIB_VERSION)
    30 # include <netpacket/packet.h>
    31 # include <net/ethernet.h>
    32 #else
    33 # include <linux/if_packet.h>
    34 # include <linux/if_ether.h>
     28#include <netinet/if_ether.h>
     29#include <linux/filter.h>
     30#include <linux/if_packet.h>
     31
     32/* "struct client_config_t client_config" is in bb_common_bufsiz1 */
     33
     34
     35#if ENABLE_LONG_OPTS
     36static const char udhcpc_longopts[] ALIGN1 =
     37    "clientid-none\0"  No_argument       "C"
     38    "vendorclass\0"    Required_argument "V"
     39    "hostname\0"       Required_argument "H"
     40    "fqdn\0"           Required_argument "F"
     41    "interface\0"      Required_argument "i"
     42    "now\0"            No_argument       "n"
     43    "pidfile\0"        Required_argument "p"
     44    "quit\0"           No_argument       "q"
     45    "release\0"        No_argument       "R"
     46    "request\0"        Required_argument "r"
     47    "script\0"         Required_argument "s"
     48    "timeout\0"        Required_argument "T"
     49    "retries\0"        Required_argument "t"
     50    "tryagain\0"       Required_argument "A"
     51    "syslog\0"         No_argument       "S"
     52    "request-option\0" Required_argument "O"
     53    "no-default-options\0" No_argument   "o"
     54    "foreground\0"     No_argument       "f"
     55    "background\0"     No_argument       "b"
     56    "broadcast\0"      No_argument       "B"
     57    IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument       "a")
     58    IF_FEATURE_UDHCP_PORT("client-port\0"   Required_argument "P")
     59    ;
    3560#endif
    36 #include <linux/filter.h>
    37 
    38 /* struct client_config_t client_config is in bb_common_bufsiz1 */
     61/* Must match getopt32 option string order */
     62enum {
     63    OPT_C = 1 << 0,
     64    OPT_V = 1 << 1,
     65    OPT_H = 1 << 2,
     66    OPT_h = 1 << 3,
     67    OPT_F = 1 << 4,
     68    OPT_i = 1 << 5,
     69    OPT_n = 1 << 6,
     70    OPT_p = 1 << 7,
     71    OPT_q = 1 << 8,
     72    OPT_R = 1 << 9,
     73    OPT_r = 1 << 10,
     74    OPT_s = 1 << 11,
     75    OPT_T = 1 << 12,
     76    OPT_t = 1 << 13,
     77    OPT_S = 1 << 14,
     78    OPT_A = 1 << 15,
     79    OPT_O = 1 << 16,
     80    OPT_o = 1 << 17,
     81    OPT_x = 1 << 18,
     82    OPT_f = 1 << 19,
     83    OPT_B = 1 << 20,
     84/* The rest has variable bit positions, need to be clever */
     85    OPTBIT_B = 20,
     86    USE_FOR_MMU(             OPTBIT_b,)
     87    IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
     88    IF_FEATURE_UDHCP_PORT(   OPTBIT_P,)
     89    USE_FOR_MMU(             OPT_b = 1 << OPTBIT_b,)
     90    IF_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,)
     91    IF_FEATURE_UDHCP_PORT(   OPT_P = 1 << OPTBIT_P,)
     92};
    3993
    4094
     
    46100    [OPTION_IP_PAIR         ] = sizeof("255.255.255.255 ") * 2,
    47101    [OPTION_STATIC_ROUTES   ] = sizeof("255.255.255.255/32 255.255.255.255 "),
     102    [OPTION_6RD             ] = sizeof("32 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 "),
    48103    [OPTION_STRING          ] = 1,
     104    [OPTION_STRING_HOST     ] = 1,
    49105#if ENABLE_FEATURE_UDHCP_RFC3397
    50106    [OPTION_DNS_STRING      ] = 1, /* unused */
     
    81137}
    82138
     139/* Check if a given label represents a valid DNS label
     140 * Return pointer to the first character after the label upon success,
     141 * NULL otherwise.
     142 * See RFC1035, 2.3.1
     143 */
     144/* We don't need to be particularly anal. For example, allowing _, hyphen
     145 * at the end, or leading and trailing dots would be ok, since it
     146 * can't be used for attacks. (Leading hyphen can be, if someone uses
     147 * cmd "$hostname"
     148 * in the script: then hostname may be treated as an option)
     149 */
     150static const char *valid_domain_label(const char *label)
     151{
     152    unsigned char ch;
     153    unsigned pos = 0;
     154
     155    for (;;) {
     156        ch = *label;
     157        if ((ch|0x20) < 'a' || (ch|0x20) > 'z') {
     158            if (pos == 0) {
     159                /* label must begin with letter */
     160                return NULL;
     161            }
     162            if (ch < '0' || ch > '9') {
     163                if (ch == '\0' || ch == '.')
     164                    return label;
     165                /* DNS allows only '-', but we are more permissive */
     166                if (ch != '-' && ch != '_')
     167                    return NULL;
     168            }
     169        }
     170        label++;
     171        pos++;
     172        //Do we want this?
     173        //if (pos > 63) /* NS_MAXLABEL; labels must be 63 chars or less */
     174        //  return NULL;
     175    }
     176}
     177
     178/* Check if a given name represents a valid DNS name */
     179/* See RFC1035, 2.3.1 */
     180static int good_hostname(const char *name)
     181{
     182    //const char *start = name;
     183
     184    for (;;) {
     185        name = valid_domain_label(name);
     186        if (!name)
     187            return 0;
     188        if (!name[0])
     189            return 1;
     190            //Do we want this?
     191            //return ((name - start) < 1025); /* NS_MAXDNAME */
     192        name++;
     193    }
     194}
     195
    83196/* Create "opt_name=opt_value" string */
    84197static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_optflag *optflag, const char *opt_name)
     
    88201    char *dest, *ret;
    89202
    90     /* option points to OPT_DATA, need to go back and get OPT_LEN */
    91     len = option[OPT_LEN - OPT_DATA];
     203    /* option points to OPT_DATA, need to go back to get OPT_LEN */
     204    len = option[-OPT_DATA + OPT_LEN];
    92205
    93206    type = optflag->flags & OPTION_TYPE_MASK;
    94207    optlen = dhcp_option_lengths[type];
    95     upper_length = len_of_option_as_string[type] * ((unsigned)len / (unsigned)optlen);
     208    upper_length = len_of_option_as_string[type]
     209        * ((unsigned)(len + optlen - 1) / (unsigned)optlen);
    96210
    97211    dest = ret = xmalloc(upper_length + strlen(opt_name) + 2);
     
    99213
    100214    while (len >= optlen) {
    101         unsigned ip_ofs = 0;
    102 
    103215        switch (type) {
     216        case OPTION_IP:
    104217        case OPTION_IP_PAIR:
    105218            dest += sprint_nip(dest, "", option);
    106             *dest++ = '/';
    107             ip_ofs = 4;
    108             /* fall through */
    109         case OPTION_IP:
    110             dest += sprint_nip(dest, "", option + ip_ofs);
     219            if (type == OPTION_IP)
     220                break;
     221            dest += sprint_nip(dest, "/", option + 4);
    111222            break;
    112223//      case OPTION_BOOLEAN:
     
    130241            break;
    131242        }
     243        /* Note: options which use 'return' instead of 'break'
     244         * (for example, OPTION_STRING) skip the code which handles
     245         * the case of list of options.
     246         */
    132247        case OPTION_STRING:
     248        case OPTION_STRING_HOST:
    133249            memcpy(dest, option, len);
    134250            dest[len] = '\0';
    135             return ret;  /* Short circuit this case */
     251            if (type == OPTION_STRING_HOST && !good_hostname(dest))
     252                safe_strncpy(dest, "bad", len);
     253            return ret;
    136254        case OPTION_STATIC_ROUTES: {
    137255            /* Option binary format:
     
    178296            return ret;
    179297        }
     298        case OPTION_6RD:
     299            /* Option binary format (see RFC 5969):
     300             *  0                   1                   2                   3
     301             *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     302             * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     303             * |  OPTION_6RD   | option-length |  IPv4MaskLen  |  6rdPrefixLen |
     304             * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     305             * |                           6rdPrefix                           |
     306             * ...                        (16 octets)                        ...
     307             * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     308             * ...                   6rdBRIPv4Address(es)                    ...
     309             * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     310             * We convert it to a string
     311             * "IPv4MaskLen 6rdPrefixLen 6rdPrefix 6rdBRIPv4Address..."
     312             *
     313             * Sanity check: ensure that our length is at least 22 bytes, that
     314             * IPv4MaskLen <= 32,
     315             * 6rdPrefixLen <= 128,
     316             * 6rdPrefixLen + (32 - IPv4MaskLen) <= 128
     317             * (2nd condition need no check - it follows from 1st and 3rd).
     318             * Else, return envvar with empty value ("optname=")
     319             */
     320            if (len >= (1 + 1 + 16 + 4)
     321             && option[0] <= 32
     322             && (option[1] + 32 - option[0]) <= 128
     323            ) {
     324                /* IPv4MaskLen */
     325                dest += sprintf(dest, "%u ", *option++);
     326                /* 6rdPrefixLen */
     327                dest += sprintf(dest, "%u ", *option++);
     328                /* 6rdPrefix */
     329                dest += sprint_nip6(dest, /* "", */ option);
     330                option += 16;
     331                len -= 1 + 1 + 16 + 4;
     332                /* "+ 4" above corresponds to the length of IPv4 addr
     333                 * we consume in the loop below */
     334                while (1) {
     335                    /* 6rdBRIPv4Address(es) */
     336                    dest += sprint_nip(dest, " ", option);
     337                    option += 4;
     338                    len -= 4; /* do we have yet another 4+ bytes? */
     339                    if (len < 0)
     340                        break; /* no */
     341                }
     342            }
     343
     344            return ret;
    180345#if ENABLE_FEATURE_UDHCP_RFC3397
    181346        case OPTION_DNS_STRING:
     
    217382#endif
    218383        } /* switch */
     384
     385        /* If we are here, try to format any remaining data
     386         * in the option as another, similarly-formatted option
     387         */
    219388        option += optlen;
    220389        len -= optlen;
     
    222391// Should we bail out/warn if we see multi-ip option which is
    223392// not allowed to be such (for example, DHCP_BROADCAST)? -
    224         if (len <= 0 /* || !(optflag->flags & OPTION_LIST) */)
     393        if (len < optlen /* || !(optflag->flags & OPTION_LIST) */)
    225394            break;
    226395        *dest++ = ' ';
    227396        *dest = '\0';
    228     }
     397    } /* while */
     398
    229399    return ret;
    230400}
     
    239409    uint8_t *temp;
    240410    uint8_t overload = 0;
     411
     412#define BITMAP unsigned
     413#define BBITS (sizeof(BITMAP) * 8)
     414#define BMASK(i) (1 << (i & (sizeof(BITMAP) * 8 - 1)))
     415#define FOUND_OPTS(i) (found_opts[(unsigned)i / BBITS])
     416    BITMAP found_opts[256 / BBITS];
     417
     418    memset(found_opts, 0, sizeof(found_opts));
    241419
    242420    /* We need 6 elements for:
     
    251429    /* +1 element for each option, +2 for subnet option: */
    252430    if (packet) {
    253         for (i = 0; dhcp_optflags[i].code; i++) {
    254             if (udhcp_get_option(packet, dhcp_optflags[i].code)) {
    255                 if (dhcp_optflags[i].code == DHCP_SUBNET)
    256                     envc++; /* for mton */
     431        /* note: do not search for "pad" (0) and "end" (255) options */
     432//TODO: change logic to scan packet _once_
     433        for (i = 1; i < 255; i++) {
     434            temp = udhcp_get_option(packet, i);
     435            if (temp) {
     436                if (i == DHCP_OPTION_OVERLOAD)
     437                    overload = *temp;
     438                else if (i == DHCP_SUBNET)
     439                    envc++; /* for $mask */
    257440                envc++;
     441                /*if (i != DHCP_MESSAGE_TYPE)*/
     442                FOUND_OPTS(i) |= BMASK(i);
    258443            }
    259444        }
    260         temp = udhcp_get_option(packet, DHCP_OPTION_OVERLOAD);
    261         if (temp)
    262             overload = *temp;
    263     }
    264     curr = envp = xzalloc(sizeof(char *) * envc);
     445    }
     446    curr = envp = xzalloc(sizeof(envp[0]) * envc);
    265447
    266448    *curr = xasprintf("interface=%s", client_config.interface);
     
    270452        return envp;
    271453
     454    /* Export BOOTP fields. Fields we don't (yet?) export:
     455     * uint8_t op;      // always BOOTREPLY
     456     * uint8_t htype;   // hardware address type. 1 = 10mb ethernet
     457     * uint8_t hlen;    // hardware address length
     458     * uint8_t hops;    // used by relay agents only
     459     * uint32_t xid;
     460     * uint16_t secs;   // elapsed since client began acquisition/renewal
     461     * uint16_t flags;  // only one flag so far: bcast. Never set by server
     462     * uint32_t ciaddr; // client IP (usually == yiaddr. can it be different
     463     *                  // if during renew server wants to give us differn IP?)
     464     * uint32_t gateway_nip; // relay agent IP address
     465     * uint8_t chaddr[16]; // link-layer client hardware address (MAC)
     466     * TODO: export gateway_nip as $giaddr?
     467     */
     468    /* Most important one: yiaddr as $ip */
    272469    *curr = xmalloc(sizeof("ip=255.255.255.255"));
    273470    sprint_nip(*curr, "ip=", (uint8_t *) &packet->yiaddr);
    274471    putenv(*curr++);
    275 
    276     opt_name = dhcp_option_strings;
    277     i = 0;
    278     while (*opt_name) {
    279         temp = udhcp_get_option(packet, dhcp_optflags[i].code);
    280         if (!temp)
    281             goto next;
    282         *curr = xmalloc_optname_optval(temp, &dhcp_optflags[i], opt_name);
    283         putenv(*curr++);
    284         if (dhcp_optflags[i].code == DHCP_SUBNET) {
    285             /* Subnet option: make things like "$ip/$mask" possible */
    286             uint32_t subnet;
    287             move_from_unaligned32(subnet, temp);
    288             *curr = xasprintf("mask=%d", mton(subnet));
    289             putenv(*curr++);
    290         }
    291  next:
    292         opt_name += strlen(opt_name) + 1;
    293         i++;
    294     }
    295472    if (packet->siaddr_nip) {
     473        /* IP address of next server to use in bootstrap */
    296474        *curr = xmalloc(sizeof("siaddr=255.255.255.255"));
    297475        sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip);
     
    308486        putenv(*curr++);
    309487    }
     488
     489    /* Export known DHCP options */
     490    opt_name = dhcp_option_strings;
     491    i = 0;
     492    while (*opt_name) {
     493        uint8_t code = dhcp_optflags[i].code;
     494        BITMAP *found_ptr = &FOUND_OPTS(code);
     495        BITMAP found_mask = BMASK(code);
     496        if (!(*found_ptr & found_mask))
     497            goto next;
     498        *found_ptr &= ~found_mask; /* leave only unknown options */
     499        temp = udhcp_get_option(packet, code);
     500        *curr = xmalloc_optname_optval(temp, &dhcp_optflags[i], opt_name);
     501        putenv(*curr++);
     502        if (code == DHCP_SUBNET) {
     503            /* Subnet option: make things like "$ip/$mask" possible */
     504            uint32_t subnet;
     505            move_from_unaligned32(subnet, temp);
     506            *curr = xasprintf("mask=%u", mton(subnet));
     507            putenv(*curr++);
     508        }
     509 next:
     510        opt_name += strlen(opt_name) + 1;
     511        i++;
     512    }
     513    /* Export unknown options */
     514    for (i = 0; i < 256;) {
     515        BITMAP bitmap = FOUND_OPTS(i);
     516        if (!bitmap) {
     517            i += BBITS;
     518            continue;
     519        }
     520        if (bitmap & BMASK(i)) {
     521            unsigned len, ofs;
     522
     523            temp = udhcp_get_option(packet, i);
     524            /* udhcp_get_option returns ptr to data portion,
     525             * need to go back to get len
     526             */
     527            len = temp[-OPT_DATA + OPT_LEN];
     528            *curr = xmalloc(sizeof("optNNN=") + 1 + len*2);
     529            ofs = sprintf(*curr, "opt%u=", i);
     530            *bin2hex(*curr + ofs, (void*) temp, len) = '\0';
     531            putenv(*curr++);
     532        }
     533        i++;
     534    }
     535
    310536    return envp;
    311537}
     
    316542    char **envp, **curr;
    317543    char *argv[3];
    318 
    319     if (client_config.script == NULL)
    320         return;
    321544
    322545    envp = fill_envp(packet);
     
    347570static void init_packet(struct dhcp_packet *packet, char type)
    348571{
     572    uint16_t secs;
     573
    349574    /* Fill in: op, htype, hlen, cookie fields; message type option: */
    350575    udhcp_init_header(packet, type);
    351576
    352577    packet->xid = random_xid();
     578
     579    client_config.last_secs = monotonic_sec();
     580    if (client_config.first_secs == 0)
     581        client_config.first_secs = client_config.last_secs;
     582    secs = client_config.last_secs - client_config.first_secs;
     583    packet->secs = htons(secs);
    353584
    354585    memcpy(packet->chaddr, client_config.client_mac, 6);
     
    359590static void add_client_options(struct dhcp_packet *packet)
    360591{
    361     uint8_t c;
    362592    int i, end, len;
    363593
     
    369599    end = udhcp_end_option(packet->options);
    370600    len = 0;
    371     for (i = 0; (c = dhcp_optflags[i].code) != 0; i++) {
    372         if ((   (dhcp_optflags[i].flags & OPTION_REQ)
    373              && !client_config.no_default_options
    374             )
    375          || (client_config.opt_mask[c >> 3] & (1 << (c & 7)))
    376         ) {
    377             packet->options[end + OPT_DATA + len] = c;
     601    for (i = 1; i < DHCP_END; i++) {
     602        if (client_config.opt_mask[i >> 3] & (1 << (i & 7))) {
     603            packet->options[end + OPT_DATA + len] = i;
    378604            len++;
    379605        }
     
    392618        udhcp_add_binary_option(packet, client_config.fqdn);
    393619
     620    /* Request broadcast replies if we have no IP addr */
     621    if ((option_mask32 & OPT_B) && packet->ciaddr == 0)
     622        packet->flags |= htons(BROADCAST_FLAG);
     623
    394624    /* Add -x options if any */
    395625    {
     
    404634//          strncpy((char*)packet->file, client_config.boot_file, sizeof(packet->file) - 1);
    405635    }
     636
     637    // This will be needed if we remove -V VENDOR_STR in favor of
     638    // -x vendor:VENDOR_STR
     639    //if (!udhcp_find_option(packet.options, DHCP_VENDOR))
     640    //  /* not set, set the default vendor ID */
     641    //  ...add (DHCP_VENDOR, "udhcp "BB_VER) opt...
    406642}
    407643
     
    548784/* Broadcast a DHCP decline message */
    549785/* NOINLINE: limit stack usage in caller */
    550 static NOINLINE int send_decline(uint32_t xid, uint32_t server, uint32_t requested)
     786static NOINLINE int send_decline(/*uint32_t xid,*/ uint32_t server, uint32_t requested)
    551787{
    552788    struct dhcp_packet packet;
     
    557793    init_packet(&packet, DHCPDECLINE);
    558794
     795#if 0
    559796    /* RFC 2131 says DHCPDECLINE's xid is randomly selected by client,
    560797     * but in case the server is buggy and wants DHCPDECLINE's xid
     
    563800     */
    564801    packet.xid = xid;
     802#endif
    565803    /* DHCPDECLINE uses "requested ip", not ciaddr, to store offered IP */
    566804    udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested);
     
    599837    struct ip_udp_dhcp_packet packet;
    600838    uint16_t check;
    601 
    602     memset(&packet, 0, sizeof(packet));
    603     bytes = safe_read(fd, &packet, sizeof(packet));
    604     if (bytes < 0) {
    605         log1("Packet read error, ignoring");
    606         /* NB: possible down interface, etc. Caller should pause. */
    607         return bytes; /* returns -1 */
     839    unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
     840    struct iovec iov;
     841    struct msghdr msg;
     842    struct cmsghdr *cmsg;
     843
     844    /* used to use just safe_read(fd, &packet, sizeof(packet))
     845     * but we need to check for TP_STATUS_CSUMNOTREADY :(
     846     */
     847    iov.iov_base = &packet;
     848    iov.iov_len = sizeof(packet);
     849    memset(&msg, 0, sizeof(msg));
     850    msg.msg_iov = &iov;
     851    msg.msg_iovlen = 1;
     852    msg.msg_control = cmsgbuf;
     853    msg.msg_controllen = sizeof(cmsgbuf);
     854    for (;;) {
     855        bytes = recvmsg(fd, &msg, 0);
     856        if (bytes < 0) {
     857            if (errno == EINTR)
     858                continue;
     859            log1("Packet read error, ignoring");
     860            /* NB: possible down interface, etc. Caller should pause. */
     861            return bytes; /* returns -1 */
     862        }
     863        break;
    608864    }
    609865
     
    623879
    624880    /* make sure its the right packet for us, and that it passes sanity checks */
    625     if (packet.ip.protocol != IPPROTO_UDP || packet.ip.version != IPVERSION
     881    if (packet.ip.protocol != IPPROTO_UDP
     882     || packet.ip.version != IPVERSION
    626883     || packet.ip.ihl != (sizeof(packet.ip) >> 2)
    627884     || packet.udp.dest != htons(CLIENT_PORT)
     
    636893    check = packet.ip.check;
    637894    packet.ip.check = 0;
    638     if (check != udhcp_checksum(&packet.ip, sizeof(packet.ip))) {
     895    if (check != inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip))) {
    639896        log1("Bad IP header checksum, ignoring");
    640897        return -2;
     898    }
     899
     900    for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
     901        if (cmsg->cmsg_level == SOL_PACKET
     902         && cmsg->cmsg_type == PACKET_AUXDATA
     903        ) {
     904            /* some VMs don't checksum UDP and TCP data
     905             * they send to the same physical machine,
     906             * here we detect this case:
     907             */
     908            struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg);
     909            if (aux->tp_status & TP_STATUS_CSUMNOTREADY)
     910                goto skip_udp_sum_check;
     911        }
    641912    }
    642913
     
    647918    check = packet.udp.check;
    648919    packet.udp.check = 0;
    649     if (check && check != udhcp_checksum(&packet, bytes)) {
     920    if (check && check != inet_cksum((uint16_t *)&packet, bytes)) {
    650921        log1("Packet with bad UDP checksum received, ignoring");
    651922        return -2;
    652923    }
    653 
    654     memcpy(dhcp_pkt, &packet.data, bytes - (sizeof(packet.ip) + sizeof(packet.udp)));
    655 
    656     if (dhcp_pkt->cookie != htonl(DHCP_MAGIC)) {
     924 skip_udp_sum_check:
     925
     926    if (packet.data.cookie != htonl(DHCP_MAGIC)) {
    657927        bb_info_msg("Packet with bad magic, ignoring");
    658928        return -2;
    659929    }
    660     log1("Got valid DHCP packet");
    661     udhcp_dump_packet(dhcp_pkt);
    662     return bytes - (sizeof(packet.ip) + sizeof(packet.udp));
     930
     931    log1("Received a packet");
     932    udhcp_dump_packet(&packet.data);
     933
     934    bytes -= sizeof(packet.ip) + sizeof(packet.udp);
     935    memcpy(dhcp_pkt, &packet.data, bytes);
     936    return bytes;
    663937}
    664938
     
    715989     * TODO: make conditional?
    716990     */
    717 #define SERVER_AND_CLIENT_PORTS  ((67 << 16) + 68)
    718991    static const struct sock_filter filter_instr[] = {
    719         /* check for udp */
     992        /* load 9th byte (protocol) */
    720993        BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 9),
    721         BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_UDP, 2, 0),     /* L5, L1, is UDP? */
    722         /* ugly check for arp on ethernet-like and IPv4 */
    723         BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 2),                      /* L1: */
    724         BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x08000604, 3, 4),      /* L3, L4 */
    725         /* skip IP header */
    726         BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0),                     /* L5: */
    727         /* check udp source and destination ports */
    728         BPF_STMT(BPF_LD|BPF_W|BPF_IND, 0),
    729         BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, SERVER_AND_CLIENT_PORTS, 0, 1), /* L3, L4 */
    730         /* returns */
    731         BPF_STMT(BPF_RET|BPF_K, 0x0fffffff ),                   /* L3: pass */
    732         BPF_STMT(BPF_RET|BPF_K, 0),                             /* L4: reject */
     994        /* jump to L1 if it is IPPROTO_UDP, else to L4 */
     995        BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_UDP, 0, 6),
     996        /* L1: load halfword from offset 6 (flags and frag offset) */
     997        BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 6),
     998        /* jump to L4 if any bits in frag offset field are set, else to L2 */
     999        BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x1fff, 4, 0),
     1000        /* L2: skip IP header (load index reg with header len) */
     1001        BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0),
     1002        /* load udp destination port from halfword[header_len + 2] */
     1003        BPF_STMT(BPF_LD|BPF_H|BPF_IND, 2),
     1004        /* jump to L3 if udp dport is CLIENT_PORT, else to L4 */
     1005        BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 68, 0, 1),
     1006        /* L3: accept packet */
     1007        BPF_STMT(BPF_RET|BPF_K, 0xffffffff),
     1008        /* L4: discard packet */
     1009        BPF_STMT(BPF_RET|BPF_K, 0),
    7331010    };
    7341011    static const struct sock_fprog filter_prog = {
     
    7411018
    7421019    fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
    743     log1("Got raw socket fd %d", fd); //log2?
    744 
    745     if (SERVER_PORT == 67 && CLIENT_PORT == 68) {
    746         /* Use only if standard ports are in use */
    747         /* Ignoring error (kernel may lack support for this) */
    748         if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog,
    749                 sizeof(filter_prog)) >= 0)
    750             log1("Attached filter to raw socket fd %d", fd); // log?
    751     }
     1020    log1("Got raw socket fd"); //log2?
    7521021
    7531022    sock.sll_family = AF_PACKET;
     
    7551024    sock.sll_ifindex = ifindex;
    7561025    xbind(fd, (struct sockaddr *) &sock, sizeof(sock));
     1026
     1027    if (CLIENT_PORT == 68) {
     1028        /* Use only if standard port is in use */
     1029        /* Ignoring error (kernel may lack support for this) */
     1030        if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog,
     1031                sizeof(filter_prog)) >= 0)
     1032            log1("Attached filter to raw socket fd"); // log?
     1033    }
     1034
     1035    if (setsockopt(fd, SOL_PACKET, PACKET_AUXDATA,
     1036            &const_int_1, sizeof(int)) < 0
     1037    ) {
     1038        if (errno != ENOPROTOOPT)
     1039            log1("Can't set PACKET_AUXDATA on raw socket");
     1040    }
     1041
    7571042    log1("Created raw socket");
    7581043
     
    7801065}
    7811066
     1067/* Called only on SIGUSR1 */
    7821068static void perform_renew(void)
    7831069{
     
    8021088}
    8031089
    804 static void perform_release(uint32_t requested_ip, uint32_t server_addr)
     1090static void perform_release(uint32_t server_addr, uint32_t requested_ip)
    8051091{
    8061092    char buffer[sizeof("255.255.255.255")];
     
    8501136//usage:#endif
    8511137//usage:#define udhcpc_trivial_usage
    852 //usage:       "[-fbnq"IF_UDHCP_VERBOSE("v")"oCR] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n"
    853 //usage:       "    [-H HOSTNAME] [-V VENDOR] [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]")
     1138//usage:       "[-fbnq"IF_UDHCP_VERBOSE("v")"oCRB] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n"
     1139//usage:       "    [-V VENDOR] [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]")
    8541140//usage:#define udhcpc_full_usage "\n"
    8551141//usage:    IF_LONG_OPTS(
     
    8571143//usage:     "\n    -p,--pidfile FILE   Create pidfile"
    8581144//usage:     "\n    -s,--script PROG    Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")"
     1145//usage:     "\n    -B,--broadcast      Request broadcast replies"
    8591146//usage:     "\n    -t,--retries N      Send up to N discover packets"
    8601147//usage:     "\n    -T,--timeout N      Pause between packets (default 3 seconds)"
     
    8831170//usage:     "\n                -x 0x3d:0100BEEFC0FFEE - option 61 (client id)"
    8841171//usage:     "\n    -F,--fqdn NAME      Ask server to update DNS mapping for NAME"
    885 //usage:     "\n    -H,-h,--hostname NAME   Send NAME as client hostname (default none)"
    8861172//usage:     "\n    -V,--vendorclass VENDOR Vendor identifier (default 'udhcp VERSION')"
    8871173//usage:     "\n    -C,--clientid-none  Don't send MAC as client identifier"
     
    8941180//usage:     "\n    -p FILE     Create pidfile"
    8951181//usage:     "\n    -s PROG     Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")"
     1182//usage:     "\n    -B      Request broadcast replies"
    8961183//usage:     "\n    -t N        Send up to N discover packets"
    8971184//usage:     "\n    -T N        Pause between packets (default 3 seconds)"
     
    9201207//usage:     "\n            -x 0x3d:0100BEEFC0FFEE - option 61 (client id)"
    9211208//usage:     "\n    -F NAME     Ask server to update DNS mapping for NAME"
    922 //usage:     "\n    -H,-h NAME  Send NAME as client hostname (default none)"
    9231209//usage:     "\n    -V VENDOR   Vendor identifier (default 'udhcp VERSION')"
    9241210//usage:     "\n    -C      Don't send MAC as client identifier"
     
    9271213//usage:    )
    9281214//usage:    )
     1215//usage:     "\nSignals:"
     1216//usage:     "\n    USR1    Renew lease"
     1217//usage:     "\n    USR2    Release lease"
     1218
    9291219
    9301220int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     
    9421232    uint32_t server_addr = server_addr; /* for compiler */
    9431233    uint32_t requested_ip = 0;
    944     uint32_t xid = 0;
    945     uint32_t lease_seconds = 0; /* can be given as 32-bit quantity */
     1234    uint32_t xid = xid; /* for compiler */
    9461235    int packet_num;
    9471236    int timeout; /* must be signed */
     
    9501239    int max_fd;
    9511240    int retval;
    952     struct timeval tv;
    953     struct dhcp_packet packet;
    9541241    fd_set rfds;
    955 
    956 #if ENABLE_LONG_OPTS
    957     static const char udhcpc_longopts[] ALIGN1 =
    958         "clientid-none\0"  No_argument       "C"
    959         "vendorclass\0"    Required_argument "V"
    960         "hostname\0"       Required_argument "H"
    961         "fqdn\0"           Required_argument "F"
    962         "interface\0"      Required_argument "i"
    963         "now\0"            No_argument       "n"
    964         "pidfile\0"        Required_argument "p"
    965         "quit\0"           No_argument       "q"
    966         "release\0"        No_argument       "R"
    967         "request\0"        Required_argument "r"
    968         "script\0"         Required_argument "s"
    969         "timeout\0"        Required_argument "T"
    970         "version\0"        No_argument       "v"
    971         "retries\0"        Required_argument "t"
    972         "tryagain\0"       Required_argument "A"
    973         "syslog\0"         No_argument       "S"
    974         "request-option\0" Required_argument "O"
    975         "no-default-options\0" No_argument   "o"
    976         "foreground\0"     No_argument       "f"
    977         "background\0"     No_argument       "b"
    978         IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument       "a")
    979         IF_FEATURE_UDHCP_PORT("client-port\0"   Required_argument "P")
    980         ;
    981 #endif
    982     enum {
    983         OPT_C = 1 << 0,
    984         OPT_V = 1 << 1,
    985         OPT_H = 1 << 2,
    986         OPT_h = 1 << 3,
    987         OPT_F = 1 << 4,
    988         OPT_i = 1 << 5,
    989         OPT_n = 1 << 6,
    990         OPT_p = 1 << 7,
    991         OPT_q = 1 << 8,
    992         OPT_R = 1 << 9,
    993         OPT_r = 1 << 10,
    994         OPT_s = 1 << 11,
    995         OPT_T = 1 << 12,
    996         OPT_t = 1 << 13,
    997         OPT_S = 1 << 14,
    998         OPT_A = 1 << 15,
    999         OPT_O = 1 << 16,
    1000         OPT_o = 1 << 17,
    1001         OPT_x = 1 << 18,
    1002         OPT_f = 1 << 19,
    1003 /* The rest has variable bit positions, need to be clever */
    1004         OPTBIT_f = 19,
    1005         USE_FOR_MMU(             OPTBIT_b,)
    1006         IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
    1007         IF_FEATURE_UDHCP_PORT(   OPTBIT_P,)
    1008         USE_FOR_MMU(             OPT_b = 1 << OPTBIT_b,)
    1009         IF_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,)
    1010         IF_FEATURE_UDHCP_PORT(   OPT_P = 1 << OPTBIT_P,)
    1011     };
    10121242
    10131243    /* Default options */
     
    10201250    /* Parse command line */
    10211251    /* O,x: list; -T,-t,-A take numeric param */
    1022     opt_complementary = "O::x::T+:t+:A+"
    1023 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
    1024         ":vv"
    1025 #endif
    1026         ;
     1252    opt_complementary = "O::x::T+:t+:A+" IF_UDHCP_VERBOSE(":vv") ;
    10271253    IF_LONG_OPTS(applet_long_options = udhcpc_longopts;)
    1028     opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:f"
     1254    opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:fB"
    10291255        USE_FOR_MMU("b")
    10301256        IF_FEATURE_UDHCPC_ARPING("a")
     
    10381264        , &list_x
    10391265        IF_FEATURE_UDHCP_PORT(, &str_P)
    1040 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
    1041         , &dhcp_verbose
    1042 #endif
    1043         );
    1044     if (opt & (OPT_h|OPT_H))
     1266        IF_UDHCP_VERBOSE(, &dhcp_verbose)
     1267    );
     1268    if (opt & (OPT_h|OPT_H)) {
     1269        //msg added 2011-11
     1270        bb_error_msg("option -h NAME is deprecated, use -x hostname:NAME");
    10451271        client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0);
     1272    }
    10461273    if (opt & OPT_F) {
    10471274        /* FQDN option format: [0x51][len][flags][0][0]<fqdn> */
     
    10671294    }
    10681295#endif
    1069     if (opt & OPT_o)
    1070         client_config.no_default_options = 1;
    10711296    while (list_O) {
    10721297        char *optstr = llist_pop(&list_O);
    1073         unsigned n = udhcp_option_idx(optstr);
    1074         n = dhcp_optflags[n].code;
     1298        unsigned n = bb_strtou(optstr, NULL, 0);
     1299        if (errno || n > 254) {
     1300            n = udhcp_option_idx(optstr);
     1301            n = dhcp_optflags[n].code;
     1302        }
    10751303        client_config.opt_mask[n >> 3] |= 1 << (n & 7);
     1304    }
     1305    if (!(opt & OPT_o)) {
     1306        unsigned i, n;
     1307        for (i = 0; (n = dhcp_optflags[i].code) != 0; i++) {
     1308            if (dhcp_optflags[i].flags & OPTION_REQ) {
     1309                client_config.opt_mask[n >> 3] |= 1 << (n & 7);
     1310            }
     1311        }
    10761312    }
    10771313    while (list_x) {
     
    11011337        memcpy(clientid_mac_ptr, client_config.client_mac, 6);
    11021338    }
    1103     if (str_V[0] != '\0')
     1339    if (str_V[0] != '\0') {
     1340        // can drop -V, str_V, client_config.vendorclass,
     1341        // but need to add "vendor" to the list of recognized
     1342        // string opts for this to work;
     1343        // and need to tweak add_client_options() too...
     1344        // ...so the question is, should we?
     1345        //bb_error_msg("option -V VENDOR is deprecated, use -x vendor:VENDOR");
    11041346        client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0);
     1347    }
     1348
    11051349#if !BB_MMU
    11061350    /* on NOMMU reexec (i.e., background) early */
     
    11401384     */
    11411385    for (;;) {
     1386        struct timeval tv;
     1387        struct dhcp_packet packet;
    11421388        /* silence "uninitialized!" warning */
    11431389        unsigned timestamp_before_wait = timestamp_before_wait;
     
    11591405        /* If we already timed out, fall through with retval = 0, else... */
    11601406        if ((int)tv.tv_sec > 0) {
     1407            log1("Waiting on select %u seconds", (int)tv.tv_sec);
    11611408            timestamp_before_wait = (unsigned)monotonic_sec();
    1162             log1("Waiting on select...");
    11631409            retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
    11641410            if (retval < 0) {
     
    11871433                    client_config.client_mac)
    11881434            ) {
    1189                 return 1; /* iface is gone? */
     1435                goto ret0; /* iface is gone? */
    11901436            }
    11911437            if (clientid_mac_ptr)
     
    11971443            switch (state) {
    11981444            case INIT_SELECTING:
    1199                 if (packet_num < discover_retries) {
     1445                if (!discover_retries || packet_num < discover_retries) {
    12001446                    if (packet_num == 0)
    12011447                        xid = random_xid();
     
    12261472                continue;
    12271473            case REQUESTING:
    1228                 if (packet_num < discover_retries) {
     1474                if (!discover_retries || packet_num < discover_retries) {
    12291475                    /* send broadcast select packet */
    12301476                    send_select(xid, server_addr, requested_ip);
     
    12431489                /* 1/2 lease passed, enter renewing state */
    12441490                state = RENEWING;
     1491                client_config.first_secs = 0; /* make secs field count from 0 */
    12451492                change_listen_mode(LISTEN_KERNEL);
    12461493                log1("Entering renew state");
     
    12821529                udhcp_run_script(NULL, "deconfig");
    12831530                state = INIT_SELECTING;
     1531                client_config.first_secs = 0; /* make secs field count from 0 */
    12841532                /*timeout = 0; - already is */
    12851533                packet_num = 0;
     
    12981546        switch (udhcp_sp_read(&rfds)) {
    12991547        case SIGUSR1:
     1548            client_config.first_secs = 0; /* make secs field count from 0 */
     1549            already_waited_sec = 0;
    13001550            perform_renew();
    1301             if (state == RENEW_REQUESTED)
     1551            if (state == RENEW_REQUESTED) {
     1552                /* We might be either on the same network
     1553                 * (in which case renew might work),
     1554                 * or we might be on a completely different one
     1555                 * (in which case renew won't ever succeed).
     1556                 * For the second case, must make sure timeout
     1557                 * is not too big, or else we can send
     1558                 * futile renew requests for hours.
     1559                 * (Ab)use -A TIMEOUT value (usually 20 sec)
     1560                 * as a cap on the timeout.
     1561                 */
     1562                if (timeout > tryagain_timeout)
     1563                    timeout = tryagain_timeout;
    13021564                goto case_RENEW_REQUESTED;
     1565            }
    13031566            /* Start things over */
    13041567            packet_num = 0;
     
    13071570            continue;
    13081571        case SIGUSR2:
    1309             perform_release(requested_ip, server_addr);
     1572            perform_release(server_addr, requested_ip);
    13101573            timeout = INT_MAX;
    13111574            continue;
    13121575        case SIGTERM:
    13131576            bb_info_msg("Received SIGTERM");
    1314             if (opt & OPT_R) /* release on quit */
    1315                 perform_release(requested_ip, server_addr);
    13161577            goto ret0;
    13171578        }
     
    13661627        switch (state) {
    13671628        case INIT_SELECTING:
    1368             /* Must be a DHCPOFFER to one of our xid's */
     1629            /* Must be a DHCPOFFER */
    13691630            if (*message == DHCPOFFER) {
    1370         /* TODO: why we don't just fetch server's IP from IP header? */
     1631/* What exactly is server's IP? There are several values.
     1632 * Example DHCP offer captured with tchdump:
     1633 *
     1634 * 10.34.25.254:67 > 10.34.25.202:68 // IP header's src
     1635 * BOOTP fields:
     1636 * Your-IP 10.34.25.202
     1637 * Server-IP 10.34.32.125   // "next server" IP
     1638 * Gateway-IP 10.34.25.254  // relay's address (if DHCP relays are in use)
     1639 * DHCP options:
     1640 * DHCP-Message Option 53, length 1: Offer
     1641 * Server-ID Option 54, length 4: 10.34.255.7       // "server ID"
     1642 * Default-Gateway Option 3, length 4: 10.34.25.254 // router
     1643 *
     1644 * We think that real server IP (one to use in renew/release)
     1645 * is one in Server-ID option. But I am not 100% sure.
     1646 * IP header's src and Gateway-IP (same in this example)
     1647 * might work too.
     1648 * "Next server" and router are definitely wrong ones to use, though...
     1649 */
    13711650                temp = udhcp_get_option(&packet, DHCP_SERVER_ID);
    13721651                if (!temp) {
     
    13921671        case REBINDING:
    13931672            if (*message == DHCPACK) {
     1673                uint32_t lease_seconds;
     1674                struct in_addr temp_addr;
     1675
    13941676                temp = udhcp_get_option(&packet, DHCP_LEASE_TIME);
    13951677                if (!temp) {
     
    14001682                    move_from_unaligned32(lease_seconds, temp);
    14011683                    lease_seconds = ntohl(lease_seconds);
    1402                     lease_seconds &= 0x0fffffff; /* paranoia: must not be prone to overflows */
    1403                     if (lease_seconds < 10) /* and not too small */
    1404                         lease_seconds = 10;
     1684                    /* paranoia: must not be too small and not prone to overflows */
     1685                    if (lease_seconds < 0x10)
     1686                        lease_seconds = 0x10;
     1687                    if (lease_seconds >= 0x10000000)
     1688                        lease_seconds = 0x0fffffff;
    14051689                }
    14061690#if ENABLE_FEATURE_UDHCPC_ARPING
     
    14231707                        bb_info_msg("Offered address is in use "
    14241708                            "(got ARP reply), declining");
    1425                         send_decline(xid, server_addr, packet.yiaddr);
     1709                        send_decline(/*xid,*/ server_addr, packet.yiaddr);
    14261710
    14271711                        if (state != REQUESTING)
     
    14291713                        change_listen_mode(LISTEN_RAW);
    14301714                        state = INIT_SELECTING;
     1715                        client_config.first_secs = 0; /* make secs field count from 0 */
    14311716                        requested_ip = 0;
    14321717                        timeout = tryagain_timeout;
     
    14391724                /* enter bound state */
    14401725                timeout = lease_seconds / 2;
    1441                 {
    1442                     struct in_addr temp_addr;
    1443                     temp_addr.s_addr = packet.yiaddr;
    1444                     bb_info_msg("Lease of %s obtained, lease time %u",
    1445                         inet_ntoa(temp_addr), (unsigned)lease_seconds);
    1446                 }
     1726                temp_addr.s_addr = packet.yiaddr;
     1727                bb_info_msg("Lease of %s obtained, lease time %u",
     1728                    inet_ntoa(temp_addr), (unsigned)lease_seconds);
    14471729                requested_ip = packet.yiaddr;
    14481730                udhcp_run_script(&packet, state == REQUESTING ? "bound" : "renew");
     
    14511733                change_listen_mode(LISTEN_NONE);
    14521734                if (opt & OPT_q) { /* quit after lease */
    1453                     if (opt & OPT_R) /* release on quit */
    1454                         perform_release(requested_ip, server_addr);
    14551735                    goto ret0;
    14561736                }
     
    14641744                }
    14651745#endif
     1746                /* make future renew packets use different xid */
     1747                /* xid = random_xid(); ...but why bother? */
    14661748                already_waited_sec = 0;
    14671749                continue; /* back to main loop */
     
    14761758                sleep(3); /* avoid excessive network traffic */
    14771759                state = INIT_SELECTING;
     1760                client_config.first_secs = 0; /* make secs field count from 0 */
    14781761                requested_ip = 0;
    14791762                timeout = 0;
     
    14891772
    14901773 ret0:
     1774    if (opt & OPT_R) /* release on quit */
     1775        perform_release(server_addr, requested_ip);
    14911776    retval = 0;
    14921777 ret:
  • branches/3.2/mindi-busybox/networking/udhcp/dhcpc.h

    r2725 r3232  
    1010struct client_config_t {
    1111    uint8_t client_mac[6];          /* Our mac address */
    12     char no_default_options;        /* Do not include default options in request */
    1312    IF_FEATURE_UDHCP_PORT(uint16_t port;)
    1413    int ifindex;                    /* Index number of the interface to use */
     
    2221    uint8_t *hostname;              /* Optional hostname to use */
    2322    uint8_t *fqdn;                  /* Optional fully qualified domain name to use */
     23
     24    uint16_t first_secs;
     25    uint16_t last_secs;
    2426} FIX_ALIASING;
    2527
  • branches/3.2/mindi-busybox/networking/udhcp/dhcpd.c

    r2725 r3232  
    2121 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    2222 */
     23
     24//usage:#define udhcpd_trivial_usage
     25//usage:       "[-fS]" IF_FEATURE_UDHCP_PORT(" [-P N]") " [CONFFILE]"
     26//usage:#define udhcpd_full_usage "\n\n"
     27//usage:       "DHCP server\n"
     28//usage:     "\n    -f  Run in foreground"
     29//usage:     "\n    -S  Log to syslog too"
     30//usage:    IF_FEATURE_UDHCP_PORT(
     31//usage:     "\n    -P N    Use port N (default 67)"
     32//usage:    )
     33
    2334#include <syslog.h>
    2435#include "common.h"
     
    134145/* We got a DHCP DISCOVER. Send an OFFER. */
    135146/* NOINLINE: limit stack usage in caller */
    136 static NOINLINE void send_offer(struct dhcp_packet *oldpacket, uint32_t static_lease_nip, struct dyn_lease *lease)
     147static NOINLINE void send_offer(struct dhcp_packet *oldpacket,
     148        uint32_t static_lease_nip,
     149        struct dyn_lease *lease,
     150        uint8_t *requested_ip_opt)
    137151{
    138152    struct dhcp_packet packet;
     
    148162        /* We have no static lease for client's chaddr */
    149163        uint32_t req_nip;
    150         uint8_t *req_ip_opt;
    151164        const char *p_host_name;
    152165
     
    159172        }
    160173        /* Or: if client has requested an IP */
    161         else if ((req_ip_opt = udhcp_get_option(oldpacket, DHCP_REQUESTED_IP)) != NULL
     174        else if (requested_ip_opt != NULL
    162175         /* (read IP) */
    163          && (move_from_unaligned32(req_nip, req_ip_opt), 1)
     176         && (move_from_unaligned32(req_nip, requested_ip_opt), 1)
    164177         /* and the IP is in the lease range */
    165178         && ntohl(req_nip) >= server_config.start_ip
     
    284297int udhcpd_main(int argc UNUSED_PARAM, char **argv)
    285298{
    286     fd_set rfds;
    287299    int server_socket = -1, retval, max_sock;
    288     struct dhcp_packet packet;
    289300    uint8_t *state;
    290     uint32_t static_lease_nip;
    291301    unsigned timeout_end;
    292302    unsigned num_ips;
    293303    unsigned opt;
    294304    struct option_set *option;
    295     struct dyn_lease *lease, fake_lease;
    296305    IF_FEATURE_UDHCP_PORT(char *str_P;)
    297306
     
    306315    opt = getopt32(argv, "fSv"
    307316        IF_FEATURE_UDHCP_PORT("P:", &str_P)
    308 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
    309         , &dhcp_verbose
    310 #endif
     317        IF_UDHCP_VERBOSE(, &dhcp_verbose)
    311318        );
    312319    if (!(opt & 1)) { /* no -f */
     
    371378    udhcp_sp_setup();
    372379
     380 continue_with_autotime:
    373381    timeout_end = monotonic_sec() + server_config.auto_time;
    374382    while (1) { /* loop until universe collapses */
     383        fd_set rfds;
     384        struct dhcp_packet packet;
    375385        int bytes;
    376386        struct timeval tv;
    377387        uint8_t *server_id_opt;
    378         uint8_t *requested_opt;
     388        uint8_t *requested_ip_opt;
    379389        uint32_t requested_nip = requested_nip; /* for compiler */
     390        uint32_t static_lease_nip;
     391        struct dyn_lease *lease, fake_lease;
    380392
    381393        if (server_socket < 0) {
     
    396408        if (retval == 0) {
    397409            write_leases();
    398             timeout_end = monotonic_sec() + server_config.auto_time;
    399             continue;
     410            goto continue_with_autotime;
    400411        }
    401412        if (retval < 0 && errno != EINTR) {
     
    409420            write_leases();
    410421            /* why not just reset the timeout, eh */
    411             timeout_end = monotonic_sec() + server_config.auto_time;
    412             continue;
     422            goto continue_with_autotime;
    413423        case SIGTERM:
    414424            bb_info_msg("Received SIGTERM");
     425            write_leases();
    415426            goto ret0;
    416427        case 0: /* no signal: read a packet */
     
    442453            bb_error_msg("no or bad message type option, ignoring packet");
    443454            continue;
     455        }
     456
     457        /* Get SERVER_ID if present */
     458        server_id_opt = udhcp_get_option(&packet, DHCP_SERVER_ID);
     459        if (server_id_opt) {
     460            uint32_t server_id_network_order;
     461            move_from_unaligned32(server_id_network_order, server_id_opt);
     462            if (server_id_network_order != server_config.server_nip) {
     463                /* client talks to somebody else */
     464                log1("server ID doesn't match, ignoring");
     465                continue;
     466            }
    444467        }
    445468
     
    456479        }
    457480
    458         /* Get REQUESTED_IP and SERVER_ID if present */
    459         server_id_opt = udhcp_get_option(&packet, DHCP_SERVER_ID);
    460         if (server_id_opt) {
    461             uint32_t server_id_net;
    462             move_from_unaligned32(server_id_net, server_id_opt);
    463             if (server_id_net != server_config.server_nip) {
    464                 /* client talks to somebody else */
    465                 log1("server ID doesn't match, ignoring");
    466                 continue;
    467             }
    468         }
    469         requested_opt = udhcp_get_option(&packet, DHCP_REQUESTED_IP);
    470         if (requested_opt) {
    471             move_from_unaligned32(requested_nip, requested_opt);
     481        /* Get REQUESTED_IP if present */
     482        requested_ip_opt = udhcp_get_option(&packet, DHCP_REQUESTED_IP);
     483        if (requested_ip_opt) {
     484            move_from_unaligned32(requested_nip, requested_ip_opt);
    472485        }
    473486
     
    477490            log1("Received DISCOVER");
    478491
    479             send_offer(&packet, static_lease_nip, lease);
     492            send_offer(&packet, static_lease_nip, lease, requested_ip_opt);
    480493            break;
    481494
     
    568581   administrative authority to do so.
    569582*/
    570             if (!requested_opt) {
     583            if (!requested_ip_opt) {
    571584                requested_nip = packet.ciaddr;
    572585                if (requested_nip == 0) {
     
    581594                break;
    582595            }
    583             if (server_id_opt) {
    584                 /* client was talking specifically to us.
    585                  * "No, we don't have this IP for you". */
     596            /* No lease for this MAC, or lease IP != requested IP */
     597
     598            if (server_id_opt    /* client is in SELECTING state */
     599             || requested_ip_opt /* client is in INIT-REBOOT state */
     600            ) {
     601                /* "No, we don't have this IP for you" */
    586602                send_NAK(&packet);
    587             }
     603            } /* else: client is in RENEWING or REBINDING, do not answer */
     604
    588605            break;
    589606
     
    604621            log1("Received DECLINE");
    605622            if (server_id_opt
    606              && requested_opt
     623             && requested_ip_opt
    607624             && lease  /* chaddr matches this lease */
    608625             && requested_nip == lease->lease_nip
  • branches/3.2/mindi-busybox/networking/udhcp/dhcprelay.c

    r2725 r3232  
    1010 * Upstream has GPL v2 or later
    1111 */
     12
     13//usage:#define dhcprelay_trivial_usage
     14//usage:       "CLIENT_IFACE[,CLIENT_IFACE2]... SERVER_IFACE [SERVER_IP]"
     15//usage:#define dhcprelay_full_usage "\n\n"
     16//usage:       "Relay DHCP requests between clients and server"
     17
    1218#include "common.h"
    1319
     
    2632    struct sockaddr_in ip;
    2733    struct xid_item *next;
    28 };
     34} FIX_ALIASING;
    2935
    3036#define dhcprelay_xid_list (*(struct xid_item*)&bb_common_bufsiz1)
  • branches/3.2/mindi-busybox/networking/udhcp/dumpleases.c

    r2725 r3232  
    33 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    44 */
     5
     6//usage:#define dumpleases_trivial_usage
     7//usage:       "[-r|-a] [-f LEASEFILE]"
     8//usage:#define dumpleases_full_usage "\n\n"
     9//usage:       "Display DHCP leases granted by udhcpd\n"
     10//usage:    IF_LONG_OPTS(
     11//usage:     "\n    -f,--file=FILE  Lease file"
     12//usage:     "\n    -r,--remaining  Show remaining time"
     13//usage:     "\n    -a,--absolute   Show expiration time"
     14//usage:    )
     15//usage:    IF_NOT_LONG_OPTS(
     16//usage:     "\n    -f FILE Lease file"
     17//usage:     "\n    -r  Show remaining time"
     18//usage:     "\n    -a  Show expiration time"
     19//usage:    )
     20
    521#include "common.h"
    622#include "dhcpd.h"
     
    5874#if ENABLE_UNICODE_SUPPORT
    5975        {
    60             char *uni_name = unicode_conv_to_printable_fixedwidth(NULL, lease.hostname, 19);
     76            char *uni_name = unicode_conv_to_printable_fixedwidth(/*NULL,*/ lease.hostname, 19);
    6177            printf(" %-16s%s ", inet_ntoa(addr), uni_name);
    6278            free(uni_name);
  • branches/3.2/mindi-busybox/networking/udhcp/files.c

    r2725 r3232  
    8181    {"option"       , udhcp_str2optset, &server_config.options      , ""},
    8282    {"opt"          , udhcp_str2optset, &server_config.options      , ""},
    83     {"notify_file"  , read_str        , &server_config.notify_file  , ""},
    84     {"sname"        , read_str        , &server_config.sname        , ""},
    85     {"boot_file"    , read_str        , &server_config.boot_file    , ""},
     83    {"notify_file"  , read_str        , &server_config.notify_file  , NULL},
     84    {"sname"        , read_str        , &server_config.sname        , NULL},
     85    {"boot_file"    , read_str        , &server_config.boot_file    , NULL},
    8686    {"static_lease" , read_staticlease, &server_config.static_leases, ""},
    8787};
  • branches/3.2/mindi-busybox/networking/udhcp/leases.c

    r2725 r3232  
    138138    struct dyn_lease *oldest_lease = NULL;
    139139
    140     addr = server_config.start_ip; /* addr is in host order here */
    141     for (; addr <= server_config.end_ip; addr++) {
     140#if ENABLE_FEATURE_UDHCPD_BASE_IP_ON_MAC
     141    uint32_t stop;
     142    unsigned i, hash;
     143
     144    /* hash hwaddr: use the SDBM hashing algorithm.  Seems to give good
     145     * dispersal even with similarly-valued "strings".
     146     */
     147    hash = 0;
     148    for (i = 0; i < 6; i++)
     149        hash += safe_mac[i] + (hash << 6) + (hash << 16) - hash;
     150
     151    /* pick a seed based on hwaddr then iterate until we find a free address. */
     152    addr = server_config.start_ip
     153        + (hash % (1 + server_config.end_ip - server_config.start_ip));
     154    stop = addr;
     155#else
     156    addr = server_config.start_ip;
     157#define stop (server_config.end_ip + 1)
     158#endif
     159    do {
    142160        uint32_t nip;
    143161        struct dyn_lease *lease;
     
    145163        /* ie, 192.168.55.0 */
    146164        if ((addr & 0xff) == 0)
    147             continue;
     165            goto next_addr;
    148166        /* ie, 192.168.55.255 */
    149167        if ((addr & 0xff) == 0xff)
    150             continue;
     168            goto next_addr;
    151169        nip = htonl(addr);
     170        /* skip our own address */
     171        if (nip == server_config.server_nip)
     172            goto next_addr;
    152173        /* is this a static lease addr? */
    153174        if (is_nip_reserved(server_config.static_leases, nip))
    154             continue;
     175            goto next_addr;
    155176
    156177        lease = find_lease_by_nip(nip);
     
    163184                oldest_lease = lease;
    164185        }
    165     }
     186
     187 next_addr:
     188        addr++;
     189#if ENABLE_FEATURE_UDHCPD_BASE_IP_ON_MAC
     190        if (addr > server_config.end_ip)
     191            addr = server_config.start_ip;
     192#endif
     193    } while (addr != stop);
    166194
    167195    if (oldest_lease
  • branches/3.2/mindi-busybox/networking/udhcp/packet.c

    r2725 r3232  
    77 * Licensed under GPLv2, see file LICENSE in this source tree.
    88 */
    9 #include <netinet/in.h>
    10 #if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined _NEWLIB_VERSION
    11 # include <netpacket/packet.h>
    12 # include <net/ethernet.h>
    13 #else
    14 # include <asm/types.h>
    15 # include <linux/if_packet.h>
    16 # include <linux/if_ether.h>
    17 #endif
    18 
    199#include "common.h"
    2010#include "dhcpd.h"
     11#include <netinet/in.h>
     12#include <netinet/if_ether.h>
     13#include <netpacket/packet.h>
    2114
    2215void FAST_FUNC udhcp_init_header(struct dhcp_packet *packet, char type)
     
    8982{
    9083    int bytes;
    91     unsigned char *vendor;
    9284
    9385    memset(packet, 0, sizeof(*packet));
     
    9890    }
    9991
    100     if (packet->cookie != htonl(DHCP_MAGIC)) {
     92    if (bytes < offsetof(struct dhcp_packet, options)
     93     || packet->cookie != htonl(DHCP_MAGIC)
     94    ) {
    10195        bb_info_msg("Packet with bad magic, ignoring");
    10296        return -2;
     
    10599    udhcp_dump_packet(packet);
    106100
    107     if (packet->op == BOOTREQUEST) {
    108         vendor = udhcp_get_option(packet, DHCP_VENDOR);
    109         if (vendor) {
    110 #if 0
    111             static const char broken_vendors[][8] = {
    112                 "MSFT 98",
    113                 ""
    114             };
    115             int i;
    116             for (i = 0; broken_vendors[i][0]; i++) {
    117                 if (vendor[OPT_LEN - OPT_DATA] == (uint8_t)strlen(broken_vendors[i])
    118                  && strncmp((char*)vendor, broken_vendors[i], vendor[OPT_LEN - OPT_DATA]) == 0
    119                 ) {
    120                     log1("Broken client (%s), forcing broadcast replies",
    121                         broken_vendors[i]);
    122                     packet->flags |= htons(BROADCAST_FLAG);
    123                 }
    124             }
    125 #else
    126             if (vendor[OPT_LEN - OPT_DATA] == (uint8_t)(sizeof("MSFT 98")-1)
    127              && memcmp(vendor, "MSFT 98", sizeof("MSFT 98")-1) == 0
    128             ) {
    129                 log1("Broken client (%s), forcing broadcast replies", "MSFT 98");
    130                 packet->flags |= htons(BROADCAST_FLAG);
    131             }
    132 #endif
    133         }
    134     }
    135 
    136101    return bytes;
    137 }
    138 
    139 uint16_t FAST_FUNC udhcp_checksum(void *addr, int count)
    140 {
    141     /* Compute Internet Checksum for "count" bytes
    142      * beginning at location "addr".
    143      */
    144     int32_t sum = 0;
    145     uint16_t *source = (uint16_t *) addr;
    146 
    147     while (count > 1)  {
    148         /*  This is the inner loop */
    149         sum += *source++;
    150         count -= 2;
    151     }
    152 
    153     /*  Add left-over byte, if any */
    154     if (count > 0) {
    155         /* Make sure that the left-over byte is added correctly both
    156          * with little and big endian hosts */
    157         uint16_t tmp = 0;
    158         *(uint8_t*)&tmp = *(uint8_t*)source;
    159         sum += tmp;
    160     }
    161     /*  Fold 32-bit sum to 16 bits */
    162     while (sum >> 16)
    163         sum = (sum & 0xffff) + (sum >> 16);
    164 
    165     return ~sum;
    166102}
    167103
     
    220156    /* for UDP checksumming, ip.len is set to UDP packet len */
    221157    packet.ip.tot_len = packet.udp.len;
    222     packet.udp.check = udhcp_checksum(&packet, IP_UDP_DHCP_SIZE - padding);
     158    packet.udp.check = inet_cksum((uint16_t *)&packet,
     159            IP_UDP_DHCP_SIZE - padding);
    223160    /* but for sending, it is set to IP packet len */
    224161    packet.ip.tot_len = htons(IP_UDP_DHCP_SIZE - padding);
     
    226163    packet.ip.version = IPVERSION;
    227164    packet.ip.ttl = IPDEFTTL;
    228     packet.ip.check = udhcp_checksum(&packet.ip, sizeof(packet.ip));
     165    packet.ip.check = inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip));
    229166
    230167    udhcp_dump_packet(dhcp_pkt);
     
    246183        uint32_t dest_nip, int dest_port)
    247184{
    248     struct sockaddr_in client;
     185    struct sockaddr_in sa;
    249186    unsigned padding;
    250187    int fd;
     
    259196    setsockopt_reuseaddr(fd);
    260197
    261     memset(&client, 0, sizeof(client));
    262     client.sin_family = AF_INET;
    263     client.sin_port = htons(source_port);
    264     client.sin_addr.s_addr = source_nip;
    265     if (bind(fd, (struct sockaddr *)&client, sizeof(client)) == -1) {
     198    memset(&sa, 0, sizeof(sa));
     199    sa.sin_family = AF_INET;
     200    sa.sin_port = htons(source_port);
     201    sa.sin_addr.s_addr = source_nip;
     202    if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
    266203        msg = "bind(%s)";
    267204        goto ret_close;
    268205    }
    269206
    270     memset(&client, 0, sizeof(client));
    271     client.sin_family = AF_INET;
    272     client.sin_port = htons(dest_port);
    273     client.sin_addr.s_addr = dest_nip;
    274     if (connect(fd, (struct sockaddr *)&client, sizeof(client)) == -1) {
     207    memset(&sa, 0, sizeof(sa));
     208    sa.sin_family = AF_INET;
     209    sa.sin_port = htons(dest_port);
     210    sa.sin_addr.s_addr = dest_nip;
     211    if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
    275212        msg = "connect";
    276213        goto ret_close;
     
    278215
    279216    udhcp_dump_packet(dhcp_pkt);
    280 
    281217    padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(dhcp_pkt->options);
    282218    result = safe_write(fd, dhcp_pkt, DHCP_SIZE - padding);
  • branches/3.2/mindi-busybox/networking/udhcp/socket.c

    r2725 r3232  
    2323 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    2424 */
     25#include "common.h"
    2526#include <net/if.h>
    26 #if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined _NEWLIB_VERSION
    27 # include <netpacket/packet.h>
    28 # include <net/ethernet.h>
    29 #else
    30 # include <asm/types.h>
    31 # include <linux/if_packet.h>
    32 # include <linux/if_ether.h>
    33 #endif
    34 
    35 #include "common.h"
    3627
    3728int FAST_FUNC udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac)
    3829{
     30    /* char buffer instead of bona-fide struct avoids aliasing warning */
     31    char ifr_buf[sizeof(struct ifreq)];
     32    struct ifreq *const ifr = (void *)ifr_buf;
     33
    3934    int fd;
    40     struct ifreq ifr;
    4135    struct sockaddr_in *our_ip;
    4236
    43     memset(&ifr, 0, sizeof(ifr));
     37    memset(ifr, 0, sizeof(*ifr));
    4438    fd = xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    4539
    46     ifr.ifr_addr.sa_family = AF_INET;
    47     strncpy_IFNAMSIZ(ifr.ifr_name, interface);
     40    ifr->ifr_addr.sa_family = AF_INET;
     41    strncpy_IFNAMSIZ(ifr->ifr_name, interface);
    4842    if (nip) {
    49         if (ioctl_or_perror(fd, SIOCGIFADDR, &ifr,
     43        if (ioctl_or_perror(fd, SIOCGIFADDR, ifr,
    5044            "is interface %s up and configured?", interface)
    5145        ) {
     
    5347            return -1;
    5448        }
    55         our_ip = (struct sockaddr_in *) &ifr.ifr_addr;
     49        our_ip = (struct sockaddr_in *) &ifr->ifr_addr;
    5650        *nip = our_ip->sin_addr.s_addr;
    5751        log1("IP %s", inet_ntoa(our_ip->sin_addr));
     
    5953
    6054    if (ifindex) {
    61         if (ioctl_or_warn(fd, SIOCGIFINDEX, &ifr) != 0) {
     55        if (ioctl_or_warn(fd, SIOCGIFINDEX, ifr) != 0) {
    6256            close(fd);
    6357            return -1;
    6458        }
    65         log1("Adapter index %d", ifr.ifr_ifindex);
    66         *ifindex = ifr.ifr_ifindex;
     59        log1("Adapter index %d", ifr->ifr_ifindex);
     60        *ifindex = ifr->ifr_ifindex;
    6761    }
    6862
    6963    if (mac) {
    70         if (ioctl_or_warn(fd, SIOCGIFHWADDR, &ifr) != 0) {
     64        if (ioctl_or_warn(fd, SIOCGIFHWADDR, ifr) != 0) {
    7165            close(fd);
    7266            return -1;
    7367        }
    74         memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
     68        memcpy(mac, ifr->ifr_hwaddr.sa_data, 6);
    7569        log1("MAC %02x:%02x:%02x:%02x:%02x:%02x",
    7670            mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
     
    8781    int fd;
    8882    struct sockaddr_in addr;
     83    char *colon;
    8984
    9085    log1("Opening listen socket on *:%d %s", port, inf);
     
    9590        bb_perror_msg_and_die("SO_BROADCAST");
    9691
    97     /* NB: bug 1032 says this doesn't work on ethernet aliases (ethN:M) */
     92    /* SO_BINDTODEVICE doesn't work on ethernet aliases (ethN:M) */
     93    colon = strrchr(inf, ':');
     94    if (colon)
     95        *colon = '\0';
     96
    9897    if (setsockopt_bindtodevice(fd, inf))
    9998        xfunc_die(); /* warning is already printed */
     99
     100    if (colon)
     101        *colon = ':';
    100102
    101103    memset(&addr, 0, sizeof(addr));
  • branches/3.2/mindi-busybox/networking/vconfig.c

    r2725 r3232  
    99
    1010/* BB_AUDIT SUSv3 N/A */
     11
     12//usage:#define vconfig_trivial_usage
     13//usage:       "COMMAND [OPTIONS]"
     14//usage:#define vconfig_full_usage "\n\n"
     15//usage:       "Create and remove virtual ethernet devices\n"
     16//usage:     "\n    add     IFACE VLAN_ID"
     17//usage:     "\n    rem     VLAN_NAME"
     18//usage:     "\n    set_flag    IFACE 0|1 VLAN_QOS"
     19//usage:     "\n    set_egress_map  VLAN_NAME SKB_PRIO VLAN_QOS"
     20//usage:     "\n    set_ingress_map VLAN_NAME SKB_PRIO VLAN_QOS"
     21//usage:     "\n    set_name_type   NAME_TYPE"
    1122
    1223#include "libbb.h"
     
    5667static const char *xfind_str(const char *table, const char *str)
    5768{
    58     while (strcasecmp(str, table+1) != 0) {
     69    while (strcasecmp(str, table + 1) != 0) {
     70        if (!table[0])
     71            bb_show_usage();
    5972        table += table[0];
    60         if (!*table) {
    61             bb_show_usage();
    62         }
    6373    }
    6474    return table - 1;
     
    6777static const char cmds[] ALIGN1 = {
    6878    4, ADD_VLAN_CMD, 7,
    69     'a', 'd', 'd', 0,
     79    'a','d','d',0,
    7080    3, DEL_VLAN_CMD, 7,
    71     'r', 'e', 'm', 0,
     81    'r','e','m',0,
    7282    3, SET_VLAN_NAME_TYPE_CMD, 17,
    73     's', 'e', 't', '_',
    74     'n', 'a', 'm', 'e', '_',
    75     't', 'y', 'p', 'e', 0,
     83    's','e','t','_','n','a','m','e','_','t','y','p','e',0,
    7684    5, SET_VLAN_FLAG_CMD, 12,
    77     's', 'e', 't', '_',
    78     'f', 'l', 'a', 'g', 0,
     85    's','e','t','_','f','l','a','g',0,
    7986    5, SET_VLAN_EGRESS_PRIORITY_CMD, 18,
    80     's', 'e', 't', '_',
    81     'e', 'g', 'r', 'e', 's', 's', '_',
    82     'm', 'a', 'p', 0,
    83     5, SET_VLAN_INGRESS_PRIORITY_CMD, 16,
    84     's', 'e', 't', '_',
    85     'i', 'n', 'g', 'r', 'e', 's', 's', '_',
    86     'm', 'a', 'p', 0,
     87    's','e','t','_','e','g','r','e','s','s','_','m','a','p',0,
     88    5, SET_VLAN_INGRESS_PRIORITY_CMD, 0,
     89    's','e','t','_','i','n','g','r','e','s','s','_','m','a','p',0,
    8790};
    8891
    8992static const char name_types[] ALIGN1 = {
    9093    VLAN_NAME_TYPE_PLUS_VID, 16,
    91     'V', 'L', 'A', 'N',
    92     '_', 'P', 'L', 'U', 'S', '_', 'V', 'I', 'D',
    93     0,
     94    'V','L','A','N','_','P','L','U','S','_','V','I','D',0,
    9495    VLAN_NAME_TYPE_PLUS_VID_NO_PAD, 22,
    95     'V', 'L', 'A', 'N',
    96     '_', 'P', 'L', 'U', 'S', '_', 'V', 'I', 'D',
    97     '_', 'N', 'O', '_', 'P', 'A', 'D', 0,
     96    'V','L','A','N','_','P','L','U','S','_','V','I','D','_','N','O','_','P','A','D',0,
    9897    VLAN_NAME_TYPE_RAW_PLUS_VID, 15,
    99     'D', 'E', 'V',
    100     '_', 'P', 'L', 'U', 'S', '_', 'V', 'I', 'D',
    101     0,
    102     VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD, 20,
    103     'D', 'E', 'V',
    104     '_', 'P', 'L', 'U', 'S', '_', 'V', 'I', 'D',
    105     '_', 'N', 'O', '_', 'P', 'A', 'D', 0,
     98    'D','E','V','_','P','L','U','S','_','V','I','D',0,
     99    VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD, 0,
     100    'D','E','V','_','P','L','U','S','_','V','I','D','_','N','O','_','P','A','D',0,
    106101};
    107 
    108 static const char conf_file_name[] ALIGN1 = "/proc/net/vlan/config";
    109102
    110103int vconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     
    115108    int fd;
    116109
    117     if (argc < 3) {
    118         bb_show_usage();
    119     }
    120 
    121     /* Don't bother closing the filedes.  It will be closed on cleanup. */
    122     /* Will die if 802.1q is not present */
    123     xopen(conf_file_name, O_RDONLY);
    124 
    125110    memset(&ifr, 0, sizeof(ifr));
    126111
    127112    ++argv;
    128     p = xfind_str(cmds+2, *argv);
     113    if (!argv[0])
     114        bb_show_usage();
     115    p = xfind_str(cmds + 2, argv[0]);
    129116    ifr.cmd = *p;
    130     if (argc != p[-1]) {
     117    if (argc != p[-1])
    131118        bb_show_usage();
    132     }
    133119
    134     if (ifr.cmd == SET_VLAN_NAME_TYPE_CMD) { /* set_name_type */
    135         ifr.u.name_type = *xfind_str(name_types+1, argv[1]);
     120    if (ifr.cmd == SET_VLAN_NAME_TYPE_CMD) {
     121        /* set_name_type */
     122        ifr.u.name_type = *xfind_str(name_types + 1, argv[1]);
    136123    } else {
    137124        strncpy_IFNAMSIZ(ifr.device1, argv[1]);
     
    142129         * (unsigned) int members of a unions.  But because of the range checking,
    143130         * doing so wouldn't save that much space and would also make maintainence
    144          * more of a pain. */
    145         if (ifr.cmd == SET_VLAN_FLAG_CMD) { /* set_flag */
    146             ifr.u.flag = xatoul_range(p, 0, 1);
     131         * more of a pain.
     132         */
     133        if (ifr.cmd == SET_VLAN_FLAG_CMD) {
     134            /* set_flag */
     135            ifr.u.flag = xatou_range(p, 0, 1);
    147136            /* DM: in order to set reorder header, qos must be set */
    148             ifr.vlan_qos = xatoul_range(argv[3], 0, 7);
    149         } else if (ifr.cmd == ADD_VLAN_CMD) { /* add */
    150             ifr.u.VID = xatoul_range(p, 0, VLAN_GROUP_ARRAY_LEN-1);
    151         } else if (ifr.cmd != DEL_VLAN_CMD) { /* set_{egress|ingress}_map */
     137            ifr.vlan_qos = xatou_range(argv[3], 0, 7);
     138        } else if (ifr.cmd == ADD_VLAN_CMD) {
     139            /* add */
     140            ifr.u.VID = xatou_range(p, 0, VLAN_GROUP_ARRAY_LEN - 1);
     141        } else if (ifr.cmd != DEL_VLAN_CMD) {
     142            /* set_{egress|ingress}_map */
    152143            ifr.u.skb_priority = xatou(p);
    153             ifr.vlan_qos = xatoul_range(argv[3], 0, 7);
     144            ifr.vlan_qos = xatou_range(argv[3], 0, 7);
    154145        }
    155146    }
     
    157148    fd = xsocket(AF_INET, SOCK_STREAM, 0);
    158149    ioctl_or_perror_and_die(fd, SIOCSIFVLAN, &ifr,
    159                         "ioctl error for %s", *argv);
     150                        "ioctl error for %s", argv[0]);
    160151
    161152    return 0;
  • branches/3.2/mindi-busybox/networking/wget.c

    r2859 r3232  
    99 * Kuhn's copyrights are licensed GPLv2-or-later.  File as a whole remains GPLv2.
    1010 */
     11
     12//usage:#define wget_trivial_usage
     13//usage:    IF_FEATURE_WGET_LONG_OPTIONS(
     14//usage:       "[-c|--continue] [-s|--spider] [-q|--quiet] [-O|--output-document FILE]\n"
     15//usage:       "    [--header 'header: value'] [-Y|--proxy on/off] [-P DIR]\n"
     16/* Since we ignore these opts, we don't show them in --help */
     17/* //usage:    "    [--no-check-certificate] [--no-cache]" */
     18//usage:       "    [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
     19//usage:    )
     20//usage:    IF_NOT_FEATURE_WGET_LONG_OPTIONS(
     21//usage:       "[-csq] [-O FILE] [-Y on/off] [-P DIR] [-U AGENT]"
     22//usage:            IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
     23//usage:    )
     24//usage:#define wget_full_usage "\n\n"
     25//usage:       "Retrieve files via HTTP or FTP\n"
     26//usage:     "\n    -s  Spider mode - only check file existence"
     27//usage:     "\n    -c  Continue retrieval of aborted transfer"
     28//usage:     "\n    -q  Quiet"
     29//usage:     "\n    -P DIR  Save to DIR (default .)"
     30//usage:    IF_FEATURE_WGET_TIMEOUT(
     31//usage:     "\n    -T SEC  Network read timeout is SEC seconds"
     32//usage:    )
     33//usage:     "\n    -O FILE Save to FILE ('-' for stdout)"
     34//usage:     "\n    -U STR  Use STR for User-Agent header"
     35//usage:     "\n    -Y  Use proxy ('on' or 'off')"
     36
    1137#include "libbb.h"
    1238
     39#if 0
     40# define log_io(...) bb_error_msg(__VA_ARGS__)
     41#else
     42# define log_io(...) ((void)0)
     43#endif
     44
     45
    1346struct host_info {
    14     // May be used if we ever will want to free() all xstrdup()s...
    15     /* char *allocated; */
     47    char *allocated;
    1648    const char *path;
    1749    const char *user;
     
    3163    bb_progress_t pmt;
    3264#endif
     65        char *dir_prefix;
     66#if ENABLE_FEATURE_WGET_LONG_OPTIONS
     67        char *post_data;
     68        char *extra_headers;
     69#endif
     70        char *fname_out;        /* where to direct output (-O) */
     71        const char *proxy_flag; /* Use proxies if env vars are set */
     72        const char *user_agent; /* "User-Agent" header field */
    3373#if ENABLE_FEATURE_WGET_TIMEOUT
    3474    unsigned timeout_seconds;
    3575#endif
     76    int output_fd;
     77    int o_flags;
    3678    smallint chunked;         /* chunked transfer encoding */
    3779    smallint got_clen;        /* got content-length: from server  */
     80    /* Local downloads do benefit from big buffer.
     81     * With 512 byte buffer, it was measured to be
     82     * an order of magnitude slower than with big one.
     83     */
     84    uint64_t just_to_align_next_member;
     85    char wget_buf[CONFIG_FEATURE_COPYBUF_KB*1024];
    3886} FIX_ALIASING;
    39 #define G (*(struct globals*)&bb_common_bufsiz1)
    40 struct BUG_G_too_big {
    41     char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
    42 };
     87#define G (*ptr_to_globals)
    4388#define INIT_G() do { \
     89        SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
    4490    IF_FEATURE_WGET_TIMEOUT(G.timeout_seconds = 900;) \
    4591} while (0)
     
    74120
    75121    if (flag == PROGRESS_START)
    76         bb_progress_init(&G.pmt);
    77 
    78     bb_progress_update(&G.pmt, G.curfile, G.beg_range, G.transferred,
    79                G.chunked ? 0 : G.beg_range + G.transferred + G.content_len);
     122        bb_progress_init(&G.pmt, G.curfile);
     123
     124    bb_progress_update(&G.pmt,
     125            G.beg_range,
     126            G.transferred,
     127            (G.chunked || !G.got_clen) ? 0 : G.beg_range + G.transferred + G.content_len
     128    );
    80129
    81130    if (flag == PROGRESS_END) {
     131        bb_progress_free(&G.pmt);
    82132        bb_putchar_stderr('\n');
    83133        G.transferred = 0;
     
    125175}
    126176
    127 /* Read NMEMB bytes into PTR from STREAM.  Returns the number of bytes read,
    128  * and a short count if an eof or non-interrupt error is encountered.  */
    129 static size_t safe_fread(void *ptr, size_t nmemb, FILE *stream)
    130 {
    131     size_t ret;
    132     char *p = (char*)ptr;
    133 
    134     do {
    135         clearerr(stream);
    136         errno = 0;
    137         ret = fread(p, 1, nmemb, stream);
    138         p += ret;
    139         nmemb -= ret;
    140     } while (nmemb && ferror(stream) && errno == EINTR);
    141 
    142     return p - (char*)ptr;
    143 }
    144 
    145 /* Read a line or SIZE-1 bytes into S, whichever is less, from STREAM.
    146  * Returns S, or NULL if an eof or non-interrupt error is encountered.  */
    147 static char *safe_fgets(char *s, int size, FILE *stream)
    148 {
    149     char *ret;
    150 
    151     do {
    152         clearerr(stream);
    153         errno = 0;
    154         ret = fgets(s, size, stream);
    155     } while (ret == NULL && ferror(stream) && errno == EINTR);
    156 
    157     return ret;
    158 }
    159 
    160177#if ENABLE_FEATURE_WGET_AUTHENTICATION
    161 /* Base64-encode character string. buf is assumed to be char buf[512]. */
    162 static char *base64enc_512(char buf[512], const char *str)
     178/* Base64-encode character string. */
     179static char *base64enc(const char *str)
    163180{
    164181    unsigned len = strlen(str);
    165     if (len > 512/4*3 - 10) /* paranoia */
    166         len = 512/4*3 - 10;
    167     bb_uuencode(buf, str, len, bb_uuenc_tbl_base64);
    168     return buf;
     182    if (len > sizeof(G.wget_buf)/4*3 - 10) /* paranoia */
     183        len = sizeof(G.wget_buf)/4*3 - 10;
     184    bb_uuencode(G.wget_buf, str, len, bb_uuenc_tbl_base64);
     185    return G.wget_buf;
    169186}
    170187#endif
     
    187204    fp = fdopen(xconnect_stream(lsa), "r+");
    188205    if (fp == NULL)
    189         bb_perror_msg_and_die("fdopen");
     206        bb_perror_msg_and_die(bb_msg_memory_exhausted);
    190207
    191208    return fp;
    192209}
    193210
    194 static int ftpcmd(const char *s1, const char *s2, FILE *fp, char *buf)
     211/* Returns '\n' if it was seen, else '\0'. Trims at first '\r' or '\n' */
     212static char fgets_and_trim(FILE *fp)
     213{
     214    char c;
     215    char *buf_ptr;
     216
     217    if (fgets(G.wget_buf, sizeof(G.wget_buf) - 1, fp) == NULL)
     218        bb_perror_msg_and_die("error getting response");
     219
     220    buf_ptr = strchrnul(G.wget_buf, '\n');
     221    c = *buf_ptr;
     222    *buf_ptr = '\0';
     223    buf_ptr = strchrnul(G.wget_buf, '\r');
     224    *buf_ptr = '\0';
     225
     226    log_io("< %s", G.wget_buf);
     227
     228    return c;
     229}
     230
     231static int ftpcmd(const char *s1, const char *s2, FILE *fp)
    195232{
    196233    int result;
    197234    if (s1) {
    198         if (!s2) s2 = "";
     235        if (!s2)
     236            s2 = "";
    199237        fprintf(fp, "%s%s\r\n", s1, s2);
    200238        fflush(fp);
     239        log_io("> %s%s", s1, s2);
    201240    }
    202241
    203242    do {
    204         char *buf_ptr;
    205 
    206         if (fgets(buf, 510, fp) == NULL) {
    207             bb_perror_msg_and_die("error getting response");
    208         }
    209         buf_ptr = strstr(buf, "\r\n");
    210         if (buf_ptr) {
    211             *buf_ptr = '\0';
    212         }
    213     } while (!isdigit(buf[0]) || buf[3] != ' ');
    214 
    215     buf[3] = '\0';
    216     result = xatoi_positive(buf);
    217     buf[3] = ' ';
     243        fgets_and_trim(fp);
     244    } while (!isdigit(G.wget_buf[0]) || G.wget_buf[3] != ' ');
     245
     246    G.wget_buf[3] = '\0';
     247    result = xatoi_positive(G.wget_buf);
     248    G.wget_buf[3] = ' ';
    218249    return result;
    219250}
    220251
    221 static void parse_url(char *src_url, struct host_info *h)
     252static void parse_url(const char *src_url, struct host_info *h)
    222253{
    223254    char *url, *p, *sp;
    224255
    225     /* h->allocated = */ url = xstrdup(src_url);
     256    free(h->allocated);
     257    h->allocated = url = xstrdup(src_url);
    226258
    227259    if (strncmp(url, "http://", 7) == 0) {
     
    271303    sp = strrchr(h->host, '@');
    272304    if (sp != NULL) {
    273         h->user = h->host;
     305        // URL-decode "user:password" string before base64-encoding:
     306        // wget http://test:my%20pass@example.com should send
     307        // Authorization: Basic dGVzdDpteSBwYXNz
     308        // which decodes to "test:my pass".
     309        // Standard wget and curl do this too.
    274310        *sp = '\0';
     311        h->user = percent_decode_in_place(h->host, /*strict:*/ 0);
    275312        h->host = sp + 1;
    276313    }
     
    279316}
    280317
    281 static char *gethdr(char *buf, size_t bufsiz, FILE *fp /*, int *istrunc*/)
     318static char *gethdr(FILE *fp)
    282319{
    283320    char *s, *hdrval;
    284321    int c;
    285322
    286     /* *istrunc = 0; */
    287 
    288323    /* retrieve header line */
    289     if (fgets(buf, bufsiz, fp) == NULL)
     324    c = fgets_and_trim(fp);
     325
     326    /* end of the headers? */
     327    if (G.wget_buf[0] == '\0')
    290328        return NULL;
    291329
    292     /* see if we are at the end of the headers */
    293     for (s = buf; *s == '\r'; ++s)
    294         continue;
    295     if (*s == '\n')
    296         return NULL;
    297 
    298330    /* convert the header name to lower case */
    299     for (s = buf; isalnum(*s) || *s == '-' || *s == '.'; ++s) {
     331    for (s = G.wget_buf; isalnum(*s) || *s == '-' || *s == '.'; ++s) {
    300332        /* tolower for "A-Z", no-op for "0-9a-z-." */
    301         *s = (*s | 0x20);
     333        *s |= 0x20;
    302334    }
    303335
    304336    /* verify we are at the end of the header name */
    305337    if (*s != ':')
    306         bb_error_msg_and_die("bad header line: %s", sanitize_string(buf));
     338        bb_error_msg_and_die("bad header line: %s", sanitize_string(G.wget_buf));
    307339
    308340    /* locate the start of the header value */
     
    310342    hdrval = skip_whitespace(s);
    311343
    312     /* locate the end of header */
    313     while (*s && *s != '\r' && *s != '\n')
    314         ++s;
    315 
    316     /* end of header found */
    317     if (*s) {
    318         *s = '\0';
    319         return hdrval;
    320     }
    321 
    322     /* Rats! The buffer isn't big enough to hold the entire header value */
    323     while (c = getc(fp), c != EOF && c != '\n')
    324         continue;
    325     /* *istrunc = 1; */
     344    if (c != '\n') {
     345        /* Rats! The buffer isn't big enough to hold the entire header value */
     346        while (c = getc(fp), c != EOF && c != '\n')
     347            continue;
     348    }
     349
    326350    return hdrval;
    327351}
    328352
    329 #if ENABLE_FEATURE_WGET_LONG_OPTIONS
    330 static char *URL_escape(const char *str)
    331 {
    332     /* URL encode, see RFC 2396 */
    333     char *dst;
    334     char *res = dst = xmalloc(strlen(str) * 3 + 1);
    335     unsigned char c;
    336 
    337     while (1) {
    338         c = *str++;
    339         if (c == '\0'
    340         /* || strchr("!&'()*-.=_~", c) - more code */
    341          || c == '!'
    342          || c == '&'
    343          || c == '\''
    344          || c == '('
    345          || c == ')'
    346          || c == '*'
    347          || c == '-'
    348          || c == '.'
    349          || c == '='
    350          || c == '_'
    351          || c == '~'
    352          || (c >= '0' && c <= '9')
    353          || ((c|0x20) >= 'a' && (c|0x20) <= 'z')
    354         ) {
    355             *dst++ = c;
    356             if (c == '\0')
    357                 return res;
    358         } else {
    359             *dst++ = '%';
    360             *dst++ = bb_hexdigits_upcase[c >> 4];
    361             *dst++ = bb_hexdigits_upcase[c & 0xf];
    362         }
    363     }
    364 }
    365 #endif
     353static void reset_beg_range_to_zero(void)
     354{
     355    bb_error_msg("restart failed");
     356    G.beg_range = 0;
     357    xlseek(G.output_fd, 0, SEEK_SET);
     358    /* Done at the end instead: */
     359    /* ftruncate(G.output_fd, 0); */
     360}
    366361
    367362static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_sockaddr *lsa)
    368363{
    369     char buf[512];
    370364    FILE *sfp;
    371365    char *str;
     
    376370
    377371    sfp = open_socket(lsa);
    378     if (ftpcmd(NULL, NULL, sfp, buf) != 220)
    379         bb_error_msg_and_die("%s", sanitize_string(buf+4));
     372    if (ftpcmd(NULL, NULL, sfp) != 220)
     373        bb_error_msg_and_die("%s", sanitize_string(G.wget_buf + 4));
    380374
    381375    /*
     
    386380    if (str)
    387381        *str++ = '\0';
    388     switch (ftpcmd("USER ", target->user, sfp, buf)) {
     382    switch (ftpcmd("USER ", target->user, sfp)) {
    389383    case 230:
    390384        break;
    391385    case 331:
    392         if (ftpcmd("PASS ", str, sfp, buf) == 230)
     386        if (ftpcmd("PASS ", str, sfp) == 230)
    393387            break;
    394388        /* fall through (failed login) */
    395389    default:
    396         bb_error_msg_and_die("ftp login: %s", sanitize_string(buf+4));
    397     }
    398 
    399     ftpcmd("TYPE I", NULL, sfp, buf);
     390        bb_error_msg_and_die("ftp login: %s", sanitize_string(G.wget_buf + 4));
     391    }
     392
     393    ftpcmd("TYPE I", NULL, sfp);
    400394
    401395    /*
    402396     * Querying file size
    403397     */
    404     if (ftpcmd("SIZE ", target->path, sfp, buf) == 213) {
    405         G.content_len = BB_STRTOOFF(buf+4, NULL, 10);
     398    if (ftpcmd("SIZE ", target->path, sfp) == 213) {
     399        G.content_len = BB_STRTOOFF(G.wget_buf + 4, NULL, 10);
    406400        if (G.content_len < 0 || errno) {
    407401            bb_error_msg_and_die("SIZE value is garbage");
     
    413407     * Entering passive mode
    414408     */
    415     if (ftpcmd("PASV", NULL, sfp, buf) != 227) {
     409    if (ftpcmd("PASV", NULL, sfp) != 227) {
    416410 pasv_error:
    417         bb_error_msg_and_die("bad response to %s: %s", "PASV", sanitize_string(buf));
     411        bb_error_msg_and_die("bad response to %s: %s", "PASV", sanitize_string(G.wget_buf));
    418412    }
    419413    // Response is "227 garbageN1,N2,N3,N4,P1,P2[)garbage]
    420414    // Server's IP is N1.N2.N3.N4 (we ignore it)
    421415    // Server's port for data connection is P1*256+P2
    422     str = strrchr(buf, ')');
     416    str = strrchr(G.wget_buf, ')');
    423417    if (str) str[0] = '\0';
    424     str = strrchr(buf, ',');
     418    str = strrchr(G.wget_buf, ',');
    425419    if (!str) goto pasv_error;
    426420    port = xatou_range(str+1, 0, 255);
    427421    *str = '\0';
    428     str = strrchr(buf, ',');
     422    str = strrchr(G.wget_buf, ',');
    429423    if (!str) goto pasv_error;
    430424    port += xatou_range(str+1, 0, 255) * 256;
    431     set_nport(lsa, htons(port));
     425    set_nport(&lsa->u.sa, htons(port));
    432426
    433427    *dfpp = open_socket(lsa);
    434428
    435     if (G.beg_range) {
    436         sprintf(buf, "REST %"OFF_FMT"u", G.beg_range);
    437         if (ftpcmd(buf, NULL, sfp, buf) == 350)
     429    if (G.beg_range != 0) {
     430        sprintf(G.wget_buf, "REST %"OFF_FMT"u", G.beg_range);
     431        if (ftpcmd(G.wget_buf, NULL, sfp) == 350)
    438432            G.content_len -= G.beg_range;
    439     }
    440 
    441     if (ftpcmd("RETR ", target->path, sfp, buf) > 150)
    442         bb_error_msg_and_die("bad response to %s: %s", "RETR", sanitize_string(buf));
     433        else
     434            reset_beg_range_to_zero();
     435    }
     436
     437    if (ftpcmd("RETR ", target->path, sfp) > 150)
     438        bb_error_msg_and_die("bad response to %s: %s", "RETR", sanitize_string(G.wget_buf));
    443439
    444440    return sfp;
    445441}
    446442
    447 static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd)
    448 {
    449     char buf[4*1024]; /* made bigger to speed up local xfers */
     443static void NOINLINE retrieve_file_data(FILE *dfp)
     444{
    450445#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
    451446# if ENABLE_FEATURE_WGET_TIMEOUT
    452     unsigned second_cnt;
     447    unsigned second_cnt = G.timeout_seconds;
    453448# endif
    454449    struct pollfd polldata;
     
    466461
    467462#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
     463        /* Must use nonblocking I/O, otherwise fread will loop
     464         * and *block* until it reads full buffer,
     465         * which messes up progress bar and/or timeout logic.
     466         * Because of nonblocking I/O, we need to dance
     467         * very carefully around EAGAIN. See explanation at
     468         * clearerr() calls.
     469         */
    468470        ndelay_on(polldata.fd);
    469471#endif
     
    472474            unsigned rdsz;
    473475
    474             rdsz = sizeof(buf);
    475             if (G.got_clen) {
    476                 if (G.content_len < (off_t)sizeof(buf)) {
    477                     if ((int)G.content_len <= 0)
    478                         break;
    479                     rdsz = (unsigned)G.content_len;
    480                 }
    481             }
    482476#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
    483 # if ENABLE_FEATURE_WGET_TIMEOUT
    484             second_cnt = G.timeout_seconds;
    485 # endif
    486             while (1) {
    487                 if (safe_poll(&polldata, 1, 1000) != 0)
    488                     break; /* error, EOF, or data is available */
    489 # if ENABLE_FEATURE_WGET_TIMEOUT
    490                 if (second_cnt != 0 && --second_cnt == 0) {
    491                     progress_meter(PROGRESS_END);
    492                     bb_perror_msg_and_die("download timed out");
    493                 }
    494 # endif
    495                 /* Needed for "stalled" indicator */
    496                 progress_meter(PROGRESS_BUMP);
    497             }
    498 #endif
    499477            /* fread internally uses read loop, which in our case
    500478             * is usually exited when we get EAGAIN.
     
    506484             */
    507485            clearerr(dfp);
     486#endif
    508487            errno = 0;
    509             n = safe_fread(buf, rdsz, dfp);
    510             /* man fread:
     488            rdsz = sizeof(G.wget_buf);
     489            if (G.got_clen) {
     490                if (G.content_len < (off_t)sizeof(G.wget_buf)) {
     491                    if ((int)G.content_len <= 0)
     492                        break;
     493                    rdsz = (unsigned)G.content_len;
     494                }
     495            }
     496            n = fread(G.wget_buf, 1, rdsz, dfp);
     497
     498            if (n > 0) {
     499                xwrite(G.output_fd, G.wget_buf, n);
     500#if ENABLE_FEATURE_WGET_STATUSBAR
     501                G.transferred += n;
     502#endif
     503                if (G.got_clen) {
     504                    G.content_len -= n;
     505                    if (G.content_len == 0)
     506                        break;
     507                }
     508#if ENABLE_FEATURE_WGET_TIMEOUT
     509                second_cnt = G.timeout_seconds;
     510#endif
     511                continue;
     512            }
     513
     514            /* n <= 0.
     515             * man fread:
    511516             * If error occurs, or EOF is reached, the return value
    512517             * is a short item count (or zero).
    513518             * fread does not distinguish between EOF and error.
    514519             */
    515             if (n <= 0) {
    516 #if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
    517                 if (errno == EAGAIN) /* poll lied, there is no data? */
    518                     continue; /* yes */
    519 #endif
    520                 if (ferror(dfp))
     520            if (errno != EAGAIN) {
     521                if (ferror(dfp)) {
     522                    progress_meter(PROGRESS_END);
    521523                    bb_perror_msg_and_die(bb_msg_read_error);
     524                }
    522525                break; /* EOF, not error */
    523526            }
    524527
    525             xwrite(output_fd, buf, n);
    526 #if ENABLE_FEATURE_WGET_STATUSBAR
    527             G.transferred += n;
     528#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
     529            /* It was EAGAIN. There is no data. Wait up to one second
     530             * then abort if timed out, or update the bar and try reading again.
     531             */
     532            if (safe_poll(&polldata, 1, 1000) == 0) {
     533# if ENABLE_FEATURE_WGET_TIMEOUT
     534                if (second_cnt != 0 && --second_cnt == 0) {
     535                    progress_meter(PROGRESS_END);
     536                    bb_error_msg_and_die("download timed out");
     537                }
     538# endif
     539                /* We used to loop back to poll here,
     540                 * but there is no great harm in letting fread
     541                 * to try reading anyway.
     542                 */
     543            }
     544            /* Need to do it _every_ second for "stalled" indicator
     545             * to be shown properly.
     546             */
    528547            progress_meter(PROGRESS_BUMP);
    529548#endif
    530             if (G.got_clen) {
    531                 G.content_len -= n;
    532                 if (G.content_len == 0)
    533                     break;
    534             }
    535         }
     549        } /* while (reading data) */
     550
    536551#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
    537         ndelay_off(polldata.fd);
    538 #endif
    539 
     552        clearerr(dfp);
     553        ndelay_off(polldata.fd); /* else fgets can get very unhappy */
     554#endif
    540555        if (!G.chunked)
    541556            break;
    542557
    543         safe_fgets(buf, sizeof(buf), dfp); /* This is a newline */
     558        fgets_and_trim(dfp); /* Eat empty line */
    544559 get_clen:
    545         safe_fgets(buf, sizeof(buf), dfp);
    546         G.content_len = STRTOOFF(buf, NULL, 16);
     560        fgets_and_trim(dfp);
     561        G.content_len = STRTOOFF(G.wget_buf, NULL, 16);
    547562        /* FIXME: error check? */
    548563        if (G.content_len == 0)
    549564            break; /* all done! */
    550565        G.got_clen = 1;
    551     }
    552 
     566        /*
     567         * Note that fgets may result in some data being buffered in dfp.
     568         * We loop back to fread, which will retrieve this data.
     569         * Also note that code has to be arranged so that fread
     570         * is done _before_ one-second poll wait - poll doesn't know
     571         * about stdio buffering and can result in spurious one second waits!
     572         */
     573    }
     574
     575    /* If -c failed, we restart from the beginning,
     576     * but we do not truncate file then, we do it only now, at the end.
     577     * This lets user to ^C if his 99% complete 10 GB file download
     578     * failed to restart *without* losing the almost complete file.
     579     */
     580    {
     581        off_t pos = lseek(G.output_fd, 0, SEEK_CUR);
     582        if (pos != (off_t)-1)
     583            ftruncate(G.output_fd, pos);
     584    }
     585
     586    /* Draw full bar and free its resources */
     587    G.chunked = 0;  /* makes it show 100% even for chunked download */
     588    G.got_clen = 1; /* makes it show 100% even for download of (formerly) unknown size */
    553589    progress_meter(PROGRESS_END);
    554590}
    555591
    556 int wget_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    557 int wget_main(int argc UNUSED_PARAM, char **argv)
    558 {
    559     char buf[512];
    560     struct host_info server, target;
     592static void download_one_url(const char *url)
     593{
     594    bool use_proxy;                 /* Use proxies if env vars are set  */
     595    int redir_limit;
    561596    len_and_sockaddr *lsa;
    562     unsigned opt;
    563     int redir_limit;
    564     char *proxy = NULL;
    565     char *dir_prefix = NULL;
    566 #if ENABLE_FEATURE_WGET_LONG_OPTIONS
    567     char *post_data;
    568     char *extra_headers = NULL;
    569     llist_t *headers_llist = NULL;
    570 #endif
    571597    FILE *sfp;                      /* socket to web/ftp server         */
    572598    FILE *dfp;                      /* socket to ftp server (data)      */
    573     char *fname_out;                /* where to direct output (-O)      */
    574     int output_fd = -1;
    575     bool use_proxy;                 /* Use proxies if env vars are set  */
    576     const char *proxy_flag = "on";  /* Use proxies if env vars are set  */
    577     const char *user_agent = "Wget";/* "User-Agent" header field        */
    578 
    579     static const char keywords[] ALIGN1 =
    580         "content-length\0""transfer-encoding\0""chunked\0""location\0";
    581     enum {
    582         KEY_content_length = 1, KEY_transfer_encoding, KEY_chunked, KEY_location
    583     };
    584 #if ENABLE_FEATURE_WGET_LONG_OPTIONS
    585     static const char wget_longopts[] ALIGN1 =
    586         /* name, has_arg, val */
    587         "continue\0"         No_argument       "c"
    588         "spider\0"           No_argument       "s"
    589         "quiet\0"            No_argument       "q"
    590         "output-document\0"  Required_argument "O"
    591         "directory-prefix\0" Required_argument "P"
    592         "proxy\0"            Required_argument "Y"
    593         "user-agent\0"       Required_argument "U"
    594 #if ENABLE_FEATURE_WGET_TIMEOUT
    595         "timeout\0"          Required_argument "T"
    596 #endif
    597         /* Ignored: */
    598         // "tries\0"            Required_argument "t"
    599         /* Ignored (we always use PASV): */
    600         "passive-ftp\0"      No_argument       "\xff"
    601         "header\0"           Required_argument "\xfe"
    602         "post-data\0"        Required_argument "\xfd"
    603         /* Ignored (we don't do ssl) */
    604         "no-check-certificate\0" No_argument   "\xfc"
    605         ;
    606 #endif
    607 
    608     INIT_G();
    609 
    610 #if ENABLE_FEATURE_WGET_LONG_OPTIONS
    611     applet_long_options = wget_longopts;
    612 #endif
    613     /* server.allocated = target.allocated = NULL; */
    614     opt_complementary = "-1" IF_FEATURE_WGET_TIMEOUT(":T+") IF_FEATURE_WGET_LONG_OPTIONS(":\xfe::");
    615     opt = getopt32(argv, "csqO:P:Y:U:T:" /*ignored:*/ "t:",
    616                 &fname_out, &dir_prefix,
    617                 &proxy_flag, &user_agent,
    618                 IF_FEATURE_WGET_TIMEOUT(&G.timeout_seconds) IF_NOT_FEATURE_WGET_TIMEOUT(NULL),
    619                 NULL /* -t RETRIES */
    620                 IF_FEATURE_WGET_LONG_OPTIONS(, &headers_llist)
    621                 IF_FEATURE_WGET_LONG_OPTIONS(, &post_data)
    622                 );
    623 #if ENABLE_FEATURE_WGET_LONG_OPTIONS
    624     if (headers_llist) {
    625         int size = 1;
    626         char *cp;
    627         llist_t *ll = headers_llist;
    628         while (ll) {
    629             size += strlen(ll->data) + 2;
    630             ll = ll->link;
    631         }
    632         extra_headers = cp = xmalloc(size);
    633         while (headers_llist) {
    634             cp += sprintf(cp, "%s\r\n", (char*)llist_pop(&headers_llist));
    635         }
    636     }
    637 #endif
    638 
    639     /* TODO: compat issue: should handle "wget URL1 URL2..." */
    640 
     599    char *proxy = NULL;
     600    char *fname_out_alloc;
     601    char *redirected_path = NULL;
     602    struct host_info server;
     603    struct host_info target;
     604
     605    server.allocated = NULL;
     606    target.allocated = NULL;
     607    server.user = NULL;
    641608    target.user = NULL;
    642     parse_url(argv[optind], &target);
     609
     610    parse_url(url, &target);
    643611
    644612    /* Use the proxy if necessary */
    645     use_proxy = (strcmp(proxy_flag, "off") != 0);
     613    use_proxy = (strcmp(G.proxy_flag, "off") != 0);
    646614    if (use_proxy) {
    647615        proxy = getenv(target.is_ftp ? "ftp_proxy" : "http_proxy");
    648         if (proxy && proxy[0]) {
    649             server.user = NULL;
     616        use_proxy = (proxy && proxy[0]);
     617        if (use_proxy)
    650618            parse_url(proxy, &server);
    651         } else {
    652             use_proxy = 0;
    653         }
    654619    }
    655620    if (!use_proxy) {
    656621        server.port = target.port;
    657622        if (ENABLE_FEATURE_IPV6) {
    658             server.host = xstrdup(target.host);
     623            //free(server.allocated); - can't be non-NULL
     624            server.host = server.allocated = xstrdup(target.host);
    659625        } else {
    660626            server.host = target.host;
     
    665631        strip_ipv6_scope_id(target.host);
    666632
    667     /* Guess an output filename, if there was no -O FILE */
    668     if (!(opt & WGET_OPT_OUTNAME)) {
    669         fname_out = bb_get_last_path_component_nostrip(target.path);
     633    /* If there was no -O FILE, guess output filename */
     634    fname_out_alloc = NULL;
     635    if (!(option_mask32 & WGET_OPT_OUTNAME)) {
     636        G.fname_out = bb_get_last_path_component_nostrip(target.path);
    670637        /* handle "wget http://kernel.org//" */
    671         if (fname_out[0] == '/' || !fname_out[0])
    672             fname_out = (char*)"index.html";
     638        if (G.fname_out[0] == '/' || !G.fname_out[0])
     639            G.fname_out = (char*)"index.html";
    673640        /* -P DIR is considered only if there was no -O FILE */
    674         if (dir_prefix)
    675             fname_out = concat_path_file(dir_prefix, fname_out);
    676     } else {
    677         if (LONE_DASH(fname_out)) {
    678             /* -O - */
    679             output_fd = 1;
    680             opt &= ~WGET_OPT_CONTINUE;
     641        if (G.dir_prefix)
     642            G.fname_out = fname_out_alloc = concat_path_file(G.dir_prefix, G.fname_out);
     643        else {
     644            /* redirects may free target.path later, need to make a copy */
     645            G.fname_out = fname_out_alloc = xstrdup(G.fname_out);
    681646        }
    682647    }
    683648#if ENABLE_FEATURE_WGET_STATUSBAR
    684     G.curfile = bb_get_last_path_component_nostrip(fname_out);
    685 #endif
    686 
    687     /* Impossible?
    688     if ((opt & WGET_OPT_CONTINUE) && !fname_out)
    689         bb_error_msg_and_die("can't specify continue (-c) without a filename (-O)");
    690     */
     649    G.curfile = bb_get_last_path_component_nostrip(G.fname_out);
     650#endif
    691651
    692652    /* Determine where to start transfer */
    693     if (opt & WGET_OPT_CONTINUE) {
    694         output_fd = open(fname_out, O_WRONLY);
    695         if (output_fd >= 0) {
    696             G.beg_range = xlseek(output_fd, 0, SEEK_END);
     653    G.beg_range = 0;
     654    if (option_mask32 & WGET_OPT_CONTINUE) {
     655        G.output_fd = open(G.fname_out, O_WRONLY);
     656        if (G.output_fd >= 0) {
     657            G.beg_range = xlseek(G.output_fd, 0, SEEK_END);
    697658        }
    698659        /* File doesn't exist. We do not create file here yet.
    699          * We are not sure it exists on remove side */
     660         * We are not sure it exists on remote side */
    700661    }
    701662
     
    703664 resolve_lsa:
    704665    lsa = xhost2sockaddr(server.host, server.port);
    705     if (!(opt & WGET_OPT_QUIET)) {
     666    if (!(option_mask32 & WGET_OPT_QUIET)) {
    706667        char *s = xmalloc_sockaddr2dotted(&lsa->u.sa);
    707668        fprintf(stderr, "Connecting to %s (%s)\n", server.host, s);
     
    709670    }
    710671 establish_session:
     672    /*G.content_len = 0; - redundant, got_clen = 0 is enough */
     673    G.got_clen = 0;
     674    G.chunked = 0;
    711675    if (use_proxy || !target.is_ftp) {
    712676        /*
     
    716680        int status;
    717681
     682
    718683        /* Open socket to http server */
    719684        sfp = open_socket(lsa);
     
    725690                target.path);
    726691        } else {
    727             if (opt & WGET_OPT_POST_DATA)
     692            if (option_mask32 & WGET_OPT_POST_DATA)
    728693                fprintf(sfp, "POST /%s HTTP/1.1\r\n", target.path);
    729694            else
     
    732697
    733698        fprintf(sfp, "Host: %s\r\nUser-Agent: %s\r\n",
    734             target.host, user_agent);
     699            target.host, G.user_agent);
    735700
    736701        /* Ask server to close the connection as soon as we are done
     
    742707        if (target.user) {
    743708            fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6,
    744                 base64enc_512(buf, target.user));
     709                base64enc(target.user));
    745710        }
    746711        if (use_proxy && server.user) {
    747712            fprintf(sfp, "Proxy-Authorization: Basic %s\r\n",
    748                 base64enc_512(buf, server.user));
    749         }
    750 #endif
    751 
    752         if (G.beg_range)
     713                base64enc(server.user));
     714        }
     715#endif
     716
     717        if (G.beg_range != 0)
    753718            fprintf(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range);
    754719
    755720#if ENABLE_FEATURE_WGET_LONG_OPTIONS
    756         if (extra_headers)
    757             fputs(extra_headers, sfp);
    758 
    759         if (opt & WGET_OPT_POST_DATA) {
    760             char *estr = URL_escape(post_data);
     721        if (G.extra_headers)
     722            fputs(G.extra_headers, sfp);
     723
     724        if (option_mask32 & WGET_OPT_POST_DATA) {
    761725            fprintf(sfp,
    762726                "Content-Type: application/x-www-form-urlencoded\r\n"
     
    764728                "\r\n"
    765729                "%s",
    766                 (int) strlen(estr), estr
     730                (int) strlen(G.post_data), G.post_data
    767731            );
    768             free(estr);
    769732        } else
    770733#endif
     
    779742         */
    780743 read_response:
    781         if (fgets(buf, sizeof(buf), sfp) == NULL)
    782             bb_error_msg_and_die("no response from server");
    783 
    784         str = buf;
     744        fgets_and_trim(sfp);
     745
     746        str = G.wget_buf;
    785747        str = skip_non_whitespace(str);
    786748        str = skip_whitespace(str);
     
    791753        case 0:
    792754        case 100:
    793             while (gethdr(buf, sizeof(buf), sfp /*, &n*/) != NULL)
     755            while (gethdr(sfp) != NULL)
    794756                /* eat all remaining headers */;
    795757            goto read_response;
     
    820782*/
    821783        case 204:
     784            if (G.beg_range != 0) {
     785                /* "Range:..." was not honored by the server.
     786                 * Restart download from the beginning.
     787                 */
     788                reset_beg_range_to_zero();
     789            }
    822790            break;
    823791        case 300:  /* redirection */
     
    826794        case 303:
    827795            break;
    828         case 206:
    829             if (G.beg_range)
     796        case 206: /* Partial Content */
     797            if (G.beg_range != 0)
     798                /* "Range:..." worked. Good. */
    830799                break;
     800            /* Partial Content even though we did not ask for it??? */
    831801            /* fall through */
    832802        default:
    833             bb_error_msg_and_die("server returned error: %s", sanitize_string(buf));
     803            bb_error_msg_and_die("server returned error: %s", sanitize_string(G.wget_buf));
    834804        }
    835805
     
    837807         * Retrieve HTTP headers.
    838808         */
    839         while ((str = gethdr(buf, sizeof(buf), sfp /*, &n*/)) != NULL) {
     809        while ((str = gethdr(sfp)) != NULL) {
     810            static const char keywords[] ALIGN1 =
     811                "content-length\0""transfer-encoding\0""location\0";
     812            enum {
     813                KEY_content_length = 1, KEY_transfer_encoding, KEY_location
     814            };
     815            smalluint key;
     816
    840817            /* gethdr converted "FOO:" string to lowercase */
    841             smalluint key;
     818
    842819            /* strip trailing whitespace */
    843820            char *s = strchrnul(str, '\0') - 1;
     
    846823                s--;
    847824            }
    848             key = index_in_strings(keywords, buf) + 1;
     825            key = index_in_strings(keywords, G.wget_buf) + 1;
    849826            if (key == KEY_content_length) {
    850827                G.content_len = BB_STRTOOFF(str, NULL, 10);
     
    856833            }
    857834            if (key == KEY_transfer_encoding) {
    858                 if (index_in_strings(keywords, str_tolower(str)) + 1 != KEY_chunked)
     835                if (strcmp(str_tolower(str), "chunked") != 0)
    859836                    bb_error_msg_and_die("transfer encoding '%s' is not supported", sanitize_string(str));
    860                 G.chunked = G.got_clen = 1;
     837                G.chunked = 1;
    861838            }
    862839            if (key == KEY_location && status >= 300) {
     
    864841                    bb_error_msg_and_die("too many redirections");
    865842                fclose(sfp);
    866                 G.got_clen = 0;
    867                 G.chunked = 0;
    868                 if (str[0] == '/')
    869                     /* free(target.allocated); */
    870                     target.path = /* target.allocated = */ xstrdup(str+1);
     843                if (str[0] == '/') {
     844                    free(redirected_path);
     845                    target.path = redirected_path = xstrdup(str+1);
    871846                    /* lsa stays the same: it's on the same server */
    872                 else {
     847                } else {
    873848                    parse_url(str, &target);
    874849                    if (!use_proxy) {
     850                        free(server.allocated);
     851                        server.allocated = NULL;
    875852                        server.host = target.host;
    876853                        /* strip_ipv6_scope_id(target.host); - no! */
     
    897874    }
    898875
    899     if (opt & WGET_OPT_SPIDER) {
    900         if (ENABLE_FEATURE_CLEAN_UP)
    901             fclose(sfp);
    902         return EXIT_SUCCESS;
    903     }
    904 
    905     if (output_fd < 0) {
    906         int o_flags = O_WRONLY | O_CREAT | O_TRUNC | O_EXCL;
     876    free(lsa);
     877
     878    if (!(option_mask32 & WGET_OPT_SPIDER)) {
     879        if (G.output_fd < 0)
     880            G.output_fd = xopen(G.fname_out, G.o_flags);
     881        retrieve_file_data(dfp);
     882        if (!(option_mask32 & WGET_OPT_OUTNAME)) {
     883            xclose(G.output_fd);
     884            G.output_fd = -1;
     885        }
     886    }
     887
     888    if (dfp != sfp) {
     889        /* It's ftp. Close data connection properly */
     890        fclose(dfp);
     891        if (ftpcmd(NULL, NULL, sfp) != 226)
     892            bb_error_msg_and_die("ftp error: %s", sanitize_string(G.wget_buf + 4));
     893        /* ftpcmd("QUIT", NULL, sfp); - why bother? */
     894    }
     895    fclose(sfp);
     896
     897    free(server.allocated);
     898    free(target.allocated);
     899    free(fname_out_alloc);
     900    free(redirected_path);
     901}
     902
     903int wget_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     904int wget_main(int argc UNUSED_PARAM, char **argv)
     905{
     906#if ENABLE_FEATURE_WGET_LONG_OPTIONS
     907    static const char wget_longopts[] ALIGN1 =
     908        /* name, has_arg, val */
     909        "continue\0"         No_argument       "c"
     910//FIXME: -s isn't --spider, it's --save-headers!
     911        "spider\0"           No_argument       "s"
     912        "quiet\0"            No_argument       "q"
     913        "output-document\0"  Required_argument "O"
     914        "directory-prefix\0" Required_argument "P"
     915        "proxy\0"            Required_argument "Y"
     916        "user-agent\0"       Required_argument "U"
     917#if ENABLE_FEATURE_WGET_TIMEOUT
     918        "timeout\0"          Required_argument "T"
     919#endif
     920        /* Ignored: */
     921        // "tries\0"            Required_argument "t"
     922        /* Ignored (we always use PASV): */
     923        "passive-ftp\0"      No_argument       "\xff"
     924        "header\0"           Required_argument "\xfe"
     925        "post-data\0"        Required_argument "\xfd"
     926        /* Ignored (we don't do ssl) */
     927        "no-check-certificate\0" No_argument   "\xfc"
     928        /* Ignored (we don't support caching) */
     929        "no-cache\0"         No_argument       "\xfb"
     930        ;
     931#endif
     932
     933#if ENABLE_FEATURE_WGET_LONG_OPTIONS
     934    llist_t *headers_llist = NULL;
     935#endif
     936
     937    INIT_G();
     938
     939    IF_FEATURE_WGET_TIMEOUT(G.timeout_seconds = 900;)
     940    G.proxy_flag = "on";   /* use proxies if env vars are set */
     941    G.user_agent = "Wget"; /* "User-Agent" header field */
     942
     943#if ENABLE_FEATURE_WGET_LONG_OPTIONS
     944    applet_long_options = wget_longopts;
     945#endif
     946    opt_complementary = "-1" IF_FEATURE_WGET_TIMEOUT(":T+") IF_FEATURE_WGET_LONG_OPTIONS(":\xfe::");
     947    getopt32(argv, "csqO:P:Y:U:T:" /*ignored:*/ "t:",
     948        &G.fname_out, &G.dir_prefix,
     949        &G.proxy_flag, &G.user_agent,
     950        IF_FEATURE_WGET_TIMEOUT(&G.timeout_seconds) IF_NOT_FEATURE_WGET_TIMEOUT(NULL),
     951        NULL /* -t RETRIES */
     952        IF_FEATURE_WGET_LONG_OPTIONS(, &headers_llist)
     953        IF_FEATURE_WGET_LONG_OPTIONS(, &G.post_data)
     954    );
     955    argv += optind;
     956
     957#if ENABLE_FEATURE_WGET_LONG_OPTIONS
     958    if (headers_llist) {
     959        int size = 1;
     960        char *cp;
     961        llist_t *ll = headers_llist;
     962        while (ll) {
     963            size += strlen(ll->data) + 2;
     964            ll = ll->link;
     965        }
     966        G.extra_headers = cp = xmalloc(size);
     967        while (headers_llist) {
     968            cp += sprintf(cp, "%s\r\n", (char*)llist_pop(&headers_llist));
     969        }
     970    }
     971#endif
     972
     973    G.output_fd = -1;
     974    G.o_flags = O_WRONLY | O_CREAT | O_TRUNC | O_EXCL;
     975    if (G.fname_out) { /* -O FILE ? */
     976        if (LONE_DASH(G.fname_out)) { /* -O - ? */
     977            G.output_fd = 1;
     978            option_mask32 &= ~WGET_OPT_CONTINUE;
     979        }
    907980        /* compat with wget: -O FILE can overwrite */
    908         if (opt & WGET_OPT_OUTNAME)
    909             o_flags = O_WRONLY | O_CREAT | O_TRUNC;
    910         output_fd = xopen(fname_out, o_flags);
    911     }
    912 
    913     retrieve_file_data(dfp, output_fd);
    914     xclose(output_fd);
    915 
    916     if (dfp != sfp) {
    917         /* It's ftp. Close it properly */
    918         fclose(dfp);
    919         if (ftpcmd(NULL, NULL, sfp, buf) != 226)
    920             bb_error_msg_and_die("ftp error: %s", sanitize_string(buf+4));
    921         /* ftpcmd("QUIT", NULL, sfp, buf); - why bother? */
    922     }
     981        G.o_flags = O_WRONLY | O_CREAT | O_TRUNC;
     982    }
     983
     984    while (*argv)
     985        download_one_url(*argv++);
     986
     987    if (G.output_fd >= 0)
     988        xclose(G.output_fd);
    923989
    924990    return EXIT_SUCCESS;
  • branches/3.2/mindi-busybox/networking/zcip.c

    r2725 r3232  
    2424// - link status monitoring (restart on link-up; stop on link-down)
    2525
     26//usage:#define zcip_trivial_usage
     27//usage:       "[OPTIONS] IFACE SCRIPT"
     28//usage:#define zcip_full_usage "\n\n"
     29//usage:       "Manage a ZeroConf IPv4 link-local address\n"
     30//usage:     "\n    -f      Run in foreground"
     31//usage:     "\n    -q      Quit after obtaining address"
     32//usage:     "\n    -r 169.254.x.x  Request this address first"
     33//usage:     "\n    -v      Verbose"
     34//usage:     "\n"
     35//usage:     "\nWith no -q, runs continuously monitoring for ARP conflicts,"
     36//usage:     "\nexits only on I/O errors (link down etc)"
     37
     38#include "libbb.h"
    2639#include <netinet/ether.h>
    27 #include <net/ethernet.h>
    2840#include <net/if.h>
    2941#include <net/if_arp.h>
    30 #include <linux/if_packet.h>
    3142#include <linux/sockios.h>
    3243
    33 #include "libbb.h"
    3444#include <syslog.h>
    3545
     
    8292#define saddr    (G.saddr   )
    8393#define eth_addr (G.eth_addr)
     94#define INIT_G() do { } while (0)
    8495
    8596
     
    214225
    215226    memset(&L, 0, sizeof(L));
     227    INIT_G();
    216228
    217229#define FOREGROUND (opts & 1)
Note: See TracChangeset for help on using the changeset viewer.