Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/networking


Ignore:
Timestamp:
Dec 20, 2016, 4:07:32 PM (7 years ago)
Author:
Bruno Cornec
Message:

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

Location:
branches/3.3
Files:
16 added
8 deleted
78 edited
1 copied

Legend:

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

    r3232 r3621  
    135135      Most other ftp servers seem to behave similar to this.
    136136
     137config FEATURE_FTP_AUTHENTICATION
     138    bool "Enable authentication"
     139    default y
     140    depends on FTPD
     141    help
     142      Enable basic system login as seen in telnet etc.
     143
    137144config FTPGET
    138145    bool "ftpget"
     
    174181      "Range: bytes=NNN-[MMM]" header. Allows for resuming interrupted
    175182      downloads, seeking in multimedia players etc.
    176 
    177 config FEATURE_HTTPD_USE_SENDFILE
    178     bool "Use sendfile system call"
    179     default y
    180     depends on HTTPD
    181     help
    182       When enabled, httpd will use the kernel sendfile() function
    183       instead of read/write loop.
    184183
    185184config FEATURE_HTTPD_SETUID
     
    499498config FEATURE_INETD_RPC
    500499    bool "Support RPC services"
    501     default y
     500    default n  # very rarely used, and needs Sun RPC support in libc
    502501    depends on INETD
    503502    select FEATURE_HAVE_RPC
     
    535534      Add support for routing table management to "ip".
    536535
     536config FEATURE_IP_ROUTE_DIR
     537    string "ip route configuration directory"
     538    default "/etc/iproute2"
     539    depends on FEATURE_IP_ROUTE
     540    help
     541      Location of the "ip" applet routing configuration.
     542
    537543config FEATURE_IP_TUNNEL
    538544    bool "ip tunnel"
     
    548554    help
    549555      Add support for rule commands to "ip".
     556
     557config FEATURE_IP_NEIGH
     558    bool "ip neighbor"
     559    default y
     560    depends on IP
     561    help
     562      Add support for neighbor commands to "ip".
    550563
    551564config FEATURE_IP_SHORT_FORMS
     
    560573      ip tunnel -> iptunnel
    561574      ip rule   -> iprule
     575      ip neigh  -> ipneigh
    562576
    563577      Say N unless you desparately need the short form of the ip
     
    599613    depends on FEATURE_IP_SHORT_FORMS && FEATURE_IP_RULE
    600614
     615config IPNEIGH
     616    bool
     617    default y
     618    depends on FEATURE_IP_SHORT_FORMS && FEATURE_IP_NEIGH
     619
    601620config IPCALC
    602621    bool "ipcalc"
     
    664683      Make ntpd usable as a NTP server. If you disable this option
    665684      ntpd will be usable only as a NTP client.
     685
     686config FEATURE_NTPD_CONF
     687    bool "Make ntpd understand /etc/ntp.conf"
     688    default y
     689    depends on NTPD
     690    help
     691      Make ntpd look in /etc/ntp.conf for peers. Only "server address"
     692      is supported.
    666693
    667694config PSCAN
     
    744771      Note that for busybox telnetd to work you need several things:
    745772      First of all, your kernel needs:
    746           UNIX98_PTYS=y
    747           DEVPTS_FS=y
     773          CONFIG_UNIX98_PTYS=y
    748774
    749775      Next, you need a /dev/pts directory on your root filesystem:
     
    942968      Creates, removes, and configures VLAN interfaces
    943969
    944 config WGET
    945     bool "wget"
    946     default y
    947     help
    948       wget is a utility for non-interactive download of files from HTTP
    949       and FTP servers.
    950 
    951 config FEATURE_WGET_STATUSBAR
    952     bool "Enable a nifty process meter (+2k)"
    953     default y
    954     depends on WGET
    955     help
    956       Enable the transfer progress bar for wget transfers.
    957 
    958 config FEATURE_WGET_AUTHENTICATION
    959     bool "Enable HTTP authentication"
    960     default y
    961     depends on WGET
    962     help
    963       Support authenticated HTTP transfers.
    964 
    965 config FEATURE_WGET_LONG_OPTIONS
    966     bool "Enable long options"
    967     default y
    968     depends on WGET && LONG_OPTS
    969     help
    970       Support long options for the wget applet.
    971 
    972 config FEATURE_WGET_TIMEOUT
    973     bool "Enable read timeout option -T SEC"
    974     default y
    975     depends on WGET
    976     help
    977       Supports network read timeout for wget, so that wget will give
    978       up and timeout when reading network data, through the -T command
    979       line option.  Currently only network data read timeout is
    980       supported (i.e., timeout is not applied to the DNS nor TCP
    981       connection initialization).  When FEATURE_WGET_LONG_OPTIONS is
    982       also enabled, the --timeout option will work in addition to -T.
    983 
    984970config ZCIP
    985971    bool "zcip"
  • branches/3.3/mindi-busybox/networking/Kbuild.src

    r3232 r3621  
    4242lib-$(CONFIG_TUNCTL)       += tunctl.o
    4343lib-$(CONFIG_VCONFIG)      += vconfig.o
    44 lib-$(CONFIG_WGET)         += wget.o
    4544lib-$(CONFIG_ZCIP)         += zcip.o
    4645
  • branches/3.3/mindi-busybox/networking/arp.c

    r3232 r3621  
    2323//usage:       "Manipulate ARP cache\n"
    2424//usage:       "\n  -a      Display (all) hosts"
    25 //usage:       "\n  -s      Set new ARP entry"
    26 //usage:       "\n  -d      Delete a specified entry"
     25//usage:       "\n  -d      Delete ARP entry"
     26//usage:       "\n  -s      Set new entry"
    2727//usage:       "\n  -v      Verbose"
    2828//usage:       "\n  -n      Don't resolve names"
    2929//usage:       "\n  -i IF       Network interface"
    30 //usage:       "\n  -D      Read <hwaddr> from given device"
     30//usage:       "\n  -D      Read HWADDR from IFACE"
    3131//usage:       "\n  -A,-p AF    Protocol family"
    3232//usage:       "\n  -H HWTYPE   Hardware address type"
    3333
    3434#include "libbb.h"
     35#include "common_bufsiz.h"
    3536#include "inet_common.h"
    3637
     
    6970    const char *device;      /* current device */
    7071    smallint hw_set;         /* flag if hw-type was set (-H) */
    71 
    7272} FIX_ALIASING;
    73 #define G (*(struct globals*)&bb_common_bufsiz1)
     73#define G (*(struct globals*)bb_common_bufsiz1)
    7474#define ap         (G.ap        )
    7575#define hw         (G.hw        )
     
    7777#define hw_set     (G.hw_set    )
    7878#define INIT_G() do { \
     79    setup_common_bufsiz(); \
    7980    device = ""; \
    8081} while (0)
     
    214215
    215216/* Get the hardware address to a specified interface name */
    216 static void arp_getdevhw(char *ifname, struct sockaddr *sa,
    217                         const struct hwtype *hwt)
     217static void arp_getdevhw(char *ifname, struct sockaddr *sa)
    218218{
    219219    struct ifreq ifr;
     
    222222    strcpy(ifr.ifr_name, ifname);
    223223    ioctl_or_perror_and_die(sockfd, SIOCGIFHWADDR, &ifr,
    224                     "cant get HW-Address for '%s'", ifname);
    225     if (hwt && (ifr.ifr_hwaddr.sa_family != hw->type)) {
     224                    "can't get HW-Address for '%s'", ifname);
     225    if (hw_set && (ifr.ifr_hwaddr.sa_family != hw->type)) {
    226226        bb_error_msg_and_die("protocol type mismatch");
    227227    }
     
    234234        }
    235235        bb_error_msg("device '%s' has HW address %s '%s'",
    236                     ifname, xhw->name,
    237                     xhw->print((unsigned char *) &ifr.ifr_hwaddr.sa_data));
     236                ifname, xhw->name,
     237                xhw->print((unsigned char *) &ifr.ifr_hwaddr.sa_data));
    238238    }
    239239}
     
    262262    }
    263263    if (option_mask32 & ARP_OPT_D) {
    264         arp_getdevhw(*args++, &req.arp_ha, hw_set ? hw : NULL);
     264        arp_getdevhw(*args++, &req.arp_ha);
    265265    } else {
    266266        if (hw->input(*args++, &req.arp_ha) < 0) {
     
    461461    }
    462462    if (option_mask32 & ARP_OPT_v)
    463         printf("Entries: %d\tSkipped: %d\tFound: %d\n",
     463        printf("Entries: %u\tSkipped: %u\tFound: %u\n",
    464464                entries, entries - shown, shown);
    465465
    466466    if (!shown) {
    467467        if (hw_set || host || device[0])
    468             printf("No match found in %d entries\n", entries);
     468            printf("No match found in %u entries\n", entries);
    469469    }
    470470    if (ENABLE_FEATURE_CLEAN_UP) {
     
    478478int arp_main(int argc UNUSED_PARAM, char **argv)
    479479{
    480     const char *hw_type = "ether";
     480    const char *hw_type;
    481481    const char *protocol;
    482482    unsigned opts;
     
    485485
    486486    xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sockfd);
     487
    487488    ap = get_aftype(DFLT_AF);
    488     if (!ap)
    489         bb_error_msg_and_die("%s: %s not supported", DFLT_AF, "address family");
     489    /* Defaults are always supported */
     490    //if (!ap)
     491    //  bb_error_msg_and_die("%s: %s not supported", DFLT_AF, "address family");
     492    hw = get_hwtype(DFLT_HW);
     493    //if (!hw)
     494    //  bb_error_msg_and_die("%s: %s not supported", DFLT_HW, "hardware type");
    490495
    491496    opts = getopt32(argv, "A:p:H:t:i:adnDsv", &protocol, &protocol,
     
    494499    if (opts & (ARP_OPT_A | ARP_OPT_p)) {
    495500        ap = get_aftype(protocol);
    496         if (ap == NULL)
     501        if (!ap)
    497502            bb_error_msg_and_die("%s: unknown %s", protocol, "address family");
    498503    }
    499     if (opts & (ARP_OPT_A | ARP_OPT_p)) {
     504    if (opts & (ARP_OPT_H | ARP_OPT_t)) {
    500505        hw = get_hwtype(hw_type);
    501         if (hw == NULL)
     506        if (!hw)
    502507            bb_error_msg_and_die("%s: unknown %s", hw_type, "hardware type");
    503508        hw_set = 1;
     
    508513        bb_error_msg_and_die("%s: kernel only supports 'inet'", ap->name);
    509514    }
    510 
    511     /* If no hw type specified get default */
    512     if (!hw) {
    513         hw = get_hwtype(DFLT_HW);
    514         if (!hw)
    515             bb_error_msg_and_die("%s: %s not supported", DFLT_HW, "hardware type");
    516     }
    517 
    518515    if (hw->alen <= 0) {
    519516        bb_error_msg_and_die("%s: %s without ARP support",
     
    529526        return arp_del(argv);
    530527    }
     528
    531529    //if (opts & ARP_OPT_a) - default
    532530    return arp_show(argv[0]);
  • branches/3.3/mindi-busybox/networking/arping.c

    r3232 r3621  
    1414//usage:     "\n    -q      Quiet"
    1515//usage:     "\n    -b      Keep broadcasting, don't go unicast"
    16 //usage:     "\n    -D      Duplicated address detection mode"
     16//usage:     "\n    -D      Exit with 1 if DST_IP replies"
    1717//usage:     "\n    -U      Unsolicited ARP mode, update your neighbors"
    1818//usage:     "\n    -A      ARP answer mode, update your neighbors"
    1919//usage:     "\n    -c N        Stop after sending N ARP requests"
    20 //usage:     "\n    -w TIMEOUT  Time to wait for ARP reply, seconds"
     20//usage:     "\n    -w TIMEOUT  Seconds to wait for ARP reply"
    2121//usage:     "\n    -I IFACE    Interface to use (default eth0)"
    2222//usage:     "\n    -s SRC_IP   Sender IP address"
     
    2929
    3030#include "libbb.h"
     31#include "common_bufsiz.h"
    3132
    3233/* We don't expect to see 1000+ seconds delay, unsigned is enough */
     
    6162    unsigned req_recv;
    6263} FIX_ALIASING;
    63 #define G (*(struct globals*)&bb_common_bufsiz1)
     64#define G (*(struct globals*)bb_common_bufsiz1)
    6465#define src        (G.src       )
    6566#define dst        (G.dst       )
     
    7778#define req_recv   (G.req_recv  )
    7879#define INIT_G() do { \
     80    setup_common_bufsiz(); \
    7981    count = -1; \
    8082} while (0)
     
    163165}
    164166
    165 static bool recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
     167static void recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
    166168{
    167169    struct arphdr *ah = (struct arphdr *) buf;
     
    182184     && FROM->sll_pkttype != PACKET_BROADCAST
    183185     && FROM->sll_pkttype != PACKET_MULTICAST)
    184         return false;
     186        return;
    185187
    186188    /* Only these types are recognized */
    187189    if (ah->ar_op != htons(ARPOP_REQUEST) && ah->ar_op != htons(ARPOP_REPLY))
    188         return false;
     190        return;
    189191
    190192    /* ARPHRD check and this darned FDDI hack here :-( */
    191193    if (ah->ar_hrd != htons(FROM->sll_hatype)
    192194     && (FROM->sll_hatype != ARPHRD_FDDI || ah->ar_hrd != htons(ARPHRD_ETHER)))
    193         return false;
     195        return;
    194196
    195197    /* Protocol must be IP. */
     
    198200     || (ah->ar_hln != me.sll_halen)
    199201     || (len < (int)(sizeof(*ah) + 2 * (4 + ah->ar_hln))))
    200         return false;
     202        return;
    201203
    202204    move_from_unaligned32(src_ip.s_addr, p + ah->ar_hln);
     
    204206
    205207    if (dst.s_addr != src_ip.s_addr)
    206         return false;
     208        return;
    207209    if (!(option_mask32 & DAD)) {
    208210        if ((src.s_addr != dst_ip.s_addr)
    209             || (memcmp(p + ah->ar_hln + 4, &me.sll_addr, ah->ar_hln)))
    210             return false;
     211         || (memcmp(p + ah->ar_hln + 4, &me.sll_addr, ah->ar_hln)))
     212            return;
    211213    } else {
    212214        /* DAD packet was:
     
    225227        if ((memcmp(p, &me.sll_addr, me.sll_halen) == 0)
    226228         || (src.s_addr && src.s_addr != dst_ip.s_addr))
    227             return false;
     229            return;
    228230    }
    229231    if (!(option_mask32 & QUIET)) {
    230232        int s_printed = 0;
    231233
    232         printf("%scast re%s from %s [%s]",
     234        printf("%scast re%s from %s [%02x:%02x:%02x:%02x:%02x:%02x]",
    233235            FROM->sll_pkttype == PACKET_HOST ? "Uni" : "Broad",
    234236            ah->ar_op == htons(ARPOP_REPLY) ? "ply" : "quest",
    235237            inet_ntoa(src_ip),
    236             ether_ntoa((struct ether_addr *) p));
     238            p[0], p[1], p[2], p[3], p[4], p[5]
     239        );
    237240        if (dst_ip.s_addr != src.s_addr) {
    238241            printf("for %s ", inet_ntoa(dst_ip));
     
    240243        }
    241244        if (memcmp(p + ah->ar_hln + 4, me.sll_addr, ah->ar_hln)) {
     245            unsigned char *pp = p + ah->ar_hln + 4;
    242246            if (!s_printed)
    243247                printf("for ");
    244             printf("[%s]",
    245                 ether_ntoa((struct ether_addr *) p + ah->ar_hln + 4));
     248            printf("[%02x:%02x:%02x:%02x:%02x:%02x]",
     249                pp[0], pp[1], pp[2], pp[3], pp[4], pp[5]
     250            );
    246251        }
    247252
     
    250255            printf(" %u.%03ums\n", diff / 1000, diff % 1000);
    251256        } else {
    252             printf(" UNSOLICITED?\n");
     257            puts(" UNSOLICITED?");
    253258        }
    254259        fflush_all();
     
    265270        option_mask32 |= UNICASTING;
    266271    }
    267     return true;
    268272}
    269273
     
    285289    //xsetuid(getuid());
    286290
    287     err_str = xasprintf("interface %s %%s", device);
    288291    {
    289292        unsigned opt;
     
    303306
    304307    target = argv[optind];
    305 
     308    err_str = xasprintf("interface %s %%s", device);
    306309    xfunc_error_retval = 2;
    307310
     
    360363            saddr.sin_addr = dst;
    361364
    362             if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, &const_int_1, sizeof(const_int_1)) == -1)
    363                 bb_perror_msg("setsockopt(SO_DONTROUTE)");
     365            if (setsockopt_SOL_SOCKET_1(probe_fd, SO_DONTROUTE) != 0)
     366                bb_perror_msg("setsockopt(%s)", "SO_DONTROUTE");
    364367            xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr));
    365368            getsockname(probe_fd, (struct sockaddr *) &saddr, &alen);
  • branches/3.3/mindi-busybox/networking/brctl.c

    r3232 r3621  
    6565
    6666#if ENABLE_FEATURE_BRCTL_FANCY
    67 # include <linux/if_bridge.h>
     67/* #include <linux/if_bridge.h>
     68 * breaks on musl: we already included netinet/in.h in libbb.h,
     69 * if we include <linux/if_bridge.h> here, we get this:
     70 * In file included from /usr/include/linux/if_bridge.h:18,
     71 *                  from networking/brctl.c:67:
     72 * /usr/include/linux/in6.h:32: error: redefinition of 'struct in6_addr'
     73 * /usr/include/linux/in6.h:49: error: redefinition of 'struct sockaddr_in6'
     74 * /usr/include/linux/in6.h:59: error: redefinition of 'struct ipv6_mreq'
     75 */
     76/* From <linux/if_bridge.h> */
     77#define BRCTL_GET_VERSION 0
     78#define BRCTL_GET_BRIDGES 1
     79#define BRCTL_ADD_BRIDGE 2
     80#define BRCTL_DEL_BRIDGE 3
     81#define BRCTL_ADD_IF 4
     82#define BRCTL_DEL_IF 5
     83#define BRCTL_GET_BRIDGE_INFO 6
     84#define BRCTL_GET_PORT_LIST 7
     85#define BRCTL_SET_BRIDGE_FORWARD_DELAY 8
     86#define BRCTL_SET_BRIDGE_HELLO_TIME 9
     87#define BRCTL_SET_BRIDGE_MAX_AGE 10
     88#define BRCTL_SET_AGEING_TIME 11
     89#define BRCTL_SET_GC_INTERVAL 12
     90#define BRCTL_GET_PORT_INFO 13
     91#define BRCTL_SET_BRIDGE_STP_STATE 14
     92#define BRCTL_SET_BRIDGE_PRIORITY 15
     93#define BRCTL_SET_PORT_PRIORITY 16
     94#define BRCTL_SET_PATH_COST 17
     95#define BRCTL_GET_FDB_ENTRIES 18
     96struct __bridge_info {
     97    uint64_t designated_root;
     98    uint64_t bridge_id;
     99    uint32_t root_path_cost;
     100    uint32_t max_age;
     101    uint32_t hello_time;
     102    uint32_t forward_delay;
     103    uint32_t bridge_max_age;
     104    uint32_t bridge_hello_time;
     105    uint32_t bridge_forward_delay;
     106    uint8_t  topology_change;
     107    uint8_t  topology_change_detected;
     108    uint8_t  root_port;
     109    uint8_t  stp_enabled;
     110    uint32_t ageing_time;
     111    uint32_t gc_interval;
     112    uint32_t hello_timer_value;
     113    uint32_t tcn_timer_value;
     114    uint32_t topology_change_timer_value;
     115    uint32_t gc_timer_value;
     116};
     117/* end <linux/if_bridge.h> */
    68118
    69119/* FIXME: These 4 funcs are not really clean and could be improved */
     
    79129    if (sscanf(time_str, "%lf", &secs) != 1)
    80130# endif
    81         bb_error_msg_and_die(bb_msg_invalid_arg, time_str, "timespec");
     131        bb_error_msg_and_die(bb_msg_invalid_arg_to, time_str, "timespec");
    82132    tv->tv_sec = secs;
    83133    tv->tv_usec = 1000000 * (secs - tv->tv_sec);
     
    156206        key = index_in_strings(keywords, *argv);
    157207        if (key == -1) /* no match found in keywords array, bail out. */
    158             bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
     208            bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name);
    159209        argv++;
    160210        fd = xsocket(AF_INET, SOCK_STREAM, 0);
     
    168218                        (unsigned long) bridx, MAX_PORTS);
    169219            num = xioctl(fd, SIOCGIFBR, args);
    170             printf("bridge name\tbridge id\t\tSTP enabled\tinterfaces\n");
     220            puts("bridge name\tbridge id\t\tSTP enabled\tinterfaces");
    171221            for (i = 0; i < num; i++) {
    172222                char ifname[IFNAMSIZ];
     
    187237                x = (unsigned char *) &bi.bridge_id;
    188238                for (j = 0; j < 8; j++) {
    189                     printf("%.2x", x[j]);
     239                    printf("%02x", x[j]);
    190240                    if (j == 1)
    191241                        bb_putchar('.');
     
    250300            int onoff = index_in_strings(no_yes, *argv);
    251301            if (onoff < 0)
    252                 bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
     302                bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name);
    253303            onoff = (unsigned)onoff / 4;
    254304            arm_ioctl(args, BRCTL_SET_BRIDGE_STP_STATE, onoff, 0);
     
    283333                port = if_nametoindex(*argv++);
    284334                if (!port)
    285                     bb_error_msg_and_die(bb_msg_invalid_arg, *argv, "port");
     335                    bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, "port");
    286336                memset(ifidx, 0, sizeof ifidx);
    287337                arm_ioctl(args, BRCTL_GET_PORT_LIST, (unsigned long)ifidx,
  • branches/3.3/mindi-busybox/networking/dnsd.c

    r3232 r3621  
    195195        /* we assume (do not check) that query_string
    196196         * ends in ".in-addr.arpa" */
    197          && strncmp(d->rip, query_string, strlen(d->rip)) == 0
     197         && is_prefixed_with(query_string, d->rip)
    198198        ) {
    199199#if DEBUG
  • branches/3.3/mindi-busybox/networking/ether-wake.c

    r3232 r3621  
    6363 *   doing so only works with adapters configured for unicast+broadcast Rx
    6464 *   filter.  That configuration consumes more power.
    65 */
     65 */
    6666
    6767//usage:#define ether_wake_trivial_usage
    68 //usage:       "[-b] [-i iface] [-p aa:bb:cc:dd[:ee:ff]] MAC"
     68//usage:       "[-b] [-i IFACE] [-p aa:bb:cc:dd[:ee:ff]/a.b.c.d] MAC"
    6969//usage:#define ether_wake_full_usage "\n\n"
    7070//usage:       "Send a magic packet to wake up sleeping machines.\n"
    7171//usage:       "MAC must be a station address (00:11:22:33:44:55) or\n"
    7272//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"
     73//usage:     "\n    -b      Broadcast the packet"
     74//usage:     "\n    -i IFACE    Interface to use (default eth0)"
     75//usage:     "\n    -p PASSWORD Append four or six byte PASSWORD to the packet"
    7676
    7777#include "libbb.h"
     
    122122    if (eap) {
    123123        bb_debug_msg("The target station address is %s\n\n", ether_ntoa(eap));
    124 #if !defined(__UCLIBC_MAJOR__) \
    125  || __UCLIBC_MAJOR__ > 0 \
    126  || __UCLIBC_MINOR__ > 9 \
    127  || (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ >= 30)
     124#if !defined(__UCLIBC__) || UCLIBC_VERSION >= KERNEL_VERSION(0, 9, 30)
    128125    } else if (ether_hostton(hostid, eaddr) == 0) {
    129126        bb_debug_msg("Station address for hostname %s is %s\n\n", hostid, ether_ntoa(eaddr));
     
    134131}
    135132
    136 static int get_fill(unsigned char *pkt, struct ether_addr *eaddr, int broadcast)
     133#define PKT_HEADER_SIZE (20 + 16*6)
     134static int fill_pkt_header(unsigned char *pkt, struct ether_addr *eaddr, int broadcast)
    137135{
    138136    int i;
     
    157155    }
    158156
    159     return 20 + 16*6; /* length of packet */
     157    return PKT_HEADER_SIZE; /* length of packet */
    160158}
    161159
     
    199197    int s;  /* Raw socket */
    200198    int pktsize;
    201     unsigned char outpack[1000];
     199    unsigned char outpack[PKT_HEADER_SIZE + 6 /* max passwd size */ + 16 /* paranoia */];
    202200
    203201    struct ether_addr eaddr;
     
    221219
    222220    /* fill out the header of the packet */
    223     pktsize = get_fill(outpack, &eaddr, flags /* & 1 OPT_BROADCAST */);
     221    pktsize = fill_pkt_header(outpack, &eaddr, flags /* & 1 OPT_BROADCAST */);
    224222
    225223    bb_debug_dump_packet(outpack, pktsize);
  • branches/3.3/mindi-busybox/networking/ftpd.c

    r3232 r3621  
    3030
    3131#include "libbb.h"
     32#include "common_bufsiz.h"
    3233#include <syslog.h>
    3334#include <netinet/tcp.h>
     
    124125    char msg_err[(sizeof("NNN " MSG_ERR) + 3) & 0xfffc];
    125126} FIX_ALIASING;
    126 #define G (*(struct globals*)&bb_common_bufsiz1)
     127#define G (*(struct globals*)bb_common_bufsiz1)
    127128#define INIT_G() do { \
     129    setup_common_bufsiz(); \
    128130    /* Moved to main */ \
    129131    /*strcpy(G.msg_ok  + 4, MSG_OK );*/ \
     
    378380    }
    379381
    380     setsockopt(remote_fd, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
     382    setsockopt_keepalive(remote_fd);
    381383    return remote_fd;
    382384}
     
    623625
    624626    argv[0] = "ftpd";
    625     argv[1] = opt; /* "-l" or "-1" */
    626 #if BB_MMU
     627    argv[1] = opt; /* "-lA" or "-1A" */
    627628    argv[2] = "--";
    628 #else
    629     /* NOMMU ftpd ls helper chdirs to argv[2],
    630      * preventing peer from seeing real root. */
    631     argv[2] = xrealloc_getcwd_or_warn(NULL);
    632 #endif
    633629    argv[3] = G.ftp_arg;
    634630    argv[4] = NULL;
     
    651647    pid = BB_MMU ? xfork() : xvfork();
    652648    if (pid == 0) {
     649#if !BB_MMU
     650        int cur_fd;
     651#endif
    653652        /* child */
    654 #if !BB_MMU
    655         /* On NOMMU, we want to execute a child - copy of ourself.
    656          * In chroot we usually can't do it. Thus we chdir
    657          * out of the chroot back to original root,
    658          * and (see later below) execute bb_busybox_exec_path
    659          * relative to current directory */
    660         if (fchdir(G.root_fd) != 0)
    661             _exit(127);
    662         /*close(G.root_fd); - close_on_exec_on() took care of this */
    663 #endif
    664653        /* NB: close _first_, then move fd! */
    665654        close(outfd.rd);
     
    675664        exit(ls_main(ARRAY_SIZE(argv) - 1, (char**) argv));
    676665#else
    677         /* + 1: we must use relative path here if in chroot.
    678          * For example, execv("/proc/self/exe") will fail, since
    679          * it looks for "/proc/self/exe" _relative to chroot!_ */
    680         execv(bb_busybox_exec_path + 1, (char**) argv);
     666        cur_fd = xopen(".", O_RDONLY | O_DIRECTORY);
     667        /* On NOMMU, we want to execute a child - copy of ourself
     668         * in order to unblock parent after vfork.
     669         * In chroot we usually can't re-exec. Thus we escape
     670         * out of the chroot back to original root.
     671         */
     672        if (G.root_fd >= 0) {
     673            if (fchdir(G.root_fd) != 0 || chroot(".") != 0)
     674                _exit(127);
     675            /*close(G.root_fd); - close_on_exec_on() took care of this */
     676        }
     677        /* Child expects directory to list on fd #3 */
     678        xmove_fd(cur_fd, 3);
     679        execv(bb_busybox_exec_path, (char**) argv);
    681680        _exit(127);
    682681#endif
     
    685684    /* parent */
    686685    close(outfd.wr);
    687 #if !BB_MMU
    688     free((char*)argv[2]);
    689 #endif
    690686    return outfd.rd;
    691687}
     
    706702        return; /* port_or_pasv_was_seen emitted error response */
    707703
    708     /* -n prevents user/groupname display,
    709      * which can be problematic in chroot */
    710     ls_fd = popen_ls((opts & LONG_LISTING) ? "-l" : "-1");
     704    ls_fd = popen_ls((opts & LONG_LISTING) ? "-lA" : "-1A");
    711705    ls_fp = xfdopen_for_read(ls_fd);
     706/* FIXME: filenames with embedded newlines are mishandled */
    712707
    713708    if (opts & USE_CTRL_CONN) {
     
    730725        if (remote_fd >= 0) {
    731726            while (1) {
    732                 line = xmalloc_fgetline(ls_fp);
     727                unsigned len;
     728
     729                line = xmalloc_fgets(ls_fp);
    733730                if (!line)
    734731                    break;
    735732                /* I've seen clients complaining when they
    736733                 * are fed with ls output with bare '\n'.
    737                  * Pity... that would be much simpler.
     734                 * Replace trailing "\n\0" with "\r\n".
    738735                 */
    739 /* TODO: need to s/LF/NUL/g here */
    740                 xwrite_str(remote_fd, line);
    741                 xwrite(remote_fd, "\r\n", 2);
     736                len = strlen(line);
     737                if (len != 0) /* paranoia check */
     738                    line[len - 1] = '\r';
     739                line[len] = '\n';
     740                xwrite(remote_fd, line, len + 1);
    742741                free(line);
    743742            }
     
    10861085    const_PORT = mk_const4('P', 'O', 'R', 'T'),
    10871086    const_PWD  = mk_const3('P', 'W', 'D'),
     1087    /* Same as PWD. Reportedly used by windows ftp client */
     1088    const_XPWD = mk_const4('X', 'P', 'W', 'D'),
    10881089    const_QUIT = mk_const4('Q', 'U', 'I', 'T'),
    10891090    const_REST = mk_const4('R', 'E', 'S', 'T'),
     
    11041105    OPT_l = (1 << 0),
    11051106    OPT_1 = (1 << 1),
    1106 #endif
    1107     OPT_v = (1 << ((!BB_MMU) * 2 + 0)),
    1108     OPT_S = (1 << ((!BB_MMU) * 2 + 1)),
    1109     OPT_w = (1 << ((!BB_MMU) * 2 + 2)) * ENABLE_FEATURE_FTP_WRITE,
     1107    OPT_A = (1 << 2),
     1108#endif
     1109    OPT_v = (1 << ((!BB_MMU) * 3 + 0)),
     1110    OPT_S = (1 << ((!BB_MMU) * 3 + 1)),
     1111    OPT_w = (1 << ((!BB_MMU) * 3 + 2)) * ENABLE_FEATURE_FTP_WRITE,
    11101112};
    11111113
     
    11171119#endif
    11181120{
     1121#if ENABLE_FEATURE_FTP_AUTHENTICATION
     1122    struct passwd *pw = NULL;
     1123#endif
    11191124    unsigned abs_timeout;
    11201125    unsigned verbose_S;
     
    11281133    opt_complementary = "t+:T+:vv:SS";
    11291134#if BB_MMU
    1130     opts = getopt32(argv,   "vS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S);
     1135    opts = getopt32(argv,    "vS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S);
    11311136#else
    1132     opts = getopt32(argv, "l1vS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S);
     1137    opts = getopt32(argv, "l1AvS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S);
    11331138    if (opts & (OPT_l|OPT_1)) {
    11341139        /* Our secret backdoor to ls */
    1135 /* TODO: pass -n? It prevents user/group resolution, which may not work in chroot anyway */
    1136 /* TODO: pass -A? It shows dot files */
    11371140/* TODO: pass --group-directories-first? would be nice, but ls doesn't do that yet */
    1138         xchdir(argv[2]);
    1139         argv[2] = (char*)"--";
     1141        if (fchdir(3) != 0)
     1142            _exit(127);
    11401143        /* memset(&G, 0, sizeof(G)); - ls_main does it */
    11411144        return ls_main(argc, argv);
     
    11751178        applet_name = xasprintf("%s[%u]", applet_name, (int)getpid());
    11761179
    1177 #if !BB_MMU
    1178     G.root_fd = xopen("/", O_RDONLY | O_DIRECTORY);
    1179     close_on_exec_on(G.root_fd);
    1180 #endif
    1181 
    1182     if (argv[optind]) {
    1183         xchroot(argv[optind]);
    1184     }
    1185 
    11861180    //umask(077); - admin can set umask before starting us
    11871181
    1188     /* Signals. We'll always take -EPIPE rather than a rude signal, thanks */
    1189     signal(SIGPIPE, SIG_IGN);
     1182    /* Signals */
     1183    bb_signals(0
     1184        /* We'll always take EPIPE rather than a rude signal, thanks */
     1185        + (1 << SIGPIPE)
     1186        /* LIST command spawns chilren. Prevent zombies */
     1187        + (1 << SIGCHLD)
     1188        , SIG_IGN);
    11901189
    11911190    /* Set up options on the command socket (do we need these all? why?) */
    1192     setsockopt(STDIN_FILENO, IPPROTO_TCP, TCP_NODELAY, &const_int_1, sizeof(const_int_1));
    1193     setsockopt(STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
     1191    setsockopt_1(STDIN_FILENO, IPPROTO_TCP, TCP_NODELAY);
     1192    setsockopt_keepalive(STDIN_FILENO);
    11941193    /* Telnet protocol over command link may send "urgent" data,
    11951194     * we prefer it to be received in the "normal" data stream: */
    1196     setsockopt(STDIN_FILENO, SOL_SOCKET, SO_OOBINLINE, &const_int_1, sizeof(const_int_1));
     1195    setsockopt_1(STDIN_FILENO, SOL_SOCKET, SO_OOBINLINE);
    11971196
    11981197    WRITE_OK(FTP_GREET);
    11991198    signal(SIGALRM, timeout_handler);
    12001199
    1201 #ifdef IF_WE_WANT_TO_REQUIRE_LOGIN
    1202     {
    1203         smallint user_was_specified = 0;
    1204         while (1) {
    1205             uint32_t cmdval = cmdio_get_cmd_and_arg();
    1206 
     1200#if ENABLE_FEATURE_FTP_AUTHENTICATION
     1201    while (1) {
     1202        uint32_t cmdval = cmdio_get_cmd_and_arg();
    12071203            if (cmdval == const_USER) {
    1208                 if (G.ftp_arg == NULL || strcasecmp(G.ftp_arg, "anonymous") != 0)
    1209                     cmdio_write_raw(STR(FTP_LOGINERR)" Server is anonymous only\r\n");
    1210                 else {
    1211                     user_was_specified = 1;
    1212                     cmdio_write_raw(STR(FTP_GIVEPWORD)" Please specify the password\r\n");
    1213                 }
    1214             } else if (cmdval == const_PASS) {
    1215                 if (user_was_specified)
    1216                     break;
    1217                 cmdio_write_raw(STR(FTP_NEEDUSER)" Login with USER\r\n");
    1218             } else if (cmdval == const_QUIT) {
    1219                 WRITE_OK(FTP_GOODBYE);
    1220                 return 0;
    1221             } else {
    1222                 cmdio_write_raw(STR(FTP_LOGINERR)" Login with USER and PASS\r\n");
     1204            pw = getpwnam(G.ftp_arg);
     1205            cmdio_write_raw(STR(FTP_GIVEPWORD)" Please specify password\r\n");
     1206        } else if (cmdval == const_PASS) {
     1207            if (check_password(pw, G.ftp_arg) > 0) {
     1208                break;  /* login success */
    12231209            }
     1210            cmdio_write_raw(STR(FTP_LOGINERR)" Login failed\r\n");
     1211            pw = NULL;
     1212        } else if (cmdval == const_QUIT) {
     1213            WRITE_OK(FTP_GOODBYE);
     1214            return 0;
     1215        } else {
     1216            cmdio_write_raw(STR(FTP_LOGINERR)" Login with USER and PASS\r\n");
    12241217        }
    12251218    }
    12261219    WRITE_OK(FTP_LOGINOK);
     1220#endif
     1221
     1222    /* Do this after auth, else /etc/passwd is not accessible */
     1223#if !BB_MMU
     1224    G.root_fd = -1;
     1225#endif
     1226    argv += optind;
     1227    if (argv[0]) {
     1228        const char *basedir = argv[0];
     1229#if !BB_MMU
     1230        G.root_fd = xopen("/", O_RDONLY | O_DIRECTORY);
     1231        close_on_exec_on(G.root_fd);
     1232#endif
     1233        if (chroot(basedir) == 0)
     1234            basedir = "/";
     1235#if !BB_MMU
     1236        else {
     1237            close(G.root_fd);
     1238            G.root_fd = -1;
     1239        }
     1240#endif
     1241        /*
     1242         * If chroot failed, assume that we aren't root,
     1243         * and at least chdir to the specified DIR
     1244         * (older versions were dying with error message).
     1245         * If chroot worked, move current dir to new "/":
     1246         */
     1247        xchdir(basedir);
     1248    }
     1249
     1250#if ENABLE_FEATURE_FTP_AUTHENTICATION
     1251    change_identity(pw);
    12271252#endif
    12281253
     
    12931318        else if (cmdval == const_SYST)
    12941319            cmdio_write_raw(STR(FTP_SYSTOK)" UNIX Type: L8\r\n");
    1295         else if (cmdval == const_PWD)
     1320        else if (cmdval == const_PWD || cmdval == const_XPWD)
    12961321            handle_pwd();
    12971322        else if (cmdval == const_CWD)
  • branches/3.3/mindi-busybox/networking/ftpgetput.c

    r3232 r3621  
    5151
    5252#include "libbb.h"
     53#include "common_bufsiz.h"
    5354
    5455struct globals {
     
    6162    char buf[4]; /* actually [BUFSZ] */
    6263} FIX_ALIASING;
    63 #define G (*(struct globals*)&bb_common_bufsiz1)
     64#define G (*(struct globals*)bb_common_bufsiz1)
    6465enum { BUFSZ = COMMON_BUFSIZE - offsetof(struct globals, buf) };
    65 struct BUG_G_too_big {
    66     char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
    67 };
    6866#define user           (G.user          )
    6967#define password       (G.password      )
     
    7371#define do_continue    (G.do_continue   )
    7472#define buf            (G.buf           )
    75 #define INIT_G() do { } while (0)
     73#define INIT_G() do { \
     74    setup_common_bufsiz(); \
     75    BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
     76} while (0)
    7677
    7778
  • branches/3.3/mindi-busybox/networking/hostname.c

    r3232 r3621  
    107107        OPT_s = 0x8,
    108108        OPT_F = 0x10,
    109         OPT_dfis = 0xf,
     109        OPT_dfi = 0x7,
    110110    };
    111111
     
    135135        opts = OPT_d;
    136136
    137     if (opts & OPT_dfis) {
     137    if (opts & OPT_dfi) {
    138138        /* Cases when we need full hostname (or its part) */
    139139        struct hostent *hp;
     
    160160            }
    161161        }
     162    } else if (opts & OPT_s) {
     163        strchrnul(buf, '.')[0] = '\0';
     164        puts(buf);
    162165    } else if (opts & OPT_F) {
    163166        /* Set the hostname */
  • branches/3.3/mindi-busybox/networking/httpd.c

    r3232 r3621  
    126126
    127127#include "libbb.h"
     128#include "common_bufsiz.h"
    128129#if ENABLE_PAM
    129130/* PAM may include <locale.h>. We may need to undefine bbox's stub define: */
     
    134135# include <security/pam_misc.h>
    135136#endif
    136 #if ENABLE_FEATURE_HTTPD_USE_SENDFILE
     137#if ENABLE_FEATURE_USE_SENDFILE
    137138# include <sys/sendfile.h>
    138139#endif
     
    308309#endif
    309310    char *iobuf;            /* [IOBUF_SIZE] */
    310 #define hdr_buf bb_common_bufsiz1
     311#define        hdr_buf bb_common_bufsiz1
     312#define sizeof_hdr_buf COMMON_BUFSIZE
    311313    char *hdr_ptr;
    312314    int hdr_cnt;
     
    369371#endif
    370372#define INIT_G() do { \
     373    setup_common_bufsiz(); \
    371374    SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
    372375    IF_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \
     
    698701            }
    699702            *host_port++ = '\0';
    700             if (strncmp(host_port, "http://", 7) == 0)
     703            if (is_prefixed_with(host_port, "http://"))
    701704                host_port += 7;
    702705            if (*host_port == '\0') {
     
    968971#endif
    969972    if (responseNum == HTTP_MOVED_TEMPORARILY) {
    970         len += sprintf(iobuf + len, "Location: %s/%s%s\r\n",
     973        /* Responding to "GET /dir" with
     974         * "HTTP/1.0 302 Found" "Location: /dir/"
     975         * - IOW, asking them to repeat with a slash.
     976         * Here, overflow IS possible, can't use sprintf:
     977         * mkdir test
     978         * python -c 'print("get /test?" + ("x" * 8192))' | busybox httpd -i -h .
     979         */
     980        len += snprintf(iobuf + len, IOBUF_SIZE-3 - len,
     981                "Location: %s/%s%s\r\n",
    971982                found_moved_temporarily,
    972983                (g_query ? "?" : ""),
    973984                (g_query ? g_query : ""));
     985        if (len > IOBUF_SIZE-3)
     986            len = IOBUF_SIZE-3;
    974987    }
    975988
    976989#if ENABLE_FEATURE_HTTPD_ERROR_PAGES
    977990    if (error_page && access(error_page, R_OK) == 0) {
    978         strcat(iobuf, "\r\n");
    979         len += 2;
    980 
    981         if (DEBUG)
     991        iobuf[len++] = '\r';
     992        iobuf[len++] = '\n';
     993        if (DEBUG) {
     994            iobuf[len] = '\0';
    982995            fprintf(stderr, "headers: '%s'\n", iobuf);
     996        }
    983997        full_write(STDOUT_FILENO, iobuf, len);
    984998        if (DEBUG)
     
    10221036                responseNum, responseString, infoString);
    10231037    }
    1024     if (DEBUG)
     1038    if (DEBUG) {
     1039        iobuf[len] = '\0';
    10251040        fprintf(stderr, "headers: '%s'\n", iobuf);
     1041    }
    10261042    if (full_write(STDOUT_FILENO, iobuf, len) != len) {
    10271043        if (verbose > 1)
     
    10541070    while (1) {
    10551071        if (hdr_cnt <= 0) {
    1056             hdr_cnt = safe_read(STDIN_FILENO, hdr_buf, sizeof(hdr_buf));
     1072            hdr_cnt = safe_read(STDIN_FILENO, hdr_buf, sizeof_hdr_buf);
    10571073            if (hdr_cnt <= 0)
    10581074                break;
     
    11051121    /* NB: breaking out of this loop jumps to log_and_exit() */
    11061122    out_cnt = 0;
     1123    pfd[FROM_CGI].fd = fromCgi_rd;
     1124    pfd[FROM_CGI].events = POLLIN;
     1125    pfd[TO_CGI].fd = toCgi_wr;
    11071126    while (1) {
    1108         memset(pfd, 0, sizeof(pfd));
    1109 
    1110         pfd[FROM_CGI].fd = fromCgi_rd;
    1111         pfd[FROM_CGI].events = POLLIN;
    1112 
    1113         if (toCgi_wr) {
    1114             pfd[TO_CGI].fd = toCgi_wr;
    1115             if (hdr_cnt > 0) {
    1116                 pfd[TO_CGI].events = POLLOUT;
    1117             } else if (post_len > 0) {
    1118                 pfd[0].events = POLLIN;
     1127        /* Note: even pfd[0].events == 0 won't prevent
     1128         * revents == POLLHUP|POLLERR reports from closed stdin.
     1129         * Setting fd to -1 works: */
     1130        pfd[0].fd = -1;
     1131        pfd[0].events = POLLIN;
     1132        pfd[0].revents = 0; /* probably not needed, paranoia */
     1133
     1134        /* We always poll this fd, thus kernel always sets revents: */
     1135        /*pfd[FROM_CGI].events = POLLIN; - moved out of loop */
     1136        /*pfd[FROM_CGI].revents = 0; - not needed */
     1137
     1138        /* gcc-4.8.0 still doesnt fill two shorts with one insn :( */
     1139        /* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47059 */
     1140        /* hopefully one day it will... */
     1141        pfd[TO_CGI].events = POLLOUT;
     1142        pfd[TO_CGI].revents = 0; /* needed! */
     1143
     1144        if (toCgi_wr && hdr_cnt <= 0) {
     1145            if (post_len > 0) {
     1146                /* Expect more POST data from network */
     1147                pfd[0].fd = 0;
    11191148            } else {
    11201149                /* post_len <= 0 && hdr_cnt <= 0:
     
    11281157
    11291158        /* Now wait on the set of sockets */
    1130         count = safe_poll(pfd, toCgi_wr ? TO_CGI+1 : FROM_CGI+1, -1);
     1159        count = safe_poll(pfd, hdr_cnt > 0 ? TO_CGI+1 : FROM_CGI+1, -1);
    11311160        if (count <= 0) {
    11321161#if 0
     
    11451174
    11461175        if (pfd[TO_CGI].revents) {
    1147             /* hdr_cnt > 0 here due to the way pfd[TO_CGI].events set */
     1176            /* hdr_cnt > 0 here due to the way poll() called */
    11481177            /* Have data from peer and can write to CGI */
    11491178            count = safe_write(toCgi_wr, hdr_ptr, hdr_cnt);
     
    11661195             * and there *is* data to read from the peer
    11671196             * (POSTDATA) */
    1168             //count = post_len > (int)sizeof(hdr_buf) ? (int)sizeof(hdr_buf) : post_len;
     1197            //count = post_len > (int)sizeof_hdr_buf ? (int)sizeof_hdr_buf : post_len;
    11691198            //count = safe_read(STDIN_FILENO, hdr_buf, count);
    1170             count = safe_read(STDIN_FILENO, hdr_buf, sizeof(hdr_buf));
     1199            count = safe_read(STDIN_FILENO, hdr_buf, sizeof_hdr_buf);
    11711200            if (count > 0) {
    11721201                hdr_cnt = count;
     
    12101239                count = 0;
    12111240                /* "Status" header format is: "Status: 302 Redirected\r\n" */
    1212                 if (out_cnt >= 8 && memcmp(rbuf, "Status: ", 8) == 0) {
     1241                if (out_cnt >= 7 && memcmp(rbuf, "Status:", 7) == 0) {
    12131242                    /* send "HTTP/1.0 " */
    12141243                    if (full_write(STDOUT_FILENO, HTTP_200, 9) != 9)
    12151244                        break;
    1216                     rbuf += 8; /* skip "Status: " */
    1217                     count = out_cnt - 8;
     1245                    rbuf += 7; /* skip "Status:" */
     1246                    count = out_cnt - 7;
    12181247                    out_cnt = -1; /* buffering off */
    12191248                } else if (out_cnt >= 4) {
     
    16121641    if (what & SEND_HEADERS)
    16131642        send_headers(HTTP_OK);
    1614 #if ENABLE_FEATURE_HTTPD_USE_SENDFILE
     1643#if ENABLE_FEATURE_USE_SENDFILE
    16151644    {
    16161645        off_t offset = range_start;
     
    16421671    }
    16431672    if (count < 0) {
    1644  IF_FEATURE_HTTPD_USE_SENDFILE(fin:)
     1673 IF_FEATURE_USE_SENDFILE(fin:)
    16451674        if (verbose > 1)
    16461675            bb_perror_msg("error");
     
    17101739            break;
    17111740        case PAM_ERROR_MSG:
    1712             case PAM_TEXT_INFO:
    1713                 s = "";
     1741        case PAM_TEXT_INFO:
     1742            s = "";
    17141743            break;
    17151744        default:
     
    18821911    Htaccess_Proxy *p;
    18831912    for (p = proxy; p; p = p->next) {
    1884         if (strncmp(url, p->url_from, strlen(p->url_from)) == 0)
     1913        if (is_prefixed_with(url, p->url_from))
    18851914            return p;
    18861915    }
     
    19651994
    19661995    /* Determine type of request (GET/POST) */
    1967     urlp = strpbrk(iobuf, " \t");
     1996    // rfc2616: method and URI is separated by exactly one space
     1997    //urlp = strpbrk(iobuf, " \t"); - no, tab isn't allowed
     1998    urlp = strchr(iobuf, ' ');
    19681999    if (urlp == NULL)
    19692000        send_headers_and_exit(HTTP_BAD_REQUEST);
     
    19832014        send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
    19842015#endif
    1985     urlp = skip_whitespace(urlp);
     2016    // rfc2616: method and URI is separated by exactly one space
     2017    //urlp = skip_whitespace(urlp); - should not be necessary
    19862018    if (urlp[0] != '/')
    19872019        send_headers_and_exit(HTTP_BAD_REQUEST);
     
    21682200                /* We know only bytes=NNN-[MMM] */
    21692201                char *s = skip_whitespace(iobuf + sizeof("Range:")-1);
    2170                 if (strncmp(s, "bytes=", 6) == 0) {
     2202                if (is_prefixed_with(s, "bytes=") == 0) {
    21712203                    s += sizeof("bytes=")-1;
    21722204                    range_start = BB_STRTOOFF(s, &s, 10);
     
    22542286
    22552287#if ENABLE_FEATURE_HTTPD_CGI
    2256     if (strncmp(tptr, "cgi-bin/", 8) == 0) {
     2288    if (is_prefixed_with(tptr, "cgi-bin/")) {
    22572289        if (tptr[8] == '\0') {
    22582290            /* protect listing "cgi-bin/" */
     
    23372369
    23382370        /* set the KEEPALIVE option to cull dead connections */
    2339         setsockopt(n, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
     2371        setsockopt_keepalive(n);
    23402372
    23412373        if (fork() == 0) {
     
    23802412
    23812413        /* set the KEEPALIVE option to cull dead connections */
    2382         setsockopt(n, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
     2414        setsockopt_keepalive(n);
    23832415
    23842416        if (vfork() == 0) {
  • branches/3.3/mindi-busybox/networking/ifconfig.c

    r3232 r3621  
    5757
    5858#if ENABLE_FEATURE_IFCONFIG_SLIP
    59 # include <net/if_slip.h>
     59# include <linux/if_slip.h>
    6060#endif
    6161
     
    265265    { NULL,          0,             ARG_HOSTNAME,    (IFF_UP | IFF_RUNNING) }
    266266};
    267 
    268 #if ENABLE_FEATURE_IFCONFIG_HW
    269 /* Input an Ethernet address and convert to binary. */
    270 static 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
    310267
    311268int ifconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  • branches/3.3/mindi-busybox/networking/ifenslave.c

    r3232 r3621  
    578578                /* remember the error and skip it */
    579579                bb_perror_msg(
    580                     "skipping %s: can't get flags",
    581                     slave_ifname);
     580                    "skipping %s: can't get %s",
     581                    slave_ifname, "flags");
    582582                res = rv;
    583583                continue;
     
    596596                /* remember the error and skip it */
    597597                bb_perror_msg(
    598                     "skipping %s: can't get settings",
    599                     slave_ifname);
     598                    "skipping %s: can't get %s",
     599                    slave_ifname, "settings");
    600600                res = rv;
    601601                continue;
  • branches/3.3/mindi-busybox/networking/ifplugd.c

    r3232 r3621  
    3939#include <linux/ethtool.h>
    4040#ifdef HAVE_NET_ETHERNET_H
    41 # include <net/ethernet.h>
     41/* musl breakage:
     42 * In file included from /usr/include/net/ethernet.h:10,
     43 *                  from networking/ifplugd.c:41:
     44 * /usr/include/netinet/if_ether.h:96: error: redefinition of 'struct ethhdr'
     45 *
     46 * Build succeeds without it on musl. Commented it out.
     47 * If on your system you need it, consider removing <linux/ethtool.h>
     48 * and copy-pasting its definitions here (<linux/ethtool.h> is what pulls in
     49 * conflicting definition of struct ethhdr on musl).
     50 */
     51/* # include <net/ethernet.h> */
    4252#endif
    4353#include <linux/netlink.h>
     
    4858#define __user
    4959#include <linux/wireless.h>
     60
     61#ifndef ETH_ALEN
     62# define ETH_ALEN  6
     63#endif
    5064
    5165/*
     
    290304};
    291305
    292 
    293 
    294306static const char *strstatus(int status)
    295307{
     
    452464{
    453465    int iface_len;
    454     char replybuf[1024];
     466    /* Buffer was 1K, but on linux-3.9.9 it was reported to be too small.
     467     * netlink.h: "limit to 8K to avoid MSG_TRUNC when PAGE_SIZE is very large".
     468     * Note: on error returns (-1) we exit, no need to free replybuf.
     469     */
     470    enum { BUF_SIZE = 8 * 1024 };
     471    char *replybuf = xmalloc(BUF_SIZE);
    455472
    456473    iface_len = strlen(G.iface);
     
    459476        ssize_t bytes;
    460477
    461         bytes = recv(netlink_fd, &replybuf, sizeof(replybuf), MSG_DONTWAIT);
     478        bytes = recv(netlink_fd, replybuf, BUF_SIZE, MSG_DONTWAIT);
    462479        if (bytes < 0) {
    463480            if (errno == EAGAIN)
    464                 return G.iface_exists;
     481                goto ret;
    465482            if (errno == EINTR)
    466483                continue;
    467 
    468484            bb_perror_msg("netlink: recv");
    469485            return -1;
     
    508524    }
    509525
     526 ret:
     527    free(replybuf);
    510528    return G.iface_exists;
    511529}
     
    557575    if (opts & FLAG_KILL) {
    558576        if (pid_from_pidfile > 0)
    559             kill(pid_from_pidfile, SIGQUIT);
     577            /* Upstream tool use SIGINT for -k */
     578            kill(pid_from_pidfile, SIGINT);
    560579        return EXIT_SUCCESS;
    561580    }
     
    646665    while (1) {
    647666        int iface_status_old;
    648         int iface_exists_old;
    649667
    650668        switch (bb_got_signal) {
     
    672690        }
    673691
    674         iface_status_old = iface_status;
    675         iface_exists_old = G.iface_exists;
    676 
    677692        if ((opts & FLAG_MONITOR)
    678693         && (netlink_pollfd[0].revents & POLLIN)
    679694        ) {
     695            int iface_exists_old;
     696
     697            iface_exists_old = G.iface_exists;
    680698            G.iface_exists = check_existence_through_netlink();
    681699            if (G.iface_exists < 0) /* error */
     
    690708
    691709        /* note: if !G.iface_exists, returns DOWN */
     710        iface_status_old = iface_status;
    692711        iface_status = detect_link();
    693712        if (iface_status == IFSTATUS_ERR) {
     
    703722            if (delay_time) {
    704723                /* link restored its old status before
    705                  * we run script. don't run the script: */
     724                 * we ran script. don't run the script: */
    706725                delay_time = 0;
    707726            } else {
     
    711730                if (iface_status == IFSTATUS_DOWN)
    712731                    delay_time += G.delay_down;
    713                 if (delay_time == 0)
    714                     delay_time++;
     732#if 0  /* if you are back in 1970... */
     733                if (delay_time == 0) {
     734                    sleep(1);
     735                    delay_time = 1;
     736                }
     737#endif
    715738            }
    716739        }
    717740
    718741        if (delay_time && (int)(monotonic_sec() - delay_time) >= 0) {
    719             delay_time = 0;
    720742            if (run_script(iface_status_str) != 0)
    721743                goto exiting;
     744            delay_time = 0;
    722745        }
    723746    } /* while (1) */
  • branches/3.3/mindi-busybox/networking/ifupdown.c

    r3232 r3621  
    4545
    4646#include "libbb.h"
     47#include "common_bufsiz.h"
    4748/* After libbb.h, since it needs sys/types.h on some systems */
    4849#include <sys/utsname.h>
     
    130131    char *shell;
    131132} FIX_ALIASING;
    132 #define G (*(struct globals*)&bb_common_bufsiz1)
    133 #define INIT_G() do { } while (0)
     133#define G (*(struct globals*)bb_common_bufsiz1)
     134#define INIT_G() do { setup_common_bufsiz(); } while (0)
    134135
    135136
     
    290291                     * unlike ifconfig, ip doesnt want <class>
    291292                     * (usually "ether" keyword). Skip it. */
    292                     if (strncmp(command, "hwaddress", 9) == 0) {
     293                    if (is_prefixed_with(command, "hwaddress")) {
    293294                        varvalue = skip_whitespace(skip_non_whitespace(varvalue));
    294295                    }
     
    299300                    /* Sigh...  Add a special case for 'ip' to convert from
    300301                     * dotted quad to bit count style netmasks.  */
    301                     if (strncmp(command, "bnmask", 6) == 0) {
     302                    if (is_prefixed_with(command, "bnmask")) {
    302303                        unsigned res;
    303304                        varvalue = get_var("netmask", 7, ifd);
     
    395396    result = execute("ip addr add %address%/%netmask% dev %iface%[[ label %label%]]", ifd, exec);
    396397    result += execute("ip link set[[ mtu %mtu%]][[ addr %hwaddress%]] %iface% up", ifd, exec);
    397     /* Was: "[[ ip ....%gateway% ]]". Removed extra spaces w/o checking */
    398     result += execute("[[ip route add ::/0 via %gateway%]][[ prio %metric%]]", ifd, exec);
     398    /* Reportedly, IPv6 needs "dev %iface%", but IPv4 does not: */
     399    result += execute("[[ip route add ::/0 via %gateway% dev %iface%]][[ metric %metric%]]", ifd, exec);
    399400# else
    400401    result = execute("ifconfig %iface%[[ media %media%]][[ hw %hwaddress%]][[ mtu %mtu%]] up", ifd, exec);
     
    422423    result += execute("ip link set %iface% up", ifd, exec);
    423424    result += execute("ip addr add %address%/%netmask% dev %iface%", ifd, exec);
    424     result += execute("[[ip route add ::/0 via %gateway%]]", ifd, exec);
     425    /* Reportedly, IPv6 needs "dev %iface%", but IPv4 does not: */
     426    result += execute("[[ip route add ::/0 via %gateway% dev %iface%]]", ifd, exec);
    425427    return ((result == 4) ? 4 : 0);
    426428}
     
    483485            "dev %iface%[[ peer %pointopoint%]][[ label %label%]]", ifd, exec);
    484486    result += execute("ip link set[[ mtu %mtu%]][[ addr %hwaddress%]] %iface% up", ifd, exec);
    485     result += execute("[[ip route add default via %gateway% dev %iface%[[ prio %metric%]]]]", ifd, exec);
     487    result += execute("[[ip route add default via %gateway% dev %iface%[[ metric %metric%]]]]", ifd, exec);
    486488    return ((result == 3) ? 3 : 0);
    487489# else
     
    535537    },
    536538    { "udhcpc",
    537         "udhcpc " UDHCPC_CMD_OPTIONS " -p /var/run/udhcpc.%iface%.pid -i %iface%[[ -H %hostname%]][[ -c %client%]]"
     539        "udhcpc " UDHCPC_CMD_OPTIONS " -p /var/run/udhcpc.%iface%.pid -i %iface%[[ -x hostname:%hostname%]][[ -c %client%]]"
    538540                "[[ -s %script%]][[ %udhcpc_opts%]]",
    539541        "kill `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null",
     
    556558#  endif
    557559    for (i = 0; i < ARRAY_SIZE(ext_dhcp_clients); i++) {
    558         if (exists_execable(ext_dhcp_clients[i].name))
     560        if (executable_exists(ext_dhcp_clients[i].name))
    559561            return execute(ext_dhcp_clients[i].startcmd, ifd, exec);
    560562    }
     
    575577#  endif
    576578    return execute("udhcpc " UDHCPC_CMD_OPTIONS " -p /var/run/udhcpc.%iface%.pid "
    577             "-i %iface%[[ -H %hostname%]][[ -c %client%]][[ -s %script%]][[ %udhcpc_opts%]]",
     579            "-i %iface%[[ -x hostname:%hostname%]][[ -c %client%]][[ -s %script%]][[ %udhcpc_opts%]]",
    578580            ifd, exec);
    579581}
     
    593595
    594596    for (i = 0; i < ARRAY_SIZE(ext_dhcp_clients); i++) {
    595         if (exists_execable(ext_dhcp_clients[i].name)) {
     597        if (executable_exists(ext_dhcp_clients[i].name)) {
    596598            result = execute(ext_dhcp_clients[i].stopcmd, ifd, exec);
    597599            if (result)
     
    686688#endif  /* FEATURE_IFUPDOWN_IPV4 */
    687689
     690static int FAST_FUNC link_up_down(struct interface_defn_t *ifd UNUSED_PARAM, execfn *exec UNUSED_PARAM)
     691{
     692    return 1;
     693}
     694
     695static const struct method_t link_methods[] = {
     696    { "none", link_up_down, link_up_down }
     697};
     698
     699static const struct address_family_t addr_link = {
     700    "link", ARRAY_SIZE(link_methods), link_methods
     701};
    688702
    689703/* Returns pointer to the next word, or NULL.
     
    744758}
    745759
    746 static struct interfaces_file_t *read_interfaces(const char *filename)
     760static struct interfaces_file_t *read_interfaces(const char *filename, struct interfaces_file_t *defn)
    747761{
    748762    /* Let's try to be compatible.
     
    759773     * A "\" character at the very end of the line indicates the next line
    760774     * should be treated as a continuation of the current one.
     775     *
     776     * Lines  beginning with "source" are used to include stanzas from
     777     * other files, so configuration can be split into many files.
     778     * The word "source" is followed by the path of file to be sourced.
    761779     */
    762780#if ENABLE_FEATURE_IFUPDOWN_MAPPING
     
    764782#endif
    765783    struct interface_defn_t *currif = NULL;
    766     struct interfaces_file_t *defn;
    767784    FILE *f;
    768785    char *buf;
     
    771788    enum { NONE, IFACE, MAPPING } currently_processing = NONE;
    772789
    773     defn = xzalloc(sizeof(*defn));
     790    if (!defn)
     791        defn = xzalloc(sizeof(*defn));
     792
     793    debug_noise("reading %s file:\n", filename);
    774794    f = xfopen_for_read(filename);
    775795
     
    826846                &addr_inet6,
    827847#endif
     848                &addr_link,
    828849                NULL
    829850            };
     
    831852            char *address_family_name;
    832853            char *method_name;
    833             llist_t *iface_list;
    834854
    835855            currif = xzalloc(sizeof(*currif));
     
    856876            if (!currif->method)
    857877                bb_error_msg_and_die("unknown method \"%s\"", method_name);
    858 
     878#if 0
     879// Allegedly, Debian allows a duplicate definition:
     880// iface eth0 inet static
     881//     address 192.168.0.15
     882//     netmask 255.255.0.0
     883//     gateway 192.168.0.1
     884//
     885// iface eth0 inet static
     886//     address 10.0.0.1
     887//     netmask 255.255.255.0
     888//
     889// This adds *two* addresses to eth0 (probably requires use of "ip", not "ifconfig"
     890//
     891            llist_t *iface_list;
    859892            for (iface_list = defn->ifaces; iface_list; iface_list = iface_list->link) {
    860893                struct interface_defn_t *tmp = (struct interface_defn_t *) iface_list->data;
     
    865898                }
    866899            }
     900#endif
    867901            llist_add_to_end(&(defn->ifaces), (char*)currif);
    868902
     
    882916            }
    883917            currently_processing = NONE;
     918        } else if (strcmp(first_word, "source") == 0) {
     919            read_interfaces(next_word(&rest_of_line), defn);
    884920        } else {
    885921            switch (currently_processing) {
     
    935971    }
    936972    fclose(f);
     973    debug_noise("\ndone reading %s\n\n", filename);
    937974
    938975    return defn;
     
    11381175static llist_t *find_iface_state(llist_t *state_list, const char *iface)
    11391176{
    1140     unsigned iface_len = strlen(iface);
    11411177    llist_t *search = state_list;
    11421178
    11431179    while (search) {
    1144         if ((strncmp(search->data, iface, iface_len) == 0)
    1145          && (search->data[iface_len] == '=')
     1180        char *after_iface = is_prefixed_with(search->data, iface);
     1181        if (after_iface
     1182         && *after_iface == '='
    11461183        ) {
    11471184            return search;
     
    12001237    }
    12011238
    1202     debug_noise("reading %s file:\n", interfaces);
    1203     defn = read_interfaces(interfaces);
    1204     debug_noise("\ndone reading %s\n\n", interfaces);
     1239    defn = read_interfaces(interfaces, NULL);
    12051240
    12061241    /* Create a list of interfaces to work on */
     
    12201255        bool okay = 0;
    12211256        int cmds_ret;
     1257        bool curr_failure = 0;
    12221258
    12231259        iface = xstrdup(target_list->data);
     
    12851321                cmds_ret = cmds(currif);
    12861322                if (cmds_ret == -1) {
    1287                     bb_error_msg("don't seem to have all the variables for %s/%s",
     1323                    bb_error_msg("don't have all variables for %s/%s",
    12881324                            liface, currif->address_family->name);
    1289                     any_failures = 1;
     1325                    any_failures = curr_failure = 1;
    12901326                } else if (cmds_ret == 0) {
    1291                     any_failures = 1;
     1327                    any_failures = curr_failure = 1;
    12921328                }
    12931329
     
    13101346            llist_t *iface_state = find_iface_state(state_list, iface);
    13111347
    1312             if (cmds == iface_up && !any_failures) {
     1348            if (cmds == iface_up && !curr_failure) {
    13131349                char *newiface = xasprintf("%s=%s", iface, liface);
    13141350                if (!iface_state) {
  • branches/3.3/mindi-busybox/networking/inetd.c

    r3232 r3621  
    171171
    172172#include "libbb.h"
     173#include "common_bufsiz.h"
    173174
    174175#if ENABLE_FEATURE_INETD_RPC
     
    328329    char line[256];          /* _at least_ 256, see LINE_SIZE */
    329330} FIX_ALIASING;
    330 #define G (*(struct globals*)&bb_common_bufsiz1)
     331#define G (*(struct globals*)bb_common_bufsiz1)
    331332enum { LINE_SIZE = COMMON_BUFSIZE - offsetof(struct globals, line) };
    332 struct BUG_G_too_big {
    333     char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
    334 };
    335333#define rlim_ofile_cur  (G.rlim_ofile_cur )
    336334#define rlim_ofile      (G.rlim_ofile     )
     
    353351#define line            (G.line           )
    354352#define INIT_G() do { \
     353    setup_common_bufsiz(); \
     354    BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
    355355    rlim_ofile_cur = OPEN_MAX; \
    356356    global_queuelen = 128; \
     
    646646
    647647/* gcc generates much more code if this is inlined */
    648 static servtab_t *parse_one_line(void)
     648static NOINLINE servtab_t *parse_one_line(void)
    649649{
    650650    int argc;
     
    676676            free(default_local_hostname);
    677677            default_local_hostname = sep->se_local_hostname;
     678            /*sep->se_local_hostname = NULL; - redundant */
     679            /* (we'll overwrite this field anyway) */
    678680            goto more;
    679681        }
     
    689691        bb_error_msg("parse error on line %u, line is ignored",
    690692                parser->lineno);
    691         free_servtab_strings(sep);
    692693        /* Just "goto more" can make sep to carry over e.g.
    693694         * "rpc"-ness (by having se_rpcver_lo != 0).
    694695         * We will be more paranoid: */
     696        free_servtab_strings(sep);
    695697        free(sep);
    696698        goto new;
     
    726728#endif
    727729        }
    728         if (strncmp(arg, "rpc/", 4) == 0) {
     730        if (is_prefixed_with(arg, "rpc/")) {
    729731#if ENABLE_FEATURE_INETD_RPC
    730732            unsigned n;
     
    816818#endif
    817819    argc = 0;
    818     while ((arg = token[6+argc]) != NULL && argc < MAXARGV)
     820    while (argc < MAXARGV && (arg = token[6+argc]) != NULL)
    819821        sep->se_argv[argc++] = xstrdup(arg);
    820822    /* Some inetd.conf files have no argv's, not even argv[0].
     
    835837    }
    836838
    837 //  bb_info_msg(
    838 //      "ENTRY[%s][%s][%s][%d][%d][%d][%d][%d][%s][%s][%s]",
    839 //      sep->se_local_hostname, sep->se_service, sep->se_proto, sep->se_wait, sep->se_proto_no,
    840 //      sep->se_max, sep->se_count, sep->se_time, sep->se_user, sep->se_group, sep->se_program);
     839    //bb_error_msg(
     840    //  "ENTRY[%s][%s][%s][%d][%d][%d][%d][%d][%s][%s][%s]",
     841    //  sep->se_local_hostname, sep->se_service, sep->se_proto, sep->se_wait, sep->se_proto_no,
     842    //  sep->se_max, sep->se_count, sep->se_time, sep->se_user, sep->se_group, sep->se_program);
    841843
    842844    /* check if the hostname specifier is a comma separated list
     
    16551657    time_t t;
    16561658
    1657     t = time(NULL);
     1659    time(&t);
    16581660    fdprintf(s, "%.24s\r\n", ctime(&t));
    16591661}
  • branches/3.3/mindi-busybox/networking/interface.c

    r3232 r3621  
    9090static const char* FAST_FUNC INET_sprint(struct sockaddr *sap, int numeric)
    9191{
    92     static char *buff; /* defaults to NULL */
    93 
    94     free(buff);
    9592    if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
    9693        return "[NONE SET]";
    97     buff = INET_rresolve((struct sockaddr_in *) sap, numeric, 0xffffff00);
    98     return buff;
     94    return auto_string(INET_rresolve((struct sockaddr_in *) sap, numeric, 0xffffff00));
    9995}
    10096
     
    172168static const char* FAST_FUNC INET6_sprint(struct sockaddr *sap, int numeric)
    173169{
    174     static char *buff;
    175 
    176     free(buff);
    177170    if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
    178171        return "[NONE SET]";
    179     buff = INET6_rresolve((struct sockaddr_in6 *) sap, numeric);
    180     return buff;
     172    return auto_string(INET6_rresolve((struct sockaddr_in6 *) sap, numeric));
    181173}
    182174
     
    224216static char* FAST_FUNC UNSPEC_print(unsigned char *ptr)
    225217{
    226     static char *buff;
    227 
     218    char *buff;
    228219    char *pos;
    229220    unsigned int i;
    230221
    231     if (!buff)
    232         buff = xmalloc(sizeof(struct sockaddr) * 3 + 1);
     222    buff = auto_string(xmalloc(sizeof(struct sockaddr) * 3 + 1));
    233223    pos = buff;
    234224    for (i = 0; i < sizeof(struct sockaddr); i++) {
     
    713703static char* FAST_FUNC ether_print(unsigned char *ptr)
    714704{
    715     static char *buff;
    716 
    717     free(buff);
     705    char *buff;
    718706    buff = xasprintf("%02X:%02X:%02X:%02X:%02X:%02X",
    719707             (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377),
    720708             (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377)
    721709        );
    722     return buff;
    723 }
    724 
    725 static int FAST_FUNC ether_input(const char *bufp, struct sockaddr *sap);
     710    return auto_string(buff);
     711}
    726712
    727713static const struct hwtype ether_hwtype = {
     
    731717    .alen  = ETH_ALEN,
    732718    .print = ether_print,
    733     .input = ether_input
    734 };
    735 
    736 static unsigned hexchar2int(char c)
    737 {
    738     if (isdigit(c))
    739         return c - '0';
    740     c &= ~0x20; /* a -> A */
    741     if ((unsigned)(c - 'A') <= 5)
    742         return c - ('A' - 10);
    743     return ~0U;
    744 }
    745 
    746 /* Input an Ethernet address and convert to binary. */
    747 static int FAST_FUNC ether_input(const char *bufp, struct sockaddr *sap)
    748 {
    749     unsigned char *ptr;
    750     char c;
    751     int i;
    752     unsigned val;
    753 
    754     sap->sa_family = ether_hwtype.type;
    755     ptr = (unsigned char*) sap->sa_data;
    756 
    757     i = 0;
    758     while ((*bufp != '\0') && (i < ETH_ALEN)) {
    759         val = hexchar2int(*bufp++) * 0x10;
    760         if (val > 0xff) {
    761             errno = EINVAL;
    762             return -1;
    763         }
    764         c = *bufp;
    765         if (c == ':' || c == 0)
    766             val >>= 4;
    767         else {
    768             val |= hexchar2int(c);
    769             if (val > 0xff) {
    770                 errno = EINVAL;
    771                 return -1;
    772             }
    773         }
    774         if (c != 0)
    775             bufp++;
    776         *ptr++ = (unsigned char) val;
    777         i++;
    778 
    779         /* We might get a semicolon here - not required. */
    780         if (*bufp == ':') {
    781             bufp++;
    782         }
    783     }
    784     return 0;
    785 }
     719    .input = in_ether
     720};
    786721
    787722static const struct hwtype ppp_hwtype = {
     
    928863{
    929864    FILE *f;
    930     char addr6[40], devname[20];
     865    char addr6[40], devname[21];
    931866    struct sockaddr_in6 sap;
    932867    int plen, scope, dad_status, if_idx;
     
    947882                    addr6p[0], addr6p[1], addr6p[2], addr6p[3],
    948883                    addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
     884            memset(&sap, 0, sizeof(sap));
    949885            inet_pton(AF_INET6, addr6,
    950886                      (struct sockaddr *) &sap.sin6_addr);
  • branches/3.3/mindi-busybox/networking/ip.c

    r3232 r3621  
    1717//usage:    IF_FEATURE_IP_LINK("link | ")
    1818//usage:    IF_FEATURE_IP_TUNNEL("tunnel | ")
     19//usage:    IF_FEATURE_IP_NEIGH("neigh | ")
    1920//usage:    IF_FEATURE_IP_RULE("rule")
    2021//usage:       "} {COMMAND}"
     
    2627//usage:    IF_FEATURE_IP_LINK("link | ")
    2728//usage:    IF_FEATURE_IP_TUNNEL("tunnel | ")
     29//usage:    IF_FEATURE_IP_NEIGH("neigh | ")
    2830//usage:    IF_FEATURE_IP_RULE("rule")
    2931//usage:       "}\n"
     
    3436//usage:       "        [dev STRING] [to PREFIX] }"
    3537//usage:#define ipaddr_full_usage "\n\n"
    36 //usage:       "ipaddr {add|delete} IFADDR dev STRING\n"
     38//usage:       "ipaddr {add|change|replace|delete} IFADDR dev STRING\n"
    3739//usage:       "ipaddr {show|flush} [dev STRING] [scope SCOPE-ID]\n"
    3840//usage:       "    [to PREFIX] [label PATTERN]\n"
     
    8183//usage:       "    [[i|o]seq] [[i|o]key KEY] [[i|o]csum]\n"
    8284//usage:       "    [ttl TTL] [tos TOS] [[no]pmtudisc] [dev PHYS_DEV]"
     85//usage:
     86//usage:#define ipneigh_trivial_usage
     87//usage:       "{ show | flush} [ to PREFIX ] [ dev DEV ] [ nud STATE ]"
     88//usage:#define ipneigh_full_usage "\n\n"
     89//usage:       "ipneigh { show | flush} [ to PREFIX ] [ dev DEV ] [ nud STATE ]"
    8390
    8491#include "libbb.h"
     
    9198 || ENABLE_FEATURE_IP_LINK \
    9299 || ENABLE_FEATURE_IP_TUNNEL \
    93  || ENABLE_FEATURE_IP_RULE
     100 || ENABLE_FEATURE_IP_RULE \
     101 || ENABLE_FEATURE_IP_NEIGH
    94102
    95103static int FAST_FUNC ip_print_help(char **argv UNUSED_PARAM)
     
    141149}
    142150#endif
     151#if ENABLE_FEATURE_IP_NEIGH
     152int ipneigh_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     153int ipneigh_main(int argc UNUSED_PARAM, char **argv)
     154{
     155    return ip_do(do_ipneigh, argv);
     156}
     157#endif
    143158
    144159
     
    154169        IF_FEATURE_IP_TUNNEL("tunl\0")
    155170        IF_FEATURE_IP_RULE("rule\0")
     171        IF_FEATURE_IP_NEIGH("neigh\0")
    156172        ;
    157173    static const ip_func_ptr_t ip_func_ptrs[] = {
     
    164180        IF_FEATURE_IP_TUNNEL(do_iptunnel,)
    165181        IF_FEATURE_IP_RULE(do_iprule,)
     182        IF_FEATURE_IP_NEIGH(do_ipneigh,)
    166183    };
    167184    ip_func_ptr_t ip_func;
  • branches/3.3/mindi-busybox/networking/ipcalc.c

    r3232 r3621  
    1414
    1515//usage:#define ipcalc_trivial_usage
    16 //usage:       "[OPTIONS] ADDRESS[[/]NETMASK] [NETMASK]"
     16//usage:       "[OPTIONS] ADDRESS"
     17//usage:       IF_FEATURE_IPCALC_FANCY("[/PREFIX]") " [NETMASK]"
    1718//usage:#define ipcalc_full_usage "\n\n"
    1819//usage:       "Calculate IP network settings from a IP address\n"
  • branches/3.3/mindi-busybox/networking/isrv.c

    r2725 r3621  
    195195}
    196196
    197 void BUG_sizeof_fd_set_is_strange(void);
    198197static void handle_fd_set(isrv_state_t *state, fd_set *fds, int (*h)(int, void **))
    199198{
     
    204203    int fd_cnt = FD_COUNT;
    205204
    206     if (LONG_CNT * sizeof(long) != sizeof(fd_set))
    207         BUG_sizeof_fd_set_is_strange();
     205    BUILD_BUG_ON(LONG_CNT * sizeof(long) != sizeof(fd_set));
    208206
    209207    fds_pos = 0;
  • branches/3.3/mindi-busybox/networking/isrv.h

    r2725 r3621  
    2424int isrv_register_peer(isrv_state_t *state, void *param);
    2525
    26 /* driver */
     26/* Driver:
     27 *
     28 * Select on listen_fd for <linger_timeout> (or forever if 0).
     29 *
     30 * If we time out and we have no peers, exit.
     31 * If we have peers, call do_timeout(peer_param),
     32 * if it returns !0, peer is removed.
     33 *
     34 * If listen_fd is active, accept new connection ("peer"),
     35 * call new_peer() on it, and if it returns 0,
     36 * add it to fds to select on.
     37 * Now, select will wait for <timeout>, not <linger_timeout>
     38 * (as long as we have more than zero peers).
     39 *
     40 * If a peer's fd is active, we call do_rd() on it if read
     41 * bit was set, and then do_wr() if write bit was also set.
     42 * If either returns !0, peer is removed.
     43 * Reaching this place also resets timeout counter for this peer.
     44 *
     45 * Note that peer must indicate that he wants to be selected
     46 * for read and/or write using isrv_want_rd()/isrv_want_wr()
     47 * [can be called in new_peer() or in do_rd()/do_wr()].
     48 * If it never wants to be selected for write, do_wr()
     49 * will never be called (can be NULL).
     50 */
    2751void isrv_run(
    2852    int listen_fd,
  • branches/3.3/mindi-busybox/networking/isrv_identd.c

    r3232 r3621  
    1919
    2020#include "libbb.h"
     21#include "common_bufsiz.h"
    2122#include <syslog.h>
    2223#include "isrv.h"
     
    2627typedef struct identd_buf_t {
    2728    int pos;
    28     int fd_flag;
    29     char buf[64 - 2*sizeof(int)];
     29    char buf[64 - sizeof(int)];
    3030} identd_buf_t;
    3131
     
    4343        return peer; /* failure, unregister peer */
    4444
    45     buf->fd_flag = fcntl(fd, F_GETFL) | O_NONBLOCK;
     45    ndelay_on(fd);
    4646    isrv_want_rd(state, fd);
    4747    return 0;
     
    5252    identd_buf_t *buf = *paramp;
    5353    char *cur, *p;
    54     int retval = 0; /* session is ok (so far) */
    5554    int sz;
    5655
    5756    cur = buf->buf + buf->pos;
    5857
    59     if (buf->fd_flag & O_NONBLOCK)
    60         fcntl(fd, F_SETFL, buf->fd_flag);
    61     sz = safe_read(fd, cur, sizeof(buf->buf) - buf->pos);
     58    sz = safe_read(fd, cur, sizeof(buf->buf) - 1 - buf->pos);
    6259
    6360    if (sz < 0) {
    6461        if (errno != EAGAIN)
    65             goto term; /* terminate this session if !EAGAIN */
    66         goto ok;
     62            goto term;
     63        return 0; /* "session is ok" */
    6764    }
    6865
     
    7269    if (p)
    7370        *p = '\0';
    74     if (!p && sz && buf->pos <= (int)sizeof(buf->buf))
    75         goto ok;
     71    if (!p && sz)
     72        return 0;  /* "session is ok" */
     73
    7674    /* Terminate session. If we are in server mode, then
    7775     * fd is still in nonblocking mode - we never block here */
    78     if (fd == 0) fd++; /* inetd mode? then write to fd 1 */
     76    if (fd == 0)
     77        fd++; /* inetd mode? then write to fd 1 */
    7978    fdprintf(fd, "%s : USERID : UNIX : %s\r\n", buf->buf, bogouser);
     79    /*
     80     * Why bother if we are going to close fd now anyway?
     81     * if (server)
     82     *  ndelay_off(fd);
     83     */
    8084 term:
    8185    free(buf);
    82     retval = 1; /* terminate */
    83  ok:
    84     if (buf->fd_flag & O_NONBLOCK)
    85         fcntl(fd, F_SETFL, buf->fd_flag & ~O_NONBLOCK);
    86     return retval;
     86    return 1; /* "terminate" */
    8787}
    8888
     
    9696    identd_buf_t *buf = xzalloc(sizeof(*buf));
    9797    /* buf->pos = 0; - xzalloc did it */
    98     /* We do NOT want nonblocking I/O here! */
    99     /* buf->fd_flag = 0; - xzalloc did it */
    10098    do
    10199        alarm(TIMEOUT);
     100        /* Note: we do NOT want nonblocking I/O here! */
    102101    while (do_rd(0, (void*)&buf) == 0);
    103102}
     
    118117    int fd;
    119118
     119    setup_common_bufsiz();
     120
    120121    opt = getopt32(argv, "fiwb:", &bind_address);
    121122    strcpy(bogouser, "nobody");
    122123    if (argv[optind])
    123         strncpy(bogouser, argv[optind], sizeof(bogouser));
     124        strncpy(bogouser, argv[optind], COMMON_BUFSIZE - 1);
    124125
    125126    /* Daemonize if no -f and no -i and no -w */
  • branches/3.3/mindi-busybox/networking/libiproute/Kbuild.src

    r2725 r3621  
    6565    rt_names.o \
    6666    utils.o
     67
     68lib-$(CONFIG_FEATURE_IP_NEIGH) += \
     69    ip_parse_common_args.o \
     70    ipneigh.o \
     71    libnetlink.o \
     72    ll_map.o \
     73    rt_names.o \
     74    utils.o
  • branches/3.3/mindi-busybox/networking/libiproute/ip_common.h

    r2725 r3621  
    2525int FAST_FUNC do_iproute(char **argv);
    2626int FAST_FUNC do_iprule(char **argv);
    27 //int FAST_FUNC do_ipneigh(char **argv);
     27int FAST_FUNC do_ipneigh(char **argv);
    2828int FAST_FUNC do_iptunnel(char **argv);
    2929int FAST_FUNC do_iplink(char **argv);
  • branches/3.3/mindi-busybox/networking/libiproute/ip_parse_common_args.c

    r2725 r3621  
    6868            arg = index_in_strings(families, *argv);
    6969            if (arg < 0)
    70                 invarg(*argv, "protocol family");
     70                invarg_1_to_2(*argv, "family");
    7171            /* now arg == 0, 1 or 2 */
    7272        } else {
  • branches/3.3/mindi-busybox/networking/libiproute/ipaddress.c

    r3232 r3621  
    1414
    1515#include "ip_common.h"  /* #include "libbb.h" is inside */
     16#include "common_bufsiz.h"
    1617#include "rt_names.h"
    1718#include "utils.h"
     
    4041typedef struct filter_t filter_t;
    4142
    42 #define G_filter (*(filter_t*)&bb_common_bufsiz1)
    43 
     43#define G_filter (*(filter_t*)bb_common_bufsiz1)
     44#define INIT_G() do { setup_common_bufsiz(); } while (0)
    4445
    4546static void print_link_flags(unsigned flags, unsigned mdown)
     
    138139        unsigned m_flag = 0;
    139140        if (tb[IFLA_LINK]) {
    140             SPRINT_BUF(b1);
    141141            int iflink = *(int*)RTA_DATA(tb[IFLA_LINK]);
    142142            if (iflink == 0)
    143143                printf("@NONE: ");
    144144            else {
    145                 printf("@%s: ", ll_idx_n2a(iflink, b1));
     145                printf("@%s: ", ll_index_to_name(iflink));
    146146                m_flag = ll_index_to_flags(iflink);
    147147                m_flag = !(m_flag & IFF_UP);
     
    159159#ifdef IFLA_MASTER
    160160    if (tb[IFLA_MASTER]) {
    161         SPRINT_BUF(b1);
    162         printf("master %s ", ll_idx_n2a(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1));
     161        printf("master %s ", ll_index_to_name(*(int*)RTA_DATA(tb[IFLA_MASTER])));
    163162    }
    164163#endif
     
    217216    struct ifaddrmsg *ifa = NLMSG_DATA(n);
    218217    int len = n->nlmsg_len;
    219     struct rtattr * rta_tb[IFA_MAX+1];
    220     char abuf[256];
    221     SPRINT_BUF(b1);
     218    struct rtattr *rta_tb[IFA_MAX+1];
    222219
    223220    if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR)
     
    251248            label = RTA_DATA(rta_tb[IFA_LABEL]);
    252249        else
    253             label = ll_idx_n2a(ifa->ifa_index, b1);
     250            label = ll_index_to_name(ifa->ifa_index);
    254251        if (fnmatch(G_filter.label, label, 0) != 0)
    255252            return 0;
     
    295292
    296293    if (rta_tb[IFA_LOCAL]) {
    297         fputs(rt_addr_n2a(ifa->ifa_family,
    298                           RTA_DATA(rta_tb[IFA_LOCAL]),
    299                           abuf, sizeof(abuf)), stdout);
     294        fputs(rt_addr_n2a(ifa->ifa_family, RTA_DATA(rta_tb[IFA_LOCAL])),
     295            stdout
     296        );
    300297
    301298        if (rta_tb[IFA_ADDRESS] == NULL
     
    305302        } else {
    306303            printf(" peer %s/%d ",
    307                 rt_addr_n2a(ifa->ifa_family,
    308                         RTA_DATA(rta_tb[IFA_ADDRESS]),
    309                         abuf, sizeof(abuf)),
    310                 ifa->ifa_prefixlen);
     304                rt_addr_n2a(ifa->ifa_family, RTA_DATA(rta_tb[IFA_ADDRESS])),
     305                ifa->ifa_prefixlen
     306            );
    311307        }
    312308    }
     
    315311        printf("brd %s ",
    316312            rt_addr_n2a(ifa->ifa_family,
    317                     RTA_DATA(rta_tb[IFA_BROADCAST]),
    318                     abuf, sizeof(abuf))
     313                RTA_DATA(rta_tb[IFA_BROADCAST]))
    319314        );
    320315    }
     
    322317        printf("any %s ",
    323318            rt_addr_n2a(ifa->ifa_family,
    324                     RTA_DATA(rta_tb[IFA_ANYCAST]),
    325                     abuf, sizeof(abuf))
     319                RTA_DATA(rta_tb[IFA_ANYCAST]))
    326320        );
    327321    }
    328     printf("scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1));
     322    printf("scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope));
    329323    if (ifa->ifa_flags & IFA_F_SECONDARY) {
    330324        ifa->ifa_flags &= ~IFA_F_SECONDARY;
     
    459453            if (rtnl_rtscope_a2n(&scope, *argv)) {
    460454                if (strcmp(*argv, "all") != 0) {
    461                     invarg(*argv, "scope");
     455                    invarg_1_to_2(*argv, "scope");
    462456                }
    463457                scope = RT_SCOPE_NOWHERE;
     
    557551                    }
    558552                    if (G_filter.label) {
    559                         SPRINT_BUF(b1);
    560553                        const char *label;
    561554                        if (tb[IFA_LABEL])
    562555                            label = RTA_DATA(tb[IFA_LABEL]);
    563556                        else
    564                             label = ll_idx_n2a(ifa->ifa_index, b1);
     557                            label = ll_index_to_name(ifa->ifa_index);
    565558                        if (fnmatch(G_filter.label, label, 0) != 0)
    566559                            continue;
     
    599592
    600593/* Return value becomes exitcode. It's okay to not return at all */
    601 static int ipaddr_modify(int cmd, char **argv)
     594static int ipaddr_modify(int cmd, int flags, char **argv)
    602595{
    603596    static const char option[] ALIGN1 =
     
    623616
    624617    req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
    625     req.n.nlmsg_flags = NLM_F_REQUEST;
     618    req.n.nlmsg_flags = NLM_F_REQUEST | flags;
    626619    req.n.nlmsg_type = cmd;
    627620    req.ifa.ifa_family = preferred_family;
    628621
    629622    while (*argv) {
    630         const smalluint arg = index_in_strings(option, *argv);
     623        unsigned arg = index_in_strings(option, *argv);
     624        /* if search fails, "local" is assumed */
     625        if ((int)arg >= 0)
     626            NEXT_ARG();
     627
    631628        if (arg <= 1) { /* peer, remote */
    632             NEXT_ARG();
    633 
    634629            if (peer_len) {
    635630                duparg("peer", *argv);
     
    644639        } else if (arg <= 3) { /* broadcast, brd */
    645640            inet_prefix addr;
    646             NEXT_ARG();
    647641            if (brd_len) {
    648642                duparg("broadcast", *argv);
     
    661655        } else if (arg == 4) { /* anycast */
    662656            inet_prefix addr;
    663             NEXT_ARG();
    664657            if (any_len) {
    665658                duparg("anycast", *argv);
     
    673666        } else if (arg == 5) { /* scope */
    674667            uint32_t scope = 0;
    675             NEXT_ARG();
    676668            if (rtnl_rtscope_a2n(&scope, *argv)) {
    677                 invarg(*argv, "scope");
     669                invarg_1_to_2(*argv, "scope");
    678670            }
    679671            req.ifa.ifa_scope = scope;
    680672            scoped = 1;
    681673        } else if (arg == 6) { /* dev */
    682             NEXT_ARG();
    683674            d = *argv;
    684675        } else if (arg == 7) { /* label */
    685             NEXT_ARG();
    686676            l = *argv;
    687677            addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l) + 1);
    688678        } else {
    689             if (arg == 8) /* local */
    690                 NEXT_ARG();
     679            /* local (specified or assumed) */
    691680            if (local_len) {
    692681                duparg2("local", *argv);
     
    706695        bb_error_msg_and_die("need \"dev IFACE\"");
    707696    }
    708     if (l && strncmp(d, l, strlen(d)) != 0) {
     697    if (l && !is_prefixed_with(l, d)) {
    709698        bb_error_msg_and_die("\"dev\" (%s) must match \"label\" (%s)", d, l);
    710699    }
     
    725714        brd = peer;
    726715        if (brd.bitlen <= 30) {
    727             for (i=31; i>=brd.bitlen; i--) {
     716            for (i = 31; i >= brd.bitlen; i--) {
    728717                if (brd_len == -1)
    729718                    brd.data[0] |= htonl(1<<(31-i));
     
    754743{
    755744    static const char commands[] ALIGN1 =
    756         "add\0""delete\0""list\0""show\0""lst\0""flush\0";
    757     smalluint cmd = 2;
     745        /* 0    1         2      3          4         5       6       7      8 */
     746        "add\0""change\0""chg\0""replace\0""delete\0""list\0""show\0""lst\0""flush\0";
     747    int cmd = 2;
     748
     749    INIT_G();
     750
    758751    if (*argv) {
    759752        cmd = index_in_substrings(commands, *argv);
    760         if (cmd > 5)
    761             bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
     753        if (cmd < 0)
     754            invarg_1_to_2(*argv, applet_name);
    762755        argv++;
    763         if (cmd <= 1)
    764             return ipaddr_modify((cmd == 0) ? RTM_NEWADDR : RTM_DELADDR, argv);
    765     }
    766     /* 2 == list, 3 == show, 4 == lst */
    767     return ipaddr_list_or_flush(argv, cmd == 5);
    768 }
     756        if (cmd <= 4) {
     757            return ipaddr_modify(
     758                /*cmd:*/ cmd == 4 ? RTM_DELADDR : RTM_NEWADDR,
     759                /*flags:*/
     760                    cmd == 0 ? NLM_F_CREATE|NLM_F_EXCL : /* add */
     761                    cmd == 1 || cmd == 2 ? NLM_F_REPLACE : /* change */
     762                    cmd == 3 ? NLM_F_CREATE|NLM_F_REPLACE : /* replace */
     763                    0 /* delete */
     764            , argv);
     765        }
     766    }
     767    return ipaddr_list_or_flush(argv, cmd == 8);
     768}
  • branches/3.3/mindi-busybox/networking/libiproute/iplink.c

    r3232 r3621  
    22/*
    33 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
     4 *          Patrick McHardy <kaber@trash.net>
    45 *
    56 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    67 */
    78#include <net/if.h>
    8 #include <net/if_packet.h>
     9/*#include <net/if_packet.h> - not needed? */
    910#include <netpacket/packet.h>
    1011#include <netinet/if_ether.h>
    1112
     13#include <linux/if_vlan.h>
    1214#include "ip_common.h"  /* #include "libbb.h" is inside */
    1315#include "rt_names.h"
    1416#include "utils.h"
    1517
     18#undef  ETH_P_8021AD
     19#define ETH_P_8021AD            0x88A8
     20#undef  VLAN_FLAG_REORDER_HDR
     21#define VLAN_FLAG_REORDER_HDR   0x1
     22#undef  VLAN_FLAG_GVRP
     23#define VLAN_FLAG_GVRP          0x2
     24#undef  VLAN_FLAG_LOOSE_BINDING
     25#define VLAN_FLAG_LOOSE_BINDING 0x4
     26#undef  VLAN_FLAG_MVRP
     27#define VLAN_FLAG_MVRP          0x8
     28#undef  IFLA_VLAN_PROTOCOL
     29#define IFLA_VLAN_PROTOCOL      5
     30
    1631#ifndef IFLA_LINKINFO
    1732# define IFLA_LINKINFO 18
    1833# define IFLA_INFO_KIND 1
     34# define IFLA_INFO_DATA 2
     35#endif
     36
     37#ifndef IFLA_VLAN_MAX
     38# define IFLA_VLAN_ID 1
     39# define IFLA_VLAN_FLAGS 2
     40struct ifla_vlan_flags {
     41    uint32_t    flags;
     42    uint32_t    mask;
     43};
    1944#endif
    2045
    2146/* taken from linux/sockios.h */
    2247#define SIOCSIFNAME  0x8923  /* set interface name */
     48
     49#if 0
     50# define dbg(...) bb_error_msg(__VA_ARGS__)
     51#else
     52# define dbg(...) ((void)0)
     53#endif
    2354
    2455/* Exits on error */
     
    278309}
    279310
     311static void vlan_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size)
     312{
     313    static const char keywords[] ALIGN1 =
     314        "id\0"
     315        "protocol\0"
     316        "reorder_hdr\0"
     317        "gvrp\0"
     318        "mvrp\0"
     319        "loose_binding\0"
     320    ;
     321    static const char protocols[] ALIGN1 =
     322        "802.1q\0"
     323        "802.1ad\0"
     324    ;
     325    static const char str_on_off[] ALIGN1 =
     326        "on\0"
     327        "off\0"
     328    ;
     329    enum {
     330        ARG_id = 0,
     331        ARG_reorder_hdr,
     332        ARG_gvrp,
     333        ARG_mvrp,
     334        ARG_loose_binding,
     335        ARG_protocol,
     336    };
     337    enum {
     338        PROTO_8021Q = 0,
     339        PROTO_8021AD,
     340    };
     341    enum {
     342        PARM_on = 0,
     343        PARM_off
     344    };
     345    int arg;
     346    uint16_t id, proto;
     347    struct ifla_vlan_flags flags = {};
     348
     349    while (*argv) {
     350        arg = index_in_substrings(keywords, *argv);
     351        if (arg < 0)
     352            invarg_1_to_2(*argv, "type vlan");
     353
     354        NEXT_ARG();
     355        if (arg == ARG_id) {
     356            id = get_u16(*argv, "id");
     357            addattr_l(n, size, IFLA_VLAN_ID, &id, sizeof(id));
     358        } else if (arg == ARG_protocol) {
     359            arg = index_in_substrings(protocols, *argv);
     360            if (arg == PROTO_8021Q)
     361                proto = ETH_P_8021Q;
     362            else if (arg == PROTO_8021AD)
     363                proto = ETH_P_8021AD;
     364            else
     365                bb_error_msg_and_die("unknown VLAN encapsulation protocol '%s'",
     366                                     *argv);
     367            addattr_l(n, size, IFLA_VLAN_PROTOCOL, &proto, sizeof(proto));
     368        } else {
     369            int param = index_in_strings(str_on_off, *argv);
     370            if (param < 0)
     371                die_must_be_on_off(nth_string(keywords, arg));
     372
     373            if (arg == ARG_reorder_hdr) {
     374                flags.mask |= VLAN_FLAG_REORDER_HDR;
     375                flags.flags &= ~VLAN_FLAG_REORDER_HDR;
     376                if (param == PARM_on)
     377                    flags.flags |= VLAN_FLAG_REORDER_HDR;
     378            } else if (arg == ARG_gvrp) {
     379                flags.mask |= VLAN_FLAG_GVRP;
     380                flags.flags &= ~VLAN_FLAG_GVRP;
     381                if (param == PARM_on)
     382                    flags.flags |= VLAN_FLAG_GVRP;
     383            } else if (arg == ARG_mvrp) {
     384                flags.mask |= VLAN_FLAG_MVRP;
     385                flags.flags &= ~VLAN_FLAG_MVRP;
     386                if (param == PARM_on)
     387                    flags.flags |= VLAN_FLAG_MVRP;
     388            } else { /*if (arg == ARG_loose_binding) */
     389                flags.mask |= VLAN_FLAG_LOOSE_BINDING;
     390                flags.flags &= ~VLAN_FLAG_LOOSE_BINDING;
     391                if (param == PARM_on)
     392                    flags.flags |= VLAN_FLAG_LOOSE_BINDING;
     393            }
     394        }
     395        argv++;
     396    }
     397
     398    if (flags.mask)
     399        addattr_l(n, size, IFLA_VLAN_FLAGS, &flags, sizeof(flags));
     400}
     401
    280402#ifndef NLMSG_TAIL
    281403#define NLMSG_TAIL(nmsg) \
     
    283405#endif
    284406/* Return value becomes exitcode. It's okay to not return at all */
    285 static int do_change(char **argv, const unsigned rtm)
     407static int do_add_or_delete(char **argv, const unsigned rtm)
    286408{
    287409    static const char keywords[] ALIGN1 =
    288         "link\0""name\0""type\0""dev\0";
     410        "link\0""name\0""type\0""dev\0""address\0";
    289411    enum {
    290412        ARG_link,
     
    292414        ARG_type,
    293415        ARG_dev,
     416        ARG_address,
    294417    };
    295418    struct rtnl_handle rth;
     
    300423    } req;
    301424    smalluint arg;
    302     char *name_str = NULL, *link_str = NULL, *type_str = NULL, *dev_str = NULL;
     425    char *name_str = NULL;
     426    char *link_str = NULL;
     427    char *type_str = NULL;
     428    char *dev_str = NULL;
     429    char *address_str = NULL;
    303430
    304431    memset(&req, 0, sizeof(req));
     
    313440    while (*argv) {
    314441        arg = index_in_substrings(keywords, *argv);
     442        if (arg == ARG_type) {
     443            NEXT_ARG();
     444            type_str = *argv++;
     445            dbg("type_str:'%s'", type_str);
     446            break;
     447        }
    315448        if (arg == ARG_link) {
    316449            NEXT_ARG();
    317450            link_str = *argv;
     451            dbg("link_str:'%s'", link_str);
    318452        } else if (arg == ARG_name) {
    319453            NEXT_ARG();
    320454            name_str = *argv;
    321         } else if (arg == ARG_type) {
    322             NEXT_ARG();
    323             type_str = *argv;
     455            dbg("name_str:'%s'", name_str);
     456        } else if (arg == ARG_address) {
     457            NEXT_ARG();
     458            address_str = *argv;
     459            dbg("address_str:'%s'", name_str);
    324460        } else {
    325461            if (arg == ARG_dev) {
     
    329465            }
    330466            dev_str = *argv;
     467            dbg("dev_str:'%s'", dev_str);
    331468        }
    332469        argv++;
     
    340477        addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type_str,
    341478                strlen(type_str));
     479
     480        if (*argv) {
     481            struct rtattr *data = NLMSG_TAIL(&req.n);
     482            addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0);
     483
     484            if (strcmp(type_str, "vlan") == 0)
     485                vlan_parse_opt(argv, &req.n, sizeof(req));
     486
     487            data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
     488        }
     489
    342490        linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
    343491    }
     
    353501            addattr_l(&req.n, sizeof(req), IFLA_LINK, &idx, 4);
    354502        }
     503        if (address_str) {
     504            unsigned char abuf[32];
     505            int len = ll_addr_a2n(abuf, sizeof(abuf), address_str);
     506            dbg("address len:%d", len);
     507            if (len < 0)
     508                return -1;
     509            addattr_l(&req.n, sizeof(req), IFLA_ADDRESS, abuf, len);
     510        }
    355511    }
    356512    if (name_str) {
    357513        const size_t name_len = strlen(name_str) + 1;
    358514        if (name_len < 2 || name_len > IFNAMSIZ)
    359             invarg(name_str, "name");
     515            invarg_1_to_2(name_str, "name");
    360516        addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name_str, name_len);
    361517    }
     
    365521}
    366522
     523/* Other keywords recognized by iproute2-3.12.0: */
     524#if 0
     525        } else if (matches(*argv, "broadcast") == 0 ||
     526                strcmp(*argv, "brd") == 0) {
     527            NEXT_ARG();
     528            len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
     529            if (len < 0)
     530                return -1;
     531            addattr_l(&req->n, sizeof(*req), IFLA_BROADCAST, abuf, len);
     532        } else if (matches(*argv, "txqueuelen") == 0 ||
     533                strcmp(*argv, "qlen") == 0 ||
     534                matches(*argv, "txqlen") == 0) {
     535            NEXT_ARG();
     536            if (qlen != -1)
     537                duparg("txqueuelen", *argv);
     538            if (get_integer(&qlen,  *argv, 0))
     539                invarg_1_to_2(*argv, "txqueuelen");
     540            addattr_l(&req->n, sizeof(*req), IFLA_TXQLEN, &qlen, 4);
     541        } else if (strcmp(*argv, "mtu") == 0) {
     542            NEXT_ARG();
     543            if (mtu != -1)
     544                duparg("mtu", *argv);
     545            if (get_integer(&mtu, *argv, 0))
     546                invarg_1_to_2(*argv, "mtu");
     547            addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4);
     548                } else if (strcmp(*argv, "netns") == 0) {
     549                        NEXT_ARG();
     550                        if (netns != -1)
     551                                duparg("netns", *argv);
     552            if ((netns = get_netns_fd(*argv)) >= 0)
     553                addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD, &netns, 4);
     554            else if (get_integer(&netns, *argv, 0) == 0)
     555                addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4);
     556            else
     557                                invarg_1_to_2(*argv, "netns");
     558        } else if (strcmp(*argv, "multicast") == 0) {
     559            NEXT_ARG();
     560            req->i.ifi_change |= IFF_MULTICAST;
     561            if (strcmp(*argv, "on") == 0) {
     562                req->i.ifi_flags |= IFF_MULTICAST;
     563            } else if (strcmp(*argv, "off") == 0) {
     564                req->i.ifi_flags &= ~IFF_MULTICAST;
     565            } else
     566                return on_off("multicast", *argv);
     567        } else if (strcmp(*argv, "allmulticast") == 0) {
     568            NEXT_ARG();
     569            req->i.ifi_change |= IFF_ALLMULTI;
     570            if (strcmp(*argv, "on") == 0) {
     571                req->i.ifi_flags |= IFF_ALLMULTI;
     572            } else if (strcmp(*argv, "off") == 0) {
     573                req->i.ifi_flags &= ~IFF_ALLMULTI;
     574            } else
     575                return on_off("allmulticast", *argv);
     576        } else if (strcmp(*argv, "promisc") == 0) {
     577            NEXT_ARG();
     578            req->i.ifi_change |= IFF_PROMISC;
     579            if (strcmp(*argv, "on") == 0) {
     580                req->i.ifi_flags |= IFF_PROMISC;
     581            } else if (strcmp(*argv, "off") == 0) {
     582                req->i.ifi_flags &= ~IFF_PROMISC;
     583            } else
     584                return on_off("promisc", *argv);
     585        } else if (strcmp(*argv, "trailers") == 0) {
     586            NEXT_ARG();
     587            req->i.ifi_change |= IFF_NOTRAILERS;
     588            if (strcmp(*argv, "off") == 0) {
     589                req->i.ifi_flags |= IFF_NOTRAILERS;
     590            } else if (strcmp(*argv, "on") == 0) {
     591                req->i.ifi_flags &= ~IFF_NOTRAILERS;
     592            } else
     593                return on_off("trailers", *argv);
     594        } else if (strcmp(*argv, "arp") == 0) {
     595            NEXT_ARG();
     596            req->i.ifi_change |= IFF_NOARP;
     597            if (strcmp(*argv, "on") == 0) {
     598                req->i.ifi_flags &= ~IFF_NOARP;
     599            } else if (strcmp(*argv, "off") == 0) {
     600                req->i.ifi_flags |= IFF_NOARP;
     601            } else
     602                return on_off("noarp", *argv);
     603        } else if (strcmp(*argv, "vf") == 0) {
     604            struct rtattr *vflist;
     605            NEXT_ARG();
     606            if (get_integer(&vf,  *argv, 0)) {
     607                invarg_1_to_2(*argv, "vf");
     608            }
     609            vflist = addattr_nest(&req->n, sizeof(*req),
     610                          IFLA_VFINFO_LIST);
     611            len = iplink_parse_vf(vf, &argc, &argv, req);
     612            if (len < 0)
     613                return -1;
     614            addattr_nest_end(&req->n, vflist);
     615        } else if (matches(*argv, "master") == 0) {
     616            int ifindex;
     617            NEXT_ARG();
     618            ifindex = ll_name_to_index(*argv);
     619            if (!ifindex)
     620                invarg_1_to_2(*argv, "master");
     621            addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
     622                  &ifindex, 4);
     623        } else if (matches(*argv, "nomaster") == 0) {
     624            int ifindex = 0;
     625            addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
     626                  &ifindex, 4);
     627        } else if (matches(*argv, "dynamic") == 0) {
     628            NEXT_ARG();
     629            req->i.ifi_change |= IFF_DYNAMIC;
     630            if (strcmp(*argv, "on") == 0) {
     631                req->i.ifi_flags |= IFF_DYNAMIC;
     632            } else if (strcmp(*argv, "off") == 0) {
     633                req->i.ifi_flags &= ~IFF_DYNAMIC;
     634            } else
     635                return on_off("dynamic", *argv);
     636        } else if (matches(*argv, "alias") == 0) {
     637            NEXT_ARG();
     638            addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS,
     639                  *argv, strlen(*argv));
     640            argc--; argv++;
     641            break;
     642        } else if (strcmp(*argv, "group") == 0) {
     643            NEXT_ARG();
     644            if (*group != -1)
     645                duparg("group", *argv);
     646            if (rtnl_group_a2n(group, *argv))
     647                invarg_1_to_2(*argv, "group");
     648        } else if (strcmp(*argv, "mode") == 0) {
     649            int mode;
     650            NEXT_ARG();
     651            mode = get_link_mode(*argv);
     652            if (mode < 0)
     653                invarg_1_to_2(*argv, "mode");
     654            addattr8(&req->n, sizeof(*req), IFLA_LINKMODE, mode);
     655        } else if (strcmp(*argv, "state") == 0) {
     656            int state;
     657            NEXT_ARG();
     658            state = get_operstate(*argv);
     659            if (state < 0)
     660                invarg_1_to_2(*argv, "state");
     661            addattr8(&req->n, sizeof(*req), IFLA_OPERSTATE, state);
     662        } else if (matches(*argv, "numtxqueues") == 0) {
     663            NEXT_ARG();
     664            if (numtxqueues != -1)
     665                duparg("numtxqueues", *argv);
     666            if (get_integer(&numtxqueues, *argv, 0))
     667                invarg_1_to_2(*argv, "numtxqueues");
     668            addattr_l(&req->n, sizeof(*req), IFLA_NUM_TX_QUEUES,
     669                  &numtxqueues, 4);
     670        } else if (matches(*argv, "numrxqueues") == 0) {
     671            NEXT_ARG();
     672            if (numrxqueues != -1)
     673                duparg("numrxqueues", *argv);
     674            if (get_integer(&numrxqueues, *argv, 0))
     675                invarg_1_to_2(*argv, "numrxqueues");
     676            addattr_l(&req->n, sizeof(*req), IFLA_NUM_RX_QUEUES,
     677                  &numrxqueues, 4);
     678        }
     679#endif
     680
    367681/* Return value becomes exitcode. It's okay to not return at all */
    368682int FAST_FUNC do_iplink(char **argv)
     
    371685        "add\0""delete\0""set\0""show\0""lst\0""list\0";
    372686    if (*argv) {
    373         smalluint key = index_in_substrings(keywords, *argv);
    374         if (key > 5) /* invalid argument */
    375             bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
     687        int key = index_in_substrings(keywords, *argv);
     688        if (key < 0) /* invalid argument */
     689            invarg_1_to_2(*argv, applet_name);
    376690        argv++;
    377691        if (key <= 1) /* add/delete */
    378             return do_change(argv, key ? RTM_DELLINK : RTM_NEWLINK);
    379         else if (key == 2) /* set */
     692            return do_add_or_delete(argv, key ? RTM_DELLINK : RTM_NEWLINK);
     693        if (key == 2) /* set */
    380694            return do_set(argv);
    381695    }
  • branches/3.3/mindi-busybox/networking/libiproute/iproute.c

    r3232 r3621  
    1212
    1313#include "ip_common.h"  /* #include "libbb.h" is inside */
     14#include "common_bufsiz.h"
    1415#include "rt_names.h"
    1516#include "utils.h"
     
    4445typedef struct filter_t filter_t;
    4546
    46 #define G_filter (*(filter_t*)&bb_common_bufsiz1)
     47#define G_filter (*(filter_t*)bb_common_bufsiz1)
     48#define INIT_G() do { setup_common_bufsiz(); } while (0)
    4749
    4850static int flush_update(void)
     
    5456    G_filter.flushp = 0;
    5557    return 0;
    56 }
    57 
    58 static unsigned get_hz(void)
    59 {
    60     static unsigned hz_internal;
    61     FILE *fp;
    62 
    63     if (hz_internal)
    64         return hz_internal;
    65 
    66     fp = fopen_for_read("/proc/net/psched");
    67     if (fp) {
    68         unsigned nom, denom;
    69 
    70         if (fscanf(fp, "%*08x%*08x%08x%08x", &nom, &denom) == 2)
    71             if (nom == 1000000)
    72                 hz_internal = denom;
    73         fclose(fp);
    74     }
    75     if (!hz_internal)
    76         hz_internal = sysconf(_SC_CLK_TCK);
    77     return hz_internal;
    7858}
    7959
     
    8464    int len = n->nlmsg_len;
    8565    struct rtattr *tb[RTA_MAX+1];
    86     char abuf[256];
    8766    inet_prefix dst;
    8867    inet_prefix src;
    8968    int host_len = -1;
    90     SPRINT_BUF(b1);
    9169
    9270    if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) {
     
    219197        if (NLMSG_ALIGN(G_filter.flushp) + n->nlmsg_len > G_filter.flushe) {
    220198            if (flush_update())
    221                 bb_error_msg_and_die("flush");
     199                xfunc_die();
    222200        }
    223201        fn = (void*)(G_filter.flushb + NLMSG_ALIGN(G_filter.flushp));
     
    237215    }
    238216    if (r->rtm_type != RTN_UNICAST /* && !G_filter.type - always 0 */) {
    239         printf("%s ", rtnl_rtntype_n2a(r->rtm_type, b1));
     217        printf("%s ", rtnl_rtntype_n2a(r->rtm_type));
    240218    }
    241219
    242220    if (tb[RTA_DST]) {
    243221        if (r->rtm_dst_len != host_len) {
    244             printf("%s/%u ", rt_addr_n2a(r->rtm_family,
    245                         RTA_DATA(tb[RTA_DST]),
    246                         abuf, sizeof(abuf)),
    247                     r->rtm_dst_len
    248                     );
     222            printf("%s/%u ",
     223                rt_addr_n2a(r->rtm_family, RTA_DATA(tb[RTA_DST])),
     224                r->rtm_dst_len
     225            );
    249226        } else {
    250227            printf("%s ", format_host(r->rtm_family,
    251228                        RTA_PAYLOAD(tb[RTA_DST]),
    252                         RTA_DATA(tb[RTA_DST]),
    253                         abuf, sizeof(abuf))
    254                     );
     229                        RTA_DATA(tb[RTA_DST]))
     230            );
    255231        }
    256232    } else if (r->rtm_dst_len) {
     
    261237    if (tb[RTA_SRC]) {
    262238        if (r->rtm_src_len != host_len) {
    263             printf("from %s/%u ", rt_addr_n2a(r->rtm_family,
    264                         RTA_DATA(tb[RTA_SRC]),
    265                         abuf, sizeof(abuf)),
    266                     r->rtm_src_len
    267                     );
     239            printf("from %s/%u ",
     240                rt_addr_n2a(r->rtm_family, RTA_DATA(tb[RTA_SRC])),
     241                r->rtm_src_len
     242            );
    268243        } else {
    269244            printf("from %s ", format_host(r->rtm_family,
    270245                        RTA_PAYLOAD(tb[RTA_SRC]),
    271                         RTA_DATA(tb[RTA_SRC]),
    272                         abuf, sizeof(abuf))
    273                     );
     246                        RTA_DATA(tb[RTA_SRC]))
     247            );
    274248        }
    275249    } else if (r->rtm_src_len) {
     
    279253        printf("via %s ", format_host(r->rtm_family,
    280254                    RTA_PAYLOAD(tb[RTA_GATEWAY]),
    281                     RTA_DATA(tb[RTA_GATEWAY]),
    282                     abuf, sizeof(abuf)));
     255                    RTA_DATA(tb[RTA_GATEWAY]))
     256        );
    283257    }
    284258    if (tb[RTA_OIF]) {
     
    293267         */
    294268        printf(" src %s ", rt_addr_n2a(r->rtm_family,
    295                     RTA_DATA(tb[RTA_PREFSRC]),
    296                     abuf, sizeof(abuf)));
     269                    RTA_DATA(tb[RTA_PREFSRC])));
    297270    }
    298271    if (tb[RTA_PRIORITY]) {
    299272        printf(" metric %d ", *(uint32_t*)RTA_DATA(tb[RTA_PRIORITY]));
    300273    }
     274    if (r->rtm_flags & RTNH_F_DEAD) {
     275        printf("dead ");
     276    }
     277    if (r->rtm_flags & RTNH_F_ONLINK) {
     278        printf("onlink ");
     279    }
     280    if (r->rtm_flags & RTNH_F_PERVASIVE) {
     281        printf("pervasive ");
     282    }
     283    if (r->rtm_flags & RTM_F_NOTIFY) {
     284        printf("notify ");
     285    }
     286
    301287    if (r->rtm_family == AF_INET6) {
    302288        struct rta_cacheinfo *ci = NULL;
     
    330316{
    331317    static const char keywords[] ALIGN1 =
    332         "src\0""via\0""mtu\0""lock\0""protocol\0"IF_FEATURE_IP_RULE("table\0")
    333         "dev\0""oif\0""to\0""metric\0";
     318        "src\0""via\0""mtu\0""lock\0""scope\0""protocol\0"IF_FEATURE_IP_RULE("table\0")
     319        "dev\0""oif\0""to\0""metric\0""onlink\0";
    334320    enum {
    335321        ARG_src,
    336322        ARG_via,
    337323        ARG_mtu, PARM_lock,
     324        ARG_scope,
    338325        ARG_protocol,
    339326IF_FEATURE_IP_RULE(ARG_table,)
     
    342329        ARG_to,
    343330        ARG_metric,
     331        ARG_onlink,
    344332    };
    345333    enum {
     
    360348    char *d = NULL;
    361349    smalluint ok = 0;
     350    smalluint scope_ok = 0;
    362351    int arg;
    363352
     
    368357    req.n.nlmsg_type = cmd;
    369358    req.r.rtm_family = preferred_family;
    370     if (RT_TABLE_MAIN) /* if it is zero, memset already did it */
     359    if (RT_TABLE_MAIN != 0) /* if it is zero, memset already did it */
    371360        req.r.rtm_table = RT_TABLE_MAIN;
    372     if (RT_SCOPE_NOWHERE)
     361    if (RT_SCOPE_NOWHERE != 0)
    373362        req.r.rtm_scope = RT_SCOPE_NOWHERE;
    374363
    375364    if (cmd != RTM_DELROUTE) {
    376         req.r.rtm_protocol = RTPROT_BOOT;
    377365        req.r.rtm_scope = RT_SCOPE_UNIVERSE;
    378         req.r.rtm_type = RTN_UNICAST;
     366        if (RTPROT_BOOT != 0)
     367            req.r.rtm_protocol = RTPROT_BOOT;
     368        if (RTN_UNICAST != 0)
     369            req.r.rtm_type = RTN_UNICAST;
    379370    }
    380371
     
    409400            mtu = get_unsigned(*argv, "mtu");
    410401            rta_addattr32(mxrta, sizeof(mxbuf), RTAX_MTU, mtu);
     402        } else if (arg == ARG_scope) {
     403            uint32_t scope;
     404            NEXT_ARG();
     405            if (rtnl_rtscope_a2n(&scope, *argv))
     406                invarg_1_to_2(*argv, "scope");
     407            req.r.rtm_scope = scope;
     408            scope_ok = 1;
    411409        } else if (arg == ARG_protocol) {
    412410            uint32_t prot;
    413411            NEXT_ARG();
    414412            if (rtnl_rtprot_a2n(&prot, *argv))
    415                 invarg(*argv, "protocol");
     413                invarg_1_to_2(*argv, "protocol");
    416414            req.r.rtm_protocol = prot;
    417415            ok |= proto_ok;
     
    421419            NEXT_ARG();
    422420            if (rtnl_rttable_a2n(&tid, *argv))
    423                 invarg(*argv, "table");
     421                invarg_1_to_2(*argv, "table");
    424422            req.r.rtm_table = tid;
    425423#endif
     
    432430            metric = get_u32(*argv, "metric");
    433431            addattr32(&req.n, sizeof(req), RTA_PRIORITY, metric);
     432        } else if (arg == ARG_onlink) {
     433            req.r.rtm_flags |= RTNH_F_ONLINK;
    434434        } else {
    435435            int type;
     
    483483    }
    484484
    485     if (req.r.rtm_type == RTN_LOCAL || req.r.rtm_type == RTN_NAT)
    486         req.r.rtm_scope = RT_SCOPE_HOST;
    487     else
    488     if (req.r.rtm_type == RTN_BROADCAST
    489      || req.r.rtm_type == RTN_MULTICAST
    490      || req.r.rtm_type == RTN_ANYCAST
    491     ) {
    492         req.r.rtm_scope = RT_SCOPE_LINK;
    493     }
    494     else if (req.r.rtm_type == RTN_UNICAST || req.r.rtm_type == RTN_UNSPEC) {
    495         if (cmd == RTM_DELROUTE)
    496             req.r.rtm_scope = RT_SCOPE_NOWHERE;
    497         else if (!(ok & gw_ok))
     485    if (!scope_ok) {
     486        if (req.r.rtm_type == RTN_LOCAL || req.r.rtm_type == RTN_NAT)
     487            req.r.rtm_scope = RT_SCOPE_HOST;
     488        else
     489        if (req.r.rtm_type == RTN_BROADCAST
     490         || req.r.rtm_type == RTN_MULTICAST
     491         || req.r.rtm_type == RTN_ANYCAST
     492        ) {
    498493            req.r.rtm_scope = RT_SCOPE_LINK;
     494        }
     495        else if (req.r.rtm_type == RTN_UNICAST || req.r.rtm_type == RTN_UNSPEC) {
     496            if (cmd == RTM_DELROUTE)
     497                req.r.rtm_scope = RT_SCOPE_NOWHERE;
     498            else if (!(ok & gw_ok))
     499                req.r.rtm_scope = RT_SCOPE_LINK;
     500        }
    499501    }
    500502
     
    605607            if (rtnl_rtprot_a2n(&prot, *argv)) {
    606608                if (index_in_strings(keywords, *argv) != KW_all)
    607                     invarg(*argv, "protocol");
     609                    invarg_1_to_2(*argv, "protocol");
    608610                prot = 0;
    609611                //G_filter.protocolmask = 0;
     
    630632                uint32_t tid;
    631633                if (rtnl_rttable_a2n(&tid, *argv))
    632                     invarg(*argv, "table");
     634                    invarg_1_to_2(*argv, "table");
    633635                G_filter.tb = tid;
    634636#else
    635                 invarg(*argv, "table");
     637                invarg_1_to_2(*argv, "table");
    636638#endif
    637639            }
     
    901903    unsigned flags = 0;
    902904    int cmd = RTM_NEWROUTE;
     905
     906    INIT_G();
    903907
    904908    if (!*argv)
     
    940944            return iproute_list_or_flush(argv+1, 1);
    941945        default:
    942             bb_error_msg_and_die("unknown command %s", *argv);
     946            invarg_1_to_2(*argv, applet_name);
    943947    }
    944948
  • branches/3.3/mindi-busybox/networking/libiproute/iprule.c

    r3232 r3621  
    4545    int host_len = -1;
    4646    struct rtattr * tb[RTA_MAX+1];
    47     char abuf[256];
    48     SPRINT_BUF(b1);
    4947
    5048    if (n->nlmsg_type != RTM_NEWRULE)
     
    7371    if (tb[RTA_SRC]) {
    7472        if (r->rtm_src_len != host_len) {
    75             printf("%s/%u", rt_addr_n2a(r->rtm_family,
    76                             RTA_DATA(tb[RTA_SRC]),
    77                             abuf, sizeof(abuf)),
     73            printf("%s/%u",
     74                rt_addr_n2a(r->rtm_family, RTA_DATA(tb[RTA_SRC])),
    7875                r->rtm_src_len
    7976            );
     
    8178            fputs(format_host(r->rtm_family,
    8279                        RTA_PAYLOAD(tb[RTA_SRC]),
    83                         RTA_DATA(tb[RTA_SRC]),
    84                         abuf, sizeof(abuf)),
     80                        RTA_DATA(tb[RTA_SRC])),
    8581                stdout
    8682            );
     
    9692        if (r->rtm_dst_len != host_len) {
    9793            printf("to %s/%u ", rt_addr_n2a(r->rtm_family,
    98                              RTA_DATA(tb[RTA_DST]),
    99                              abuf, sizeof(abuf)),
     94                             RTA_DATA(tb[RTA_DST])),
    10095                r->rtm_dst_len
    10196                );
     
    10398            printf("to %s ", format_host(r->rtm_family,
    10499                               RTA_PAYLOAD(tb[RTA_DST]),
    105                                RTA_DATA(tb[RTA_DST]),
    106                                abuf, sizeof(abuf)));
     100                               RTA_DATA(tb[RTA_DST])));
    107101        }
    108102    } else if (r->rtm_dst_len) {
     
    111105
    112106    if (r->rtm_tos) {
    113         printf("tos %s ", rtnl_dsfield_n2a(r->rtm_tos, b1));
     107        printf("tos %s ", rtnl_dsfield_n2a(r->rtm_tos));
    114108    }
    115109    if (tb[RTA_PROTOINFO]) {
     
    122116
    123117    if (r->rtm_table)
    124         printf("lookup %s ", rtnl_rttable_n2a(r->rtm_table, b1));
     118        printf("lookup %s ", rtnl_rttable_n2a(r->rtm_table));
    125119
    126120    if (tb[RTA_FLOW]) {
     
    130124        if (from) {
    131125            printf("realms %s/",
    132                 rtnl_rtrealm_n2a(from, b1));
     126                rtnl_rtrealm_n2a(from));
    133127        }
    134128        printf("%s ",
    135             rtnl_rtrealm_n2a(to, b1));
     129            rtnl_rtrealm_n2a(to));
    136130    }
    137131
     
    141135                format_host(r->rtm_family,
    142136                        RTA_PAYLOAD(tb[RTA_GATEWAY]),
    143                         RTA_DATA(tb[RTA_GATEWAY]),
    144                         abuf, sizeof(abuf)));
     137                        RTA_DATA(tb[RTA_GATEWAY]))
     138            );
    145139        } else
    146140            printf("masquerade");
    147141    } else if (r->rtm_type != RTN_UNICAST)
    148         fputs(rtnl_rtntype_n2a(r->rtm_type, b1), stdout);
     142        fputs(rtnl_rtntype_n2a(r->rtm_type), stdout);
    149143
    150144    bb_putchar('\n');
     
    216210        key = index_in_substrings(keywords, *argv) + 1;
    217211        if (key == 0) /* no match found in keywords array, bail out. */
    218             bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
     212            invarg_1_to_2(*argv, applet_name);
    219213        if (key == ARG_from) {
    220214            inet_prefix dst;
     
    241235            NEXT_ARG();
    242236            if (rtnl_dsfield_a2n(&tos, *argv))
    243                 invarg(*argv, "TOS");
     237                invarg_1_to_2(*argv, "TOS");
    244238            req.r.rtm_tos = tos;
    245239        } else if (key == ARG_fwmark) {
     
    252246            NEXT_ARG();
    253247            if (get_rt_realms(&realm, *argv))
    254                 invarg(*argv, "realms");
     248                invarg_1_to_2(*argv, "realms");
    255249            addattr32(&req.n, sizeof(req), RTA_FLOW, realm);
    256250        } else if (key == ARG_table ||
     
    260254            NEXT_ARG();
    261255            if (rtnl_rttable_a2n(&tid, *argv))
    262                 invarg(*argv, "table ID");
     256                invarg_1_to_2(*argv, "table ID");
    263257            req.r.rtm_table = tid;
    264258            table_ok = 1;
     
    283277                bb_show_usage();
    284278            if (rtnl_rtntype_a2n(&type, *argv))
    285                 invarg(*argv, "type");
     279                invarg_1_to_2(*argv, "type");
    286280            req.r.rtm_type = type;
    287281        }
     
    309303        "add\0""delete\0""list\0""show\0";
    310304    if (*argv) {
    311         smalluint cmd = index_in_substrings(ip_rule_commands, *argv);
    312         if (cmd > 3)
    313             bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
     305        int cmd = index_in_substrings(ip_rule_commands, *argv);
     306        if (cmd < 0)
     307            invarg_1_to_2(*argv, applet_name);
    314308        argv++;
    315309        if (cmd < 2)
  • branches/3.3/mindi-busybox/networking/libiproute/iptunnel.c

    r3232 r3621  
    295295                uval = get_unsigned(*argv, "TTL");
    296296                if (uval > 255)
    297                     invarg(*argv, "TTL must be <=255");
     297                    invarg_1_to_2(*argv, "TTL");
    298298                p->iph.ttl = uval;
    299299            }
     
    306306            if (key != ARG_inherit) {
    307307                if (rtnl_dsfield_a2n(&uval, *argv))
    308                     invarg(*argv, "TOS");
     308                    invarg_1_to_2(*argv, "TOS");
    309309                p->iph.tos = uval;
    310310            } else
     
    405405static void print_tunnel(struct ip_tunnel_parm *p)
    406406{
    407     char s1[256];
    408     char s2[256];
    409     char s3[64];
    410     char s4[64];
    411 
    412     format_host(AF_INET, 4, &p->iph.daddr, s1, sizeof(s1));
    413     format_host(AF_INET, 4, &p->iph.saddr, s2, sizeof(s2));
    414     inet_ntop(AF_INET, &p->i_key, s3, sizeof(s3));
    415     inet_ntop(AF_INET, &p->o_key, s4, sizeof(s4));
     407    char s3[INET_ADDRSTRLEN];
     408    char s4[INET_ADDRSTRLEN];
    416409
    417410    printf("%s: %s/ip  remote %s  local %s ",
    418            p->name,
    419            p->iph.protocol == IPPROTO_IPIP ? "ip" :
    420            (p->iph.protocol == IPPROTO_GRE ? "gre" :
    421         (p->iph.protocol == IPPROTO_IPV6 ? "ipv6" : "unknown")),
    422            p->iph.daddr ? s1 : "any", p->iph.saddr ? s2 : "any");
     411        p->name,
     412        p->iph.protocol == IPPROTO_IPIP ? "ip" :
     413            p->iph.protocol == IPPROTO_GRE ? "gre" :
     414            p->iph.protocol == IPPROTO_IPV6 ? "ipv6" :
     415            "unknown",
     416        p->iph.daddr ? format_host(AF_INET, 4, &p->iph.daddr) : "any",
     417        p->iph.saddr ? format_host(AF_INET, 4, &p->iph.saddr) : "any"
     418    );
    423419    if (p->link) {
    424420        char *n = do_ioctl_get_ifname(p->link);
     
    433429        printf(" ttl inherit ");
    434430    if (p->iph.tos) {
    435         SPRINT_BUF(b1);
    436431        printf(" tos");
    437432        if (p->iph.tos & 1)
     
    439434        if (p->iph.tos & ~1)
    440435            printf("%c%s ", p->iph.tos & 1 ? '/' : ' ',
    441                 rtnl_dsfield_n2a(p->iph.tos & ~1, b1));
     436                rtnl_dsfield_n2a(p->iph.tos & ~1));
    442437    }
    443438    if (!(p->iph.frag_off & htons(IP_DF)))
    444439        printf(" nopmtudisc");
    445440
     441    inet_ntop(AF_INET, &p->i_key, s3, sizeof(s3));
     442    inet_ntop(AF_INET, &p->o_key, s4, sizeof(s4));
    446443    if ((p->i_flags & GRE_KEY) && (p->o_flags & GRE_KEY) && p->o_key == p->i_key)
    447444        printf(" key %s", s3);
    448     else if ((p->i_flags | p->o_flags) & GRE_KEY) {
     445    else {
    449446        if (p->i_flags & GRE_KEY)
    450447            printf(" ikey %s ", s3);
     
    562559
    563560    if (*argv) {
    564         smalluint key = index_in_substrings(keywords, *argv);
    565         if (key > 5)
    566             bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
     561        int key = index_in_substrings(keywords, *argv);
     562        if (key < 0)
     563            invarg_1_to_2(*argv, applet_name);
    567564        argv++;
    568565        if (key == ARG_add)
  • branches/3.3/mindi-busybox/networking/libiproute/libnetlink.c

    r3232 r3621  
    7272    struct sockaddr_nl nladdr;
    7373    struct iovec iov[2] = { { &nlh, sizeof(nlh) }, { req, len } };
     74    /* Use designated initializers, struct layout is non-portable */
    7475    struct msghdr msg = {
    75         (void*)&nladdr, sizeof(nladdr),
    76         iov,  2,
    77         NULL, 0,
    78         0
     76        .msg_name = (void*)&nladdr,
     77        .msg_namelen = sizeof(nladdr),
     78        .msg_iov = iov,
     79        .msg_iovlen = 2,
     80        .msg_control = NULL,
     81        .msg_controllen = 0,
     82        .msg_flags = 0
    7983    };
    8084
     
    105109        int status;
    106110        struct nlmsghdr *h;
    107 
     111        /* Use designated initializers, struct layout is non-portable */
    108112        struct msghdr msg = {
    109             (void*)&nladdr, sizeof(nladdr),
    110             &iov, 1,
    111             NULL, 0,
    112             0
     113            .msg_name = (void*)&nladdr,
     114            .msg_namelen = sizeof(nladdr),
     115            .msg_iov = &iov,
     116            .msg_iovlen = 1,
     117            .msg_control = NULL,
     118            .msg_controllen = 0,
     119            .msg_flags = 0
    113120        };
    114121
     
    212219    struct iovec iov = { (void*)n, n->nlmsg_len };
    213220    char   *buf = xmalloc(8*1024); /* avoid big stack buffer */
     221    /* Use designated initializers, struct layout is non-portable */
    214222    struct msghdr msg = {
    215         (void*)&nladdr, sizeof(nladdr),
    216         &iov, 1,
    217         NULL, 0,
    218         0
     223        .msg_name = (void*)&nladdr,
     224        .msg_namelen = sizeof(nladdr),
     225        .msg_iov = &iov,
     226        .msg_iovlen = 1,
     227        .msg_control = NULL,
     228        .msg_controllen = 0,
     229        .msg_flags = 0
    219230    };
    220231
  • branches/3.3/mindi-busybox/networking/libiproute/ll_map.c

    r2725 r3621  
    8787}
    8888
    89 const char FAST_FUNC *ll_idx_n2a(int idx, char *buf)
     89static
     90const char FAST_FUNC *ll_idx_n2a(int idx/*, char *buf*/)
    9091{
    9192    struct idxmap *im;
     
    9697    if (im)
    9798        return im->name;
    98     snprintf(buf, 16, "if%d", idx);
    99     return buf;
     99    //snprintf(buf, 16, "if%d", idx);
     100    //return buf;
     101    return auto_string(xasprintf("if%d", idx));
    100102}
    101 
    102103
    103104const char FAST_FUNC *ll_index_to_name(int idx)
    104105{
    105     static char nbuf[16];
    106 
    107     return ll_idx_n2a(idx, nbuf);
     106    //static char nbuf[16];
     107    return ll_idx_n2a(idx/*, nbuf*/);
    108108}
    109109
     
    137137{
    138138    int ret = 0;
    139     int sock_fd;
    140139
    141140/* caching is not warranted - no users which repeatedly call it */
     
    165164        }
    166165    }
    167     /* We have not found the interface in our cache, but the kernel
    168      * may still know about it. One reason is that we may be using
    169      * module on-demand loading, which means that the kernel will
    170      * load the module and make the interface exist only when
    171      * we explicitely request it (check for dev_load() in net/core/dev.c).
    172      * I can think of other similar scenario, but they are less common...
    173      * Jean II */
    174166#endif
    175 
    176     sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
    177     if (sock_fd >= 0) {
    178         struct ifreq ifr;
    179         int tmp;
    180 
    181         strncpy_IFNAMSIZ(ifr.ifr_name, name);
    182         ifr.ifr_ifindex = -1;
    183         tmp = ioctl(sock_fd, SIOCGIFINDEX, &ifr);
    184         close(sock_fd);
    185         if (tmp >= 0)
    186             /* In theory, we should redump the interface list
    187              * to update our cache, this is left as an exercise
    188              * to the reader... Jean II */
    189             ret = ifr.ifr_ifindex;
    190     }
     167    ret = if_nametoindex(name);
    191168/* out:*/
    192169    if (ret <= 0)
  • branches/3.3/mindi-busybox/networking/libiproute/ll_map.h

    r2725 r3621  
    88int ll_init_map(struct rtnl_handle *rth) FAST_FUNC;
    99int xll_name_to_index(const char *name) FAST_FUNC;
     10//static: const char *ll_idx_n2a(int idx, char *buf) FAST_FUNC;
    1011const char *ll_index_to_name(int idx) FAST_FUNC;
    11 const char *ll_idx_n2a(int idx, char *buf) FAST_FUNC;
    1212/* int ll_index_to_type(int idx); */
    1313unsigned ll_index_to_flags(int idx) FAST_FUNC;
  • branches/3.3/mindi-busybox/networking/libiproute/ll_proto.c

    r3232 r3621  
    8585/* Keep declarations above and below in sync! */
    8686
    87 static const char llproto_names[] =
     87static const char llproto_names[] ALIGN1 =
    8888#define __PF(f,n) #n "\0"
    8989__PF(LOOP,loop)
  • branches/3.3/mindi-busybox/networking/libiproute/ll_types.c

    r3232 r3621  
    1717const char* FAST_FUNC ll_type_n2a(int type, char *buf)
    1818{
    19     static const char arphrd_name[] =
     19    static const char arphrd_name[] ALIGN1 =
    2020    /* 0,                  */ "generic" "\0"
    2121    /* ARPHRD_LOOPBACK,    */ "loopback" "\0"
     
    106106    /* Keep these arrays in sync! */
    107107
    108     static const uint16_t arphrd_type[] = {
     108    static const uint16_t arphrd_type[] ALIGN2 = {
    109109    0,                  /* "generic" "\0" */
    110110    ARPHRD_LOOPBACK,    /* "loopback" "\0" */
  • branches/3.3/mindi-busybox/networking/libiproute/rt_names.c

    r2725 r3621  
    1111#include "rt_names.h"
    1212
     13#define CONFDIR          CONFIG_FEATURE_IP_ROUTE_DIR
     14
    1315typedef struct rtnl_tab_t {
    1416    const char *cached_str;
    1517    unsigned cached_result;
    16     const char *tab[256];
     18    /* upstream version switched to a hash table and removed
     19     * id < 256 limit. For now bbox bumps this array size from 256
     20     * to 1024. If you plan to change this to a hash table,
     21     * consider merging several hash tables we have (for example,
     22     * awk has resizable one!
     23     */
     24#define RT_TABLE_MAX 1023
     25    const char *tab[RT_TABLE_MAX+1];
    1726} rtnl_tab_t;
    1827
     
    2029{
    2130    char *token[2];
    22     parser_t *parser = config_open2(file, fopen_for_read);
    23 
     31    char fullname[sizeof(CONFDIR"/rt_dsfield") + 8];
     32    parser_t *parser;
     33
     34    sprintf(fullname, CONFDIR"/rt_%s", file);
     35    parser = config_open2(fullname, fopen_for_read);
    2436    while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) {
    2537        unsigned id = bb_strtou(token[0], NULL, 0);
    26         if (id > 256) {
     38        if (id > RT_TABLE_MAX) {
    2739            bb_error_msg("database %s is corrupted at line %d",
    2840                file, parser->lineno);
     
    4355    }
    4456
    45     for (i = 0; i < 256; i++) {
     57    for (i = 0; i <= RT_TABLE_MAX; i++) {
    4658        if (tab->tab[i]
    4759         && strcmp(tab->tab[i], arg) == 0
     
    5567
    5668    i = bb_strtou(arg, NULL, base);
    57     if (i > 255)
     69    if (i > RT_TABLE_MAX)
    5870        return -1;
    5971    *id = i;
     
    8698    rtnl_rtprot_tab = xzalloc(sizeof(*rtnl_rtprot_tab));
    8799    memcpy(rtnl_rtprot_tab->tab, init_tab, sizeof(init_tab));
    88     rtnl_tab_initialize("/etc/iproute2/rt_protos", rtnl_rtprot_tab->tab);
    89 }
    90 
    91 const char* FAST_FUNC rtnl_rtprot_n2a(int id, char *buf)
    92 {
    93     if (id < 0 || id >= 256) {
    94         sprintf(buf, "%d", id);
    95         return buf;
     100    rtnl_tab_initialize("protos", rtnl_rtprot_tab->tab);
     101}
     102
     103#if 0 /* UNUSED */
     104const char* FAST_FUNC rtnl_rtprot_n2a(int id)
     105{
     106    if (id < 0 || id > RT_TABLE_MAX) {
     107        return itoa(id);
    96108    }
    97109
     
    100112    if (rtnl_rtprot_tab->tab[id])
    101113        return rtnl_rtprot_tab->tab[id];
    102     /* buf is SPRINT_BSIZE big */
    103     sprintf(buf, "%d", id);
    104     return buf;
    105 }
     114    return itoa(id);
     115}
     116#endif
    106117
    107118int FAST_FUNC rtnl_rtprot_a2n(uint32_t *id, char *arg)
     
    124135    rtnl_rtscope_tab->tab[253] = "link";
    125136    rtnl_rtscope_tab->tab[200] = "site";
    126     rtnl_tab_initialize("/etc/iproute2/rt_scopes", rtnl_rtscope_tab->tab);
    127 }
    128 
    129 const char* FAST_FUNC rtnl_rtscope_n2a(int id, char *buf)
    130 {
    131     if (id < 0 || id >= 256) {
    132         sprintf(buf, "%d", id);
    133         return buf;
     137    rtnl_tab_initialize("scopes", rtnl_rtscope_tab->tab);
     138}
     139
     140const char* FAST_FUNC rtnl_rtscope_n2a(int id)
     141{
     142    if (id < 0 || id > RT_TABLE_MAX) {
     143        return itoa(id);
    134144    }
    135145
     
    138148    if (rtnl_rtscope_tab->tab[id])
    139149        return rtnl_rtscope_tab->tab[id];
    140     /* buf is SPRINT_BSIZE big */
    141     sprintf(buf, "%d", id);
    142     return buf;
     150    return itoa(id);
    143151}
    144152
     
    157165    rtnl_rtrealm_tab = xzalloc(sizeof(*rtnl_rtrealm_tab));
    158166    rtnl_rtrealm_tab->tab[0] = "unknown";
    159     rtnl_tab_initialize("/etc/iproute2/rt_realms", rtnl_rtrealm_tab->tab);
     167    rtnl_tab_initialize("realms", rtnl_rtrealm_tab->tab);
    160168}
    161169
     
    167175
    168176#if ENABLE_FEATURE_IP_RULE
    169 const char* FAST_FUNC rtnl_rtrealm_n2a(int id, char *buf)
    170 {
    171     if (id < 0 || id >= 256) {
    172         sprintf(buf, "%d", id);
    173         return buf;
     177const char* FAST_FUNC rtnl_rtrealm_n2a(int id)
     178{
     179    if (id < 0 || id > RT_TABLE_MAX) {
     180        return itoa(id);
    174181    }
    175182
     
    178185    if (rtnl_rtrealm_tab->tab[id])
    179186        return rtnl_rtrealm_tab->tab[id];
    180     /* buf is SPRINT_BSIZE big */
    181     sprintf(buf, "%d", id);
    182     return buf;
     187    return itoa(id);
    183188}
    184189#endif
     
    192197    rtnl_rtdsfield_tab = xzalloc(sizeof(*rtnl_rtdsfield_tab));
    193198    rtnl_rtdsfield_tab->tab[0] = "0";
    194     rtnl_tab_initialize("/etc/iproute2/rt_dsfield", rtnl_rtdsfield_tab->tab);
    195 }
    196 
    197 const char* FAST_FUNC rtnl_dsfield_n2a(int id, char *buf)
    198 {
    199     if (id < 0 || id >= 256) {
    200         sprintf(buf, "%d", id);
    201         return buf;
     199    rtnl_tab_initialize("dsfield", rtnl_rtdsfield_tab->tab);
     200}
     201
     202const char* FAST_FUNC rtnl_dsfield_n2a(int id)
     203{
     204    if (id < 0 || id > RT_TABLE_MAX) {
     205        return itoa(id);
    202206    }
    203207
     
    206210    if (rtnl_rtdsfield_tab->tab[id])
    207211        return rtnl_rtdsfield_tab->tab[id];
    208     /* buf is SPRINT_BSIZE big */
    209     sprintf(buf, "0x%02x", id);
    210     return buf;
     212    return itoa(id);
    211213}
    212214
     
    223225static void rtnl_rttable_initialize(void)
    224226{
    225     if (rtnl_rtdsfield_tab) return;
     227    if (rtnl_rttable_tab)
     228        return;
     229
    226230    rtnl_rttable_tab = xzalloc(sizeof(*rtnl_rttable_tab));
    227231    rtnl_rttable_tab->tab[0] = "unspec";
     
    229233    rtnl_rttable_tab->tab[254] = "main";
    230234    rtnl_rttable_tab->tab[253] = "default";
    231     rtnl_tab_initialize("/etc/iproute2/rt_tables", rtnl_rttable_tab->tab);
    232 }
    233 
    234 const char* FAST_FUNC rtnl_rttable_n2a(int id, char *buf)
    235 {
    236     if (id < 0 || id >= 256) {
    237         sprintf(buf, "%d", id);
    238         return buf;
     235    rtnl_tab_initialize("tables", rtnl_rttable_tab->tab);
     236}
     237
     238const char* FAST_FUNC rtnl_rttable_n2a(int id)
     239{
     240    if (id < 0 || id > RT_TABLE_MAX) {
     241        return itoa(id);
    239242    }
    240243
     
    243246    if (rtnl_rttable_tab->tab[id])
    244247        return rtnl_rttable_tab->tab[id];
    245     /* buf is SPRINT_BSIZE big */
    246     sprintf(buf, "%d", id);
    247     return buf;
     248    return itoa(id);
    248249}
    249250
  • branches/3.3/mindi-busybox/networking/libiproute/rt_names.h

    r2725 r3621  
    55PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
    66
    7 /* buf is SPRINT_BSIZE big */
    8 extern const char* rtnl_rtprot_n2a(int id, char *buf) FAST_FUNC;
    9 extern const char* rtnl_rtscope_n2a(int id, char *buf) FAST_FUNC;
    10 extern const char* rtnl_rtrealm_n2a(int id, char *buf) FAST_FUNC;
    11 extern const char* rtnl_dsfield_n2a(int id, char *buf) FAST_FUNC;
    12 extern const char* rtnl_rttable_n2a(int id, char *buf) FAST_FUNC;
     7extern const char* rtnl_rtprot_n2a(int id) FAST_FUNC;
     8extern const char* rtnl_rtscope_n2a(int id) FAST_FUNC;
     9extern const char* rtnl_rtrealm_n2a(int id) FAST_FUNC;
     10extern const char* rtnl_dsfield_n2a(int id) FAST_FUNC;
     11extern const char* rtnl_rttable_n2a(int id) FAST_FUNC;
    1312extern int rtnl_rtprot_a2n(uint32_t *id, char *arg) FAST_FUNC;
    1413extern int rtnl_rtscope_a2n(uint32_t *id, char *arg) FAST_FUNC;
  • branches/3.3/mindi-busybox/networking/libiproute/rtm_map.c

    r2725 r3621  
    1313#include "utils.h"
    1414
    15 const char* FAST_FUNC rtnl_rtntype_n2a(int id, char *buf)
     15const char* FAST_FUNC rtnl_rtntype_n2a(int id)
    1616{
    1717    switch (id) {
     
    4141        return "xresolve";
    4242    default:
    43         /* buf is SPRINT_BSIZE big */
    44         sprintf(buf, "%d", id);
    45         return buf;
     43        return itoa(id);
    4644    }
    4745}
  • branches/3.3/mindi-busybox/networking/libiproute/rtm_map.h

    r2725 r3621  
    55PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
    66
    7 const char *rtnl_rtntype_n2a(int id, char *buf) FAST_FUNC;
     7const char *rtnl_rtntype_n2a(int id) FAST_FUNC;
    88int rtnl_rtntype_a2n(int *id, char *arg) FAST_FUNC;
    99
  • branches/3.3/mindi-busybox/networking/libiproute/utils.c

    r3232 r3621  
    1414#include "inet_common.h"
    1515
     16unsigned get_hz(void)
     17{
     18    static unsigned hz_internal;
     19    FILE *fp;
     20
     21    if (hz_internal)
     22        return hz_internal;
     23
     24    fp = fopen_for_read("/proc/net/psched");
     25    if (fp) {
     26        unsigned nom, denom;
     27
     28        if (fscanf(fp, "%*08x%*08x%08x%08x", &nom, &denom) == 2)
     29            if (nom == 1000000)
     30                hz_internal = denom;
     31        fclose(fp);
     32    }
     33    if (!hz_internal)
     34        hz_internal = bb_clk_tck();
     35    return hz_internal;
     36}
     37
    1638unsigned get_unsigned(char *arg, const char *errmsg)
    1739{
     
    2648        }
    2749    }
    28     invarg(arg, errmsg); /* does not return */
     50    invarg_1_to_2(arg, errmsg); /* does not return */
    2951}
    3052
     
    4163        }
    4264    }
    43     invarg(arg, errmsg); /* does not return */
     65    invarg_1_to_2(arg, errmsg); /* does not return */
    4466}
    4567
     
    5678        }
    5779    }
    58     invarg(arg, errmsg); /* does not return */
     80    invarg_1_to_2(arg, errmsg); /* does not return */
    5981}
    6082
     
    209231void incomplete_command(void)
    210232{
    211     bb_error_msg_and_die("command line is not complete, try option \"help\"");
    212 }
    213 
    214 void invarg(const char *arg, const char *opt)
    215 {
    216     bb_error_msg_and_die(bb_msg_invalid_arg, arg, opt);
     233    bb_error_msg_and_die("command line is not complete, try \"help\"");
     234}
     235
     236void invarg_1_to_2(const char *arg, const char *opt)
     237{
     238    bb_error_msg_and_die(bb_msg_invalid_arg_to, arg, opt);
    217239}
    218240
     
    255277}
    256278
    257 const char *rt_addr_n2a(int af,
    258         void *addr, char *buf, int buflen)
     279const char *rt_addr_n2a(int af, void *addr)
    259280{
    260281    switch (af) {
    261282    case AF_INET:
    262283    case AF_INET6:
    263         return inet_ntop(af, addr, buf, buflen);
     284        return inet_ntop(af, addr,
     285            auto_string(xzalloc(INET6_ADDRSTRLEN)), INET6_ADDRSTRLEN
     286        );
    264287    default:
    265288        return "???";
     
    268291
    269292#ifdef RESOLVE_HOSTNAMES
    270 const char *format_host(int af, int len, void *addr, char *buf, int buflen)
     293const char *format_host(int af, int len, void *addr)
    271294{
    272295    if (resolve_hosts) {
     
    287310            h_ent = gethostbyaddr(addr, len, af);
    288311            if (h_ent != NULL) {
    289                 safe_strncpy(buf, h_ent->h_name, buflen);
    290                 return buf;
    291             }
    292         }
    293     }
    294     return rt_addr_n2a(af, addr, buf, buflen);
     312                return auto_string(xstrdup(h_ent->h_name));
     313            }
     314        }
     315    }
     316    return rt_addr_n2a(af, addr);
    295317}
    296318#endif
  • branches/3.3/mindi-busybox/networking/libiproute/utils.h

    r3232 r3621  
    6767extern uint16_t get_u16(char *arg, const char *errmsg);
    6868
    69 extern const char *rt_addr_n2a(int af, void *addr, char *buf, int buflen);
     69extern const char *rt_addr_n2a(int af, void *addr);
    7070#ifdef RESOLVE_HOSTNAMES
    71 extern const char *format_host(int af, int len, void *addr, char *buf, int buflen);
     71extern const char *format_host(int af, int len, void *addr);
    7272#else
    73 #define format_host(af, len, addr, buf, buflen) \
    74     rt_addr_n2a(af, addr, buf, buflen)
     73#define format_host(af, len, addr) \
     74    rt_addr_n2a(af, addr)
    7575#endif
    7676
    77 void invarg(const char *, const char *) NORETURN;
     77void invarg_1_to_2(const char *, const char *) NORETURN;
    7878void duparg(const char *, const char *) NORETURN;
    7979void duparg2(const char *, const char *) NORETURN;
     
    8686int ipx_pton(int af, const char *src, void *addr);
    8787
     88unsigned get_hz(void);
     89
    8890POP_SAVED_FUNCTION_VISIBILITY
    8991
  • branches/3.3/mindi-busybox/networking/nameif.c

    r3232 r3621  
    162162            *next++ = '\0';
    163163        /* Check for selectors, mac= is assumed */
    164         if (strncmp(selector, "bus=", 4) == 0) {
     164        if (is_prefixed_with(selector, "bus=")) {
    165165            ch->bus_info = xstrdup(selector + 4);
    166166            found_selector++;
    167         } else if (strncmp(selector, "driver=", 7) == 0) {
     167        } else if (is_prefixed_with(selector, "driver=")) {
    168168            ch->driver = xstrdup(selector + 7);
    169169            found_selector++;
    170         } else if (strncmp(selector, "phyaddr=", 8) == 0) {
     170        } else if (is_prefixed_with(selector, "phyaddr=")) {
    171171            ch->phy_address = xatoi_positive(selector + 8);
    172172            found_selector++;
     
    174174#endif
    175175            lmac = xmalloc(ETH_ALEN);
    176             ch->mac = ether_aton_r(selector + (strncmp(selector, "mac=", 4) != 0 ? 0 : 4), lmac);
     176            ch->mac = ether_aton_r(selector + (is_prefixed_with(selector, "mac=") ? 4 : 0), lmac);
    177177            if (ch->mac == NULL)
    178178                bb_error_msg_and_die("can't parse %s", selector);
     
    293293                continue;
    294294            /* if we came here, all selectors have matched */
    295             break;
     295            goto found;
    296296        }
    297297        /* Nothing found for current interface */
    298         if (!ch)
    299             continue;
    300 
     298        continue;
     299 found:
    301300        if (strcmp(ifr.ifr_name, ch->ifname) != 0) {
    302301            strcpy(ifr.ifr_newname, ch->ifname);
     
    314313        if (ENABLE_FEATURE_CLEAN_UP)
    315314            delete_eth_table(ch);
    316     }
     315    } /* while */
     316
    317317    if (ENABLE_FEATURE_CLEAN_UP) {
    318         for (ch = clist; ch; ch = ch->next)
     318        ethtable_t *next;
     319        for (ch = clist; ch; ch = next) {
     320            next = ch->next;
    319321            delete_eth_table(ch);
     322        }
    320323        config_close(parser);
    321324    };
  • branches/3.3/mindi-busybox/networking/nbd-client.c

    r3232 r3621  
    5858        char data[124];
    5959    } nbd_header;
    60     struct bug_check {
    61         char c[offsetof(struct nbd_header_t, data) == 8+8+8+4 ? 1 : -1];
    62     };
     60
     61    BUILD_BUG_ON(offsetof(struct nbd_header_t, data) != 8+8+8+4);
    6362
    6463    // Parse command line stuff (just a stub now)
     
    8483        // Find and connect to server
    8584        sock = create_and_connect_stream_or_die(host, xatou16(port));
    86         setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &const_int_1, sizeof(const_int_1));
     85        setsockopt_1(sock, IPPROTO_TCP, TCP_NODELAY);
    8786
    8887        // Log on to the server
  • branches/3.3/mindi-busybox/networking/nc.c

    r3232 r3621  
    99
    1010#include "libbb.h"
     11#include "common_bufsiz.h"
    1112
    1213//config:config NC
     
    2526//config:
    2627//config:config NC_EXTRA
    27 //config:   bool "Netcat extensions (-eiw and filename)"
     28//config:   bool "Netcat extensions (-eiw and -f FILE)"
    2829//config:   default y
    2930//config:   depends on NC
     
    4142//config:     The code is about 2.5k bigger. It enables
    4243//config:     -s ADDR, -n, -u, -v, -o FILE, -z options, but loses
    43 //config:     busybox-specific extensions: -f FILE and -ll.
     44//config:     busybox-specific extensions: -f FILE.
    4445
    4546#if ENABLE_NC_110_COMPAT
     
    6162//usage:       "Open a pipe to IP:PORT" IF_NC_EXTRA(" or FILE")
    6263//usage:    NC_OPTIONS_STR
    63 //usage:    IF_NC_EXTRA(
    64 //usage:     "\n    -e PROG Run PROG after connect"
    6564//usage:    IF_NC_SERVER(
    6665//usage:     "\n    -l  Listen mode, for inbound connects"
    6766//usage:    IF_NC_EXTRA(
    68 //usage:     "\n        (use -l twice with -e for persistent server)")
     67//usage:     "\n        (use -ll with -e for persistent server)"
     68//usage:    )
    6969//usage:     "\n    -p PORT Local port"
    7070//usage:    )
    71 //usage:     "\n    -w SEC  Timeout for connect"
     71//usage:    IF_NC_EXTRA(
     72//usage:     "\n    -w SEC  Connect timeout"
    7273//usage:     "\n    -i SEC  Delay interval for lines sent"
    7374//usage:     "\n    -f FILE Use file (ala /dev/ttyS0) instead of network"
     75//usage:     "\n    -e PROG Run PROG after connect"
    7476//usage:    )
    7577//usage:
     
    148150                    }
    149151                )
    150                 /* optind points to argv[arvc] (NULL) now.
     152                /* optind points to argv[argc] (NULL) now.
    151153                ** FIXME: we assume that getopt will not count options
    152154                ** possibly present on "-e PROG ARGS" and will not
     
    227229        xmove_fd(cfd, 0);
    228230        xdup2(0, 1);
    229         xdup2(0, 2);
     231        /*xdup2(0, 2); - original nc 1.10 does this, we don't */
    230232        IF_NC_EXTRA(BB_EXECVP(execparam[0], execparam);)
    231         /* Don't print stuff or it will go over the wire... */
    232         _exit(127);
     233        IF_NC_EXTRA(bb_perror_msg_and_die("can't execute '%s'", execparam[0]);)
    233234    }
    234235
     
    239240    FD_SET(STDIN_FILENO, &readfds);
    240241
     242#define iobuf bb_common_bufsiz1
     243    setup_common_bufsiz();
    241244    for (;;) {
    242245        int fd;
     
    249252            bb_perror_msg_and_die("select");
    250253
    251 #define iobuf bb_common_bufsiz1
    252254        fd = STDIN_FILENO;
    253255        while (1) {
    254256            if (FD_ISSET(fd, &testfds)) {
    255                 nread = safe_read(fd, iobuf, sizeof(iobuf));
     257                nread = safe_read(fd, iobuf, COMMON_BUFSIZE);
    256258                if (fd == cfd) {
    257259                    if (nread < 1)
     
    262264                        /* Close outgoing half-connection so they get EOF,
    263265                         * but leave incoming alone so we can see response */
    264                         shutdown(cfd, 1);
     266                        shutdown(cfd, SHUT_WR);
    265267                        FD_CLR(STDIN_FILENO, &readfds);
    266268                    }
  • branches/3.3/mindi-busybox/networking/nc_bloaty.c

    r3232 r3621  
    4949 *   on the command line, but accept() says that it came from different addr)
    5050 *   are closed, but we don't exit - we continue to listen/accept.
     51 * Since bbox 1.22:
     52 * - nc exits when _both_ stdin and network are closed.
     53 *   This makes these two commands:
     54 *    echo "Yes" | nc 127.0.0.1 1234
     55 *    echo "no" | nc -lp 1234
     56 *   exchange their data _and exit_ instead of being stuck.
    5157 */
    5258
     
    6470//usage:    IF_NC_SERVER(
    6571//usage:     "\n    -l  Listen mode, for inbound connects"
     72//usage:     "\n    -lk With -e, provides persistent server"
     73/* -ll does the same as -lk, but its our extension, while -k is BSD'd,
     74 * presumably more widely known. Therefore we advertise it, not -ll.
     75 * I would like to drop -ll support, but our "small" nc supports it,
     76 * and Rob uses it.
     77 */
    6678//usage:    )
    6779//usage:     "\n    -p PORT Local port"
     
    129141    jmp_buf jbuf;                /* timer crud */
    130142
    131     fd_set ding1;                /* for select loop */
    132     fd_set ding2;
    133143    char bigbuf_in[BIGSIZ];      /* data buffers */
    134144    char bigbuf_net[BIGSIZ];
     
    142152#define remend     (G.remend    )
    143153#define jbuf       (G.jbuf      )
    144 #define ding1      (G.ding1     )
    145 #define ding2      (G.ding2     )
    146154#define bigbuf_in  (G.bigbuf_in )
    147155#define bigbuf_net (G.bigbuf_net)
     
    167175    OPT_w = (1 << 5),
    168176    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,
     177    OPT_k = (1 << 7) * ENABLE_NC_SERVER,
     178    OPT_i = (1 << (6+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
     179    OPT_o = (1 << (7+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
     180    OPT_z = (1 << (8+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
    172181};
    173182
    174183#define o_nflag   (option_mask32 & OPT_n)
    175184#define o_udpmode (option_mask32 & OPT_u)
    176 #if ENABLE_NC_SERVER
    177 #define o_listen  (option_mask32 & OPT_l)
    178 #else
    179 #define o_listen  0
    180 #endif
    181185#if ENABLE_NC_EXTRA
    182186#define o_ofile   (option_mask32 & OPT_o)
     
    299303 given host/port args, any connections from elsewhere are rejected.  This
    300304 in conjunction with local-address binding should limit things nicely... */
    301 static void dolisten(void)
     305static void dolisten(int is_persistent, char **proggie)
    302306{
    303307    int rr;
     
    372376    } else {
    373377        /* TCP */
     378 another:
    374379        arm(o_wait); /* wrap this in a timer, too; 0 = forever */
    375380        if (setjmp(jbuf) == 0) {
     
    406411        } else
    407412            bb_error_msg_and_die("timeout");
     413
     414        if (is_persistent && proggie) {
     415            /* -l -k -e PROG */
     416            signal(SIGCHLD, SIG_IGN); /* no zombies please */
     417            if (xvfork() != 0) {
     418                /* parent: go back and accept more connections */
     419                close(rr);
     420                goto another;
     421            }
     422            /* child */
     423            signal(SIGCHLD, SIG_DFL);
     424        }
     425
    408426        xmove_fd(rr, netfd); /* dump the old socket, here's our new one */
    409427        /* find out what address the connection was *to* on our end, in case we're
     
    455473            free(remhostname);
    456474    }
     475
     476    if (proggie)
     477        doexec(proggie);
    457478}
    458479
     
    572593    unsigned rnleft;
    573594    unsigned netretry;              /* net-read retry counter */
    574     unsigned wretry;                /* net-write sanity counter */
    575     unsigned wfirst;                /* one-shot flag to skip first net read */
     595    unsigned fds_open;
    576596
    577597    /* if you don't have all this FD_* macro hair in sys/types.h, you'll have to
    578598     either find it or do your own bit-bashing: *ding1 |= (1 << fd), etc... */
    579     FD_SET(netfd, &ding1);                /* global: the net is open */
     599    fd_set ding1;                   /* for select loop */
     600    fd_set ding2;
     601    FD_ZERO(&ding1);
     602    FD_SET(netfd, &ding1);
     603    FD_SET(STDIN_FILENO, &ding1);
     604    fds_open = 2;
     605
    580606    netretry = 2;
    581     wfirst = 0;
    582607    rzleft = rnleft = 0;
    583608    if (o_interval)
    584609        sleep(o_interval);                /* pause *before* sending stuff, too */
    585610
    586     errno = 0;                        /* clear from sleep, close, whatever */
    587611    /* and now the big ol' select shoveling loop ... */
    588     while (FD_ISSET(netfd, &ding1)) {        /* i.e. till the *net* closes! */
    589         wretry = 8200;                        /* more than we'll ever hafta write */
    590         if (wfirst) {                        /* any saved stdin buffer? */
    591             wfirst = 0;                        /* clear flag for the duration */
    592             goto shovel;                        /* and go handle it first */
    593         }
     612    /* nc 1.10 has "while (FD_ISSET(netfd)" here */
     613    while (fds_open) {
     614        unsigned wretry = 8200;               /* net-write sanity counter */
     615
    594616        ding2 = ding1;                        /* FD_COPY ain't portable... */
    595617    /* some systems, notably linux, crap into their select timers on return, so
     
    611633     from the net during that time, assume it's dead and close it too. */
    612634        if (rr == 0) {
    613             if (!FD_ISSET(STDIN_FILENO, &ding1))
     635            if (!FD_ISSET(STDIN_FILENO, &ding1)) {
    614636                netretry--;                        /* we actually try a coupla times. */
    615             if (!netretry) {
    616                 if (o_verbose > 1)                /* normally we don't care */
    617                     fprintf(stderr, "net timeout\n");
    618                 close(netfd);
    619                 return 0;                        /* not an error! */
     637                if (!netretry) {
     638                    if (o_verbose > 1)         /* normally we don't care */
     639                        fprintf(stderr, "net timeout\n");
     640                    /*close(netfd); - redundant, exit will do it */
     641                    return 0;                  /* not an error! */
     642                }
    620643            }
    621644        } /* select timeout */
     
    631654                    bb_perror_msg("net read");
    632655                }
    633                 FD_CLR(netfd, &ding1);                /* net closed, we'll finish up... */
     656                FD_CLR(netfd, &ding1);                /* net closed */
     657                fds_open--;
    634658                rzleft = 0;                        /* can't write anymore: broken pipe */
    635659            } else {
     
    651675     mobygrams are kinda fun and exercise the reassembler. */
    652676            if (rr <= 0) {                        /* at end, or fukt, or ... */
    653                 FD_CLR(STDIN_FILENO, &ding1);                /* disable and close stdin */
    654                 close(STDIN_FILENO);
    655 // Does it make sense to shutdown(net_fd, SHUT_WR)
    656 // to let other side know that we won't write anything anymore?
    657 // (and what about keeping compat if we do that?)
     677                FD_CLR(STDIN_FILENO, &ding1); /* disable stdin */
     678                /*close(STDIN_FILENO); - not really necessary */
     679                /* Let peer know we have no more data */
     680                /* nc 1.10 doesn't do this: */
     681                shutdown(netfd, SHUT_WR);
     682                fds_open--;
    658683            } else {
    659684                rzleft = rr;
     
    666691     not sure if the order of this matters, but write net -> stdout first. */
    667692
    668     /* sanity check.  Works because they're both unsigned... */
    669         if ((rzleft > 8200) || (rnleft > 8200)) {
    670             holler_error("bogus buffers: %u, %u", rzleft, rnleft);
    671             rzleft = rnleft = 0;
    672         }
    673     /* net write retries sometimes happen on UDP connections */
    674         if (!wretry) {                        /* is something hung? */
    675             holler_error("too many output retries");
    676             return 1;
    677         }
    678693        if (rnleft) {
    679694            rr = write(STDOUT_FILENO, np, rnleft);
     
    681696                if (o_ofile) /* log the stdout */
    682697                    oprint('<', (unsigned char *)np, rr);
    683                 np += rr;                        /* fix up ptrs and whatnot */
    684                 rnleft -= rr;                        /* will get sanity-checked above */
    685                 wrote_out += rr;                /* global count */
     698                np += rr;
     699                rnleft -= rr;
     700                wrote_out += rr; /* global count */
    686701            }
    687702Debug("wrote %d to stdout, errno %d", rr, errno);
     
    698713                zp += rr;
    699714                rzleft -= rr;
    700                 wrote_net += rr;                /* global count */
     715                wrote_net += rr; /* global count */
    701716            }
    702717Debug("wrote %d to net, errno %d", rr, errno);
     
    704719        if (o_interval) {                        /* cycle between slow lines, or ... */
    705720            sleep(o_interval);
    706             errno = 0;                        /* clear from sleep */
    707721            continue;                        /* ...with hairy select loop... */
    708722        }
    709         if ((rzleft) || (rnleft)) {                /* shovel that shit till they ain't */
     723        if (rzleft || rnleft) {                  /* shovel that shit till they ain't */
    710724            wretry--;                        /* none left, and get another load */
     725    /* net write retries sometimes happen on UDP connections */
     726            if (!wretry) {                   /* is something hung? */
     727                holler_error("too many output retries");
     728                return 1;
     729            }
    711730            goto shovel;
    712731        }
    713     } /* while ding1:netfd is open */
     732    } /* while (fds_open) */
    714733
    715734    /* XXX: maybe want a more graceful shutdown() here, or screw around with
     
    731750    char **proggie;
    732751    int x;
     752    unsigned cnt_l = 0;
    733753    unsigned o_lport = 0;
    734754
     
    761781            char *optpos = *proggie + 1;
    762782            /* Skip all valid opts w/o params */
    763             optpos = optpos + strspn(optpos, "nuv"IF_NC_SERVER("l")IF_NC_EXTRA("z"));
     783            optpos = optpos + strspn(optpos, "nuv"IF_NC_SERVER("lk")IF_NC_EXTRA("z"));
    764784            if (*optpos == 'e' && !optpos[1]) {
    765785                *optpos = '\0';
     
    775795
    776796    // -g -G -t -r deleted, unimplemented -a deleted too
    777     opt_complementary = "?2:vv:w+"; /* max 2 params; -v is a counter; -w N */
    778     getopt32(argv, "np:s:uvw:" IF_NC_SERVER("l")
     797    opt_complementary = "?2:vv:ll:w+"; /* max 2 params; -v and -l are counters; -w N */
     798    getopt32(argv, "np:s:uvw:" IF_NC_SERVER("lk")
    779799            IF_NC_EXTRA("i:o:z"),
    780800            &str_p, &str_s, &o_wait
    781             IF_NC_EXTRA(, &str_i, &str_o), &o_verbose);
     801            IF_NC_EXTRA(, &str_i, &str_o), &o_verbose IF_NC_SERVER(, &cnt_l));
    782802    argv += optind;
    783803#if ENABLE_NC_EXTRA
     
    785805        o_interval = xatou_range(str_i, 1, 0xffff);
    786806#endif
     807#if ENABLE_NC_SERVER
    787808    //if (option_mask32 & OPT_l) /* listen mode */
     809    if (option_mask32 & OPT_k) /* persistent server mode */
     810        cnt_l = 2;
     811#endif
    788812    //if (option_mask32 & OPT_n) /* numeric-only, no DNS lookups */
    789813    //if (option_mask32 & OPT_o) /* hexdump log */
     
    834858        socket_want_pktinfo(netfd);
    835859    if (!ENABLE_FEATURE_UNIX_LOCAL
    836      || o_listen
     860     || cnt_l != 0 /* listen */
    837861     || ouraddr->u.sa.sa_family != AF_UNIX
    838862    ) {
     
    840864    }
    841865#if 0
    842     setsockopt(netfd, SOL_SOCKET, SO_RCVBUF, &o_rcvbuf, sizeof o_rcvbuf);
    843     setsockopt(netfd, SOL_SOCKET, SO_SNDBUF, &o_sndbuf, sizeof o_sndbuf);
     866    setsockopt_SOL_SOCKET_int(netfd, SO_RCVBUF, o_rcvbuf);
     867    setsockopt_SOL_SOCKET_int(netfd, SO_SNDBUF, o_sndbuf);
    844868#endif
    845869
     
    853877#endif
    854878
    855     FD_SET(STDIN_FILENO, &ding1);                        /* stdin *is* initially open */
    856879    if (proggie) {
    857         close(0); /* won't need stdin */
     880        close(STDIN_FILENO); /* won't need stdin */
    858881        option_mask32 &= ~OPT_o; /* -o with -e is meaningless! */
    859882    }
     
    863886#endif
    864887
    865     if (o_listen) {
    866         dolisten();
     888    if (cnt_l != 0) {
     889        dolisten((cnt_l - 1), proggie);
    867890        /* dolisten does its own connect reporting */
    868         if (proggie) /* -e given? */
    869             doexec(proggie);
    870891        x = readwrite(); /* it even works with UDP! */
    871892    } else {
  • branches/3.3/mindi-busybox/networking/netstat.c

    r3232 r3621  
    120120/* When there are IPv6 connections the IPv6 addresses will be
    121121 * truncated to none-recognition. The '-W' option makes the
    122  * address columns wide enough to accomodate for longest possible
     122 * address columns wide enough to accommodate for longest possible
    123123 * IPv6 addresses, i.e. addresses of the form
    124124 * xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:ddd.ddd.ddd.ddd
     
    126126#define ADDR_WIDE                51  /* INET6_ADDRSTRLEN + 5 for the port number */
    127127#if ENABLE_FEATURE_NETSTAT_WIDE
    128 # define FMT_NET_CONN_DATA       "%s   %6ld %6ld %-*s %-*s %-12s"
     128# define FMT_NET_CONN_DATA       "%s   %6lu %6lu %-*s %-*s %-12s"
    129129# define FMT_NET_CONN_HEADER     "\nProto Recv-Q Send-Q %-*s %-*s State       %s\n"
    130130#else
    131 # define FMT_NET_CONN_DATA       "%s   %6ld %6ld %-23s %-23s %-12s"
     131# define FMT_NET_CONN_DATA       "%s   %6lu %6lu %-23s %-23s %-12s"
    132132# define FMT_NET_CONN_HEADER     "\nProto Recv-Q Send-Q %-23s %-23s State       %s\n"
    133133#endif
     
    229229    long inode = -1;
    230230
    231     if (strncmp(lname, "socket:[", sizeof("socket:[")-1) == 0) {
     231    if (is_prefixed_with(lname, "socket:[")) {
    232232        /* "socket:[12345]", extract the "12345" as inode */
    233233        inode = bb_strtoul(lname + sizeof("socket:[")-1, (char**)&lname, 0);
    234234        if (*lname != ']')
    235235            inode = -1;
    236     } else if (strncmp(lname, "[0000]:", sizeof("[0000]:")-1) == 0) {
     236    } else if (is_prefixed_with(lname, "[0000]:")) {
    237237        /* "[0000]:12345", extract the "12345" as inode */
    238238        inode = bb_strtoul(lname + sizeof("[0000]:")-1, NULL, 0);
     
    404404            "%32[0-9A-Fa-f]:%X %X "
    405405            "%lX:%lX %*X:%*X "
    406             "%*X %d %*d %ld ",
     406            "%*X %d %*d %lu ",
    407407            local_addr, &param->local_port,
    408408            rem_addr, &param->rem_port, &param->state,
     
    612612    strcat(ss_flags, "]");
    613613
    614     printf("%-5s %-6ld %-11s %-10s %-13s %6lu ",
     614    printf("%-5s %-6lu %-11s %-10s %-13s %6lu ",
    615615        ss_proto, refcnt, ss_flags, ss_type, ss_state, inode
    616616        );
     
    623623    /* TODO: currently we stop at first NUL byte. Is it a problem? */
    624624    line += path_ofs;
    625     *strchrnul(line, '\n') = '\0';
     625    chomp(line);
    626626    while (*line)
    627627        fputc_printable(*line++, stdout);
  • branches/3.3/mindi-busybox/networking/nslookup.c

    r3232 r3621  
    139139    len_and_sockaddr *lsa;
    140140
     141    if (!server)
     142        return;
     143
    141144    /* NB: this works even with, say, "[::1]:5353"! :) */
    142145    lsa = xhost2sockaddr(server, 53);
     
    182185    /*_res.options |= RES_USE_INET6;*/
    183186
    184     if (argv[2])
    185         set_default_dns(argv[2]);
     187    set_default_dns(argv[2]);
    186188
    187189    server_print();
     190
     191    /* getaddrinfo and friends are free to request a resolver
     192     * reinitialization. Just in case, set_default_dns() again
     193     * after getaddrinfo (in server_print). This reportedly helps
     194     * with bug 675 "nslookup does not properly use second argument"
     195     * at least on Debian Wheezy and Openwrt AA (eglibc based).
     196     */
     197    set_default_dns(argv[2]);
     198
    188199    return print_host(argv[1], "Name:");
    189200}
  • branches/3.3/mindi-busybox/networking/ntpd.c

    r3232 r3621  
    22 * NTP client/server, based on OpenNTPD 3.9p1
    33 *
    4  * Author: Adam Tkac <vonsch@gmail.com>
     4 * Busybox port author: Adam Tkac (C) 2009 <vonsch@gmail.com>
    55 *
    6  * Licensed under GPLv2, see file LICENSE in this source tree.
     6 * OpenNTPd 3.9p1 copyright holders:
     7 *   Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
     8 *   Copyright (c) 2004 Alexander Guy <alexander.guy@andern.org>
     9 *
     10 * OpenNTPd code is licensed under ISC-style licence:
     11 *
     12 * Permission to use, copy, modify, and distribute this software for any
     13 * purpose with or without fee is hereby granted, provided that the above
     14 * copyright notice and this permission notice appear in all copies.
     15 *
     16 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     17 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     18 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     19 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     20 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
     21 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
     22 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     23 ***********************************************************************
    724 *
    825 * Parts of OpenNTPD clock syncronization code is replaced by
    9  * code which is based on ntp-4.2.6, whuch carries the following
     26 * code which is based on ntp-4.2.6, which carries the following
    1027 * copyright notice:
    1128 *
    12  ***********************************************************************
    13  *                                                                     *
    14  * Copyright (c) University of Delaware 1992-2009                      *
    15  *                                                                     *
    16  * Permission to use, copy, modify, and distribute this software and   *
    17  * its documentation for any purpose with or without fee is hereby     *
    18  * granted, provided that the above copyright notice appears in all    *
    19  * copies and that both the copyright notice and this permission       *
    20  * notice appear in supporting documentation, and that the name        *
    21  * University of Delaware not be used in advertising or publicity      *
    22  * pertaining to distribution of the software without specific,        *
    23  * written prior permission. The University of Delaware makes no       *
    24  * representations about the suitability this software for any         *
    25  * purpose. It is provided "as is" without express or implied          *
    26  * warranty.                                                           *
    27  *                                                                     *
     29 * Copyright (c) University of Delaware 1992-2009
     30 *
     31 * Permission to use, copy, modify, and distribute this software and
     32 * its documentation for any purpose with or without fee is hereby
     33 * granted, provided that the above copyright notice appears in all
     34 * copies and that both the copyright notice and this permission
     35 * notice appear in supporting documentation, and that the name
     36 * University of Delaware not be used in advertising or publicity
     37 * pertaining to distribution of the software without specific,
     38 * written prior permission. The University of Delaware makes no
     39 * representations about the suitability this software for any
     40 * purpose. It is provided "as is" without express or implied warranty.
    2841 ***********************************************************************
    2942 */
    3043
    3144//usage:#define ntpd_trivial_usage
    32 //usage:    "[-dnqNw"IF_FEATURE_NTPD_SERVER("l")"] [-S PROG] [-p PEER]..."
     45//usage:    "[-dnqNw"IF_FEATURE_NTPD_SERVER("l -I IFACE")"] [-S PROG] [-p PEER]..."
    3346//usage:#define ntpd_full_usage "\n\n"
    3447//usage:       "NTP client/server\n"
     
    3851//usage:     "\n    -N  Run at high priority"
    3952//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:    )
    4353//usage:     "\n    -S PROG Run PROG after stepping time, stratum change, and every 11 mins"
    4454//usage:     "\n    -p PEER Obtain time from PEER (may be repeated)"
     55//usage:    IF_FEATURE_NTPD_CONF(
     56//usage:     "\n        If -p is not given, 'server HOST' lines"
     57//usage:     "\n        from /etc/ntp.conf are used"
     58//usage:    )
     59//usage:    IF_FEATURE_NTPD_SERVER(
     60//usage:     "\n    -l  Also run as server on port 123"
     61//usage:     "\n    -I IFACE Bind server to IFACE, implies -l"
     62//usage:    )
     63
     64// -l and -p options are not compatible with "standard" ntpd:
     65// it has them as "-l logfile" and "-p pidfile".
     66// -S and -w are not compat either, "standard" ntpd has no such opts.
    4567
    4668#include "libbb.h"
     
    5274# define IPTOS_LOWDELAY 0x10
    5375#endif
    54 #ifndef IP_PKTINFO
    55 # error "Sorry, your kernel has to support IP_PKTINFO"
    56 #endif
    5776
    5877
    5978/* Verbosity control (max level of -dddd options accepted).
    60  * max 5 is very talkative (and bloated). 2 is non-bloated,
     79 * max 6 is very talkative (and bloated). 3 is non-bloated,
    6180 * production level setting.
    6281 */
    63 #define MAX_VERBOSE     2
     82#define MAX_VERBOSE     3
    6483
    6584
     
    91110 * then the time is stepped, all datapoints are discarded,
    92111 * and we go back to steady state.
     112 *
     113 * Made some changes to speed up re-syncing after our clock goes bad
     114 * (tested with suspending my laptop):
     115 * - if largish offset (>= STEP_THRESHOLD == 1 sec) is seen
     116 *   from a peer, schedule next query for this peer soon
     117 *   without drastically lowering poll interval for everybody.
     118 *   This makes us collect enough data for step much faster:
     119 *   e.g. at poll = 10 (1024 secs), step was done within 5 minutes
     120 *   after first reply which indicated that our clock is 14 seconds off.
     121 * - on step, do not discard d_dispersion data of the existing datapoints,
     122 *   do not clear reachable_bits. This prevents discarding first ~8
     123 *   datapoints after the step.
    93124 */
    94125
    95 #define RETRY_INTERVAL  5       /* on error, retry in N secs */
    96 #define RESPONSE_INTERVAL 15    /* wait for reply up to N secs */
    97 #define INITIAL_SAMPLES 4       /* how many samples do we want for init */
    98 
    99 /* Clock discipline parameters and constants */
     126#define INITIAL_SAMPLES    4    /* how many samples do we want for init */
     127#define BAD_DELAY_GROWTH   4    /* drop packet if its delay grew by more than this */
     128
     129#define RETRY_INTERVAL    32    /* on send/recv error, retry in N secs (need to be power of 2) */
     130#define NOREPLY_INTERVAL 512    /* sent, but got no reply: cap next query by this many seconds */
     131#define RESPONSE_INTERVAL 16    /* wait for reply up to N secs */
    100132
    101133/* Step threshold (sec). std ntpd uses 0.128.
    102  * Using exact power of 2 (1/8) results in smaller code */
    103 #define STEP_THRESHOLD  0.125
    104 #define WATCH_THRESHOLD 128     /* stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */
     134 */
     135#define STEP_THRESHOLD     1
     136/* Slew threshold (sec): adjtimex() won't accept offsets larger than this.
     137 * Using exact power of 2 (1/8) results in smaller code
     138 */
     139#define SLEW_THRESHOLD 0.125
     140/* Stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */
     141#define WATCH_THRESHOLD  128
    105142/* NB: set WATCH_THRESHOLD to ~60 when debugging to save time) */
    106143//UNUSED: #define PANIC_THRESHOLD 1000    /* panic threshold (sec) */
     144
     145/*
     146 * If we got |offset| > BIGOFF from a peer, cap next query interval
     147 * for this peer by this many seconds:
     148 */
     149#define BIGOFF          STEP_THRESHOLD
     150#define BIGOFF_INTERVAL (1 << 7) /* 128 s */
    107151
    108152#define FREQ_TOLERANCE  0.000015 /* frequency tolerance (15 PPM) */
    109153#define BURSTPOLL       0       /* initial poll */
    110154#define MINPOLL         5       /* minimum poll interval. std ntpd uses 6 (6: 64 sec) */
    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_).
     155/*
     156 * If offset > discipline_jitter * POLLADJ_GATE, and poll interval is > 2^BIGPOLL,
     157 * then it is decreased _at once_. (If <= 2^BIGPOLL, it will be decreased _eventually_).
    113158 */
    114 #define BIGPOLL         10      /* 2^10 sec ~= 17 min */
     159#define BIGPOLL         9       /* 2^9 sec ~= 8.5 min */
    115160#define MAXPOLL         12      /* maximum poll interval (12: 1.1h, 17: 36.4h). std ntpd uses 17 */
    116 /* Actively lower poll when we see such big offsets.
    117  * With STEP_THRESHOLD = 0.125, it means we try to sync more aggressively
    118  * if offset increases over ~0.04 sec */
    119 #define POLLDOWN_OFFSET (STEP_THRESHOLD / 3)
     161/*
     162 * Actively lower poll when we see such big offsets.
     163 * With SLEW_THRESHOLD = 0.125, it means we try to sync more aggressively
     164 * if offset increases over ~0.04 sec
     165 */
     166//#define POLLDOWN_OFFSET (SLEW_THRESHOLD / 3)
    120167#define MINDISP         0.01    /* minimum dispersion (sec) */
    121168#define MAXDISP         16      /* maximum dispersion (sec) */
     
    228275    uint8_t          lastpkt_stratum;
    229276    uint8_t          reachable_bits;
    230         /* when to send new query (if p_fd == -1)
    231         * or when receive times out (if p_fd >= 0): */
     277    /* when to send new query (if p_fd == -1)
     278    * or when receive times out (if p_fd >= 0): */
    232279    double           next_action_time;
    233280    double           p_xmttime;
     281    double           p_raw_delay;
     282    /* p_raw_delay is set even by "high delay" packets */
     283    /* lastpkt_delay isn't */
    234284    double           lastpkt_recv_time;
    235285    double           lastpkt_delay;
     
    243293    /* last sent packet: */
    244294    msg_t            p_xmt_msg;
     295    char             p_hostname[1];
    245296} peer_t;
    246297
     
    260311    OPT_S = (1 << 6),
    261312    OPT_l = (1 << 7) * ENABLE_FEATURE_NTPD_SERVER,
     313    OPT_I = (1 << 8) * ENABLE_FEATURE_NTPD_SERVER,
    262314    /* We hijack some bits for other purposes */
    263315    OPT_qq = (1 << 31),
     
    278330#if ENABLE_FEATURE_NTPD_SERVER
    279331    int      listen_fd;
     332    char     *if_name;
    280333# define G_listen_fd (G.listen_fd)
    281334#else
     
    329382#define G_precision_sec  0.002
    330383    uint8_t  stratum;
    331     /* Bool. After set to 1, never goes back to 0: */
    332     smallint initial_poll_complete;
    333384
    334385#define STATE_NSET      0       /* initial state, "nothing is set" */
    335386//#define STATE_FSET    1       /* frequency set from file */
    336 #define STATE_SPIK      2       /* spike detected */
     387//#define STATE_SPIK    2       /* spike detected */
    337388//#define STATE_FREQ    3       /* initial frequency */
    338389#define STATE_SYNC      4       /* clock synchronized (normal operation) */
     
    359410#define G (*ptr_to_globals)
    360411
    361 static const int const_IPTOS_LOWDELAY = IPTOS_LOWDELAY;
    362 
    363412
    364413#define VERB1 if (MAX_VERBOSE && G.verbose)
     
    367416#define VERB4 if (MAX_VERBOSE >= 4 && G.verbose >= 4)
    368417#define VERB5 if (MAX_VERBOSE >= 5 && G.verbose >= 5)
     418#define VERB6 if (MAX_VERBOSE >= 6 && G.verbose >= 6)
    369419
    370420
     
    568618    sum = 0;
    569619    for (i = 0; i < NUM_DATAPOINTS; i++) {
    570         VERB4 {
     620        VERB5 {
    571621            bb_error_msg("datapoint[%d]: off:%f disp:%f(%f) age:%f%s",
    572622                i,
     
    665715    p->filter_jitter = sum > G_precision_sec ? sum : G_precision_sec;
    666716
    667     VERB3 bb_error_msg("filter offset:%+f disp:%f jitter:%f",
     717    VERB4 bb_error_msg("filter offset:%+f disp:%f jitter:%f",
    668718            p->filter_offset,
    669719            p->filter_dispersion,
     
    675725{
    676726    int i;
    677     bool small_ofs = fabs(offset) < 16 * STEP_THRESHOLD;
     727    bool small_ofs = fabs(offset) < STEP_THRESHOLD;
     728
     729    /* Used to set p->filter_datapoint[i].d_dispersion = MAXDISP
     730     * and clear reachable bits, but this proved to be too agressive:
     731     * after step (tested with suspending laptop for ~30 secs),
     732     * this caused all previous data to be considered invalid,
     733     * making us needing to collect full ~8 datapoins per peer
     734     * after step in order to start trusting them.
     735     * In turn, this was making poll interval decrease even after
     736     * step was done. (Poll interval decreases already before step
     737     * in this scenario, because we see large offsets and end up with
     738     * no good peer to select).
     739     */
    678740
    679741    for (i = 0; i < NUM_DATAPOINTS; i++) {
     
    690752            p->filter_datapoint[i].d_recv_time  = G.cur_time;
    691753            p->filter_datapoint[i].d_offset     = 0;
    692             p->filter_datapoint[i].d_dispersion = MAXDISP;
     754            /*p->filter_datapoint[i].d_dispersion = MAXDISP;*/
    693755        }
    694756    }
     
    696758        p->lastpkt_recv_time += offset;
    697759    } else {
    698         p->reachable_bits = 0;
     760        /*p->reachable_bits = 0;*/
    699761        p->lastpkt_recv_time = G.cur_time;
    700762    }
    701763    filter_datapoints(p); /* recalc p->filter_xxx */
    702     VERB5 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time);
     764    VERB6 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time);
    703765}
    704766
    705767static void
    706 add_peers(char *s)
    707 {
     768resolve_peer_hostname(peer_t *p, int loop_on_fail)
     769{
     770    len_and_sockaddr *lsa;
     771
     772 again:
     773    lsa = host2sockaddr(p->p_hostname, 123);
     774    if (!lsa) {
     775        /* error message already emitted by host2sockaddr() */
     776        if (!loop_on_fail)
     777            return;
     778//FIXME: do this to avoid infinite looping on typo in a hostname?
     779//well... in which case, what is a good value for loop_on_fail?
     780        //if (--loop_on_fail == 0)
     781        //  xfunc_die();
     782        sleep(5);
     783        goto again;
     784    }
     785    free(p->p_lsa);
     786    free(p->p_dotted);
     787    p->p_lsa = lsa;
     788    p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
     789}
     790
     791static void
     792add_peers(const char *s)
     793{
     794    llist_t *item;
    708795    peer_t *p;
    709796
    710     p = xzalloc(sizeof(*p));
    711     p->p_lsa = xhost2sockaddr(s, 123);
    712     p->p_dotted = xmalloc_sockaddr2dotted_noport(&p->p_lsa->u.sa);
     797    p = xzalloc(sizeof(*p) + strlen(s));
     798    strcpy(p->p_hostname, s);
     799    resolve_peer_hostname(p, /*loop_on_fail=*/ 1);
     800
     801    /* Names like N.<country2chars>.pool.ntp.org are randomly resolved
     802     * to a pool of machines. Sometimes different N's resolve to the same IP.
     803     * It is not useful to have two peers with same IP. We skip duplicates.
     804     */
     805    for (item = G.ntp_peers; item != NULL; item = item->link) {
     806        peer_t *pp = (peer_t *) item->data;
     807        if (strcmp(p->p_dotted, pp->p_dotted) == 0) {
     808            bb_error_msg("duplicate peer %s (%s)", s, p->p_dotted);
     809            free(p->p_lsa);
     810            free(p->p_dotted);
     811            free(p);
     812            return;
     813        }
     814    }
     815
    713816    p->p_fd = -1;
    714817    p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3);
    715818    p->next_action_time = G.cur_time; /* = set_next(p, 0); */
    716     reset_peer_stats(p, 16 * STEP_THRESHOLD);
     819    reset_peer_stats(p, STEP_THRESHOLD);
    717820
    718821    llist_add_to(&G.ntp_peers, p);
     
    778881        if (family == AF_INET)
    779882#endif
    780             setsockopt(fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY));
     883            setsockopt_int(fd, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY);
    781884        free(local_lsa);
    782885    }
     
    801904     * Save the real transmit timestamp locally.
    802905     */
    803     p->p_xmt_msg.m_xmttime.int_partl = random();
    804     p->p_xmt_msg.m_xmttime.fractionl = random();
     906    p->p_xmt_msg.m_xmttime.int_partl = rand();
     907    p->p_xmt_msg.m_xmttime.fractionl = rand();
    805908    p->p_xmttime = gettime1900d();
     909
     910    /* Were doing it only if sendto worked, but
     911     * loss of sync detection needs reachable_bits updated
     912     * even if sending fails *locally*:
     913     * "network is unreachable" because cable was pulled?
     914     * We still need to declare "unsync" if this condition persists.
     915     */
     916    p->reachable_bits <<= 1;
    806917
    807918    if (do_sendto(p->p_fd, /*from:*/ NULL, /*to:*/ &p->p_lsa->u.sa, /*addrlen:*/ p->p_lsa->len,
     
    810921        close(p->p_fd);
    811922        p->p_fd = -1;
     923        /*
     924         * We know that we sent nothing.
     925         * We can retry *soon* without fearing
     926         * that we are flooding the peer.
     927         */
    812928        set_next(p, RETRY_INTERVAL);
    813929        return;
    814930    }
    815931
    816     p->reachable_bits <<= 1;
    817932    set_next(p, RESPONSE_INTERVAL);
    818933}
     
    820935
    821936/* Note that there is no provision to prevent several run_scripts
    822  * to be done in quick succession. In fact, it happens rather often
     937 * to be started in quick succession. In fact, it happens rather often
    823938 * if initial syncronization results in a step.
    824939 * You will see "step" and then "stratum" script runs, sometimes
     
    830945    char *argv[3];
    831946    char *env1, *env2, *env3, *env4;
     947
     948    G.last_script_run = G.cur_time;
    832949
    833950    if (!G.script_name)
     
    867984    free(env3);
    868985    free(env4);
    869 
    870     G.last_script_run = G.cur_time;
    871986}
    872987
     
    8881003    VERB2 {
    8891004        tval = tvc.tv_sec;
    890         strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&tval));
     1005        strftime_YYYYMMDDHHMMSS(buf, sizeof(buf), &tval);
    8911006        bb_error_msg("current time is %s.%06u", buf, (unsigned)tvc.tv_usec);
    8921007    }
    8931008    tval = tvn.tv_sec;
    894     strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&tval));
     1009    strftime_YYYYMMDDHHMMSS(buf, sizeof(buf), &tval);
    8951010    bb_error_msg("setting time to %s.%06u (offset %+fs)", buf, (unsigned)tvn.tv_usec, offset);
    8961011
     
    9211036}
    9221037
     1038static void clamp_pollexp_and_set_MAXSTRAT(void)
     1039{
     1040    if (G.poll_exp < MINPOLL)
     1041        G.poll_exp = MINPOLL;
     1042    if (G.poll_exp > BIGPOLL)
     1043        G.poll_exp = BIGPOLL;
     1044    G.polladj_count = 0;
     1045    G.stratum = MAXSTRAT;
     1046}
     1047
    9231048
    9241049/*
     
    9601085    if ((p->reachable_bits & (p->reachable_bits-1)) == 0) {
    9611086        /* One or zero bits in reachable_bits */
    962         VERB3 bb_error_msg("peer %s unfit for selection: unreachable", p->p_dotted);
     1087        VERB4 bb_error_msg("peer %s unfit for selection: unreachable", p->p_dotted);
    9631088        return 0;
    9641089    }
     
    9671092     || p->lastpkt_stratum >= MAXSTRAT
    9681093    ) {
    969         VERB3 bb_error_msg("peer %s unfit for selection: bad status/stratum", p->p_dotted);
     1094        VERB4 bb_error_msg("peer %s unfit for selection: bad status/stratum", p->p_dotted);
    9701095        return 0;
    9711096    }
     
    9731098    /* rd is root_distance(p) */
    9741099    if (rd > MAXDIST + FREQ_TOLERANCE * (1 << G.poll_exp)) {
    975         VERB3 bb_error_msg("peer %s unfit for selection: root distance too high", p->p_dotted);
     1100        VERB4 bb_error_msg("peer %s unfit for selection: root distance too high", p->p_dotted);
    9761101        return 0;
    9771102    }
     
    10021127    num_points = 0;
    10031128    item = G.ntp_peers;
    1004     if (G.initial_poll_complete) while (item != NULL) {
     1129    while (item != NULL) {
    10051130        double rd, offset;
    10061131
     
    10131138        }
    10141139
    1015         VERB4 bb_error_msg("interval: [%f %f %f] %s",
     1140        VERB5 bb_error_msg("interval: [%f %f %f] %s",
    10161141                offset - rd,
    10171142                offset,
     
    10381163    num_candidates = num_points / 3;
    10391164    if (num_candidates == 0) {
    1040         VERB3 bb_error_msg("no valid datapoints, no peer selected");
     1165        VERB3 bb_error_msg("no valid datapoints%s", ", no peer selected");
    10411166        return NULL;
    10421167    }
     
    10961221        num_falsetickers++;
    10971222        if (num_falsetickers * 2 >= num_candidates) {
    1098             VERB3 bb_error_msg("too many falsetickers:%d (candidates:%d), no peer selected",
    1099                     num_falsetickers, num_candidates);
     1223            VERB3 bb_error_msg("falsetickers:%d, candidates:%d%s",
     1224                    num_falsetickers, num_candidates,
     1225                    ", no peer selected");
    11001226            return NULL;
    11011227        }
    11021228    }
    1103     VERB3 bb_error_msg("selected interval: [%f, %f]; candidates:%d falsetickers:%d",
     1229    VERB4 bb_error_msg("selected interval: [%f, %f]; candidates:%d falsetickers:%d",
    11041230            low, high, num_candidates, num_falsetickers);
    11051231
     
    11191245        /* x.opt_rd == root_distance(p); */
    11201246        survivor[num_survivors].metric = MAXDIST * p->lastpkt_stratum + point[i].opt_rd;
    1121         VERB4 bb_error_msg("survivor[%d] metric:%f peer:%s",
     1247        VERB5 bb_error_msg("survivor[%d] metric:%f peer:%s",
    11221248            num_survivors, survivor[num_survivors].metric, p->p_dotted);
    11231249        num_survivors++;
     
    11291255     */
    11301256    if (num_survivors < MIN_SELECTED) {
    1131         VERB3 bb_error_msg("num_survivors %d < %d, no peer selected",
    1132                 num_survivors, MIN_SELECTED);
     1257        VERB3 bb_error_msg("survivors:%d%s",
     1258                num_survivors,
     1259                ", no peer selected");
    11331260        return NULL;
    11341261    }
     
    11501277
    11511278        if (num_survivors <= MIN_CLUSTERED) {
    1152             VERB3 bb_error_msg("num_survivors %d <= %d, not discarding more",
     1279            VERB4 bb_error_msg("num_survivors %d <= %d, not discarding more",
    11531280                    num_survivors, MIN_CLUSTERED);
    11541281            break;
     
    11761303                max_idx = i;
    11771304            }
    1178             VERB5 bb_error_msg("survivor %d selection_jitter^2:%f",
     1305            VERB6 bb_error_msg("survivor %d selection_jitter^2:%f",
    11791306                    i, selection_jitter_sq);
    11801307        }
    11811308        max_selection_jitter = SQRT(max_selection_jitter / num_survivors);
    1182         VERB4 bb_error_msg("max_selection_jitter (at %d):%f min_jitter:%f",
     1309        VERB5 bb_error_msg("max_selection_jitter (at %d):%f min_jitter:%f",
    11831310                max_idx, max_selection_jitter, min_jitter);
    11841311
     
    11891316         */
    11901317        if (max_selection_jitter < min_jitter) {
    1191             VERB3 bb_error_msg("max_selection_jitter:%f < min_jitter:%f, num_survivors:%d, not discarding more",
     1318            VERB4 bb_error_msg("max_selection_jitter:%f < min_jitter:%f, num_survivors:%d, not discarding more",
    11921319                    max_selection_jitter, min_jitter, num_survivors);
    11931320            break;
     
    11971324         * and go around again.
    11981325         */
    1199         VERB5 bb_error_msg("dropping survivor %d", max_idx);
     1326        VERB6 bb_error_msg("dropping survivor %d", max_idx);
    12001327        num_survivors--;
    12011328        while (max_idx < num_survivors) {
     
    12391366        for (i = 1; i < num_survivors; i++) {
    12401367            if (G.last_update_peer == survivor[i].p) {
    1241                 VERB4 bb_error_msg("keeping old synced peer");
     1368                VERB5 bb_error_msg("keeping old synced peer");
    12421369                p = G.last_update_peer;
    12431370                goto keep_old;
     
    12471374    G.last_update_peer = p;
    12481375 keep_old:
    1249     VERB3 bb_error_msg("selected peer %s filter_offset:%+f age:%f",
     1376    VERB4 bb_error_msg("selected peer %s filter_offset:%+f age:%f",
    12501377            p->p_dotted,
    12511378            p->filter_offset,
     
    12661393     * the current time.
    12671394     */
    1268     VERB3 bb_error_msg("disc_state=%d last update offset=%f recv_time=%f",
     1395    VERB4 bb_error_msg("disc_state=%d last update offset=%f recv_time=%f",
    12691396            disc_state, offset, recv_time);
    12701397    G.discipline_state = disc_state;
     
    12851412    double freq_drift;
    12861413#endif
     1414#if !USING_KERNEL_PLL_LOOP || USING_INITIAL_FREQ_ESTIMATION
    12871415    double since_last_update;
     1416#endif
    12881417    double etemp, dtemp;
    12891418
     
    13041433     */
    13051434    if (recv_time <= G.last_update_recv_time) {
    1306         VERB3 bb_error_msg("same or older datapoint: %f >= %f, not using it",
    1307                 G.last_update_recv_time, recv_time);
     1435        VERB3 bb_error_msg("update from %s: same or older datapoint, not using it",
     1436            p->p_dotted);
    13081437        return 0; /* "leave poll interval as is" */
    13091438    }
     
    13131442     * and frequency errors.
    13141443     */
     1444#if !USING_KERNEL_PLL_LOOP || USING_INITIAL_FREQ_ESTIMATION
    13151445    since_last_update = recv_time - G.reftime;
     1446#endif
    13161447#if !USING_KERNEL_PLL_LOOP
    13171448    freq_drift = 0;
     
    13211452        /* Ignore updates until the stepout threshold */
    13221453        if (since_last_update < WATCH_THRESHOLD) {
    1323             VERB3 bb_error_msg("measuring drift, datapoint ignored, %f sec remains",
     1454            VERB4 bb_error_msg("measuring drift, datapoint ignored, %f sec remains",
    13241455                    WATCH_THRESHOLD - since_last_update);
    13251456            return 0; /* "leave poll interval as is" */
     
    13351466     */
    13361467    if (abs_offset > STEP_THRESHOLD) {
     1468#if 0
     1469        double remains;
     1470
     1471// This "spike state" seems to be useless, peer selection already drops
     1472// occassional "bad" datapoints. If we are here, there were _many_
     1473// large offsets. When a few first large offsets are seen,
     1474// we end up in "no valid datapoints, no peer selected" state.
     1475// Only when enough of them are seen (which means it's not a fluke),
     1476// we end up here. Looks like _our_ clock is off.
    13371477        switch (G.discipline_state) {
    13381478        case STATE_SYNC:
    13391479            /* The first outlyer: ignore it, switch to SPIK state */
    1340             VERB3 bb_error_msg("offset:%+f - spike detected", offset);
     1480            VERB3 bb_error_msg("update from %s: offset:%+f, spike%s",
     1481                p->p_dotted, offset,
     1482                "");
    13411483            G.discipline_state = STATE_SPIK;
    13421484            return -1; /* "decrease poll interval" */
     
    13461488             * is found or the stepout threshold is exceeded.
    13471489             */
    1348             if (since_last_update < WATCH_THRESHOLD) {
    1349                 VERB3 bb_error_msg("spike detected, datapoint ignored, %f sec remains",
    1350                         WATCH_THRESHOLD - since_last_update);
     1490            remains = WATCH_THRESHOLD - since_last_update;
     1491            if (remains > 0) {
     1492                VERB3 bb_error_msg("update from %s: offset:%+f, spike%s",
     1493                    p->p_dotted, offset,
     1494                    ", datapoint ignored");
    13511495                return -1; /* "decrease poll interval" */
    13521496            }
    13531497            /* fall through: we need to step */
    13541498        } /* switch */
     1499#endif
    13551500
    13561501        /* Step the time and clamp down the poll interval.
     
    13751520         * intervals.
    13761521         */
    1377         VERB3 bb_error_msg("stepping time by %+f; poll_exp=MINPOLL", offset);
     1522        VERB4 bb_error_msg("stepping time by %+f; poll_exp=MINPOLL", offset);
    13781523        step_time(offset);
    13791524        if (option_mask32 & OPT_q) {
     
    13821527        }
    13831528
    1384         G.polladj_count = 0;
    1385         G.poll_exp = MINPOLL;
    1386         G.stratum = MAXSTRAT;
     1529        clamp_pollexp_and_set_MAXSTRAT();
    13871530
    13881531        run_script("step", offset);
     1532
     1533        recv_time += offset;
    13891534
    13901535#if USING_INITIAL_FREQ_ESTIMATION
     
    13961541        abs_offset = offset = 0;
    13971542        set_new_values(STATE_SYNC, offset, recv_time);
    1398 
    13991543    } else { /* abs_offset <= STEP_THRESHOLD */
    14001544
    1401         if (G.poll_exp < MINPOLL && G.initial_poll_complete) {
    1402             VERB3 bb_error_msg("small offset:%+f, disabling burst mode", offset);
    1403             G.polladj_count = 0;
    1404             G.poll_exp = MINPOLL;
    1405         }
     1545        /* The ratio is calculated before jitter is updated to make
     1546         * poll adjust code more sensitive to large offsets.
     1547         */
     1548        G.offset_to_jitter_ratio = abs_offset / G.discipline_jitter;
    14061549
    14071550        /* Compute the clock jitter as the RMS of exponentially
     
    14111554        dtemp = SQUARE(offset - G.last_update_offset);
    14121555        G.discipline_jitter = SQRT(etemp + (dtemp - etemp) / AVG);
     1556        if (G.discipline_jitter < G_precision_sec)
     1557            G.discipline_jitter = G_precision_sec;
    14131558
    14141559        switch (G.discipline_state) {
     
    14291574            set_new_values(STATE_SYNC, offset, recv_time);
    14301575#endif
    1431             VERB3 bb_error_msg("transitioning to FREQ, datapoint ignored");
     1576            VERB4 bb_error_msg("transitioning to FREQ, datapoint ignored");
    14321577            return 0; /* "leave poll interval as is" */
    14331578
     
    14871632    }
    14881633
    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 
    14931634    G.reftime = G.cur_time;
    14941635    G.ntp_status = p->lastpkt_status;
     
    14981639    dtemp += MAXD(p->filter_dispersion + FREQ_TOLERANCE * (G.cur_time - p->lastpkt_recv_time) + abs_offset, MINDISP);
    14991640    G.rootdisp = p->lastpkt_rootdisp + dtemp;
    1500     VERB3 bb_error_msg("updating leap/refid/reftime/rootdisp from peer %s", p->p_dotted);
     1641    VERB4 bb_error_msg("updating leap/refid/reftime/rootdisp from peer %s", p->p_dotted);
    15011642
    15021643    /* We are in STATE_SYNC now, but did not do adjtimex yet.
     
    15181659    G.discipline_wander = SQRT(etemp + (dtemp - etemp) / AVG);
    15191660
    1520     VERB3 bb_error_msg("discipline freq_drift=%.9f(int:%ld corr:%e) wander=%f",
     1661    VERB4 bb_error_msg("discipline freq_drift=%.9f(int:%ld corr:%e) wander=%f",
    15211662            G.discipline_freq_drift,
    15221663            (long)(G.discipline_freq_drift * 65536e6),
     
    15241665            G.discipline_wander);
    15251666#endif
    1526     VERB3 {
     1667    VERB4 {
    15271668        memset(&tmx, 0, sizeof(tmx));
    15281669        if (adjtimex(&tmx) < 0)
     
    15431684#endif
    15441685    tmx.modes = ADJ_OFFSET | ADJ_STATUS | ADJ_TIMECONST;// | ADJ_MAXERROR | ADJ_ESTERROR;
    1545     tmx.offset = (offset * 1000000); /* usec */
    1546     tmx.status = STA_PLL;
    1547     if (G.ntp_status & LI_PLUSSEC)
    1548         tmx.status |= STA_INS;
    1549     if (G.ntp_status & LI_MINUSSEC)
    1550         tmx.status |= STA_DEL;
    1551 
    1552     tmx.constant = G.poll_exp - 4;
     1686    tmx.constant = (int)G.poll_exp - 4;
    15531687    /* EXPERIMENTAL.
    15541688     * The below if statement should be unnecessary, but...
     
    15611695     * larger than jitter.
    15621696     */
    1563     if (tmx.constant > 0 && G.offset_to_jitter_ratio >= TIMECONST_HACK_GATE)
     1697    if (G.offset_to_jitter_ratio >= TIMECONST_HACK_GATE)
    15641698        tmx.constant--;
     1699    tmx.offset = (long)(offset * 1000000); /* usec */
     1700    if (SLEW_THRESHOLD < STEP_THRESHOLD) {
     1701        if (tmx.offset > (long)(SLEW_THRESHOLD * 1000000)) {
     1702            tmx.offset = (long)(SLEW_THRESHOLD * 1000000);
     1703            tmx.constant--;
     1704        }
     1705        if (tmx.offset < -(long)(SLEW_THRESHOLD * 1000000)) {
     1706            tmx.offset = -(long)(SLEW_THRESHOLD * 1000000);
     1707            tmx.constant--;
     1708        }
     1709    }
     1710    if (tmx.constant < 0)
     1711        tmx.constant = 0;
     1712
     1713    tmx.status = STA_PLL;
     1714    if (G.ntp_status & LI_PLUSSEC)
     1715        tmx.status |= STA_INS;
     1716    if (G.ntp_status & LI_MINUSSEC)
     1717        tmx.status |= STA_DEL;
    15651718
    15661719    //tmx.esterror = (uint32_t)(clock_jitter * 1e6);
     
    15721725     * Not sure why. Perhaps it is normal.
    15731726     */
    1574     VERB3 bb_error_msg("adjtimex:%d freq:%ld offset:%+ld status:0x%x",
     1727    VERB4 bb_error_msg("adjtimex:%d freq:%ld offset:%+ld status:0x%x",
    15751728                rc, tmx.freq, tmx.offset, tmx.status);
    15761729    G.kernel_freq_drift = tmx.freq / 65536;
    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);
     1730    VERB2 bb_error_msg("update from:%s offset:%+f delay:%f jitter:%f clock drift:%+.3fppm tc:%d",
     1731            p->p_dotted,
     1732            offset,
     1733            p->lastpkt_delay,
     1734            G.discipline_jitter,
     1735            (double)tmx.freq / 65536,
     1736            (int)tmx.constant
     1737    );
    15791738
    15801739    return 1; /* "ok to increase poll interval" */
     
    15871746 */
    15881747static unsigned
    1589 retry_interval(void)
    1590 {
    1591     /* Local problem, want to retry soon */
    1592     unsigned interval, r;
    1593     interval = RETRY_INTERVAL;
    1594     r = random();
    1595     interval += r % (unsigned)(RETRY_INTERVAL / 4);
    1596     VERB3 bb_error_msg("chose retry interval:%u", interval);
     1748poll_interval(int upper_bound)
     1749{
     1750    unsigned interval, r, mask;
     1751    interval = 1 << G.poll_exp;
     1752    if (interval > upper_bound)
     1753        interval = upper_bound;
     1754    mask = ((interval-1) >> 4) | 1;
     1755    r = rand();
     1756    interval += r & mask; /* ~ random(0..1) * interval/16 */
     1757    VERB4 bb_error_msg("chose poll interval:%u (poll_exp:%d)", interval, G.poll_exp);
    15971758    return interval;
    15981759}
    1599 static unsigned
    1600 poll_interval(int exponent)
    1601 {
    1602     unsigned interval, r;
    1603     exponent = G.poll_exp + exponent;
    1604     if (exponent < 0)
    1605         exponent = 0;
    1606     interval = 1 << exponent;
    1607     r = random();
    1608     interval += ((r & (interval-1)) >> 4) + ((r >> 8) & 1); /* + 1/16 of interval, max */
    1609     VERB3 bb_error_msg("chose poll interval:%u (poll_exp:%d exp:%d)", interval, G.poll_exp, exponent);
    1610     return interval;
     1760static void
     1761adjust_poll(int count)
     1762{
     1763    G.polladj_count += count;
     1764    if (G.polladj_count > POLLADJ_LIMIT) {
     1765        G.polladj_count = 0;
     1766        if (G.poll_exp < MAXPOLL) {
     1767            G.poll_exp++;
     1768            VERB4 bb_error_msg("polladj: discipline_jitter:%f ++poll_exp=%d",
     1769                    G.discipline_jitter, G.poll_exp);
     1770        }
     1771    } else if (G.polladj_count < -POLLADJ_LIMIT || (count < 0 && G.poll_exp > BIGPOLL)) {
     1772        G.polladj_count = 0;
     1773        if (G.poll_exp > MINPOLL) {
     1774            llist_t *item;
     1775
     1776            G.poll_exp--;
     1777            /* Correct p->next_action_time in each peer
     1778             * which waits for sending, so that they send earlier.
     1779             * Old pp->next_action_time are on the order
     1780             * of t + (1 << old_poll_exp) + small_random,
     1781             * we simply need to subtract ~half of that.
     1782             */
     1783            for (item = G.ntp_peers; item != NULL; item = item->link) {
     1784                peer_t *pp = (peer_t *) item->data;
     1785                if (pp->p_fd < 0)
     1786                    pp->next_action_time -= (1 << G.poll_exp);
     1787            }
     1788            VERB4 bb_error_msg("polladj: discipline_jitter:%f --poll_exp=%d",
     1789                    G.discipline_jitter, G.poll_exp);
     1790        }
     1791    } else {
     1792        VERB4 bb_error_msg("polladj: count:%d", G.polladj_count);
     1793    }
    16111794}
    16121795static NOINLINE void
     
    16171800    msg_t       msg;
    16181801    double      T1, T2, T3, T4;
     1802    double      offset;
     1803    double      prev_delay, delay;
    16191804    unsigned    interval;
    16201805    datapoint_t *datapoint;
    16211806    peer_t      *q;
    16221807
     1808    offset = 0;
     1809
    16231810    /* We can recvfrom here and check from.IP, but some multihomed
    16241811     * ntp servers reply from their *other IP*.
    16251812     * TODO: maybe we should check at least what we can: from.port == 123?
    16261813     */
     1814 recv_again:
    16271815    size = recv(p->p_fd, &msg, sizeof(msg), MSG_DONTWAIT);
    1628     if (size == -1) {
    1629         bb_perror_msg("recv(%s) error", p->p_dotted);
    1630         if (errno == EHOSTUNREACH || errno == EHOSTDOWN
    1631          || errno == ENETUNREACH || errno == ENETDOWN
    1632          || errno == ECONNREFUSED || errno == EADDRNOTAVAIL
    1633          || errno == EAGAIN
    1634         ) {
    1635 //TODO: always do this?
    1636             interval = retry_interval();
    1637             goto set_next_and_ret;
    1638         }
    1639         xfunc_die();
     1816    if (size < 0) {
     1817        if (errno == EINTR)
     1818            /* Signal caught */
     1819            goto recv_again;
     1820        if (errno == EAGAIN)
     1821            /* There was no packet after all
     1822             * (poll() returning POLLIN for a fd
     1823             * is not a ironclad guarantee that data is there)
     1824             */
     1825            return;
     1826        /*
     1827         * If you need a different handling for a specific
     1828         * errno, always explain it in comment.
     1829         */
     1830        bb_perror_msg_and_die("recv(%s) error", p->p_dotted);
    16401831    }
    16411832
     
    16631854     || msg.m_stratum > NTP_MAXSTRATUM
    16641855    ) {
    1665 // TODO: stratum 0 responses may have commands in 32-bit m_refid field:
    1666 // "DENY", "RSTR" - peer does not like us at all
    1667 // "RATE" - peer is overloaded, reduce polling freq
    1668         interval = poll_interval(0);
    1669         bb_error_msg("reply from %s: peer is unsynced, next query in %us", p->p_dotted, interval);
    1670         goto set_next_and_ret;
     1856        bb_error_msg("reply from %s: peer is unsynced", p->p_dotted);
     1857        /*
     1858         * Stratum 0 responses may have commands in 32-bit m_refid field:
     1859         * "DENY", "RSTR" - peer does not like us at all,
     1860         * "RATE" - peer is overloaded, reduce polling freq.
     1861         * If poll interval is small, increase it.
     1862         */
     1863        if (G.poll_exp < BIGPOLL)
     1864            goto increase_interval;
     1865        goto pick_normal_interval;
    16711866    }
    16721867
     
    16741869//  if (msg.m_rootdelay / 2 + msg.m_rootdisp >= MAXDISP || p->lastpkt_reftime > msg.m_xmt)
    16751870//      return;                 /* invalid header values */
    1676 
    1677     p->lastpkt_status = msg.m_status;
    1678     p->lastpkt_stratum = msg.m_stratum;
    1679     p->lastpkt_rootdelay = sfp_to_d(msg.m_rootdelay);
    1680     p->lastpkt_rootdisp = sfp_to_d(msg.m_rootdisp);
    1681     p->lastpkt_refid = msg.m_refid;
    16821871
    16831872    /*
     
    17001889    T4 = G.cur_time;
    17011890
    1702     p->lastpkt_recv_time = T4;
    1703 
    1704     VERB5 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time);
    1705     p->datapoint_idx = p->reachable_bits ? (p->datapoint_idx + 1) % NUM_DATAPOINTS : 0;
    1706     datapoint = &p->filter_datapoint[p->datapoint_idx];
    1707     datapoint->d_recv_time = T4;
    1708     datapoint->d_offset    = ((T2 - T1) + (T3 - T4)) / 2;
    17091891    /* The delay calculation is a special case. In cases where the
    17101892     * server and client clocks are running at different rates and
     
    17131895     * the delay is clamped not less than the system precision.
    17141896     */
    1715     p->lastpkt_delay = (T4 - T1) - (T3 - T2);
    1716     if (p->lastpkt_delay < G_precision_sec)
    1717         p->lastpkt_delay = G_precision_sec;
     1897    delay = (T4 - T1) - (T3 - T2);
     1898    if (delay < G_precision_sec)
     1899        delay = G_precision_sec;
     1900    /*
     1901     * If this packet's delay is much bigger than the last one,
     1902     * it's better to just ignore it than use its much less precise value.
     1903     */
     1904    prev_delay = p->p_raw_delay;
     1905    p->p_raw_delay = delay;
     1906    if (p->reachable_bits && delay > prev_delay * BAD_DELAY_GROWTH) {
     1907        bb_error_msg("reply from %s: delay %f is too high, ignoring", p->p_dotted, delay);
     1908        goto pick_normal_interval;
     1909    }
     1910
     1911    p->lastpkt_delay = delay;
     1912    p->lastpkt_recv_time = T4;
     1913    VERB6 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time);
     1914    p->lastpkt_status = msg.m_status;
     1915    p->lastpkt_stratum = msg.m_stratum;
     1916    p->lastpkt_rootdelay = sfp_to_d(msg.m_rootdelay);
     1917    p->lastpkt_rootdisp = sfp_to_d(msg.m_rootdisp);
     1918    p->lastpkt_refid = msg.m_refid;
     1919
     1920    p->datapoint_idx = p->reachable_bits ? (p->datapoint_idx + 1) % NUM_DATAPOINTS : 0;
     1921    datapoint = &p->filter_datapoint[p->datapoint_idx];
     1922    datapoint->d_recv_time = T4;
     1923    datapoint->d_offset    = offset = ((T2 - T1) + (T3 - T4)) / 2;
    17181924    datapoint->d_dispersion = LOG2D(msg.m_precision_exp) + G_precision_sec;
    17191925    if (!p->reachable_bits) {
     
    17211927        int i;
    17221928        for (i = 0; i < NUM_DATAPOINTS; i++) {
    1723             p->filter_datapoint[i].d_offset = datapoint->d_offset;
     1929            p->filter_datapoint[i].d_offset = offset;
    17241930        }
    17251931    }
     
    17291935        bb_error_msg("reply from %s: offset:%+f delay:%f status:0x%02x strat:%d refid:0x%08x rootdelay:%f reach:0x%02x",
    17301936            p->p_dotted,
    1731             datapoint->d_offset,
     1937            offset,
    17321938            p->lastpkt_delay,
    17331939            p->lastpkt_status,
     
    17451951    filter_datapoints(p);
    17461952    q = select_and_cluster();
    1747     rc = -1;
     1953    rc = 0;
    17481954    if (q) {
    1749         rc = 0;
    17501955        if (!(option_mask32 & OPT_w)) {
    17511956            rc = update_local_clock(q);
     1957#if 0
     1958//Disabled this because there is a case where largish offsets
     1959//are unavoidable: if network round-trip delay is, say, ~0.6s,
     1960//error in offset estimation would be ~delay/2 ~= 0.3s.
     1961//Thus, offsets will be usually in -0.3...0.3s range.
     1962//In this case, this code would keep poll interval small,
     1963//but it won't be helping.
     1964//BIGOFF check below deals with a case of seeing multi-second offsets.
     1965
    17521966            /* If drift is dangerously large, immediately
    17531967             * drop poll interval one step down.
    17541968             */
    17551969            if (fabs(q->filter_offset) >= POLLDOWN_OFFSET) {
    1756                 VERB3 bb_error_msg("offset:%+f > POLLDOWN_OFFSET", q->filter_offset);
    1757                 goto poll_down;
     1970                VERB4 bb_error_msg("offset:%+f > POLLDOWN_OFFSET", q->filter_offset);
     1971                adjust_poll(-POLLADJ_LIMIT * 3);
     1972                rc = 0;
    17581973            }
    1759         }
    1760     }
    1761     /* else: no peer selected, rc = -1: we want to poll more often */
     1974#endif
     1975        }
     1976    } else {
     1977        /* No peer selected.
     1978         * If poll interval is small, increase it.
     1979         */
     1980        if (G.poll_exp < BIGPOLL)
     1981            goto increase_interval;
     1982    }
    17621983
    17631984    if (rc != 0) {
     
    17711992            /* was += G.poll_exp but it is a bit
    17721993             * too optimistic for my taste at high poll_exp's */
    1773             G.polladj_count += MINPOLL;
    1774             if (G.polladj_count > POLLADJ_LIMIT) {
    1775                 G.polladj_count = 0;
    1776                 if (G.poll_exp < MAXPOLL) {
    1777                     G.poll_exp++;
    1778                     VERB3 bb_error_msg("polladj: discipline_jitter:%f ++poll_exp=%d",
    1779                             G.discipline_jitter, G.poll_exp);
    1780                 }
    1781             } else {
    1782                 VERB3 bb_error_msg("polladj: incr:%d", G.polladj_count);
    1783             }
     1994 increase_interval:
     1995            adjust_poll(MINPOLL);
    17841996        } else {
    1785             G.polladj_count -= G.poll_exp * 2;
    1786             if (G.polladj_count < -POLLADJ_LIMIT || G.poll_exp >= BIGPOLL) {
    1787  poll_down:
    1788                 G.polladj_count = 0;
    1789                 if (G.poll_exp > MINPOLL) {
    1790                     llist_t *item;
    1791 
    1792                     G.poll_exp--;
    1793                     /* Correct p->next_action_time in each peer
    1794                      * which waits for sending, so that they send earlier.
    1795                      * Old pp->next_action_time are on the order
    1796                      * of t + (1 << old_poll_exp) + small_random,
    1797                      * we simply need to subtract ~half of that.
    1798                      */
    1799                     for (item = G.ntp_peers; item != NULL; item = item->link) {
    1800                         peer_t *pp = (peer_t *) item->data;
    1801                         if (pp->p_fd < 0)
    1802                             pp->next_action_time -= (1 << G.poll_exp);
    1803                     }
    1804                     VERB3 bb_error_msg("polladj: discipline_jitter:%f --poll_exp=%d",
    1805                             G.discipline_jitter, G.poll_exp);
    1806                 }
    1807             } else {
    1808                 VERB3 bb_error_msg("polladj: decr:%d", G.polladj_count);
    1809             }
     1997            VERB3 if (rc > 0)
     1998                bb_error_msg("want smaller interval: offset/jitter = %u",
     1999                    G.offset_to_jitter_ratio);
     2000            adjust_poll(-G.poll_exp * 2);
    18102001        }
    18112002    }
    18122003
    18132004    /* Decide when to send new query for this peer */
    1814     interval = poll_interval(0);
    1815 
    1816  set_next_and_ret:
     2005 pick_normal_interval:
     2006    interval = poll_interval(INT_MAX);
     2007    if (fabs(offset) >= BIGOFF && interval > BIGOFF_INTERVAL) {
     2008        /* If we are synced, offsets are less than SLEW_THRESHOLD,
     2009         * or at the very least not much larger than it.
     2010         * Now we see a largish one.
     2011         * Either this peer is feeling bad, or packet got corrupted,
     2012         * or _our_ clock is wrong now and _all_ peers will show similar
     2013         * largish offsets too.
     2014         * I observed this with laptop suspend stopping clock.
     2015         * In any case, it makes sense to make next request soonish:
     2016         * cases 1 and 2: get a better datapoint,
     2017         * case 3: allows to resync faster.
     2018         */
     2019        interval = BIGOFF_INTERVAL;
     2020    }
     2021
    18172022    set_next(p, interval);
    18182023}
     
    18442049        bb_error_msg("malformed packet received from %s: size %u", addr, (int)size);
    18452050        free(addr);
     2051        goto bail;
     2052    }
     2053
     2054    /* Respond only to client and symmetric active packets */
     2055    if ((msg.m_status & MODE_MASK) != MODE_CLIENT
     2056     && (msg.m_status & MODE_MASK) != MODE_SYM_ACT
     2057    ) {
    18462058        goto bail;
    18472059    }
     
    19792191    llist_t *peers;
    19802192
    1981     srandom(getpid());
     2193    srand(getpid());
    19822194
    19832195    if (getuid())
     
    19852197
    19862198    /* Set some globals */
     2199    G.discipline_jitter = G_precision_sec;
    19872200    G.stratum = MAXSTRAT;
    19882201    if (BURSTPOLL != 0)
     
    19922205    /* Parse options */
    19932206    peers = NULL;
    1994     opt_complementary = "dd:p::wn"; /* d: counter; p: list; -w implies -n */
     2207    opt_complementary = "dd:p::wn"         /* -d: counter; -p: list; -w implies -n */
     2208        IF_FEATURE_NTPD_SERVER(":Il"); /* -I implies -l */
    19952209    opts = getopt32(argv,
    19962210            "nqNx" /* compat */
    19972211            "wp:S:"IF_FEATURE_NTPD_SERVER("l") /* NOT compat */
     2212            IF_FEATURE_NTPD_SERVER("I:") /* compat */
    19982213            "d" /* compat */
    19992214            "46aAbgL", /* compat, ignored */
    2000             &peers, &G.script_name, &G.verbose);
    2001     if (!(opts & (OPT_p|OPT_l)))
    2002         bb_show_usage();
     2215            &peers,&G.script_name,
     2216#if ENABLE_FEATURE_NTPD_SERVER
     2217            &G.if_name,
     2218#endif
     2219            &G.verbose);
     2220
    20032221//  if (opts & OPT_x) /* disable stepping, only slew is allowed */
    20042222//      G.time_was_stepped = 1;
     
    20062224        while (peers)
    20072225            add_peers(llist_pop(&peers));
    2008     } else {
     2226    }
     2227#if ENABLE_FEATURE_NTPD_CONF
     2228    else {
     2229        parser_t *parser;
     2230        char *token[3];
     2231
     2232        parser = config_open("/etc/ntp.conf");
     2233        while (config_read(parser, token, 3, 1, "# \t", PARSE_NORMAL)) {
     2234            if (strcmp(token[0], "server") == 0 && token[1]) {
     2235                add_peers(token[1]);
     2236                continue;
     2237            }
     2238            bb_error_msg("skipping %s:%u: unimplemented command '%s'",
     2239                "/etc/ntp.conf", parser->lineno, token[0]
     2240            );
     2241        }
     2242        config_close(parser);
     2243    }
     2244#endif
     2245    if (G.peer_cnt == 0) {
     2246        if (!(opts & OPT_l))
     2247            bb_show_usage();
    20092248        /* -l but no peers: "stratum 1 server" mode */
    20102249        G.stratum = 1;
    2011     }
    2012     if (!(opts & OPT_n)) {
    2013         bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv);
    2014         logmode = LOGMODE_NONE;
    20152250    }
    20162251#if ENABLE_FEATURE_NTPD_SERVER
     
    20182253    if (opts & OPT_l) {
    20192254        G_listen_fd = create_and_bind_dgram_or_die(NULL, 123);
     2255        if (opts & OPT_I) {
     2256            if (setsockopt_bindtodevice(G_listen_fd, G.if_name))
     2257                xfunc_die();
     2258        }
    20202259        socket_want_pktinfo(G_listen_fd);
    2021         setsockopt(G_listen_fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY));
    2022     }
    2023 #endif
     2260        setsockopt_int(G_listen_fd, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY);
     2261    }
     2262#endif
     2263    if (!(opts & OPT_n)) {
     2264        bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv);
     2265        logmode = LOGMODE_NONE;
     2266    }
    20242267    /* I hesitate to set -20 prio. -15 should be high enough for timekeeping */
    20252268    if (opts & OPT_N)
     
    21092352                    /* Time to send new req */
    21102353                    if (--cnt == 0) {
    2111                         G.initial_poll_complete = 1;
     2354                        VERB4 bb_error_msg("disabling burst mode");
     2355                        G.polladj_count = 0;
     2356                        G.poll_exp = MINPOLL;
    21122357                    }
    21132358                    send_query_to_peer(p);
     
    21162361                    close(p->p_fd);
    21172362                    p->p_fd = -1;
    2118                     timeout = poll_interval(-2); /* -2: try a bit sooner */
     2363                    /* If poll interval is small, increase it */
     2364                    if (G.poll_exp < BIGPOLL)
     2365                        adjust_poll(MINPOLL);
     2366                    timeout = poll_interval(NOREPLY_INTERVAL);
    21192367                    bb_error_msg("timed out waiting for %s, reach 0x%02x, next query in %us",
    21202368                            p->p_dotted, p->reachable_bits, timeout);
     2369
     2370                    /* What if don't see it because it changed its IP? */
     2371                    if (p->reachable_bits == 0)
     2372                        resolve_peer_hostname(p, /*loop_on_fail=*/ 0);
     2373
    21212374                    set_next(p, timeout);
    21222375                }
     
    21602413        gettime1900d(); /* sets G.cur_time */
    21612414        if (nfds <= 0) {
    2162             if (G.script_name && G.cur_time - G.last_script_run > 11*60) {
     2415            if (!bb_got_signal /* poll wasn't interrupted by a signal */
     2416             && G.cur_time - G.last_script_run > 11*60
     2417            ) {
    21632418                /* Useful for updating battery-backed RTC and such */
    21642419                run_script("periodic", G.last_update_offset);
    21652420                gettime1900d(); /* sets G.cur_time */
    21662421            }
    2167             continue;
     2422            goto check_unsync;
    21682423        }
    21692424
     
    21952450                gettime1900d(); /* sets G.cur_time */
    21962451            }
     2452        }
     2453
     2454 check_unsync:
     2455        if (G.ntp_peers && G.stratum != MAXSTRAT) {
     2456            for (item = G.ntp_peers; item != NULL; item = item->link) {
     2457                peer_t *p = (peer_t *) item->data;
     2458                if (p->reachable_bits)
     2459                    goto have_reachable_peer;
     2460            }
     2461            /* No peer responded for last 8 packets, panic */
     2462            clamp_pollexp_and_set_MAXSTRAT();
     2463            run_script("unsync", 0.0);
     2464 have_reachable_peer: ;
    21972465        }
    21982466    } /* while (!bb_got_signal) */
  • branches/3.3/mindi-busybox/networking/ping.c

    r3232 r3621  
    2929#include <netinet/ip_icmp.h>
    3030#include "libbb.h"
     31#include "common_bufsiz.h"
    3132
    3233#ifdef __BIONIC__
     
    9091//usage:# define ping_full_usage "\n\n"
    9192//usage:       "Send ICMP ECHO_REQUEST packets to network hosts\n"
     93//usage:    IF_PING6(
    9294//usage:     "\n    -4,-6       Force IP or IPv6 name resolution"
     95//usage:    )
    9396//usage:     "\n    -c CNT      Send only CNT pings"
    9497//usage:     "\n    -s SIZE     Send SIZE data bytes in packets (default:56)"
     
    99102//usage:     "\n    -w SEC      Seconds until ping exits (default:infinite)"
    100103//usage:     "\n            (can exit earlier with -c CNT)"
    101 //usage:     "\n    -q      Quiet, only displays output at start"
     104//usage:     "\n    -q      Quiet, only display output at start"
    102105//usage:     "\n            and when finished"
     106//usage:     "\n    -p      Pattern to use for payload"
    103107//usage:
    104108//usage:# define ping6_trivial_usage
     
    109113//usage:     "\n    -s SIZE     Send SIZE data bytes in packets (default:56)"
    110114//usage:     "\n    -I IFACE/IP Use interface or IP address as source"
    111 //usage:     "\n    -q      Quiet, only displays output at start"
     115//usage:     "\n    -q      Quiet, only display output at start"
    112116//usage:     "\n            and when finished"
     117//usage:     "\n    -p      Pattern to use for payload"
    113118//usage:
    114119//usage:#endif
     
    148153    MAXWAIT = 10,
    149154    PINGINTERVAL = 1, /* 1 second */
     155    pingsock = 0,
    150156};
     157
     158static void
     159#if ENABLE_PING6
     160create_icmp_socket(len_and_sockaddr *lsa)
     161#else
     162create_icmp_socket(void)
     163#define create_icmp_socket(lsa) create_icmp_socket()
     164#endif
     165{
     166    int sock;
     167#if ENABLE_PING6
     168    if (lsa->u.sa.sa_family == AF_INET6)
     169        sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
     170    else
     171#endif
     172        sock = socket(AF_INET, SOCK_RAW, 1); /* 1 == ICMP */
     173    if (sock < 0) {
     174        if (errno == EPERM)
     175            bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
     176        bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket);
     177    }
     178
     179    xmove_fd(sock, pingsock);
     180}
    151181
    152182#if !ENABLE_FEATURE_FANCY_PING
     
    158188    char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
    159189} FIX_ALIASING;
    160 #define G (*(struct globals*)&bb_common_bufsiz1)
    161 #define INIT_G() do { } while (0)
     190#define G (*(struct globals*)bb_common_bufsiz1)
     191#define INIT_G() do { setup_common_bufsiz(); } while (0)
    162192
    163193static void noresp(int ign UNUSED_PARAM)
     
    170200{
    171201    struct icmp *pkt;
    172     int pingsock, c;
    173 
    174     pingsock = create_icmp_socket();
     202    int c;
    175203
    176204    pkt = (struct icmp *) G.packet;
    177     memset(pkt, 0, sizeof(G.packet));
     205    /*memset(pkt, 0, sizeof(G.packet)); already is */
    178206    pkt->icmp_type = ICMP_ECHO;
    179207    pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, sizeof(G.packet));
     
    183211    /* listen for replies */
    184212    while (1) {
     213#if 0
    185214        struct sockaddr_in from;
    186215        socklen_t fromlen = sizeof(from);
     
    188217        c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0,
    189218                (struct sockaddr *) &from, &fromlen);
     219#else
     220        c = recv(pingsock, G.packet, sizeof(G.packet), 0);
     221#endif
    190222        if (c < 0) {
    191223            if (errno != EINTR)
     
    209241{
    210242    struct icmp6_hdr *pkt;
    211     int pingsock, c;
     243    int c;
    212244    int sockopt;
    213245
    214     pingsock = create_icmp6_socket();
    215 
    216246    pkt = (struct icmp6_hdr *) G.packet;
    217     memset(pkt, 0, sizeof(G.packet));
     247    /*memset(pkt, 0, sizeof(G.packet)); already is */
    218248    pkt->icmp6_type = ICMP6_ECHO_REQUEST;
    219249
    220250    sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
    221     setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, &sockopt, sizeof(sockopt));
     251    setsockopt_int(pingsock, SOL_RAW, IPV6_CHECKSUM, sockopt);
    222252
    223253    xsendto(pingsock, G.packet, DEFDATALEN + sizeof(struct icmp6_hdr), &lsa->u.sa, lsa->len);
     
    225255    /* listen for replies */
    226256    while (1) {
     257#if 0
    227258        struct sockaddr_in6 from;
    228259        socklen_t fromlen = sizeof(from);
     
    230261        c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0,
    231262                (struct sockaddr *) &from, &fromlen);
     263#else
     264        c = recv(pingsock, G.packet, sizeof(G.packet), 0);
     265#endif
    232266        if (c < 0) {
    233267            if (errno != EINTR)
     
    235269            continue;
    236270        }
    237         if (c >= ICMP_MINLEN) {         /* icmp6_hdr */
    238             pkt = (struct icmp6_hdr *) G.packet;
     271        if (c >= ICMP_MINLEN) { /* icmp6_hdr */
    239272            if (pkt->icmp6_type == ICMP6_ECHO_REPLY)
    240273                break;
     
    284317    alarm(5); /* give the host 5000ms to respond */
    285318
     319    create_icmp_socket(lsa);
    286320#if ENABLE_PING6
    287321    if (lsa->u.sa.sa_family == AF_INET6)
     
    300334/* Full(er) version */
    301335
    302 #define OPT_STRING ("qvc:s:t:w:W:I:4" IF_PING6("6"))
     336#define OPT_STRING ("qvc:s:t:w:W:I:np:4" IF_PING6("6"))
    303337enum {
    304338    OPT_QUIET = 1 << 0,
     
    310344    OPT_W = 1 << 6,
    311345    OPT_I = 1 << 7,
    312     OPT_IPV4 = 1 << 8,
    313     OPT_IPV6 = (1 << 9) * ENABLE_PING6,
     346    /*OPT_n = 1 << 8, - ignored */
     347    OPT_p = 1 << 9,
     348    OPT_IPV4 = 1 << 10,
     349    OPT_IPV6 = (1 << 11) * ENABLE_PING6,
    314350};
    315351
    316352
    317353struct globals {
    318     int pingsock;
    319354    int if_index;
    320355    char *str_I;
     
    325360    unsigned long ntransmitted, nreceived, nrepeats;
    326361    uint16_t myid;
     362    uint8_t pattern;
    327363    unsigned tmin, tmax; /* in us */
    328364    unsigned long long tsum; /* in us, sum of all times */
     
    342378#endif
    343379    } pingaddr;
    344     char rcvd_tbl[MAX_DUP_CHK / 8];
     380    unsigned char rcvd_tbl[MAX_DUP_CHK / 8];
    345381} FIX_ALIASING;
    346 #define G (*(struct globals*)&bb_common_bufsiz1)
    347 #define pingsock     (G.pingsock    )
     382#define G (*(struct globals*)bb_common_bufsiz1)
    348383#define if_index     (G.if_index    )
    349384#define source_lsa   (G.source_lsa  )
    350385#define str_I        (G.str_I       )
    351386#define datalen      (G.datalen     )
    352 #define ntransmitted (G.ntransmitted)
    353 #define nreceived    (G.nreceived   )
    354 #define nrepeats     (G.nrepeats    )
    355387#define pingcount    (G.pingcount   )
    356388#define opt_ttl      (G.opt_ttl     )
     
    366398#define pingaddr     (G.pingaddr    )
    367399#define rcvd_tbl     (G.rcvd_tbl    )
    368 void BUG_ping_globals_too_big(void);
    369400#define INIT_G() do { \
    370     if (sizeof(G) > COMMON_BUFSIZE) \
    371         BUG_ping_globals_too_big(); \
    372     pingsock = -1; \
     401    setup_common_bufsiz(); \
     402    BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
    373403    datalen = DEFDATALEN; \
    374404    timeout = MAXWAIT; \
     
    377407
    378408
    379 #define A(bit)      rcvd_tbl[(bit)>>3]  /* identify byte in array */
    380 #define B(bit)      (1 << ((bit) & 0x07))   /* identify bit in byte */
    381 #define SET(bit)    (A(bit) |= B(bit))
    382 #define CLR(bit)    (A(bit) &= (~B(bit)))
    383 #define TST(bit)    (A(bit) & B(bit))
    384 
    385 /**************************************************************************/
     409#define BYTE(bit)   rcvd_tbl[(bit)>>3]
     410#define MASK(bit)   (1 << ((bit) & 7))
     411#define SET(bit)    (BYTE(bit) |= MASK(bit))
     412#define CLR(bit)    (BYTE(bit) &= (~MASK(bit)))
     413#define TST(bit)    (BYTE(bit) & MASK(bit))
    386414
    387415static void print_stats_and_exit(int junk) NORETURN;
    388416static void print_stats_and_exit(int junk UNUSED_PARAM)
    389417{
     418    unsigned long ul;
     419    unsigned long nrecv;
     420
    390421    signal(SIGINT, SIG_IGN);
    391422
    392     printf("\n--- %s ping statistics ---\n", hostname);
    393     printf("%lu packets transmitted, ", ntransmitted);
    394     printf("%lu packets received, ", nreceived);
    395     if (nrepeats)
    396         printf("%lu duplicates, ", nrepeats);
    397     if (ntransmitted)
    398         ntransmitted = (ntransmitted - nreceived) * 100 / ntransmitted;
    399     printf("%lu%% packet loss\n", ntransmitted);
     423    nrecv = G.nreceived;
     424    printf("\n--- %s ping statistics ---\n"
     425        "%lu packets transmitted, "
     426        "%lu packets received, ",
     427        hostname, G.ntransmitted, nrecv
     428    );
     429    if (G.nrepeats)
     430        printf("%lu duplicates, ", G.nrepeats);
     431    ul = G.ntransmitted;
     432    if (ul != 0)
     433        ul = (ul - nrecv) * 100 / ul;
     434    printf("%lu%% packet loss\n", ul);
    400435    if (tmin != UINT_MAX) {
    401         unsigned tavg = tsum / (nreceived + nrepeats);
     436        unsigned tavg = tsum / (nrecv + G.nrepeats);
    402437        printf("round-trip min/avg/max = %u.%03u/%u.%03u/%u.%03u ms\n",
    403438            tmin / 1000, tmin % 1000,
     
    406441    }
    407442    /* if condition is true, exit with 1 -- 'failure' */
    408     exit(nreceived == 0 || (deadline && nreceived < pingcount));
     443    exit(nrecv == 0 || (deadline && nrecv < pingcount));
    409444}
    410445
     
    413448    int sz;
    414449
    415     CLR((uint16_t)ntransmitted % MAX_DUP_CHK);
    416     ntransmitted++;
     450    CLR((uint16_t)G.ntransmitted % MAX_DUP_CHK);
     451    G.ntransmitted++;
    417452
    418453    size_pkt += datalen;
     
    424459        bb_error_msg_and_die(bb_msg_write_error);
    425460
    426     if (pingcount == 0 || deadline || ntransmitted < pingcount) {
     461    if (pingcount == 0 || deadline || G.ntransmitted < pingcount) {
    427462        /* Didn't send all pings yet - schedule next in 1s */
    428463        signal(SIGALRM, sp);
     
    440475        unsigned expire = timeout;
    441476
    442         if (nreceived) {
     477        if (G.nreceived) {
    443478            /* approx. 2*tmax, in seconds (2 RTT) */
    444479            expire = tmax / (512*1024);
     
    455490    struct icmp *pkt = G.snd_packet;
    456491
    457     //memset(pkt, 0, datalen + ICMP_MINLEN + 4); - G.snd_packet was xzalloced
     492    memset(pkt, G.pattern, datalen + ICMP_MINLEN + 4);
    458493    pkt->icmp_type = ICMP_ECHO;
    459494    /*pkt->icmp_code = 0;*/
    460495    pkt->icmp_cksum = 0; /* cksum is calculated with this field set to 0 */
    461     pkt->icmp_seq = htons(ntransmitted); /* don't ++ here, it can be a macro */
     496    pkt->icmp_seq = htons(G.ntransmitted); /* don't ++ here, it can be a macro */
    462497    pkt->icmp_id = myid;
    463498
     
    478513    struct icmp6_hdr *pkt = G.snd_packet;
    479514
    480     //memset(pkt, 0, datalen + sizeof(struct icmp6_hdr) + 4);
     515    memset(pkt, G.pattern, datalen + sizeof(struct icmp6_hdr) + 4);
    481516    pkt->icmp6_type = ICMP6_ECHO_REQUEST;
    482517    /*pkt->icmp6_code = 0;*/
    483518    /*pkt->icmp6_cksum = 0;*/
    484     pkt->icmp6_seq = htons(ntransmitted); /* don't ++ here, it can be a macro */
     519    pkt->icmp6_seq = htons(G.ntransmitted); /* don't ++ here, it can be a macro */
    485520    pkt->icmp6_id = myid;
    486521
    487522    /*if (datalen >= 4)*/
    488         *(uint32_t*)(&pkt->icmp6_data8[4]) = monotonic_us();
     523        *(bb__aliased_uint32_t*)(&pkt->icmp6_data8[4]) = monotonic_us();
    489524
    490525    //TODO? pkt->icmp_cksum = inet_cksum(...);
     
    546581        uint16_t recv_seq, int ttl)
    547582{
     583    unsigned char *b, m;
    548584    const char *dupmsg = " (DUP!)";
    549585    unsigned triptime = triptime; /* for gcc */
    550 
    551     ++nreceived;
    552586
    553587    if (tp) {
     
    562596    }
    563597
    564     if (TST(recv_seq % MAX_DUP_CHK)) {
    565         ++nrepeats;
    566         --nreceived;
     598    b = &BYTE(recv_seq % MAX_DUP_CHK);
     599    m = MASK(recv_seq % MAX_DUP_CHK);
     600    /*if TST(recv_seq % MAX_DUP_CHK):*/
     601    if (*b & m) {
     602        ++G.nrepeats;
    567603    } else {
    568         SET(recv_seq % MAX_DUP_CHK);
     604        /*SET(recv_seq % MAX_DUP_CHK):*/
     605        *b |= m;
     606        ++G.nreceived;
    569607        dupmsg += 7;
    570608    }
     
    649687    int sockopt;
    650688
    651     pingsock = create_icmp_socket();
    652689    pingaddr.sin = lsa->u.sin;
    653690    if (source_lsa) {
     
    657694        xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
    658695    }
    659     if (str_I)
    660         setsockopt_bindtodevice(pingsock, str_I);
    661696
    662697    /* enable broadcast pings */
     
    666701     * broadcast ping etc) */
    667702    sockopt = (datalen * 2) + 7 * 1024; /* giving it a bit of extra room */
    668     setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt));
     703    setsockopt_SOL_SOCKET_int(pingsock, SO_RCVBUF, sockopt);
    669704
    670705    if (opt_ttl != 0) {
    671         setsockopt(pingsock, IPPROTO_IP, IP_TTL, &opt_ttl, sizeof(opt_ttl));
     706        setsockopt_int(pingsock, IPPROTO_IP, IP_TTL, opt_ttl);
    672707        /* above doesnt affect packets sent to bcast IP, so... */
    673         setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, &opt_ttl, sizeof(opt_ttl));
     708        setsockopt_int(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, opt_ttl);
    674709    }
    675710
     
    693728        }
    694729        unpack4(G.rcv_packet, c, &from);
    695         if (pingcount && nreceived >= pingcount)
     730        if (pingcount && G.nreceived >= pingcount)
    696731            break;
    697732    }
    698733}
    699734#if ENABLE_PING6
    700 extern int BUG_bad_offsetof_icmp6_cksum(void);
    701735static void ping6(len_and_sockaddr *lsa)
    702736{
     
    707741    char control_buf[CMSG_SPACE(36)];
    708742
    709     pingsock = create_icmp6_socket();
    710743    pingaddr.sin6 = lsa->u.sin6;
    711     /* untested whether "-I addr" really works for IPv6: */
    712744    if (source_lsa)
    713745        xbind(pingsock, &source_lsa->u.sa, source_lsa->len);
    714     if (str_I)
    715         setsockopt_bindtodevice(pingsock, str_I);
    716746
    717747#ifdef ICMP6_FILTER
     
    726756        if (setsockopt(pingsock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
    727757                    sizeof(filt)) < 0)
    728             bb_error_msg_and_die("setsockopt(ICMP6_FILTER)");
     758            bb_error_msg_and_die("setsockopt(%s)", "ICMP6_FILTER");
    729759    }
    730760#endif /*ICMP6_FILTER*/
     
    736766     * broadcast ping etc) */
    737767    sockopt = (datalen * 2) + 7 * 1024; /* giving it a bit of extra room */
    738     setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt));
     768    setsockopt_SOL_SOCKET_int(pingsock, SO_RCVBUF, sockopt);
    739769
    740770    sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
    741     if (offsetof(struct icmp6_hdr, icmp6_cksum) != 2)
    742         BUG_bad_offsetof_icmp6_cksum();
    743     setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, &sockopt, sizeof(sockopt));
     771    BUILD_BUG_ON(offsetof(struct icmp6_hdr, icmp6_cksum) != 2);
     772    setsockopt_int(pingsock, SOL_RAW, IPV6_CHECKSUM, sockopt);
    744773
    745774    /* request ttl info to be returned in ancillary data */
    746     setsockopt(pingsock, SOL_IPV6, IPV6_HOPLIMIT, &const_int_1, sizeof(const_int_1));
     775    setsockopt_1(pingsock, SOL_IPV6, IPV6_HOPLIMIT);
    747776
    748777    if (if_index)
     
    785814        }
    786815        unpack6(G.rcv_packet, c, &from, hoplimit);
    787         if (pingcount && nreceived >= pingcount)
     816        if (pingcount && G.nreceived >= pingcount)
    788817            break;
    789818    }
     
    799828    }
    800829    printf(": %d data bytes\n", datalen);
     830
     831    create_icmp_socket(lsa);
     832    /* untested whether "-I addr" really works for IPv6: */
     833    if (str_I)
     834        setsockopt_bindtodevice(pingsock, str_I);
    801835
    802836    G.sizeof_rcv_packet = datalen + MAXIPLEN + MAXICMPLEN;
     
    819853{
    820854    len_and_sockaddr *lsa;
    821     char *str_s;
     855    char *str_s, *str_p;
    822856
    823857    INIT_G();
     
    825859    /* exactly one argument needed; -v and -q don't mix; -c NUM, -t NUM, -w NUM, -W NUM */
    826860    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);
     861    opt |= getopt32(argv, OPT_STRING, &pingcount, &str_s, &opt_ttl, &deadline, &timeout, &str_I, &str_p);
    828862    if (opt & OPT_s)
    829863        datalen = xatou16(str_s); // -s
     
    836870        }
    837871    }
     872    if (opt & OPT_p)
     873        G.pattern = xstrtou_range(str_p, 16, 0, 255);
     874
    838875    myid = (uint16_t) getpid();
    839876    hostname = argv[optind];
  • branches/3.3/mindi-busybox/networking/pscan.c

    r3232 r3621  
    158158    if (ENABLE_FEATURE_CLEAN_UP) free(lsap);
    159159
    160     printf("%d closed, %d open, %d timed out (or blocked) ports\n",
     160    printf("%u closed, %u open, %u timed out (or blocked) ports\n",
    161161                    closed_ports,
    162162                    open_ports,
  • branches/3.3/mindi-busybox/networking/route.c

    r3232 r3621  
    5656#define RTF_IRTT        0x0100  /* Initial round trip time      */
    5757#define RTF_REJECT      0x0200  /* Reject route                 */
     58#define RTF_NONEXTHOP   0x00200000 /* route with no nexthop */
    5859#endif
    5960
     
    129130;
    130131
    131 static const int flags_ipvx[] = { /* MUST match tbl_ipvx[] values above. */
     132static const uint16_t flags_ipvx[] = { /* MUST match tbl_ipvx[] values above. */
    132133#ifdef RTF_REJECT
    133134    RTF_REJECT,
     
    284285            rt->rt_flags |= RTF_IRTT;
    285286            rt->rt_irtt = xatoul(args_m1);
    286             rt->rt_irtt *= (sysconf(_SC_CLK_TCK) / 100);    /* FIXME */
     287            rt->rt_irtt *= (bb_clk_tck() / 100);    /* FIXME */
    287288#if 0                   /* FIXME: do we need to check anything of this? */
    288289            if (rt->rt_irtt < 1 || rt->rt_irtt > (120 * HZ)) {
     
    450451#endif
    451452
    452 static const unsigned flagvals[] = { /* Must agree with flagchars[]. */
     453static const
     454IF_NOT_FEATURE_IPV6(uint16_t)
     455IF_FEATURE_IPV6(unsigned)
     456flagvals[] = { /* Must agree with flagchars[]. */
     457    RTF_UP,
    453458    RTF_GATEWAY,
    454459    RTF_HOST,
     
    459464    RTF_DEFAULT,
    460465    RTF_ADDRCONF,
    461     RTF_CACHE
     466    RTF_CACHE,
     467    RTF_REJECT,
     468    RTF_NONEXTHOP, /* this one doesn't fit into 16 bits */
    462469#endif
    463470};
    464 
    465 #define IPV4_MASK (RTF_GATEWAY|RTF_HOST|RTF_REINSTATE|RTF_DYNAMIC|RTF_MODIFIED)
    466 #define IPV6_MASK (RTF_GATEWAY|RTF_HOST|RTF_DEFAULT|RTF_ADDRCONF|RTF_CACHE)
    467 
    468471/* Must agree with flagvals[]. */
    469472static const char flagchars[] ALIGN1 =
    470     "GHRDM"
     473    "UGHRDM"
    471474#if ENABLE_FEATURE_IPV6
    472     "DAC"
     475    "DAC!n"
    473476#endif
    474477;
     478#define IPV4_MASK (RTF_UP|RTF_GATEWAY|RTF_HOST|RTF_REINSTATE|RTF_DYNAMIC|RTF_MODIFIED)
     479#define IPV6_MASK (RTF_UP|RTF_GATEWAY|RTF_HOST|RTF_DEFAULT|RTF_ADDRCONF|RTF_CACHE|RTF_REJECT|RTF_NONEXTHOP)
    475480
    476481static void set_flags(char *flagstr, int flags)
    477482{
    478483    int i;
    479 
    480     *flagstr++ = 'U';
    481484
    482485    for (i = 0; (*flagstr = flagchars[i]) != 0; i++) {
     
    492495    char devname[64], flags[16], *sdest, *sgw;
    493496    unsigned long d, g, m;
     497    int r;
    494498    int flgs, ref, use, metric, mtu, win, ir;
    495499    struct sockaddr_in s_addr;
     
    502506            netstatfmt ? "  MSS Window  irtt" : "Metric Ref    Use");
    503507
    504     if (fscanf(fp, "%*[^\n]\n") < 0) { /* Skip the first line. */
    505         goto ERROR;                /* Empty or missing line, or read error. */
     508    /* Skip the first line. */
     509    r = fscanf(fp, "%*[^\n]\n");
     510    if (r < 0) {
     511        /* Empty line, read error, or EOF. Yes, if routing table
     512         * is completely empty, /proc/net/route has no header.
     513         */
     514        goto ERROR;
    506515    }
    507516    while (1) {
    508         int r;
    509517        r = fscanf(fp, "%63s%lx%lx%X%d%d%d%lx%d%d%d\n",
    510518                devname, &d, &g, &flgs, &ref, &use, &metric, &m,
    511519                &mtu, &win, &ir);
    512520        if (r != 11) {
     521 ERROR:
    513522            if ((r < 0) && feof(fp)) { /* EOF with no (nonspace) chars read. */
    514523                break;
    515524            }
    516  ERROR:
    517             bb_error_msg_and_die("fscanf");
     525            bb_perror_msg_and_die(bb_msg_read_error);
    518526        }
    519527
     
    575583        r = fscanf(fp, "%32s%x%*s%x%32s%x%x%x%x%s\n",
    576584                addr6x+14, &prefix_len, &slen, addr6x+40+7,
    577                 &metric, &use, &refcnt, &iflags, iface);
     585                &metric, &refcnt, &use, &iflags, iface);
    578586        if (r != 9) {
    579587            if ((r < 0) && feof(fp)) { /* EOF with no (nonspace) chars read. */
     
    581589            }
    582590 ERROR:
    583             bb_error_msg_and_die("fscanf");
     591            bb_perror_msg_and_die(bb_msg_read_error);
    584592        }
    585593
     
    607615        }
    608616
    609         if (!(iflags & RTF_UP)) { /* Skip interfaces that are down. */
    610             continue;
    611         }
    612 
    613617        set_flags(flags, (iflags & IPV6_MASK));
    614618
  • branches/3.3/mindi-busybox/networking/slattach.c

    r3232 r3621  
    2828
    2929#include "libbb.h"
    30 #include "libiproute/utils.h" /* invarg() */
     30#include "common_bufsiz.h"
     31#include "libiproute/utils.h" /* invarg_1_to_2() */
    3132
    3233struct globals {
     
    3536    struct termios saved_state;
    3637} FIX_ALIASING;
    37 #define G (*(struct globals*)&bb_common_bufsiz1)
     38#define G (*(struct globals*)bb_common_bufsiz1)
    3839#define handle       (G.handle      )
    3940#define saved_disc   (G.saved_disc  )
    4041#define saved_state  (G.saved_state )
    41 #define INIT_G() do { } while (0)
     42#define INIT_G() do { setup_common_bufsiz(); } while (0)
    4243
    4344
     
    176177
    177178    if (encap < 0)
    178         invarg(proto, "protocol");
     179        invarg_1_to_2(proto, "protocol");
    179180    if (encap > 3)
    180181        encap = 8;
     
    184185        baud_code = tty_value_to_baud(xatoi(baud_str));
    185186        if (baud_code < 0)
    186             invarg(baud_str, "baud rate");
     187            invarg_1_to_2(baud_str, "baud rate");
    187188    }
    188189
  • branches/3.3/mindi-busybox/networking/tc.c

    r3232 r3621  
    3030
    3131#include "libbb.h"
     32#include "common_bufsiz.h"
    3233
    3334#include "libiproute/utils.h"
     
    6465    uint32_t filter_proto;
    6566} FIX_ALIASING;
    66 #define G (*(struct globals*)&bb_common_bufsiz1)
    67 struct BUG_G_too_big {
    68         char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
    69 };
     67#define G (*(struct globals*)bb_common_bufsiz1)
    7068#define filter_ifindex (G.filter_ifindex)
    7169#define filter_qdisc (G.filter_qdisc)
     
    7371#define filter_prio (G.filter_prio)
    7472#define filter_proto (G.filter_proto)
    75 #define INIT_G() do { } while (0)
     73#define INIT_G() do { \
     74    setup_common_bufsiz(); \
     75    BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
     76} while (0)
    7677
    7778/* Allocates a buffer containing the name of a class id.
     
    152153
    153154    if (use_iec) {
    154         if (tmp >= 1000.0*1024.0*1024.0)
    155             snprintf(buf, len, "%.0fMibit", tmp/1024.0*1024.0);
    156         else if (tmp >= 1000.0*1024)
     155        if (tmp >= 1000*1024*1024)
     156            snprintf(buf, len, "%.0fMibit", tmp/(1024*1024));
     157        else if (tmp >= 1000*1024)
    157158            snprintf(buf, len, "%.0fKibit", tmp/1024);
    158159        else
    159160            snprintf(buf, len, "%.0fbit", tmp);
    160161    } else {
    161         if (tmp >= 1000.0*1000000.0)
    162             snprintf(buf, len, "%.0fMbit", tmp/1000000.0);
    163         else if (tmp >= 1000.0 * 1000.0)
    164             snprintf(buf, len, "%.0fKbit", tmp/1000.0);
     162        if (tmp >= 1000*1000000)
     163            snprintf(buf, len, "%.0fMbit", tmp/1000000);
     164        else if (tmp >= 1000*1000)
     165            snprintf(buf, len, "%.0fKbit", tmp/1000);
    165166        else
    166167            snprintf(buf, len, "%.0fbit",  tmp);
     
    419420                        struct nlmsghdr *hdr, void *arg UNUSED_PARAM)
    420421{
    421     struct tcmsg *msg = NLMSG_DATA(hdr);
    422     int len = hdr->nlmsg_len;
    423     struct rtattr * tb[TCA_MAX+1];
    424422    return 0;
    425423}
     
    464462    obj = index_in_substrings(objects, *argv++);
    465463
    466     if (obj < OBJ_qdisc)
     464    if (obj < 0)
    467465        bb_show_usage();
    468466    if (!*argv)
     
    471469        cmd = index_in_substrings(commands, *argv);
    472470        if (cmd < 0)
    473             bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name);
     471            invarg_1_to_2(*argv, argv[-1]);
    474472        argv++;
    475473    }
     
    494492            /* We don't care about duparg2("qdisc handle",*argv) for now */
    495493            if (get_qdisc_handle(&filter_qdisc, *argv))
    496                 invarg(*argv, "qdisc");
     494                invarg_1_to_2(*argv, "qdisc");
    497495        } else
    498496        if (obj != OBJ_qdisc
     
    504502            /* nothing */
    505503        } else {
    506             invarg(*argv, "command");
     504            invarg_1_to_2(*argv, "command");
    507505        }
    508506        NEXT_ARG();
     
    518516                duparg(*argv, "parent");
    519517            if (get_tc_classid(&handle, *argv))
    520                 invarg(*argv, "parent");
     518                invarg_1_to_2(*argv, "parent");
    521519            msg.tcm_parent = handle;
    522520            if (obj == OBJ_filter)
     
    543541                duparg(*argv, "protocol");
    544542            if (ll_proto_a2n(&tmp, *argv))
    545                 invarg(*argv, "protocol");
     543                invarg_1_to_2(*argv, "protocol");
    546544            filter_proto = tmp;
    547545        }
  • branches/3.3/mindi-busybox/networking/tcpudp.c

    r3232 r3621  
    6868
    6969#include "libbb.h"
     70#include "common_bufsiz.h"
    7071
    7172/* Wants <limits.h> etc, thus included after libbb.h: */
     
    9293    char *env_var[1]; /* actually bigger */
    9394} FIX_ALIASING;
    94 #define G (*(struct globals*)&bb_common_bufsiz1)
     95#define G (*(struct globals*)bb_common_bufsiz1)
    9596#define verbose      (G.verbose     )
    9697#define max_per_host (G.max_per_host)
     
    101102#define env_var      (G.env_var     )
    102103#define INIT_G() do { \
     104    setup_common_bufsiz(); \
    103105    cmax = 30; \
    104106    env_cur = &env_var[0]; \
  • branches/3.3/mindi-busybox/networking/telnet.c

    r3232 r3621  
    4040#include <netinet/in.h>
    4141#include "libbb.h"
     42#include "common_bufsiz.h"
    4243
    4344#ifdef __BIONIC__
     
    109110    struct termios termios_raw;
    110111} FIX_ALIASING;
    111 #define G (*(struct globals*)&bb_common_bufsiz1)
     112#define G (*(struct globals*)bb_common_bufsiz1)
    112113#define INIT_G() do { \
    113     struct G_sizecheck { \
    114         char G_sizecheck[sizeof(G) > COMMON_BUFSIZE ? -1 : 1]; \
    115     }; \
     114    setup_common_bufsiz(); \
     115    BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
    116116} while (0)
    117117
     
    126126static void iac_flush(void)
    127127{
    128     write(netfd, G.iacbuf, G.iaclen);
     128    full_write(netfd, G.iacbuf, G.iaclen);
    129129    G.iaclen = 0;
    130130}
    131 
    132 #define write_str(fd, str) write(fd, str, sizeof(str) - 1)
    133131
    134132static void doexit(int ev) NORETURN;
     
    146144        rawmode();
    147145
    148     write_str(1, "\r\nConsole escape. Commands are:\r\n\n"
     146    full_write1_str("\r\nConsole escape. Commands are:\r\n\n"
    149147            " l go to line mode\r\n"
    150148            " c go to character mode\r\n"
     
    177175    }
    178176
    179     write_str(1, "continuing...\r\n");
     177    full_write1_str("continuing...\r\n");
    180178
    181179    if (bb_got_signal)
     
    384382    put_iac(c);
    385383
    386     put_iac((x >> 8) & 0xff);
    387     put_iac(x & 0xff);
    388     put_iac((y >> 8) & 0xff);
    389     put_iac(y & 0xff);
     384    /* "... & 0xff" implicitly done below */
     385    put_iac(x >> 8);
     386    put_iac(x);
     387    put_iac(y >> 8);
     388    put_iac(y);
    390389
    391390    put_iac(IAC);
     
    625624    xmove_fd(create_and_connect_stream_or_die(host, port), netfd);
    626625
    627     setsockopt(netfd, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
     626    setsockopt_keepalive(netfd);
    628627
    629628    signal(SIGINT, record_signo);
  • branches/3.3/mindi-busybox/networking/telnetd.c

    r3232 r3621  
    4545
    4646#include "libbb.h"
     47#include "common_bufsiz.h"
    4748#include <syslog.h>
    4849
     
    8384    int maxfd;
    8485} FIX_ALIASING;
    85 #define G (*(struct globals*)&bb_common_bufsiz1)
     86#define G (*(struct globals*)bb_common_bufsiz1)
    8687#define INIT_G() do { \
     88    setup_common_bufsiz(); \
    8789    G.loginpath = "/bin/login"; \
    8890    G.issuefile = "/etc/issue.net"; \
     
    266268
    267269    /* SO_KEEPALIVE by popular demand */
    268     setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
     270    setsockopt_keepalive(sock);
    269271#if ENABLE_FEATURE_TELNETD_STANDALONE
    270272    ts->sockfd_read = sock;
     
    463465            if (ts->shell_pid == pid) {
    464466                ts->shell_pid = -1;
    465 // man utmp:
    466 // When init(8) finds that a process has exited, it locates its utmp entry
    467 // by ut_pid, sets ut_type to DEAD_PROCESS, and clears ut_user, ut_host
    468 // and ut_time with null bytes.
    469 // [same applies to other processes which maintain utmp entries, like telnetd]
    470 //
    471 // We do not bother actually clearing fields:
    472 // it might be interesting to know who was logged in and from where
    473                 update_utmp(pid, DEAD_PROCESS, /*tty_name:*/ NULL, /*username:*/ NULL, /*hostname:*/ NULL);
     467                update_utmp_DEAD_PROCESS(pid);
    474468                break;
    475469            }
     
    740734 kill_session:
    741735        if (ts->shell_pid > 0)
    742             update_utmp(ts->shell_pid, DEAD_PROCESS, /*tty_name:*/ NULL, /*username:*/ NULL, /*hostname:*/ NULL);
     736            update_utmp_DEAD_PROCESS(ts->shell_pid);
    743737        free_session(ts);
    744738        ts = next;
  • branches/3.3/mindi-busybox/networking/telnetd.ctrlSQ.patch

    r2725 r3621  
    9595+#ifdef TIOCPKT
    9696+   int control;
    97 +   static const char lflow_on[] =
     97+   static const char lflow_on[] ALIGN1 =
    9898+       {IAC, SB, TELOPT_LFLOW, LFLOW_ON, IAC, SE};
    99 +   static const char lflow_off[] =
     99+   static const char lflow_off[] ALIGN1 =
    100100+       {IAC, SB, TELOPT_LFLOW, LFLOW_OFF, IAC, SE};
    101101+# define RESERVED sizeof(lflow_on)
  • branches/3.3/mindi-busybox/networking/tftp.c

    r3232 r3621  
    5252
    5353#include "libbb.h"
     54#include "common_bufsiz.h"
    5455#include <syslog.h>
    5556
     
    118119    uint8_t error_pkt[4 + 32];
    119120    struct passwd *pw;
    120     /* used in tftpd_main(), a bit big for stack: */
    121     char block_buf[TFTP_BLKSIZE_DEFAULT];
     121    /* Used in tftpd_main() for initial packet */
     122    /* Some HP PA-RISC firmware always sends fixed 516-byte requests */
     123    char block_buf[516];
     124    char block_buf_tail[1];
    122125#if ENABLE_FEATURE_TFTP_PROGRESS_BAR
    123126    off_t pos;
     
    127130#endif
    128131} FIX_ALIASING;
    129 #define G (*(struct globals*)&bb_common_bufsiz1)
    130 struct BUG_G_too_big {
    131     char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
    132 };
    133 #define INIT_G() do { } while (0)
     132#define G (*(struct globals*)bb_common_bufsiz1)
     133#define INIT_G() do { \
     134    setup_common_bufsiz(); \
     135    BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
     136} while (0)
    134137
    135138#define G_error_pkt_reason (G.error_pkt[3])
     
    347350            block_nr = 0;
    348351        }
    349 
    350352    } else { /* tftp */
    351353        /* Open file (must be after changing user) */
     
    758760    len_and_sockaddr *our_lsa;
    759761    len_and_sockaddr *peer_lsa;
    760     char *local_file, *mode, *user_opt;
     762    char *mode, *user_opt;
     763    char *local_file = local_file;
    761764    const char *error_msg;
    762765    int opt, result, opcode;
     
    794797    }
    795798
    796     result = recv_from_to(STDIN_FILENO, G.block_buf, sizeof(G.block_buf),
     799    result = recv_from_to(STDIN_FILENO,
     800            G.block_buf, sizeof(G.block_buf) + 1,
     801            /* ^^^ sizeof+1 to reliably detect oversized input */
    797802            0 /* flags */,
    798803            &peer_lsa->u.sa, &our_lsa->u.sa, our_lsa->len);
     
    800805    error_msg = "malformed packet";
    801806    opcode = ntohs(*(uint16_t*)G.block_buf);
    802     if (result < 4 || result >= sizeof(G.block_buf)
    803      || G.block_buf[result-1] != '\0'
     807    if (result < 4 || result > sizeof(G.block_buf)
     808    /*|| G.block_buf[result-1] != '\0' - bug compatibility, see below */
    804809     || (IF_FEATURE_TFTP_PUT(opcode != TFTP_RRQ) /* not download */
    805810         IF_GETPUT(&&)
     
    809814        goto err;
    810815    }
     816    /* Some HP PA-RISC firmware always sends fixed 516-byte requests,
     817     * with trailing garbage.
     818     * Support that by not requiring NUL to be the last byte (see above).
     819     * To make strXYZ() ops safe, force NUL termination:
     820     */
     821    G.block_buf_tail[0] = '\0';
     822
    811823    local_file = G.block_buf + 2;
    812824    if (local_file[0] == '.' || strstr(local_file, "/.")) {
  • branches/3.3/mindi-busybox/networking/traceroute.c

    r3232 r3621  
    212212
    213213//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"
     214//usage:       "[-"IF_TRACEROUTE6("46")"FIlnrv] [-f 1ST_TTL] [-m MAXTTL] [-q PROBES] [-p PORT]\n"
     215//usage:       "    [-t TOS] [-w WAIT_SEC]"
     216//usage:       IF_FEATURE_TRACEROUTE_SOURCE_ROUTE(" [-g GATEWAY]")" [-s SRC_IP] [-i IFACE]\n"
    216217//usage:       "    [-z PAUSE_MSEC] HOST [BYTES]"
    217218//usage:#define traceroute_full_usage "\n\n"
     
    220221//usage:     "\n    -4,-6   Force IP or IPv6 name resolution"
    221222//usage:    )
    222 //usage:     "\n    -F  Set the don't fragment bit"
     223//usage:     "\n    -F  Set don't fragment bit"
     224//usage:    IF_FEATURE_TRACEROUTE_USE_ICMP(
    223225//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:    )
     227//usage:     "\n    -l  Display TTL value of the returned packet"
     228//Currently disabled (TRACEROUTE_SO_DEBUG==0)
     229////usage:     "\n  -d  Set SO_DEBUG options to socket"
    226230//usage:     "\n    -n  Print numeric addresses"
    227231//usage:     "\n    -r  Bypass routing tables, send directly to HOST"
     232//usage:    IF_FEATURE_TRACEROUTE_VERBOSE(
    228233//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"
     234//usage:    )
     235//usage:     "\n    -f N    First number of hops (default 1)"
     236//usage:     "\n    -m N    Max number of hops"
     237//usage:     "\n    -q N    Number of probes per hop (default 3)"
     238//usage:     "\n    -p N    Base UDP port number used in probes"
    231239//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)"
     240//usage:     "\n    -s IP   Source address"
     241//usage:     "\n    -i IFACE Source interface"
     242//usage:     "\n    -t N    Type-of-service in probe packets (default 0)"
     243//usage:     "\n    -w SEC  Time to wait for a response (default 3)"
     244//usage:     "\n    -g IP   Loose source route gateway (8 max)"
    237245//usage:
    238246//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"
     247//usage:       "[-nrv] [-m MAXTTL] [-q PROBES] [-p PORT]\n"
     248//usage:       "    [-t TOS] [-w WAIT_SEC] [-s SRC_IP] [-i IFACE]\n"
    241249//usage:       "    HOST [BYTES]"
    242250//usage:#define traceroute6_full_usage "\n\n"
    243251//usage:       "Trace the route to HOST\n"
    244 //usage:     "\n    -d  Set SO_DEBUG options to socket"
     252//Currently disabled (TRACEROUTE_SO_DEBUG==0)
     253////usage:     "\n  -d  Set SO_DEBUG options to socket"
    245254//usage:     "\n    -n  Print numeric addresses"
    246255//usage:     "\n    -r  Bypass routing tables, send directly to HOST"
     256//usage:    IF_FEATURE_TRACEROUTE_VERBOSE(
    247257//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)"
     258//usage:    )
     259//usage:     "\n    -m N    Max number of hops"
     260//usage:     "\n    -q N    Number of probes per hop (default 3)"
     261//usage:     "\n    -p N    Base UDP port number used in probes"
     262//usage:     "\n        (default 33434)"
     263//usage:     "\n    -s IP   Source address"
     264//usage:     "\n    -i IFACE Source interface"
     265//usage:     "\n    -t N    Type-of-service in probe packets (default 0)"
     266//usage:     "\n    -w SEC  Time wait for a response (default 3)"
    255267
    256268#define TRACEROUTE_SO_DEBUG 0
    257 
    258 /* TODO: undefs were uncommented - ??! we have config system for that! */
    259 /* probably ok to remove altogether */
    260 //#undef CONFIG_FEATURE_TRACEROUTE_VERBOSE
    261 //#define CONFIG_FEATURE_TRACEROUTE_VERBOSE
    262 //#undef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
    263 //#define CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
    264 //#undef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
    265 //#define CONFIG_FEATURE_TRACEROUTE_USE_ICMP
    266 
    267269
    268270#include <net/if.h>
     
    388390
    389391
    390 /* libbb candidate? tftp uses this idiom too */
    391 static len_and_sockaddr* dup_sockaddr(const len_and_sockaddr *lsa)
    392 {
    393     len_and_sockaddr *new_lsa = xzalloc(LSA_LEN_SIZE + lsa->len);
    394     memcpy(new_lsa, lsa, LSA_LEN_SIZE + lsa->len);
    395     return new_lsa;
    396 }
    397 
    398 
    399392static int
    400393wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timestamp_us, int *left_ms)
     
    481474#if ENABLE_TRACEROUTE6
    482475    if (dest_lsa->u.sa.sa_family == AF_INET6) {
    483         res = setsockopt(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
    484         if (res < 0)
    485             bb_perror_msg_and_die("setsockopt UNICAST_HOPS %d", ttl);
     476        res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl);
     477        if (res != 0)
     478            bb_perror_msg_and_die("setsockopt(%s) %d", "UNICAST_HOPS", ttl);
    486479        out = outip;
    487480        len = packlen;
     
    490483    {
    491484#if defined IP_TTL
    492         res = setsockopt(sndsock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
    493         if (res < 0)
    494             bb_perror_msg_and_die("setsockopt ttl %d", ttl);
     485        res = setsockopt_int(sndsock, IPPROTO_IP, IP_TTL, ttl);
     486        if (res != 0)
     487            bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl);
    495488#endif
    496489        out = outicmp;
     
    505498    res = xsendto(sndsock, out, len, &dest_lsa->u.sa, dest_lsa->len);
    506499    if (res != len)
    507         bb_info_msg("sent %d octets, ret=%d", len, res);
     500        bb_error_msg("sent %d octets, ret=%d", len, res);
    508501}
    509502
     
    792785{
    793786    int minpacket;
     787#ifdef IP_TOS
    794788    int tos = 0;
     789#endif
    795790    int max_ttl = 30;
    796791    int nprobes = 3;
     
    806801    char *pausemsecs_str;
    807802    char *first_ttl_str;
     803    char *dest_str;
    808804#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
    809805    llist_t *source_route_list = NULL;
     
    838834        bb_error_msg("warning: ip checksums disabled");
    839835#endif
     836#ifdef IP_TOS
    840837    if (op & OPT_TOS)
    841838        tos = xatou_range(tos_str, 0, 255);
     839#endif
    842840    if (op & OPT_MAX_TTL)
    843841        max_ttl = xatou_range(max_ttl_str, 1, 255);
     
    905903        xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock);
    906904# ifdef IPV6_RECVPKTINFO
    907         setsockopt(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO,
    908                 &const_int_1, sizeof(const_int_1));
    909         setsockopt(rcvsock, SOL_IPV6, IPV6_2292PKTINFO,
    910                 &const_int_1, sizeof(const_int_1));
     905        setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO);
     906        setsockopt_1(rcvsock, SOL_IPV6, IPV6_2292PKTINFO);
    911907# else
    912         setsockopt(rcvsock, SOL_IPV6, IPV6_PKTINFO,
    913                 &const_int_1, sizeof(const_int_1));
     908        setsockopt_1(rcvsock, SOL_IPV6, IPV6_PKTINFO);
    914909# endif
    915910    } else
     
    921916#if TRACEROUTE_SO_DEBUG
    922917    if (op & OPT_DEBUG)
    923         setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG,
    924                 &const_int_1, sizeof(const_int_1));
     918        setsockopt_SOL_SOCKET_1(rcvsock, SO_DEBUG);
    925919#endif
    926920    if (op & OPT_BYPASS_ROUTE)
    927         setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE,
    928                 &const_int_1, sizeof(const_int_1));
     921        setsockopt_SOL_SOCKET_1(rcvsock, SO_DONTROUTE);
    929922
    930923#if ENABLE_TRACEROUTE6
    931924    if (af == AF_INET6) {
    932         static const int two = 2;
    933         if (setsockopt(rcvsock, SOL_RAW, IPV6_CHECKSUM, &two, sizeof(two)) < 0)
    934             bb_perror_msg_and_die("setsockopt RAW_CHECKSUM");
     925        if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0)
     926            bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM");
    935927        xmove_fd(xsocket(af, SOCK_DGRAM, 0), sndsock);
    936928    } else
     
    969961
    970962#ifdef SO_SNDBUF
    971     if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, &packlen, sizeof(packlen)) < 0) {
    972         bb_perror_msg_and_die("SO_SNDBUF");
     963    if (setsockopt_SOL_SOCKET_int(sndsock, SO_SNDBUF, packlen) != 0) {
     964        bb_perror_msg_and_die("setsockopt(%s)", "SO_SNDBUF");
    973965    }
    974966#endif
    975967#ifdef IP_TOS
    976     if ((op & OPT_TOS) && setsockopt(sndsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
    977         bb_perror_msg_and_die("setsockopt tos %d", tos);
     968    if ((op & OPT_TOS) && setsockopt_int(sndsock, IPPROTO_IP, IP_TOS, tos) != 0) {
     969        bb_perror_msg_and_die("setsockopt(%s) %d", "TOS", tos);
    978970    }
    979971#endif
    980972#ifdef IP_DONTFRAG
    981973    if (op & OPT_DONT_FRAGMNT)
    982         setsockopt(sndsock, IPPROTO_IP, IP_DONTFRAG,
    983                 &const_int_1, sizeof(const_int_1));
     974        setsockopt_1(sndsock, IPPROTO_IP, IP_DONTFRAG);
    984975#endif
    985976#if TRACEROUTE_SO_DEBUG
    986977    if (op & OPT_DEBUG)
    987         setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
    988                 &const_int_1, sizeof(const_int_1));
     978        setsockopt_SOL_SOCKET_1(sndsock, SO_DEBUG);
    989979#endif
    990980    if (op & OPT_BYPASS_ROUTE)
    991         setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
    992                 &const_int_1, sizeof(const_int_1));
     981        setsockopt_SOL_SOCKET_1(sndsock, SO_DONTROUTE);
    993982
    994983    outip = xzalloc(packlen);
     
    10601049    xsetuid(getuid());
    10611050
    1062     printf("traceroute to %s (%s)", argv[0],
    1063             xmalloc_sockaddr2dotted_noport(&dest_lsa->u.sa));
     1051    dest_str = xmalloc_sockaddr2dotted_noport(&dest_lsa->u.sa);
     1052    printf("traceroute to %s (%s)", argv[0], dest_str);
     1053    if (ENABLE_FEATURE_CLEAN_UP) {
     1054        free(dest_str);
     1055    }
     1056
    10641057    if (op & OPT_SOURCE)
    10651058        printf(" from %s", source);
    10661059    printf(", %d hops max, %d byte packets\n", max_ttl, packlen);
    10671060
    1068     from_lsa = dup_sockaddr(dest_lsa);
     1061    from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len);
    10691062    lastaddr = xzalloc(dest_lsa->len);
    10701063    to = xzalloc(dest_lsa->len);
     
    12171210    }
    12181211
     1212    if (ENABLE_FEATURE_CLEAN_UP) {
     1213        free(to);
     1214        free(lastaddr);
     1215        free(from_lsa);
     1216    }
     1217
    12191218    return 0;
    12201219}
  • branches/3.3/mindi-busybox/networking/tunctl.c

    r3232 r3621  
    8383    if (opts & OPT_d) {
    8484        IOCTL(fd, TUNSETPERSIST, (void *)(uintptr_t)0);
    85         bb_info_msg("Set '%s' %spersistent", ifr.ifr_name, "non");
     85        printf("Set '%s' nonpersistent\n", ifr.ifr_name);
    8686        return EXIT_SUCCESS;
    8787    }
  • branches/3.3/mindi-busybox/networking/udhcp/Config.src

    r3232 r3621  
    8585      and restart the discover process.
    8686
     87config FEATURE_UDHCPC_SANITIZEOPT
     88    bool "Do not pass malformed host and domain names"
     89    default y
     90    depends on UDHCPC
     91    help
     92      If selected, udhcpc will check some options (such as option 12 -
     93      hostname) and if they don't look like valid hostnames
     94      (for example, if they start with dash or contain spaces),
     95      they will be replaced with string "bad" when exporting
     96      to the environment.
     97
    8798config FEATURE_UDHCP_PORT
    8899    bool "Enable '-P port' option for udhcpd and udhcpc"
  • branches/3.3/mindi-busybox/networking/udhcp/arpping.c

    r3232 r3621  
    4040        uint32_t from_ip,
    4141        uint8_t *from_mac,
    42         const char *interface)
     42        const char *interface,
     43        unsigned timeo)
    4344{
    4445    int timeout_ms;
     
    4849    struct sockaddr addr;   /* for interface name */
    4950    struct arpMsg arp;
     51
     52    if (!timeo)
     53        return 1;
    5054
    5155    s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP));
     
    8488
    8589    /* wait for arp reply, and check it */
    86     timeout_ms = 2000;
     90    timeout_ms = (int)timeo;
    8791    do {
    8892        typedef uint32_t aliased_uint32_t FIX_ALIASING;
     
    125129         * (people did see overflows here when system time jumps):
    126130         */
    127     } while ((unsigned)timeout_ms <= 2000);
     131    } while ((unsigned)timeout_ms <= timeo);
    128132
    129133 ret:
    130134    close(s);
    131     log1("%srp reply received for this address", rv ? "No a" : "A");
     135    log1("%srp reply received for this address", rv ? "no a" : "A");
    132136    return rv;
    133137}
  • branches/3.3/mindi-busybox/networking/udhcp/common.c

    r3232 r3621  
    6363    { OPTION_U8                               , 0x85 }, /* DHCP_VLAN_PRIORITY */
    6464#endif
     65    { OPTION_STRING                           , 0xd1 }, /* DHCP_PXE_CONF_FILE */
     66    { OPTION_STRING                           , 0xd2 }, /* DHCP_PXE_PATH_PREFIX */
    6567    { OPTION_6RD                              , 0xd4 }, /* DHCP_6RD           */
    6668    { OPTION_STATIC_ROUTES | OPTION_LIST      , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */
     
    129131    "vlanpriority" "\0"/* DHCP_VLAN_PRIORITY  */
    130132#endif
     133    "pxeconffile" "\0" /* DHCP_PXE_CONF_FILE  */
     134    "pxepathprefix" "\0" /* DHCP_PXE_PATH_PREFIX  */
    131135    "ip6rd" "\0"       /* DHCP_6RD            */
    132136    "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */
     
    139143 * xmalloc_optname_optval: to estimate string length
    140144 * from binary option length: (option[LEN] / dhcp_option_lengths[opt_type])
    141  * is the number of elements, multiply in by one element's string width
     145 * is the number of elements, multiply it by one element's string width
    142146 * (len_of_option_as_string[opt_type]) and you know how wide string you need.
    143147 */
     
    159163    /* Just like OPTION_STRING, we use minimum length here */
    160164    [OPTION_STATIC_ROUTES] = 5,
    161     [OPTION_6RD] =    22,  /* ignored by udhcp_str2optset */
     165    [OPTION_6RD] =    12,  /* ignored by udhcp_str2optset */
     166    /* The above value was chosen as follows:
     167     * len_of_option_as_string[] for this option is >60: it's a string of the form
     168     * "32 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 ".
     169     * Each additional ipv4 address takes 4 bytes in binary option and appends
     170     * another "255.255.255.255 " 16-byte string. We can set [OPTION_6RD] = 4
     171     * but this severely overestimates string length: instead of 16 bytes,
     172     * it adds >60 for every 4 bytes in binary option.
     173     * We cheat and declare here that option is in units of 12 bytes.
     174     * This adds more than 60 bytes for every three ipv4 addresses - more than enough.
     175     * (Even 16 instead of 12 should work, but let's be paranoid).
     176     */
    162177};
    163178
     
    169184        char buf[256 * 2 + 2];
    170185        *bin2hex(buf, (void*) (opt + OPT_DATA), opt[OPT_LEN]) = '\0';
    171         bb_info_msg("%s: 0x%02x %s", pfx, opt[OPT_CODE], buf);
     186        bb_error_msg("%s: 0x%02x %s", pfx, opt[OPT_CODE], buf);
    172187    }
    173188}
     
    243258
    244259        if (optionptr[OPT_CODE] == code) {
    245             log_option("Option found", optionptr);
     260            log_option("option found", optionptr);
    246261            return optionptr + OPT_DATA;
    247262        }
     
    255270
    256271    /* log3 because udhcpc uses it a lot - very noisy */
    257     log3("Option 0x%02x not found", code);
     272    log3("option 0x%02x not found", code);
    258273    return NULL;
    259274}
     
    289304        return;
    290305    }
    291     log_option("Adding option", addopt);
     306    log_option("adding option", addopt);
    292307    memcpy(optionptr + end, addopt, len);
    293308    optionptr[end + len] = DHCP_END;
     
    372387        int length)
    373388{
    374     struct option_set *existing, *new, **curr;
    375     char *allocated = NULL;
     389    struct option_set *existing;
     390    char *allocated;
     391
     392    allocated = allocate_tempopt_if_needed(optflag, buffer, &length);
     393#if ENABLE_FEATURE_UDHCP_RFC3397
     394    if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) {
     395        /* reuse buffer and length for RFC1035-formatted string */
     396        allocated = buffer = (char *)dname_enc(NULL, 0, buffer, &length);
     397    }
     398#endif
    376399
    377400    existing = udhcp_find_option(*opt_list, optflag->code);
    378401    if (!existing) {
    379         log2("Attaching option %02x to list", optflag->code);
    380         allocated = allocate_tempopt_if_needed(optflag, buffer, &length);
    381 #if ENABLE_FEATURE_UDHCP_RFC3397
    382         if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) {
    383             /* reuse buffer and length for RFC1035-formatted string */
    384             allocated = buffer = (char *)dname_enc(NULL, 0, buffer, &length);
    385         }
    386 #endif
     402        struct option_set *new, **curr;
     403
    387404        /* make a new option */
     405        log2("attaching option %02x to list", optflag->code);
    388406        new = xmalloc(sizeof(*new));
    389407        new->data = xmalloc(length + OPT_DATA);
     
    405423
    406424        /* add it to an existing option */
    407         log2("Attaching option %02x to existing member of list", optflag->code);
    408         allocated = allocate_tempopt_if_needed(optflag, buffer, &length);
     425        log2("attaching option %02x to existing member of list", optflag->code);
    409426        old_len = existing->data[OPT_LEN];
    410 #if ENABLE_FEATURE_UDHCP_RFC3397
    411         if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) {
    412             /* reuse buffer and length for RFC1035-formatted string */
    413             allocated = buffer = (char *)dname_enc(existing->data + OPT_DATA, old_len, buffer, &length);
    414         }
    415 #endif
    416427        if (old_len + length < 255) {
    417428            /* actually 255 is ok too, but adding a space can overlow it */
     
    425436                old_len++;
    426437            }
    427             memcpy(existing->data + OPT_DATA + old_len, buffer, length);
     438            memcpy(existing->data + OPT_DATA + old_len, (allocated ? allocated : buffer), length);
    428439            existing->data[OPT_LEN] = old_len + length;
    429440        } /* else, ignore the data, we could put this in a second option in the future */
  • branches/3.3/mindi-busybox/networking/udhcp/common.h

    r3232 r3621  
    1010
    1111#include "libbb.h"
     12#include "common_bufsiz.h"
    1213#include <netinet/udp.h>
    1314#include <netinet/ip.h>
     
    150151//#define DHCP_SIP_SERVERS      0x78 /* RFC 3361. flag byte, then: 0: domain names, 1: IP addrs */
    151152//#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 */
     153//#define DHCP_VLAN_ID          0x84 /* 802.1P VLAN ID */
     154//#define DHCP_VLAN_PRIORITY    0x85 /* 802.1Q VLAN priority */
     155//#define DHCP_PXE_CONF_FILE    0xd1 /* RFC 5071 Configuration File */
     156//#define DHCP_PXE_PATH_PREFIX  0xd2 /* RFC 5071 Configuration File */
    154157//#define DHCP_MS_STATIC_ROUTES 0xf9 /* Microsoft's pre-RFC 3442 code for 0x79? */
    155158//#define DHCP_WPAD             0xfc /* MSIE's Web Proxy Autodiscovery Protocol */
     
    255258# define IF_UDHCP_VERBOSE(...) __VA_ARGS__
    256259extern unsigned dhcp_verbose;
    257 # define log1(...) do { if (dhcp_verbose >= 1) bb_info_msg(__VA_ARGS__); } while (0)
     260# define log1(...) do { if (dhcp_verbose >= 1) bb_error_msg(__VA_ARGS__); } while (0)
    258261# if CONFIG_UDHCP_DEBUG >= 2
    259262void udhcp_dump_packet(struct dhcp_packet *packet) FAST_FUNC;
    260 #  define log2(...) do { if (dhcp_verbose >= 2) bb_info_msg(__VA_ARGS__); } while (0)
     263#  define log2(...) do { if (dhcp_verbose >= 2) bb_error_msg(__VA_ARGS__); } while (0)
    261264# else
    262265#  define udhcp_dump_packet(...) ((void)0)
     
    264267# endif
    265268# if CONFIG_UDHCP_DEBUG >= 3
    266 #  define log3(...) do { if (dhcp_verbose >= 3) bb_info_msg(__VA_ARGS__); } while (0)
     269#  define log3(...) do { if (dhcp_verbose >= 3) bb_error_msg(__VA_ARGS__); } while (0)
    267270# else
    268271#  define log3(...) ((void)0)
     
    310313        uint32_t from_ip,
    311314        uint8_t *from_mac,
    312         const char *interface) FAST_FUNC;
     315        const char *interface,
     316        unsigned timeo) FAST_FUNC;
    313317
    314318/* note: ip is a pointer to an IPv6 in network order, possibly misaliged */
  • branches/3.3/mindi-busybox/networking/udhcp/dhcpc.c

    r3306 r3621  
    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#ifndef PACKET_AUXDATA
     33# define PACKET_AUXDATA 8
     34struct tpacket_auxdata {
     35    uint32_t tp_status;
     36    uint32_t tp_len;
     37    uint32_t tp_snaplen;
     38    uint16_t tp_mac;
     39    uint16_t tp_net;
     40    uint16_t tp_vlan_tci;
     41    uint16_t tp_padding;
     42};
    3543#endif
    36 #include <linux/filter.h>
     44
    3745
    3846/* "struct client_config_t client_config" is in bb_common_bufsiz1 */
     
    6169    "background\0"     No_argument       "b"
    6270    "broadcast\0"      No_argument       "B"
    63     IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument      "a")
     71    IF_FEATURE_UDHCPC_ARPING("arping\0" Optional_argument "a")
    6472    IF_FEATURE_UDHCP_PORT("client-port\0"   Required_argument "P")
    6573    ;
     
    102110
    103111/* get a rough idea of how long an option will be (rounding up...) */
    104 static const uint8_t len_of_option_as_string[] = {
     112static const uint8_t len_of_option_as_string[] ALIGN1 = {
    105113    [OPTION_IP              ] = sizeof("255.255.255.255 "),
    106114    [OPTION_IP_PAIR         ] = sizeof("255.255.255.255 ") * 2,
    107115    [OPTION_STATIC_ROUTES   ] = sizeof("255.255.255.255/32 255.255.255.255 "),
    108     [OPTION_6RD             ] = sizeof("32 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 "),
     116    [OPTION_6RD             ] = sizeof("132 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 "),
    109117    [OPTION_STRING          ] = 1,
    110118    [OPTION_STRING_HOST     ] = 1,
     
    143151}
    144152
     153#if ENABLE_FEATURE_UDHCPC_SANITIZEOPT
    145154/* Check if a given label represents a valid DNS label
    146155 * Return pointer to the first character after the label upon success,
     
    162171        ch = *label;
    163172        if ((ch|0x20) < 'a' || (ch|0x20) > 'z') {
    164             if (pos == 0) {
    165                 /* label must begin with letter */
    166                 return NULL;
    167             }
    168173            if (ch < '0' || ch > '9') {
    169174                if (ch == '\0' || ch == '.')
     
    197202            //return ((name - start) < 1025); /* NS_MAXDNAME */
    198203        name++;
    199     }
    200 }
     204        if (*name == '\0')
     205            return 1; // We allow trailing dot too
     206    }
     207}
     208#else
     209# define good_hostname(name) 1
     210#endif
    201211
    202212/* Create "opt_name=opt_value" string */
     
    213223    optlen = dhcp_option_lengths[type];
    214224    upper_length = len_of_option_as_string[type]
    215         * ((unsigned)(len + optlen - 1) / (unsigned)optlen);
     225        * ((unsigned)(len + optlen) / (unsigned)optlen);
    216226
    217227    dest = ret = xmalloc(upper_length + strlen(opt_name) + 2);
     
    552562
    553563    /* call script */
    554     log1("Executing %s %s", client_config.script, name);
     564    log1("executing %s %s", client_config.script, name);
    555565    argv[0] = (char*) client_config.script;
    556566    argv[1] = (char*) name;
     
    666676 */
    667677
    668 static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet)
     678static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet, uint32_t src_nip)
    669679{
    670680    return udhcp_send_raw_packet(packet,
    671         /*src*/ INADDR_ANY, CLIENT_PORT,
     681        /*src*/ src_nip, CLIENT_PORT,
    672682        /*dst*/ INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR,
    673683        client_config.ifindex);
     684}
     685
     686static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server)
     687{
     688    if (server)
     689        return udhcp_send_kernel_packet(packet,
     690            ciaddr, CLIENT_PORT,
     691            server, SERVER_PORT);
     692    return raw_bcast_from_client_config_ifindex(packet, ciaddr);
    674693}
    675694
     
    696715    add_client_options(&packet);
    697716
    698     bb_info_msg("Sending discover...");
    699     return raw_bcast_from_client_config_ifindex(&packet);
     717    bb_error_msg("sending %s", "discover");
     718    return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY);
    700719}
    701720
     
    740759
    741760    addr.s_addr = requested;
    742     bb_info_msg("Sending select for %s...", inet_ntoa(addr));
    743     return raw_bcast_from_client_config_ifindex(&packet);
     761    bb_error_msg("sending select for %s", inet_ntoa(addr));
     762    return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY);
    744763}
    745764
     
    779798    add_client_options(&packet);
    780799
    781     bb_info_msg("Sending renew...");
    782     if (server)
    783         return udhcp_send_kernel_packet(&packet,
    784             ciaddr, CLIENT_PORT,
    785             server, SERVER_PORT);
    786     return raw_bcast_from_client_config_ifindex(&packet);
     800    bb_error_msg("sending %s", "renew");
     801    return bcast_or_ucast(&packet, ciaddr, server);
    787802}
    788803
     
    812827    udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
    813828
    814     bb_info_msg("Sending decline...");
    815     return raw_bcast_from_client_config_ifindex(&packet);
     829    bb_error_msg("sending %s", "decline");
     830    return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY);
    816831}
    817832#endif
     
    832847    udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
    833848
    834     bb_info_msg("Sending release...");
    835     return udhcp_send_kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT);
     849    bb_error_msg("sending %s", "release");
     850    /* Note: normally we unicast here since "server" is not zero.
     851     * However, there _are_ people who run "address-less" DHCP servers,
     852     * and reportedly ISC dhcp client and Windows allow that.
     853     */
     854    return bcast_or_ucast(&packet, ciaddr, server);
    836855}
    837856
     
    843862    struct ip_udp_dhcp_packet packet;
    844863    uint16_t check;
    845 #ifdef PACKET_AUXDATA
    846864    unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
    847     struct cmsghdr *cmsg;
    848 #endif
    849865    struct iovec iov;
    850866    struct msghdr msg;
    851 
    852 #ifdef PACKET_AUXDATA
     867    struct cmsghdr *cmsg;
     868
    853869    /* used to use just safe_read(fd, &packet, sizeof(packet))
    854870     * but we need to check for TP_STATUS_CSUMNOTREADY :(
     
    866882            if (errno == EINTR)
    867883                continue;
    868             log1("Packet read error, ignoring");
     884            log1("packet read error, ignoring");
    869885            /* NB: possible down interface, etc. Caller should pause. */
    870886            return bytes; /* returns -1 */
     
    872888        break;
    873889    }
    874 #else
    875     memset(&packet, 0, sizeof(packet));
    876     bytes = safe_read(fd, &packet, sizeof(packet));
    877     if (bytes < 0) {
    878         log1("Packet read error, ignoring");
    879         /* NB: possible down interface, etc. Caller should pause. */
    880         return bytes; /* returns -1 */
    881     }
    882 #endif
    883890
    884891    if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) {
    885         log1("Packet is too short, ignoring");
     892        log1("packet is too short, ignoring");
    886893        return -2;
    887894    }
     
    889896    if (bytes < ntohs(packet.ip.tot_len)) {
    890897        /* packet is bigger than sizeof(packet), we did partial read */
    891         log1("Oversized packet, ignoring");
     898        log1("oversized packet, ignoring");
    892899        return -2;
    893900    }
     
    904911     || ntohs(packet.udp.len) != (uint16_t)(bytes - sizeof(packet.ip))
    905912    ) {
    906         log1("Unrelated/bogus packet, ignoring");
     913        log1("unrelated/bogus packet, ignoring");
    907914        return -2;
    908915    }
     
    912919    packet.ip.check = 0;
    913920    if (check != inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip))) {
    914         log1("Bad IP header checksum, ignoring");
     921        log1("bad IP header checksum, ignoring");
    915922        return -2;
    916923    }
    917924
    918 #ifdef PACKET_AUXDATA
    919925    for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
    920926        if (cmsg->cmsg_level == SOL_PACKET
     
    930936        }
    931937    }
    932 #endif
    933938
    934939    /* verify UDP checksum. IP header has to be modified for this */
     
    939944    packet.udp.check = 0;
    940945    if (check && check != inet_cksum((uint16_t *)&packet, bytes)) {
    941         log1("Packet with bad UDP checksum received, ignoring");
     946        log1("packet with bad UDP checksum received, ignoring");
    942947        return -2;
    943948    }
    944 #ifdef PACKET_AUXDATA
    945949 skip_udp_sum_check:
    946 #endif
    947950
    948951    if (packet.data.cookie != htonl(DHCP_MAGIC)) {
    949         bb_info_msg("Packet with bad magic, ignoring");
     952        bb_error_msg("packet with bad magic, ignoring");
    950953        return -2;
    951954    }
    952955
    953     log1("Received a packet");
     956    log1("received %s", "a packet");
    954957    udhcp_dump_packet(&packet.data);
    955958
     
    990993    struct sockaddr_ll sock;
    991994
    992     /*
    993      * Comment:
    994      *
    995      *  I've selected not to see LL header, so BPF doesn't see it, too.
    996      *  The filter may also pass non-IP and non-ARP packets, but we do
    997      *  a more complete check when receiving the message in userspace.
    998      *
    999      * and filter shamelessly stolen from:
    1000      *
    1001      *  http://www.flamewarmaster.de/software/dhcpclient/
    1002      *
    1003      * There are a few other interesting ideas on that page (look under
    1004      * "Motivation").  Use of netlink events is most interesting.  Think
    1005      * of various network servers listening for events and reconfiguring.
    1006      * That would obsolete sending HUP signals and/or make use of restarts.
    1007      *
    1008      * Copyright: 2006, 2007 Stefan Rompf <sux@loplof.de>.
    1009      * License: GPL v2.
    1010      *
    1011      * TODO: make conditional?
     995    log1("opening raw socket on ifindex %d", ifindex); //log2?
     996
     997    fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
     998    /* ^^^^^
     999     * SOCK_DGRAM: remove link-layer headers on input (SOCK_RAW keeps them)
     1000     * ETH_P_IP: want to receive only packets with IPv4 eth type
    10121001     */
    1013     static const struct sock_filter filter_instr[] = {
    1014         /* load 9th byte (protocol) */
    1015         BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 9),
    1016         /* jump to L1 if it is IPPROTO_UDP, else to L4 */
    1017         BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_UDP, 0, 6),
    1018         /* L1: load halfword from offset 6 (flags and frag offset) */
    1019         BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 6),
    1020         /* jump to L4 if any bits in frag offset field are set, else to L2 */
    1021         BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x1fff, 4, 0),
    1022         /* L2: skip IP header (load index reg with header len) */
    1023         BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0),
    1024         /* load udp destination port from halfword[header_len + 2] */
    1025         BPF_STMT(BPF_LD|BPF_H|BPF_IND, 2),
    1026         /* jump to L3 if udp dport is CLIENT_PORT, else to L4 */
    1027         BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 68, 0, 1),
    1028         /* L3: accept packet */
    1029         BPF_STMT(BPF_RET|BPF_K, 0xffffffff),
    1030         /* L4: discard packet */
    1031         BPF_STMT(BPF_RET|BPF_K, 0),
    1032     };
    1033     static const struct sock_fprog filter_prog = {
    1034         .len = sizeof(filter_instr) / sizeof(filter_instr[0]),
    1035         /* casting const away: */
    1036         .filter = (struct sock_filter *) filter_instr,
    1037     };
    1038 
    1039     log1("Opening raw socket on ifindex %d", ifindex); //log2?
    1040 
    1041     fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
    1042     log1("Got raw socket fd"); //log2?
     1002    log1("got raw socket fd"); //log2?
    10431003
    10441004    sock.sll_family = AF_PACKET;
     
    10471007    xbind(fd, (struct sockaddr *) &sock, sizeof(sock));
    10481008
     1009#if 0 /* Several users reported breakage when BPF filter is used */
    10491010    if (CLIENT_PORT == 68) {
    10501011        /* Use only if standard port is in use */
     1012        /*
     1013         *  I've selected not to see LL header, so BPF doesn't see it, too.
     1014         *  The filter may also pass non-IP and non-ARP packets, but we do
     1015         *  a more complete check when receiving the message in userspace.
     1016         *
     1017         * and filter shamelessly stolen from:
     1018         *
     1019         *  http://www.flamewarmaster.de/software/dhcpclient/
     1020         *
     1021         * There are a few other interesting ideas on that page (look under
     1022         * "Motivation").  Use of netlink events is most interesting.  Think
     1023         * of various network servers listening for events and reconfiguring.
     1024         * That would obsolete sending HUP signals and/or make use of restarts.
     1025         *
     1026         * Copyright: 2006, 2007 Stefan Rompf <sux@loplof.de>.
     1027         * License: GPL v2.
     1028         */
     1029        static const struct sock_filter filter_instr[] = {
     1030            /* load 9th byte (protocol) */
     1031            BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 9),
     1032            /* jump to L1 if it is IPPROTO_UDP, else to L4 */
     1033            BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_UDP, 0, 6),
     1034            /* L1: load halfword from offset 6 (flags and frag offset) */
     1035            BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 6),
     1036            /* jump to L4 if any bits in frag offset field are set, else to L2 */
     1037            BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x1fff, 4, 0),
     1038            /* L2: skip IP header (load index reg with header len) */
     1039            BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0),
     1040            /* load udp destination port from halfword[header_len + 2] */
     1041            BPF_STMT(BPF_LD|BPF_H|BPF_IND, 2),
     1042            /* jump to L3 if udp dport is CLIENT_PORT, else to L4 */
     1043            BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 68, 0, 1),
     1044            /* L3: accept packet ("accept 0x7fffffff bytes") */
     1045            /* Accepting 0xffffffff works too but kernel 2.6.19 is buggy */
     1046            BPF_STMT(BPF_RET|BPF_K, 0x7fffffff),
     1047            /* L4: discard packet ("accept zero bytes") */
     1048            BPF_STMT(BPF_RET|BPF_K, 0),
     1049        };
     1050        static const struct sock_fprog filter_prog = {
     1051            .len = sizeof(filter_instr) / sizeof(filter_instr[0]),
     1052            /* casting const away: */
     1053            .filter = (struct sock_filter *) filter_instr,
     1054        };
    10511055        /* Ignoring error (kernel may lack support for this) */
    10521056        if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog,
    10531057                sizeof(filter_prog)) >= 0)
    1054             log1("Attached filter to raw socket fd"); // log?
    1055     }
    1056 
    1057 #ifdef PACKET_AUXDATA
    1058     if (setsockopt(fd, SOL_PACKET, PACKET_AUXDATA,
    1059             &const_int_1, sizeof(int)) < 0
    1060     ) {
     1058            log1("attached filter to raw socket fd"); // log?
     1059    }
     1060#endif
     1061
     1062    if (setsockopt_1(fd, SOL_PACKET, PACKET_AUXDATA) != 0) {
    10611063        if (errno != ENOPROTOOPT)
    1062             log1("Can't set PACKET_AUXDATA on raw socket");
    1063     }
    1064 #else
    1065     sock.sll_family = AF_PACKET;
    1066     sock.sll_protocol = htons(ETH_P_IP);
    1067     sock.sll_ifindex = ifindex;
    1068     xbind(fd, (struct sockaddr *) &sock, sizeof(sock));
    1069 #endif
    1070 
    1071     log1("Created raw socket");
     1064            log1("can't set PACKET_AUXDATA on raw socket");
     1065    }
     1066
     1067    log1("created raw socket");
    10721068
    10731069    return fd;
     
    10761072static void change_listen_mode(int new_mode)
    10771073{
    1078     log1("Entering listen mode: %s",
     1074    log1("entering listen mode: %s",
    10791075        new_mode != LISTEN_NONE
    10801076            ? (new_mode == LISTEN_KERNEL ? "kernel" : "raw")
     
    10971093static void perform_renew(void)
    10981094{
    1099     bb_info_msg("Performing a DHCP renew");
     1095    bb_error_msg("performing DHCP renew");
    11001096    switch (state) {
    11011097    case BOUND:
     
    11271123        strcpy(buffer, inet_ntoa(temp_addr));
    11281124        temp_addr.s_addr = requested_ip;
    1129         bb_info_msg("Unicasting a release of %s to %s",
     1125        bb_error_msg("unicasting a release of %s to %s",
    11301126                inet_ntoa(temp_addr), buffer);
    11311127        send_release(server_addr, requested_ip); /* unicast */
    11321128        udhcp_run_script(NULL, "deconfig");
    11331129    }
    1134     bb_info_msg("Entering released state");
     1130    bb_error_msg("entering released state");
    11351131
    11361132    change_listen_mode(LISTEN_NONE);
     
    11651161//usage:#endif
    11661162//usage:#define udhcpc_trivial_usage
    1167 //usage:       "[-fbnq"IF_UDHCP_VERBOSE("v")"oCRB] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n"
    1168 //usage:       "    [-V VENDOR] [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]")
     1163//usage:       "[-fbq"IF_UDHCP_VERBOSE("v")"RB]"IF_FEATURE_UDHCPC_ARPING(" [-a[MSEC]]")" [-t N] [-T SEC] [-A SEC/-n]\n"
     1164//usage:       "    [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s PROG] [-p PIDFILE]\n"
     1165//usage:       "    [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]..."
    11691166//usage:#define udhcpc_full_usage "\n"
    11701167//usage:    IF_LONG_OPTS(
    11711168//usage:     "\n    -i,--interface IFACE    Interface to use (default eth0)"
     1169//usage:    IF_FEATURE_UDHCP_PORT(
     1170//usage:     "\n    -P,--client-port PORT   Use PORT (default 68)"
     1171//usage:    )
     1172//usage:     "\n    -s,--script PROG    Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")"
    11721173//usage:     "\n    -p,--pidfile FILE   Create pidfile"
    1173 //usage:     "\n    -s,--script PROG    Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")"
    11741174//usage:     "\n    -B,--broadcast      Request broadcast replies"
    1175 //usage:     "\n    -t,--retries N      Send up to N discover packets"
    1176 //usage:     "\n    -T,--timeout N      Pause between packets (default 3 seconds)"
    1177 //usage:     "\n    -A,--tryagain N     Wait N seconds after failure (default 20)"
     1175//usage:     "\n    -t,--retries N      Send up to N discover packets (default 3)"
     1176//usage:     "\n    -T,--timeout SEC    Pause between packets (default 3)"
     1177//usage:     "\n    -A,--tryagain SEC   Wait if lease is not obtained (default 20)"
     1178//usage:     "\n    -n,--now        Exit if lease is not obtained"
     1179//usage:     "\n    -q,--quit       Exit after obtaining lease"
     1180//usage:     "\n    -R,--release        Release IP on exit"
    11781181//usage:     "\n    -f,--foreground     Run in foreground"
    11791182//usage:    USE_FOR_MMU(
    11801183//usage:     "\n    -b,--background     Background if lease is not obtained"
    11811184//usage:    )
    1182 //usage:     "\n    -n,--now        Exit if lease is not obtained"
    1183 //usage:     "\n    -q,--quit       Exit after obtaining lease"
    1184 //usage:     "\n    -R,--release        Release IP on exit"
    11851185//usage:     "\n    -S,--syslog     Log to syslog too"
    1186 //usage:    IF_FEATURE_UDHCP_PORT(
    1187 //usage:     "\n    -P,--client-port N  Use port N (default 68)"
     1186//usage:    IF_FEATURE_UDHCPC_ARPING(
     1187//usage:     "\n    -a[MSEC],--arping[=MSEC] Validate offered address with ARP ping"
    11881188//usage:    )
    1189 //usage:    IF_FEATURE_UDHCPC_ARPING(
    1190 //usage:     "\n    -a,--arping     Use arping to validate offered address"
    1191 //usage:    )
     1189//usage:     "\n    -r,--request IP     Request this IP address"
     1190//usage:     "\n    -o,--no-default-options Don't request any options (unless -O is given)"
    11921191//usage:     "\n    -O,--request-option OPT Request option OPT from server (cumulative)"
    1193 //usage:     "\n    -o,--no-default-options Don't request any options (unless -O is given)"
    1194 //usage:     "\n    -r,--request IP     Request this IP address"
    11951192//usage:     "\n    -x OPT:VAL      Include option OPT in sent packets (cumulative)"
    11961193//usage:     "\n                Examples of string, numeric, and hex byte opts:"
     
    12071204//usage:    IF_NOT_LONG_OPTS(
    12081205//usage:     "\n    -i IFACE    Interface to use (default eth0)"
     1206//usage:    IF_FEATURE_UDHCP_PORT(
     1207//usage:     "\n    -P PORT     Use PORT (default 68)"
     1208//usage:    )
     1209//usage:     "\n    -s PROG     Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")"
    12091210//usage:     "\n    -p FILE     Create pidfile"
    1210 //usage:     "\n    -s PROG     Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")"
    12111211//usage:     "\n    -B      Request broadcast replies"
    1212 //usage:     "\n    -t N        Send up to N discover packets"
    1213 //usage:     "\n    -T N        Pause between packets (default 3 seconds)"
    1214 //usage:     "\n    -A N        Wait N seconds (default 20) after failure"
     1212//usage:     "\n    -t N        Send up to N discover packets (default 3)"
     1213//usage:     "\n    -T SEC      Pause between packets (default 3)"
     1214//usage:     "\n    -A SEC      Wait if lease is not obtained (default 20)"
     1215//usage:     "\n    -n      Exit if lease is not obtained"
     1216//usage:     "\n    -q      Exit after obtaining lease"
     1217//usage:     "\n    -R      Release IP on exit"
    12151218//usage:     "\n    -f      Run in foreground"
    12161219//usage:    USE_FOR_MMU(
    12171220//usage:     "\n    -b      Background if lease is not obtained"
    12181221//usage:    )
    1219 //usage:     "\n    -n      Exit if lease is not obtained"
    1220 //usage:     "\n    -q      Exit after obtaining lease"
    1221 //usage:     "\n    -R      Release IP on exit"
    12221222//usage:     "\n    -S      Log to syslog too"
    1223 //usage:    IF_FEATURE_UDHCP_PORT(
    1224 //usage:     "\n    -P N        Use port N (default 68)"
     1223//usage:    IF_FEATURE_UDHCPC_ARPING(
     1224//usage:     "\n    -a[MSEC]    Validate offered address with ARP ping"
    12251225//usage:    )
    1226 //usage:    IF_FEATURE_UDHCPC_ARPING(
    1227 //usage:     "\n    -a      Use arping to validate offered address"
    1228 //usage:    )
     1226//usage:     "\n    -r IP       Request this IP address"
     1227//usage:     "\n    -o      Don't request any options (unless -O is given)"
    12291228//usage:     "\n    -O OPT      Request option OPT from server (cumulative)"
    1230 //usage:     "\n    -o      Don't request any options (unless -O is given)"
    1231 //usage:     "\n    -r IP       Request this IP address"
    12321229//usage:     "\n    -x OPT:VAL  Include option OPT in sent packets (cumulative)"
    12331230//usage:     "\n            Examples of string, numeric, and hex byte opts:"
     
    12501247int udhcpc_main(int argc UNUSED_PARAM, char **argv)
    12511248{
    1252     uint8_t *temp, *message;
     1249    uint8_t *message;
    12531250    const char *str_V, *str_h, *str_F, *str_r;
     1251    IF_FEATURE_UDHCPC_ARPING(const char *str_a = "2000";)
    12541252    IF_FEATURE_UDHCP_PORT(char *str_P;)
    12551253    void *clientid_mac_ptr;
     
    12661264    unsigned already_waited_sec;
    12671265    unsigned opt;
     1266    IF_FEATURE_UDHCPC_ARPING(unsigned arpping_ms;)
    12681267    int max_fd;
    12691268    int retval;
    12701269    fd_set rfds;
     1270
     1271    setup_common_bufsiz();
    12711272
    12721273    /* Default options */
     
    12831284    opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:fB"
    12841285        USE_FOR_MMU("b")
    1285         IF_FEATURE_UDHCPC_ARPING("a")
     1286        IF_FEATURE_UDHCPC_ARPING("a::")
    12861287        IF_FEATURE_UDHCP_PORT("P:")
    12871288        "v"
     
    12921293        , &list_O
    12931294        , &list_x
     1295        IF_FEATURE_UDHCPC_ARPING(, &str_a)
    12941296        IF_FEATURE_UDHCP_PORT(, &str_P)
    12951297        IF_UDHCP_VERBOSE(, &dhcp_verbose)
     
    13231325    }
    13241326#endif
     1327    IF_FEATURE_UDHCPC_ARPING(arpping_ms = xatou(str_a);)
    13251328    while (list_O) {
    13261329        char *optstr = llist_pop(&list_O);
     
    13951398    write_pidfile(client_config.pidfile);
    13961399    /* Goes to stdout (unless NOMMU) and possibly syslog */
    1397     bb_info_msg("%s (v"BB_VER") started", applet_name);
     1400    bb_error_msg("started, v"BB_VER);
    13981401    /* Set up the signal pipe */
    13991402    udhcp_sp_setup();
     
    14341437        /* If we already timed out, fall through with retval = 0, else... */
    14351438        if ((int)tv.tv_sec > 0) {
    1436             log1("Waiting on select %u seconds", (int)tv.tv_sec);
     1439            log1("waiting on select %u seconds", (int)tv.tv_sec);
    14371440            timestamp_before_wait = (unsigned)monotonic_sec();
    14381441            retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
     
    14851488#if BB_MMU /* -b is not supported on NOMMU */
    14861489                if (opt & OPT_b) { /* background if no lease */
    1487                     bb_info_msg("No lease, forking to background");
     1490                    bb_error_msg("no lease, forking to background");
    14881491                    client_background();
    14891492                    /* do not background again! */
     
    14921495#endif
    14931496                if (opt & OPT_n) { /* abort if no lease */
    1494                     bb_info_msg("No lease, failing");
     1497                    bb_error_msg("no lease, failing");
    14951498                    retval = 1;
    14961499                    goto ret;
     
    15011504                continue;
    15021505            case REQUESTING:
    1503                 if (!discover_retries || packet_num < discover_retries) {
     1506                if (packet_num < 3) {
    15041507                    /* send broadcast select packet */
    15051508                    send_select(xid, server_addr, requested_ip);
     
    15201523                client_config.first_secs = 0; /* make secs field count from 0 */
    15211524                change_listen_mode(LISTEN_KERNEL);
    1522                 log1("Entering renew state");
     1525                log1("entering renew state");
    15231526                /* fall right through */
    15241527            case RENEW_REQUESTED: /* manual (SIGUSR1) renew */
     
    15401543                }
    15411544                /* Timed out, enter rebinding state */
    1542                 log1("Entering rebinding state");
     1545                log1("entering rebinding state");
    15431546                state = REBINDING;
    15441547                /* fall right through */
     
    15551558                }
    15561559                /* Timed out, enter init state */
    1557                 bb_info_msg("Lease lost, entering init state");
     1560                bb_error_msg("lease lost, entering init state");
    15581561                udhcp_run_script(NULL, "deconfig");
    15591562                state = INIT_SELECTING;
     
    16031606            continue;
    16041607        case SIGTERM:
    1605             bb_info_msg("Received SIGTERM");
     1608            bb_error_msg("received %s", "SIGTERM");
    16061609            goto ret0;
    16071610        }
     
    16211624            if (len == -1) {
    16221625                /* Error is severe, reopen socket */
    1623                 bb_info_msg("Read error: %s, reopening socket", strerror(errno));
     1626                bb_error_msg("read error: %s, reopening socket", strerror(errno));
    16241627                sleep(discover_timeout); /* 3 seconds by default */
    16251628                change_listen_mode(listen_mode); /* just close and reopen */
     
    16581661            /* Must be a DHCPOFFER */
    16591662            if (*message == DHCPOFFER) {
     1663                uint8_t *temp;
     1664
    16601665/* What exactly is server's IP? There are several values.
    16611666 * Example DHCP offer captured with tchdump:
     
    16771682 * "Next server" and router are definitely wrong ones to use, though...
    16781683 */
     1684/* We used to ignore pcakets without DHCP_SERVER_ID.
     1685 * I've got user reports from people who run "address-less" servers.
     1686 * They either supply DHCP_SERVER_ID of 0.0.0.0 or don't supply it at all.
     1687 * They say ISC DHCP client supports this case.
     1688 */
     1689                server_addr = 0;
    16791690                temp = udhcp_get_option(&packet, DHCP_SERVER_ID);
    16801691                if (!temp) {
    1681                     bb_error_msg("no server ID, ignoring packet");
    1682                     continue;
    1683                     /* still selecting - this server looks bad */
     1692                    bb_error_msg("no server ID, using 0.0.0.0");
     1693                } else {
     1694                    /* it IS unaligned sometimes, don't "optimize" */
     1695                    move_from_unaligned32(server_addr, temp);
    16841696                }
    1685                 /* it IS unaligned sometimes, don't "optimize" */
    1686                 move_from_unaligned32(server_addr, temp);
    16871697                /*xid = packet.xid; - already is */
    16881698                requested_ip = packet.yiaddr;
     
    17001710        case REBINDING:
    17011711            if (*message == DHCPACK) {
     1712                unsigned start;
    17021713                uint32_t lease_seconds;
    17031714                struct in_addr temp_addr;
     1715                uint8_t *temp;
    17041716
    17051717                temp = udhcp_get_option(&packet, DHCP_LEASE_TIME);
     
    17321744                            (uint32_t) 0,
    17331745                            client_config.client_mac,
    1734                             client_config.interface)
     1746                            client_config.interface,
     1747                            arpping_ms)
    17351748                    ) {
    1736                         bb_info_msg("Offered address is in use "
     1749                        bb_error_msg("offered address is in use "
    17371750                            "(got ARP reply), declining");
    17381751                        send_decline(/*xid,*/ server_addr, packet.yiaddr);
     
    17521765#endif
    17531766                /* enter bound state */
    1754                 timeout = lease_seconds / 2;
    17551767                temp_addr.s_addr = packet.yiaddr;
    1756                 bb_info_msg("Lease of %s obtained, lease time %u",
     1768                bb_error_msg("lease of %s obtained, lease time %u",
    17571769                    inet_ntoa(temp_addr), (unsigned)lease_seconds);
    17581770                requested_ip = packet.yiaddr;
     1771
     1772                start = monotonic_sec();
    17591773                udhcp_run_script(&packet, state == REQUESTING ? "bound" : "renew");
     1774                already_waited_sec = (unsigned)monotonic_sec() - start;
     1775                timeout = lease_seconds / 2;
     1776                if ((unsigned)timeout < already_waited_sec) {
     1777                    /* Something went wrong. Back to discover state */
     1778                    timeout = already_waited_sec = 0;
     1779                }
    17601780
    17611781                state = BOUND;
     
    17751795                /* make future renew packets use different xid */
    17761796                /* xid = random_xid(); ...but why bother? */
    1777                 already_waited_sec = 0;
     1797
    17781798                continue; /* back to main loop */
    17791799            }
    17801800            if (*message == DHCPNAK) {
     1801                /* If network has more than one DHCP server,
     1802                 * "wrong" server can reply first, with a NAK.
     1803                 * Do not interpret it as a NAK from "our" server.
     1804                 */
     1805                if (server_addr != 0) {
     1806                    uint32_t svid;
     1807                    uint8_t *temp;
     1808
     1809                    temp = udhcp_get_option(&packet, DHCP_SERVER_ID);
     1810                    if (!temp) {
     1811 non_matching_svid:
     1812                        log1("%s with wrong server ID, ignoring packet",
     1813                            "Received DHCP NAK"
     1814                        );
     1815                        continue;
     1816                    }
     1817                    move_from_unaligned32(svid, temp);
     1818                    if (svid != server_addr)
     1819                        goto non_matching_svid;
     1820                }
    17811821                /* return to init state */
    1782                 bb_info_msg("Received DHCP NAK");
     1822                bb_error_msg("received %s", "DHCP NAK");
    17831823                udhcp_run_script(&packet, "nak");
    17841824                if (state != REQUESTING)
  • branches/3.3/mindi-busybox/networking/udhcp/dhcpc.h

    r3232 r3621  
    3030
    3131#if ENABLE_FEATURE_UDHCP_PORT
    32 #define CLIENT_PORT (client_config.port)
     32#define CLIENT_PORT  (client_config.port)
     33#define CLIENT_PORT6 (client_config.port)
    3334#else
    34 #define CLIENT_PORT 68
     35#define CLIENT_PORT  68
     36#define CLIENT_PORT6 546
    3537#endif
    3638
  • branches/3.3/mindi-busybox/networking/udhcp/dhcpd.c

    r3232 r3621  
    2323
    2424//usage:#define udhcpd_trivial_usage
    25 //usage:       "[-fS]" IF_FEATURE_UDHCP_PORT(" [-P N]") " [CONFFILE]"
     25//usage:       "[-fS] [-I ADDR]" IF_FEATURE_UDHCP_PORT(" [-P N]") " [CONFFILE]"
    2626//usage:#define udhcpd_full_usage "\n\n"
    2727//usage:       "DHCP server\n"
    2828//usage:     "\n    -f  Run in foreground"
    2929//usage:     "\n    -S  Log to syslog too"
     30//usage:     "\n    -I ADDR Local address"
     31//usage:     "\n    -a MSEC Timeout for ARP ping (default 2000)"
    3032//usage:    IF_FEATURE_UDHCP_PORT(
    3133//usage:     "\n    -P N    Use port N (default 67)"
     
    6062     || dhcp_pkt->ciaddr == 0
    6163    ) {
    62         log1("Broadcasting packet to client");
     64        log1("broadcasting packet to client");
    6365        ciaddr = INADDR_BROADCAST;
    6466        chaddr = MAC_BCAST_ADDR;
    6567    } else {
    66         log1("Unicasting packet to client ciaddr");
     68        log1("unicasting packet to client ciaddr");
    6769        ciaddr = dhcp_pkt->ciaddr;
    6870        chaddr = dhcp_pkt->chaddr;
     
    7880static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt)
    7981{
    80     log1("Forwarding packet to relay");
     82    log1("forwarding packet to relay");
    8183
    8284    udhcp_send_kernel_packet(dhcp_pkt,
     
    148150        uint32_t static_lease_nip,
    149151        struct dyn_lease *lease,
    150         uint8_t *requested_ip_opt)
     152        uint8_t *requested_ip_opt,
     153        unsigned arpping_ms)
    151154{
    152155    struct dhcp_packet packet;
     
    187190        else {
    188191            /* Otherwise, find a free IP */
    189             packet.yiaddr = find_free_or_expired_nip(oldpacket->chaddr);
     192            packet.yiaddr = find_free_or_expired_nip(oldpacket->chaddr, arpping_ms);
    190193        }
    191194
     
    212215
    213216    addr.s_addr = packet.yiaddr;
    214     bb_info_msg("Sending OFFER of %s", inet_ntoa(addr));
     217    bb_error_msg("sending OFFER of %s", inet_ntoa(addr));
    215218    /* send_packet emits error message itself if it detects failure */
    216219    send_packet(&packet, /*force_bcast:*/ 0);
     
    224227    init_packet(&packet, oldpacket, DHCPNAK);
    225228
    226     log1("Sending NAK");
     229    log1("sending %s", "NAK");
    227230    send_packet(&packet, /*force_bcast:*/ 1);
    228231}
     
    245248
    246249    addr.s_addr = yiaddr;
    247     bb_info_msg("Sending ACK to %s", inet_ntoa(addr));
     250    bb_error_msg("sending ACK to %s", inet_ntoa(addr));
    248251    send_packet(&packet, /*force_bcast:*/ 0);
    249252
     
    303306    unsigned opt;
    304307    struct option_set *option;
     308    char *str_I = str_I;
     309    const char *str_a = "2000";
     310    unsigned arpping_ms;
    305311    IF_FEATURE_UDHCP_PORT(char *str_P;)
    306312
    307 #if ENABLE_FEATURE_UDHCP_PORT
    308     SERVER_PORT = 67;
    309     CLIENT_PORT = 68;
    310 #endif
     313    setup_common_bufsiz();
     314
     315    IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;)
     316    IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;)
    311317
    312318#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
    313319    opt_complementary = "vv";
    314320#endif
    315     opt = getopt32(argv, "fSv"
    316         IF_FEATURE_UDHCP_PORT("P:", &str_P)
     321    opt = getopt32(argv, "fSI:va:"
     322        IF_FEATURE_UDHCP_PORT("P:")
     323        , &str_I
     324        , &str_a
     325        IF_FEATURE_UDHCP_PORT(, &str_P)
    317326        IF_UDHCP_VERBOSE(, &dhcp_verbose)
    318327        );
     
    327336        logmode |= LOGMODE_SYSLOG;
    328337    }
     338    if (opt & 4) { /* -I */
     339        len_and_sockaddr *lsa = xhost_and_af2sockaddr(str_I, 0, AF_INET);
     340        server_config.server_nip = lsa->u.sin.sin_addr.s_addr;
     341        free(lsa);
     342    }
    329343#if ENABLE_FEATURE_UDHCP_PORT
    330     if (opt & 8) { /* -P */
     344    if (opt & 32) { /* -P */
    331345        SERVER_PORT = xatou16(str_P);
    332346        CLIENT_PORT = SERVER_PORT + 1;
    333347    }
    334348#endif
     349    arpping_ms = xatou(str_a);
     350
    335351    /* Would rather not do read_config before daemonization -
    336352     * otherwise NOMMU machines will parse config twice */
     
    346362    /* if (!..) bb_perror_msg("can't create pidfile %s", pidfile); */
    347363
    348     bb_info_msg("%s (v"BB_VER") started", applet_name);
     364    bb_error_msg("started, v"BB_VER);
    349365
    350366    option = udhcp_find_option(server_config.options, DHCP_LEASE_TIME);
     
    368384    if (udhcp_read_interface(server_config.interface,
    369385            &server_config.ifindex,
    370             &server_config.server_nip,
     386            (server_config.server_nip == 0 ? &server_config.server_nip : NULL),
    371387            server_config.server_mac)
    372388    ) {
     
    398414        max_sock = udhcp_sp_fd_set(&rfds, server_socket);
    399415        if (server_config.auto_time) {
    400             tv.tv_sec = timeout_end - monotonic_sec();
     416            /* cast to signed is essential if tv_sec is wider than int */
     417            tv.tv_sec = (int)(timeout_end - monotonic_sec());
    401418            tv.tv_usec = 0;
    402419        }
     
    411428        }
    412429        if (retval < 0 && errno != EINTR) {
    413             log1("Error on select");
     430            log1("error on select");
    414431            continue;
    415432        }
     
    417434        switch (udhcp_sp_read(&rfds)) {
    418435        case SIGUSR1:
    419             bb_info_msg("Received SIGUSR1");
     436            bb_error_msg("received %s", "SIGUSR1");
    420437            write_leases();
    421438            /* why not just reset the timeout, eh */
    422439            goto continue_with_autotime;
    423440        case SIGTERM:
    424             bb_info_msg("Received SIGTERM");
     441            bb_error_msg("received %s", "SIGTERM");
    425442            write_leases();
    426443            goto ret0;
     
    435452            /* bytes can also be -2 ("bad packet data") */
    436453            if (bytes == -1 && errno != EINTR) {
    437                 log1("Read error: %s, reopening socket", strerror(errno));
     454                log1("read error: %s, reopening socket", strerror(errno));
    438455                close(server_socket);
    439456                server_socket = -1;
     
    470487        static_lease_nip = get_static_nip_by_mac(server_config.static_leases, &packet.chaddr);
    471488        if (static_lease_nip) {
    472             bb_info_msg("Found static lease: %x", static_lease_nip);
     489            bb_error_msg("found static lease: %x", static_lease_nip);
    473490            memcpy(&fake_lease.lease_mac, &packet.chaddr, 6);
    474491            fake_lease.lease_nip = static_lease_nip;
     
    488505
    489506        case DHCPDISCOVER:
    490             log1("Received DISCOVER");
    491 
    492             send_offer(&packet, static_lease_nip, lease, requested_ip_opt);
     507            log1("received %s", "DISCOVER");
     508
     509            send_offer(&packet, static_lease_nip, lease, requested_ip_opt, arpping_ms);
    493510            break;
    494511
    495512        case DHCPREQUEST:
    496             log1("Received REQUEST");
     513            log1("received %s", "REQUEST");
    497514/* RFC 2131:
    498515
     
    619636             * ciaddr must be 0 (we do not check this)
    620637             */
    621             log1("Received DECLINE");
     638            log1("received %s", "DECLINE");
    622639            if (server_id_opt
    623640             && requested_ip_opt
     
    639656             * ciaddr must be filled in
    640657             */
    641             log1("Received RELEASE");
     658            log1("received %s", "RELEASE");
    642659            if (server_id_opt
    643660             && lease  /* chaddr matches this lease */
     
    649666
    650667        case DHCPINFORM:
    651             log1("Received INFORM");
     668            log1("received %s", "INFORM");
    652669            send_inform(&packet);
    653670            break;
  • branches/3.3/mindi-busybox/networking/udhcp/dhcpd.h

    r2725 r3621  
    5858} FIX_ALIASING;
    5959
    60 #define server_config (*(struct server_config_t*)&bb_common_bufsiz1)
     60#define server_config (*(struct server_config_t*)bb_common_bufsiz1)
    6161/* client_config sits in 2nd half of bb_common_bufsiz1 */
    6262
    6363#if ENABLE_FEATURE_UDHCP_PORT
    64 #define SERVER_PORT (server_config.port)
     64#define SERVER_PORT  (server_config.port)
     65#define SERVER_PORT6 (server_config.port)
    6566#else
    66 #define SERVER_PORT 67
     67#define SERVER_PORT  67
     68#define SERVER_PORT6 547
    6769#endif
    6870
     
    99101struct dyn_lease *find_lease_by_mac(const uint8_t *mac) FAST_FUNC;
    100102struct dyn_lease *find_lease_by_nip(uint32_t nip) FAST_FUNC;
    101 uint32_t find_free_or_expired_nip(const uint8_t *safe_mac) FAST_FUNC;
     103uint32_t find_free_or_expired_nip(const uint8_t *safe_mac, unsigned arpping_ms) FAST_FUNC;
    102104
    103105
  • branches/3.3/mindi-busybox/networking/udhcp/dhcprelay.c

    r3232 r3621  
    3434} FIX_ALIASING;
    3535
    36 #define dhcprelay_xid_list (*(struct xid_item*)&bb_common_bufsiz1)
     36#define dhcprelay_xid_list (*(struct xid_item*)bb_common_bufsiz1)
     37#define INIT_G() do { setup_common_bufsiz(); } while (0)
    3738
    3839static struct xid_item *xid_add(uint32_t xid, struct sockaddr_in *ip, int client)
     
    257258    int num_sockets, max_socket;
    258259    uint32_t our_nip;
     260
     261    INIT_G();
    259262
    260263    server_addr.sin_family = AF_INET;
  • branches/3.3/mindi-busybox/networking/udhcp/domain_codec.c

    r2725 r3621  
    88 */
    99#ifdef DNS_COMPR_TESTING
     10# define _GNU_SOURCE
    1011# define FAST_FUNC /* nothing */
    1112# define xmalloc malloc
     
    4344    while (1) {
    4445        /* note: "return NULL" below are leak-safe since
    45          * dst isn't yet allocated */
     46         * dst isn't allocated yet */
    4647        const uint8_t *c;
    4748        unsigned crtpos, retpos, depth, len;
     
    6465                    return NULL;
    6566                if (dst)
    66                     memcpy(dst + len, c + 1, *c);
     67                    /* \3com ---> "com." */
     68                    ((char*)mempcpy(dst + len, c + 1, *c))[0] = '.';
    6769                len += *c + 1;
    6870                crtpos += *c + 1;
    69                 if (dst)
    70                     dst[len - 1] = '.';
    7171            } else {
    7272                /* NUL: end of current domain name */
     
    7979                    retpos = depth = 0;
    8080                }
    81                 if (dst)
     81                if (dst && len != 0)
     82                    /* \4host\3com\0\4host and we are at \0:
     83                     * \3com was converted to "com.", change dot to space.
     84                     */
    8285                    dst[len - 1] = ' ';
    8386            }
     
    9699            /* allocate dst buffer and copy pre */
    97100            unsigned plen = strlen(pre);
    98             ret = dst = xmalloc(plen + len);
    99             memcpy(dst, pre, plen);
    100             dst += plen;
     101            ret = xmalloc(plen + len);
     102            dst = stpcpy(ret, pre);
    101103        } else {
    102104            dst[len - 1] = '\0';
     
    229231    uint8_t *encoded;
    230232
     233        uint8_t str[6] = { 0x00, 0x00, 0x02, 0x65, 0x65, 0x00 };
     234        printf("NUL:'%s'\n",   dname_dec(str, 6, ""));
     235
    231236#define DNAME_DEC(encoded,pre) dname_dec((uint8_t*)(encoded), sizeof(encoded), (pre))
    232237    printf("'%s'\n",       DNAME_DEC("\4host\3com\0", "test1:"));
  • branches/3.3/mindi-busybox/networking/udhcp/dumpleases.c

    r3232 r3621  
    55
    66//usage:#define dumpleases_trivial_usage
    7 //usage:       "[-r|-a] [-f LEASEFILE]"
     7//usage:       "[-r|-a] [-d] [-f LEASEFILE]"
    88//usage:#define dumpleases_full_usage "\n\n"
    99//usage:       "Display DHCP leases granted by udhcpd\n"
     
    1212//usage:     "\n    -r,--remaining  Show remaining time"
    1313//usage:     "\n    -a,--absolute   Show expiration time"
     14//usage:     "\n    -d,--decimal    Show time in seconds"
    1415//usage:    )
    1516//usage:    IF_NOT_LONG_OPTS(
     
    1718//usage:     "\n    -r  Show remaining time"
    1819//usage:     "\n    -a  Show expiration time"
     20//usage:     "\n    -d  Show time in seconds"
    1921//usage:    )
    2022
     
    2931    int i;
    3032    unsigned opt;
    31     int64_t written_at, curr, expires_abs;
     33    int64_t written_at, curr;
    3234    const char *file = LEASES_FILE;
    3335    struct dyn_lease lease;
    34     struct in_addr addr;
    3536
    3637    enum {
     
    3839        OPT_r = 0x2, // -r
    3940        OPT_f = 0x4, // -f
     41        OPT_d = 0x8, // -d
    4042    };
    4143#if ENABLE_LONG_OPTS
     
    4446        "remaining\0" No_argument       "r"
    4547        "file\0"      Required_argument "f"
     48        "decimal\0"   No_argument       "d"
    4649        ;
    4750
     
    5154
    5255    opt_complementary = "=0:a--r:r--a";
    53     opt = getopt32(argv, "arf:", &file);
     56    opt = getopt32(argv, "arf:d", &file);
    5457
    5558    fd = xopen(file, O_RDONLY);
    5659
    57     printf("Mac Address       IP Address      Host Name           Expires %s\n", (opt & OPT_a) ? "at" : "in");
     60    /*     "123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 */
    5861    /*     "00:00:00:00:00:00 255.255.255.255 ABCDEFGHIJKLMNOPQRS Wed Jun 30 21:49:08 1993" */
    59     /*     "123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 */
     62    printf("Mac %-14s"       "IP %-13s"      "Host %-15s"        "Expires %s\n",
     63        "Address", "Address", "Name",
     64        (opt & OPT_a) ? "at" : "in"
     65    );
    6066
    6167    xread(fd, &written_at, sizeof(written_at));
     
    6672
    6773    while (full_read(fd, &lease, sizeof(lease)) == sizeof(lease)) {
     74        struct in_addr addr;
     75        int64_t expires_abs;
     76
    6877        const char *fmt = ":%02x" + 1;
    6978        for (i = 0; i < 6; i++) {
     
    8897            continue;
    8998        }
     99        if (opt & OPT_d) {
     100            /* -d: decimal time */
     101            if (!(opt & OPT_a))
     102                expires_abs -= curr;
     103            printf("%llu\n", (unsigned long long) expires_abs);
     104            continue;
     105        }
    90106        if (!(opt & OPT_a)) { /* no -a */
    91107            unsigned d, h, m;
  • branches/3.3/mindi-busybox/networking/udhcp/files.c

    r3232 r3621  
    5858    const char *keyword;
    5959    int (*handler)(const char *line, void *var) FAST_FUNC;
    60     void *var;
     60    unsigned ofs;
    6161    const char *def;
    6262};
    6363
     64#define OFS(field) offsetof(struct server_config_t, field)
     65
    6466static const struct config_keyword keywords[] = {
    6567    /* keyword        handler           variable address               default */
    66     {"start"        , udhcp_str2nip   , &server_config.start_ip     , "192.168.0.20"},
    67     {"end"          , udhcp_str2nip   , &server_config.end_ip       , "192.168.0.254"},
    68     {"interface"    , read_str        , &server_config.interface    , "eth0"},
     68    {"start"        , udhcp_str2nip   , OFS(start_ip     ), "192.168.0.20"},
     69    {"end"          , udhcp_str2nip   , OFS(end_ip       ), "192.168.0.254"},
     70    {"interface"    , read_str        , OFS(interface    ), "eth0"},
    6971    /* Avoid "max_leases value not sane" warning by setting default
    7072     * to default_end_ip - default_start_ip + 1: */
    71     {"max_leases"   , read_u32        , &server_config.max_leases   , "235"},
    72     {"auto_time"    , read_u32        , &server_config.auto_time    , "7200"},
    73     {"decline_time" , read_u32        , &server_config.decline_time , "3600"},
    74     {"conflict_time", read_u32        , &server_config.conflict_time, "3600"},
    75     {"offer_time"   , read_u32        , &server_config.offer_time   , "60"},
    76     {"min_lease"    , read_u32        , &server_config.min_lease_sec, "60"},
    77     {"lease_file"   , read_str        , &server_config.lease_file   , LEASES_FILE},
    78     {"pidfile"      , read_str        , &server_config.pidfile      , "/var/run/udhcpd.pid"},
    79     {"siaddr"       , udhcp_str2nip   , &server_config.siaddr_nip   , "0.0.0.0"},
     73    {"max_leases"   , read_u32        , OFS(max_leases   ), "235"},
     74    {"auto_time"    , read_u32        , OFS(auto_time    ), "7200"},
     75    {"decline_time" , read_u32        , OFS(decline_time ), "3600"},
     76    {"conflict_time", read_u32        , OFS(conflict_time), "3600"},
     77    {"offer_time"   , read_u32        , OFS(offer_time   ), "60"},
     78    {"min_lease"    , read_u32        , OFS(min_lease_sec), "60"},
     79    {"lease_file"   , read_str        , OFS(lease_file   ), LEASES_FILE},
     80    {"pidfile"      , read_str        , OFS(pidfile      ), "/var/run/udhcpd.pid"},
     81    {"siaddr"       , udhcp_str2nip   , OFS(siaddr_nip   ), "0.0.0.0"},
    8082    /* keywords with no defaults must be last! */
    81     {"option"       , udhcp_str2optset, &server_config.options      , ""},
    82     {"opt"          , udhcp_str2optset, &server_config.options      , ""},
    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},
    86     {"static_lease" , read_staticlease, &server_config.static_leases, ""},
     83    {"option"       , udhcp_str2optset, OFS(options      ), ""},
     84    {"opt"          , udhcp_str2optset, OFS(options      ), ""},
     85    {"notify_file"  , read_str        , OFS(notify_file  ), NULL},
     86    {"sname"        , read_str        , OFS(sname        ), NULL},
     87    {"boot_file"    , read_str        , OFS(boot_file    ), NULL},
     88    {"static_lease" , read_staticlease, OFS(static_leases), ""},
    8789};
    8890enum { KWS_WITH_DEFAULTS = ARRAY_SIZE(keywords) - 6 };
     
    9698
    9799    for (i = 0; i < KWS_WITH_DEFAULTS; i++)
    98         keywords[i].handler(keywords[i].def, keywords[i].var);
     100        keywords[i].handler(keywords[i].def, (char*)&server_config + keywords[i].ofs);
    99101
    100102    parser = config_open(file);
     
    102104        for (k = keywords, i = 0; i < ARRAY_SIZE(keywords); k++, i++) {
    103105            if (strcasecmp(token[0], k->keyword) == 0) {
    104                 if (!k->handler(token[1], k->var)) {
     106                if (!k->handler(token[1], (char*)&server_config + k->ofs)) {
    105107                    bb_error_msg("can't parse line %u in %s",
    106108                            parser->lineno, file);
    107109                    /* reset back to the default value */
    108                     k->handler(k->def, k->var);
     110                    k->handler(k->def, (char*)&server_config + k->ofs);
    109111                }
    110112                break;
     
    190192
    191193    while (full_read(fd, &lease, sizeof(lease)) == sizeof(lease)) {
    192 //FIXME: what if it matches some static lease?
    193194        uint32_t y = ntohl(lease.lease_nip);
    194195        if (y >= server_config.start_ip && y <= server_config.end_ip) {
    195196            signed_leasetime_t expires = ntohl(lease.expires) - (signed_leasetime_t)time_passed;
     197            uint32_t static_nip;
     198
    196199            if (expires <= 0)
     200                /* We keep expired leases: add_lease() will add
     201                 * a lease with 0 seconds remaining.
     202                 * Fewer IP address changes this way for mass reboot scenario.
     203                 */
     204                expires = 0;
     205
     206            /* Check if there is a different static lease for this IP or MAC */
     207            static_nip = get_static_nip_by_mac(server_config.static_leases, lease.lease_mac);
     208            if (static_nip) {
     209                /* NB: we do not add lease even if static_nip == lease.lease_nip.
     210                 */
    197211                continue;
     212            }
     213            if (is_nip_reserved(server_config.static_leases, lease.lease_nip))
     214                continue;
     215
    198216            /* NB: add_lease takes "relative time", IOW,
    199217             * lease duration, not lease deadline. */
     
    211229        }
    212230    }
    213     log1("Read %d leases", i);
     231    log1("read %d leases", i);
    214232 ret:
    215233    close(fd);
  • branches/3.3/mindi-busybox/networking/udhcp/leases.c

    r3232 r3621  
    1818     * and therefore can't ever match */
    1919    for (i = 0; i < server_config.max_leases; i++) {
    20         if (g_leases[i].expires < oldest_time) {
     20        if (g_leases[i].expires == 0 /* empty entry */
     21         || g_leases[i].expires < oldest_time
     22        ) {
    2123            oldest_time = g_leases[i].expires;
    2224            oldest_lease = &g_leases[i];
     
    6668                hostname_len = sizeof(oldest->hostname);
    6769            p = safe_strncpy(oldest->hostname, hostname, hostname_len);
    68             /* sanitization (s/non-ASCII/^/g) */
     70            /*
     71             * Sanitization (s/bad_char/./g).
     72             * The intent is not to allow only "DNS-valid" hostnames,
     73             * but merely make dumpleases output safe for shells to use.
     74             * We accept "0-9A-Za-z._-", all other chars turn to dots.
     75             */
    6976            while (*p) {
    70                 if (*p < ' ' || *p > 126)
    71                     *p = '^';
     77                if (!isalnum(*p) && *p != '-' && *p != '_')
     78                    *p = '.';
    7279                p++;
    7380            }
     
    113120
    114121/* Check if the IP is taken; if it is, add it to the lease table */
    115 static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac)
     122static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac, unsigned arpping_ms)
    116123{
    117124    struct in_addr temp;
     
    121128            server_config.server_nip,
    122129            server_config.server_mac,
    123             server_config.interface);
     130            server_config.interface,
     131            arpping_ms);
    124132    if (r)
    125133        return r;
    126134
    127135    temp.s_addr = nip;
    128     bb_info_msg("%s belongs to someone, reserving it for %u seconds",
     136    bb_error_msg("%s belongs to someone, reserving it for %u seconds",
    129137        inet_ntoa(temp), (unsigned)server_config.conflict_time);
    130138    add_lease(NULL, nip, server_config.conflict_time, NULL, 0);
     
    133141
    134142/* Find a new usable (we think) address */
    135 uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac)
     143uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac, unsigned arpping_ms)
    136144{
    137145    uint32_t addr;
     
    178186        if (!lease) {
    179187//TODO: DHCP servers do not always sit on the same subnet as clients: should *ping*, not arp-ping!
    180             if (nobody_responds_to_arp(nip, safe_mac))
     188            if (nobody_responds_to_arp(nip, safe_mac, arpping_ms))
    181189                return nip;
    182190        } else {
     
    195203    if (oldest_lease
    196204     && is_expired_lease(oldest_lease)
    197      && nobody_responds_to_arp(oldest_lease->lease_nip, safe_mac)
     205     && nobody_responds_to_arp(oldest_lease->lease_nip, safe_mac, arpping_ms)
    198206    ) {
    199207        return oldest_lease->lease_nip;
  • branches/3.3/mindi-busybox/networking/udhcp/packet.c

    r3232 r3621  
    3939        return;
    4040
    41     bb_info_msg(
    42         //" op %x"
     41    bb_error_msg(
     42        //"op %x"
    4343        //" htype %x"
    4444        " hlen %x"
     
    7474    );
    7575    *bin2hex(buf, (void *) packet->chaddr, sizeof(packet->chaddr)) = '\0';
    76     bb_info_msg(" chaddr %s", buf);
     76    bb_error_msg("chaddr %s", buf);
    7777}
    7878#endif
     
    8686    bytes = safe_read(fd, packet, sizeof(*packet));
    8787    if (bytes < 0) {
    88         log1("Packet read error, ignoring");
     88        log1("packet read error, ignoring");
    8989        return bytes; /* returns -1 */
    9090    }
     
    9393     || packet->cookie != htonl(DHCP_MAGIC)
    9494    ) {
    95         bb_info_msg("Packet with bad magic, ignoring");
     95        bb_error_msg("packet with bad magic, ignoring");
    9696        return -2;
    9797    }
    98     log1("Received a packet");
     98    log1("received %s", "a packet");
    9999    udhcp_dump_packet(packet);
    100100
     
    144144     * In order to work with those buggy servers,
    145145     * we truncate packets after end option byte.
     146     *
     147     * However, RFC 1542 says "The IP Total Length and UDP Length
     148     * must be large enough to contain the minimal BOOTP header of 300 octets".
     149     * Thus, we retain enough padding to not go below 300 BOOTP bytes.
     150     * Some devices have filters which drop DHCP packets shorter than that.
    146151     */
    147152    padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(packet.data.options);
     153    if (padding > DHCP_SIZE - 300)
     154        padding = DHCP_SIZE - 300;
    148155
    149156    packet.ip.protocol = IPPROTO_UDP;
     
    216223    udhcp_dump_packet(dhcp_pkt);
    217224    padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(dhcp_pkt->options);
     225    if (padding > DHCP_SIZE - 300)
     226        padding = DHCP_SIZE - 300;
    218227    result = safe_write(fd, dhcp_pkt, DHCP_SIZE - padding);
    219228    msg = "write";
  • branches/3.3/mindi-busybox/networking/udhcp/socket.c

    r3232 r3621  
    5757            return -1;
    5858        }
    59         log1("Adapter index %d", ifr->ifr_ifindex);
     59        log1("adapter index %d", ifr->ifr_ifindex);
    6060        *ifindex = ifr->ifr_ifindex;
    6161    }
     
    8383    char *colon;
    8484
    85     log1("Opening listen socket on *:%d %s", port, inf);
     85    log1("opening listen socket on *:%d %s", port, inf);
    8686    fd = xsocket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
    8787
  • branches/3.3/mindi-busybox/networking/udhcp/static_leases.c

    r2725 r3621  
    6767    cur = *st_lease_pp;
    6868    while (cur) {
    69         bb_info_msg("static lease: mac:%02x:%02x:%02x:%02x:%02x:%02x nip:%x",
     69        bb_error_msg("static lease: mac:%02x:%02x:%02x:%02x:%02x:%02x nip:%x",
    7070            cur->mac[0], cur->mac[1], cur->mac[2],
    7171            cur->mac[3], cur->mac[4], cur->mac[5],
  • branches/3.3/mindi-busybox/networking/wget.c

    r3232 r3621  
    1010 */
    1111
     12//config:config WGET
     13//config:   bool "wget"
     14//config:   default y
     15//config:   help
     16//config:     wget is a utility for non-interactive download of files from HTTP
     17//config:     and FTP servers.
     18//config:
     19//config:config FEATURE_WGET_STATUSBAR
     20//config:   bool "Enable a nifty process meter (+2k)"
     21//config:   default y
     22//config:   depends on WGET
     23//config:   help
     24//config:     Enable the transfer progress bar for wget transfers.
     25//config:
     26//config:config FEATURE_WGET_AUTHENTICATION
     27//config:   bool "Enable HTTP authentication"
     28//config:   default y
     29//config:   depends on WGET
     30//config:   help
     31//config:     Support authenticated HTTP transfers.
     32//config:
     33//config:config FEATURE_WGET_LONG_OPTIONS
     34//config:   bool "Enable long options"
     35//config:   default y
     36//config:   depends on WGET && LONG_OPTS
     37//config:   help
     38//config:     Support long options for the wget applet.
     39//config:
     40//config:config FEATURE_WGET_TIMEOUT
     41//config:   bool "Enable timeout option -T SEC"
     42//config:   default y
     43//config:   depends on WGET
     44//config:   help
     45//config:     Supports network read and connect timeouts for wget,
     46//config:     so that wget will give up and timeout, through the -T
     47//config:     command line option.
     48//config:
     49//config:     Currently only connect and network data read timeout are
     50//config:     supported (i.e., timeout is not applied to the DNS query). When
     51//config:     FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option
     52//config:     will work in addition to -T.
     53//config:
     54//config:config FEATURE_WGET_OPENSSL
     55//config:   bool "Try to connect to HTTPS using openssl"
     56//config:   default y
     57//config:   depends on WGET
     58//config:   help
     59//config:     Choose how wget establishes SSL connection for https:// URLs.
     60//config:
     61//config:     Busybox itself contains no SSL code. wget will spawn
     62//config:     a helper program to talk over HTTPS.
     63//config:
     64//config:     OpenSSL has a simple SSL client for debug purposes.
     65//config:     If you select "openssl" helper, wget will effectively call
     66//config:     "openssl s_client -quiet -connect IP:443 2>/dev/null"
     67//config:     and pipe its data through it.
     68//config:     Note inconvenient API: host resolution is done twice,
     69//config:     and there is no guarantee openssl's idea of IPv6 address
     70//config:     format is the same as ours.
     71//config:     Another problem is that s_client prints debug information
     72//config:     to stderr, and it needs to be suppressed. This means
     73//config:     all error messages get suppressed too.
     74//config:     openssl is also a big binary, often dynamically linked
     75//config:     against ~15 libraries.
     76//config:
     77//config:config FEATURE_WGET_SSL_HELPER
     78//config:   bool "Try to connect to HTTPS using ssl_helper"
     79//config:   default y
     80//config:   depends on WGET
     81//config:   help
     82//config:     Choose how wget establishes SSL connection for https:// URLs.
     83//config:
     84//config:     Busybox itself contains no SSL code. wget will spawn
     85//config:     a helper program to talk over HTTPS.
     86//config:
     87//config:     ssl_helper is a tool which can be built statically
     88//config:     from busybox sources against a small embedded SSL library.
     89//config:     Please see networking/ssl_helper/README.
     90//config:     It does not require double host resolution and emits
     91//config:     error messages to stderr.
     92//config:
     93//config:     Precompiled static binary may be available at
     94//config:     http://busybox.net/downloads/binaries/
     95
     96//applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP))
     97
     98//kbuild:lib-$(CONFIG_WGET) += wget.o
     99
    12100//usage:#define wget_trivial_usage
    13101//usage:    IF_FEATURE_WGET_LONG_OPTIONS(
     
    15103//usage:       "    [--header 'header: value'] [-Y|--proxy on/off] [-P DIR]\n"
    16104/* Since we ignore these opts, we don't show them in --help */
    17 /* //usage:    "    [--no-check-certificate] [--no-cache]" */
     105/* //usage:    "    [--no-check-certificate] [--no-cache] [--passive-ftp] [-t TRIES]" */
     106/* //usage:    "    [-nv] [-nc] [-nH] [-np]" */
    18107//usage:       "    [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
    19108//usage:    )
     
    39128#if 0
    40129# define log_io(...) bb_error_msg(__VA_ARGS__)
     130# define SENDFMT(fp, fmt, ...) \
     131    do { \
     132        log_io("> " fmt, ##__VA_ARGS__); \
     133        fprintf(fp, fmt, ##__VA_ARGS__); \
     134    } while (0);
    41135#else
    42136# define log_io(...) ((void)0)
     137# define SENDFMT(fp, fmt, ...) fprintf(fp, fmt, ##__VA_ARGS__)
    43138#endif
    44139
     
    47142    char *allocated;
    48143    const char *path;
    49     const char *user;
     144    char       *user;
     145    const char *protocol;
    50146    char       *host;
    51147    int         port;
    52     smallint    is_ftp;
    53148};
    54 
     149static const char P_FTP[] ALIGN1 = "ftp";
     150static const char P_HTTP[] ALIGN1 = "http";
     151#if ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER
     152static const char P_HTTPS[] ALIGN1 = "https";
     153#endif
     154
     155#if ENABLE_FEATURE_WGET_LONG_OPTIONS
     156/* User-specified headers prevent using our corresponding built-in headers.  */
     157enum {
     158    HDR_HOST          = (1<<0),
     159    HDR_USER_AGENT    = (1<<1),
     160    HDR_RANGE         = (1<<2),
     161    HDR_AUTH          = (1<<3) * ENABLE_FEATURE_WGET_AUTHENTICATION,
     162    HDR_PROXY_AUTH    = (1<<4) * ENABLE_FEATURE_WGET_AUTHENTICATION,
     163};
     164static const char wget_user_headers[] ALIGN1 =
     165    "Host:\0"
     166    "User-Agent:\0"
     167    "Range:\0"
     168# if ENABLE_FEATURE_WGET_AUTHENTICATION
     169    "Authorization:\0"
     170    "Proxy-Authorization:\0"
     171# endif
     172    ;
     173# define USR_HEADER_HOST       (G.user_headers & HDR_HOST)
     174# define USR_HEADER_USER_AGENT (G.user_headers & HDR_USER_AGENT)
     175# define USR_HEADER_RANGE      (G.user_headers & HDR_RANGE)
     176# define USR_HEADER_AUTH       (G.user_headers & HDR_AUTH)
     177# define USR_HEADER_PROXY_AUTH (G.user_headers & HDR_PROXY_AUTH)
     178#else /* No long options, no user-headers :( */
     179# define USR_HEADER_HOST       0
     180# define USR_HEADER_USER_AGENT 0
     181# define USR_HEADER_RANGE      0
     182# define USR_HEADER_AUTH       0
     183# define USR_HEADER_PROXY_AUTH 0
     184#endif
    55185
    56186/* Globals */
     
    63193    bb_progress_t pmt;
    64194#endif
    65         char *dir_prefix;
     195    char *dir_prefix;
    66196#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 */
     197    char *post_data;
     198    char *extra_headers;
     199    unsigned char user_headers; /* Headers mentioned by the user */
     200#endif
     201    char *fname_out;        /* where to direct output (-O) */
     202    const char *proxy_flag; /* Use proxies if env vars are set */
     203    const char *user_agent; /* "User-Agent" header field */
    73204#if ENABLE_FEATURE_WGET_TIMEOUT
    74205    unsigned timeout_seconds;
     206    bool die_if_timed_out;
    75207#endif
    76208    int output_fd;
     
    87219#define G (*ptr_to_globals)
    88220#define INIT_G() do { \
    89         SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
    90     IF_FEATURE_WGET_TIMEOUT(G.timeout_seconds = 900;) \
     221    SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
     222} while (0)
     223#define FINI_G() do { \
     224    FREE_PTR_TO_GLOBALS(); \
    91225} while (0)
    92226
     
    196330}
    197331
     332#if ENABLE_FEATURE_WGET_TIMEOUT
     333static void alarm_handler(int sig UNUSED_PARAM)
     334{
     335    /* This is theoretically unsafe (uses stdio and malloc in signal handler) */
     336    if (G.die_if_timed_out)
     337        bb_error_msg_and_die("download timed out");
     338}
     339static void set_alarm(void)
     340{
     341    if (G.timeout_seconds) {
     342        alarm(G.timeout_seconds);
     343        G.die_if_timed_out = 1;
     344    }
     345}
     346# define clear_alarm() ((void)(G.die_if_timed_out = 0))
     347#else
     348# define set_alarm()   ((void)0)
     349# define clear_alarm() ((void)0)
     350#endif
     351
    198352static FILE *open_socket(len_and_sockaddr *lsa)
    199353{
     354    int fd;
    200355    FILE *fp;
     356
     357    set_alarm();
     358    fd = xconnect_stream(lsa);
     359    clear_alarm();
    201360
    202361    /* glibc 2.4 seems to try seeking on it - ??! */
    203362    /* hopefully it understands what ESPIPE means... */
    204     fp = fdopen(xconnect_stream(lsa), "r+");
    205     if (fp == NULL)
     363    fp = fdopen(fd, "r+");
     364    if (!fp)
    206365        bb_perror_msg_and_die(bb_msg_memory_exhausted);
    207366
     
    215374    char *buf_ptr;
    216375
     376    set_alarm();
    217377    if (fgets(G.wget_buf, sizeof(G.wget_buf) - 1, fp) == NULL)
    218378        bb_perror_msg_and_die("error getting response");
     379    clear_alarm();
    219380
    220381    buf_ptr = strchrnul(G.wget_buf, '\n');
     
    257418    h->allocated = url = xstrdup(src_url);
    258419
    259     if (strncmp(url, "http://", 7) == 0) {
    260         h->port = bb_lookup_port("http", "tcp", 80);
    261         h->host = url + 7;
    262         h->is_ftp = 0;
    263     } else if (strncmp(url, "ftp://", 6) == 0) {
    264         h->port = bb_lookup_port("ftp", "tcp", 21);
    265         h->host = url + 6;
    266         h->is_ftp = 1;
    267     } else
    268         bb_error_msg_and_die("not an http or ftp url: %s", sanitize_string(url));
     420    h->protocol = P_FTP;
     421    p = strstr(url, "://");
     422    if (p) {
     423        *p = '\0';
     424        h->host = p + 3;
     425        if (strcmp(url, P_FTP) == 0) {
     426            h->port = bb_lookup_port(P_FTP, "tcp", 21);
     427        } else
     428#if ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER
     429        if (strcmp(url, P_HTTPS) == 0) {
     430            h->port = bb_lookup_port(P_HTTPS, "tcp", 443);
     431            h->protocol = P_HTTPS;
     432        } else
     433#endif
     434        if (strcmp(url, P_HTTP) == 0) {
     435 http:
     436            h->port = bb_lookup_port(P_HTTP, "tcp", 80);
     437            h->protocol = P_HTTP;
     438        } else {
     439            *p = ':';
     440            bb_error_msg_and_die("not an http or ftp url: %s", sanitize_string(url));
     441        }
     442    } else {
     443        // GNU wget is user-friendly and falls back to http://
     444        h->host = url;
     445        goto http;
     446    }
    269447
    270448    // FYI:
     
    298476    }
    299477
    300     // We used to set h->user to NULL here, but this interferes
    301     // with handling of code 302 ("object was moved")
    302 
    303478    sp = strrchr(h->host, '@');
    304479    if (sp != NULL) {
     
    309484        // Standard wget and curl do this too.
    310485        *sp = '\0';
    311         h->user = percent_decode_in_place(h->host, /*strict:*/ 0);
     486        free(h->user);
     487        h->user = xstrdup(percent_decode_in_place(h->host, /*strict:*/ 0));
    312488        h->host = sp + 1;
    313489    }
    314 
    315     sp = h->host;
     490    /* else: h->user remains NULL, or as set by original request
     491     * before redirect (if we are here after a redirect).
     492     */
    316493}
    317494
     
    329506
    330507    /* convert the header name to lower case */
    331     for (s = G.wget_buf; isalnum(*s) || *s == '-' || *s == '.'; ++s) {
    332         /* tolower for "A-Z", no-op for "0-9a-z-." */
     508    for (s = G.wget_buf; isalnum(*s) || *s == '-' || *s == '.' || *s == '_'; ++s) {
     509        /*
     510         * No-op for 20-3f and 60-7f. "0-9a-z-." are in these ranges.
     511         * 40-5f range ("@A-Z[\]^_") maps to 60-7f.
     512         * "A-Z" maps to "a-z".
     513         * "@[\]" can't occur in header names.
     514         * "^_" maps to "~,DEL" (which is wrong).
     515         * "^" was never seen yet, "_" was seen from web.archive.org
     516         * (x-archive-orig-x_commoncrawl_Signature: HEXSTRING).
     517         */
    333518        *s |= 0x20;
    334519    }
     
    441626}
    442627
     628#if ENABLE_FEATURE_WGET_OPENSSL
     629static int spawn_https_helper_openssl(const char *host, unsigned port)
     630{
     631    char *allocated = NULL;
     632    int sp[2];
     633    int pid;
     634    IF_FEATURE_WGET_SSL_HELPER(volatile int child_failed = 0;)
     635
     636    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0)
     637        /* Kernel can have AF_UNIX support disabled */
     638        bb_perror_msg_and_die("socketpair");
     639
     640    if (!strchr(host, ':'))
     641        host = allocated = xasprintf("%s:%u", host, port);
     642
     643    fflush_all();
     644    pid = xvfork();
     645    if (pid == 0) {
     646        /* Child */
     647        char *argv[6];
     648
     649        close(sp[0]);
     650        xmove_fd(sp[1], 0);
     651        xdup2(0, 1);
     652        /*
     653         * openssl s_client -quiet -connect www.kernel.org:443 2>/dev/null
     654         * It prints some debug stuff on stderr, don't know how to suppress it.
     655         * Work around by dev-nulling stderr. We lose all error messages :(
     656         */
     657        xmove_fd(2, 3);
     658        xopen("/dev/null", O_RDWR);
     659        argv[0] = (char*)"openssl";
     660        argv[1] = (char*)"s_client";
     661        argv[2] = (char*)"-quiet";
     662        argv[3] = (char*)"-connect";
     663        argv[4] = (char*)host;
     664        argv[5] = NULL;
     665        BB_EXECVP(argv[0], argv);
     666        xmove_fd(3, 2);
     667# if ENABLE_FEATURE_WGET_SSL_HELPER
     668        child_failed = 1;
     669        xfunc_die();
     670# else
     671        bb_perror_msg_and_die("can't execute '%s'", argv[0]);
     672# endif
     673        /* notreached */
     674    }
     675
     676    /* Parent */
     677    free(allocated);
     678    close(sp[1]);
     679# if ENABLE_FEATURE_WGET_SSL_HELPER
     680    if (child_failed) {
     681        close(sp[0]);
     682        return -1;
     683    }
     684# endif
     685    return sp[0];
     686}
     687#endif
     688
     689/* See networking/ssl_helper/README how to build one */
     690#if ENABLE_FEATURE_WGET_SSL_HELPER
     691static void spawn_https_helper_small(int network_fd)
     692{
     693    int sp[2];
     694    int pid;
     695
     696    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0)
     697        /* Kernel can have AF_UNIX support disabled */
     698        bb_perror_msg_and_die("socketpair");
     699
     700    pid = BB_MMU ? xfork() : xvfork();
     701    if (pid == 0) {
     702        /* Child */
     703        char *argv[3];
     704
     705        close(sp[0]);
     706        xmove_fd(sp[1], 0);
     707        xdup2(0, 1);
     708        xmove_fd(network_fd, 3);
     709        /*
     710         * A simple ssl/tls helper
     711         */
     712        argv[0] = (char*)"ssl_helper";
     713        argv[1] = (char*)"-d3";
     714        argv[2] = NULL;
     715        BB_EXECVP(argv[0], argv);
     716        bb_perror_msg_and_die("can't execute '%s'", argv[0]);
     717        /* notreached */
     718    }
     719
     720    /* Parent */
     721    close(sp[1]);
     722    xmove_fd(sp[0], network_fd);
     723}
     724#endif
     725
    443726static void NOINLINE retrieve_file_data(FILE *dfp)
    444727{
     
    509792                second_cnt = G.timeout_seconds;
    510793#endif
    511                 continue;
     794                goto bump;
    512795            }
    513796
     
    542825                 */
    543826            }
     827#endif
     828 bump:
    544829            /* Need to do it _every_ second for "stalled" indicator
    545830             * to be shown properly.
    546831             */
    547832            progress_meter(PROGRESS_BUMP);
    548 #endif
    549833        } /* while (reading data) */
    550834
     
    613897    use_proxy = (strcmp(G.proxy_flag, "off") != 0);
    614898    if (use_proxy) {
    615         proxy = getenv(target.is_ftp ? "ftp_proxy" : "http_proxy");
     899        proxy = getenv(target.protocol == P_FTP ? "ftp_proxy" : "http_proxy");
     900//FIXME: what if protocol is https? Ok to use http_proxy?
    616901        use_proxy = (proxy && proxy[0]);
    617902        if (use_proxy)
     
    673958    G.got_clen = 0;
    674959    G.chunked = 0;
    675     if (use_proxy || !target.is_ftp) {
     960    if (use_proxy || target.protocol != P_FTP) {
    676961        /*
    677962         *  HTTP session
     
    680965        int status;
    681966
    682 
    683         /* Open socket to http server */
     967        /* Open socket to http(s) server */
     968#if ENABLE_FEATURE_WGET_OPENSSL
     969        /* openssl (and maybe ssl_helper) support is configured */
     970        if (target.protocol == P_HTTPS) {
     971            /* openssl-based helper
     972             * Inconvenient API since we can't give it an open fd
     973             */
     974            int fd = spawn_https_helper_openssl(server.host, server.port);
     975# if ENABLE_FEATURE_WGET_SSL_HELPER
     976            if (fd < 0) { /* no openssl? try ssl_helper */
     977                sfp = open_socket(lsa);
     978                spawn_https_helper_small(fileno(sfp));
     979                goto socket_opened;
     980            }
     981# else
     982            /* We don't check for exec("openssl") failure in this case */
     983# endif
     984            sfp = fdopen(fd, "r+");
     985            if (!sfp)
     986                bb_perror_msg_and_die(bb_msg_memory_exhausted);
     987            goto socket_opened;
     988        }
    684989        sfp = open_socket(lsa);
    685 
     990 socket_opened:
     991#elif ENABLE_FEATURE_WGET_SSL_HELPER
     992        /* Only ssl_helper support is configured */
     993        sfp = open_socket(lsa);
     994        if (target.protocol == P_HTTPS)
     995            spawn_https_helper_small(fileno(sfp));
     996#else
     997        /* ssl (https) support is not configured */
     998        sfp = open_socket(lsa);
     999#endif
    6861000        /* Send HTTP request */
    6871001        if (use_proxy) {
    688             fprintf(sfp, "GET %stp://%s/%s HTTP/1.1\r\n",
    689                 target.is_ftp ? "f" : "ht", target.host,
     1002            SENDFMT(sfp, "GET %s://%s/%s HTTP/1.1\r\n",
     1003                target.protocol, target.host,
    6901004                target.path);
    6911005        } else {
    692             if (option_mask32 & WGET_OPT_POST_DATA)
    693                 fprintf(sfp, "POST /%s HTTP/1.1\r\n", target.path);
    694             else
    695                 fprintf(sfp, "GET /%s HTTP/1.1\r\n", target.path);
    696         }
    697 
    698         fprintf(sfp, "Host: %s\r\nUser-Agent: %s\r\n",
    699             target.host, G.user_agent);
     1006            SENDFMT(sfp, "%s /%s HTTP/1.1\r\n",
     1007                (option_mask32 & WGET_OPT_POST_DATA) ? "POST" : "GET",
     1008                target.path);
     1009        }
     1010        if (!USR_HEADER_HOST)
     1011            SENDFMT(sfp, "Host: %s\r\n", target.host);
     1012        if (!USR_HEADER_USER_AGENT)
     1013            SENDFMT(sfp, "User-Agent: %s\r\n", G.user_agent);
    7001014
    7011015        /* Ask server to close the connection as soon as we are done
    7021016         * (IOW: we do not intend to send more requests)
    7031017         */
    704         fprintf(sfp, "Connection: close\r\n");
     1018        SENDFMT(sfp, "Connection: close\r\n");
    7051019
    7061020#if ENABLE_FEATURE_WGET_AUTHENTICATION
    707         if (target.user) {
    708             fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6,
     1021        if (target.user && !USR_HEADER_AUTH) {
     1022            SENDFMT(sfp, "Proxy-Authorization: Basic %s\r\n"+6,
    7091023                base64enc(target.user));
    7101024        }
    711         if (use_proxy && server.user) {
    712             fprintf(sfp, "Proxy-Authorization: Basic %s\r\n",
     1025        if (use_proxy && server.user && !USR_HEADER_PROXY_AUTH) {
     1026            SENDFMT(sfp, "Proxy-Authorization: Basic %s\r\n",
    7131027                base64enc(server.user));
    7141028        }
    7151029#endif
    7161030
    717         if (G.beg_range != 0)
    718             fprintf(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range);
     1031        if (G.beg_range != 0 && !USR_HEADER_RANGE)
     1032            SENDFMT(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range);
    7191033
    7201034#if ENABLE_FEATURE_WGET_LONG_OPTIONS
    721         if (G.extra_headers)
     1035        if (G.extra_headers) {
     1036            log_io(G.extra_headers);
    7221037            fputs(G.extra_headers, sfp);
     1038        }
    7231039
    7241040        if (option_mask32 & WGET_OPT_POST_DATA) {
    725             fprintf(sfp,
     1041            SENDFMT(sfp,
    7261042                "Content-Type: application/x-www-form-urlencoded\r\n"
    7271043                "Content-Length: %u\r\n"
     
    7331049#endif
    7341050        {
    735             fprintf(sfp, "\r\n");
     1051            SENDFMT(sfp, "\r\n");
    7361052        }
    7371053
     
    8481164                    parse_url(str, &target);
    8491165                    if (!use_proxy) {
     1166                        /* server.user remains untouched */
    8501167                        free(server.allocated);
    8511168                        server.allocated = NULL;
     
    8661183        /* For HTTP, data is pumped over the same connection */
    8671184        dfp = sfp;
    868 
    8691185    } else {
    8701186        /*
     
    8971213    free(server.allocated);
    8981214    free(target.allocated);
     1215    free(server.user);
     1216    free(target.user);
    8991217    free(fname_out_alloc);
    9001218    free(redirected_path);
     
    9151233        "proxy\0"            Required_argument "Y"
    9161234        "user-agent\0"       Required_argument "U"
    917 #if ENABLE_FEATURE_WGET_TIMEOUT
    918         "timeout\0"          Required_argument "T"
    919 #endif
     1235IF_FEATURE_WGET_TIMEOUT(
     1236        "timeout\0"          Required_argument "T")
    9201237        /* Ignored: */
    921         // "tries\0"            Required_argument "t"
     1238IF_DESKTOP( "tries\0"            Required_argument "t")
     1239        "header\0"           Required_argument "\xff"
     1240        "post-data\0"        Required_argument "\xfe"
    9221241        /* 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"
     1242IF_DESKTOP( "passive-ftp\0"      No_argument       "\xf0")
    9261243        /* Ignored (we don't do ssl) */
    927         "no-check-certificate\0" No_argument   "\xfc"
     1244IF_DESKTOP( "no-check-certificate\0" No_argument   "\xf0")
    9281245        /* Ignored (we don't support caching) */
    929         "no-cache\0"         No_argument       "\xfb"
     1246IF_DESKTOP( "no-cache\0"         No_argument       "\xf0")
     1247IF_DESKTOP( "no-verbose\0"       No_argument       "\xf0")
     1248IF_DESKTOP( "no-clobber\0"       No_argument       "\xf0")
     1249IF_DESKTOP( "no-host-directories\0" No_argument    "\xf0")
     1250IF_DESKTOP( "no-parent\0"        No_argument       "\xf0")
    9301251        ;
    9311252#endif
     
    9371258    INIT_G();
    9381259
    939     IF_FEATURE_WGET_TIMEOUT(G.timeout_seconds = 900;)
     1260#if ENABLE_FEATURE_WGET_TIMEOUT
     1261    G.timeout_seconds = 900;
     1262    signal(SIGALRM, alarm_handler);
     1263#endif
    9401264    G.proxy_flag = "on";   /* use proxies if env vars are set */
    9411265    G.user_agent = "Wget"; /* "User-Agent" header field */
     
    9441268    applet_long_options = wget_longopts;
    9451269#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,
     1270    opt_complementary = "-1" /* at least one URL */
     1271        IF_FEATURE_WGET_TIMEOUT(":T+") /* -T NUM */
     1272        IF_FEATURE_WGET_LONG_OPTIONS(":\xff::"); /* --header is a list */
     1273    getopt32(argv, "csqO:P:Y:U:T:"
     1274        /*ignored:*/ "t:"
     1275        /*ignored:*/ "n::"
     1276        /* wget has exactly four -n<letter> opts, all of which we can ignore:
     1277         * -nv --no-verbose: be moderately quiet (-q is full quiet)
     1278         * -nc --no-clobber: abort if exists, neither download to FILE.n nor overwrite FILE
     1279         * -nH --no-host-directories: wget -r http://host/ won't create host/
     1280         * -np --no-parent
     1281         * "n::" above says that we accept -n[ARG].
     1282         * Specifying "n:" would be a bug: "-n ARG" would eat ARG!
     1283         */
     1284        , &G.fname_out, &G.dir_prefix,
    9491285        &G.proxy_flag, &G.user_agent,
    9501286        IF_FEATURE_WGET_TIMEOUT(&G.timeout_seconds) IF_NOT_FEATURE_WGET_TIMEOUT(NULL),
    951         NULL /* -t RETRIES */
     1287        NULL, /* -t RETRIES */
     1288        NULL  /* -n[ARG] */
    9521289        IF_FEATURE_WGET_LONG_OPTIONS(, &headers_llist)
    9531290        IF_FEATURE_WGET_LONG_OPTIONS(, &G.post_data)
     
    9571294#if ENABLE_FEATURE_WGET_LONG_OPTIONS
    9581295    if (headers_llist) {
    959         int size = 1;
    960         char *cp;
     1296        int size = 0;
     1297        char *hdr;
    9611298        llist_t *ll = headers_llist;
    9621299        while (ll) {
     
    9641301            ll = ll->link;
    9651302        }
    966         G.extra_headers = cp = xmalloc(size);
     1303        G.extra_headers = hdr = xmalloc(size + 1);
    9671304        while (headers_llist) {
    968             cp += sprintf(cp, "%s\r\n", (char*)llist_pop(&headers_llist));
     1305            int bit;
     1306            const char *words;
     1307
     1308            size = sprintf(hdr, "%s\r\n",
     1309                    (char*)llist_pop(&headers_llist));
     1310            /* a bit like index_in_substrings but don't match full key */
     1311            bit = 1;
     1312            words = wget_user_headers;
     1313            while (*words) {
     1314                if (strstr(hdr, words) == hdr) {
     1315                    G.user_headers |= bit;
     1316                    break;
     1317                }
     1318                bit <<= 1;
     1319                words += strlen(words) + 1;
     1320            }
     1321            hdr += size;
    9691322        }
    9701323    }
     
    9881341        xclose(G.output_fd);
    9891342
     1343#if ENABLE_FEATURE_CLEAN_UP && ENABLE_FEATURE_WGET_LONG_OPTIONS
     1344    free(G.extra_headers);
     1345#endif
     1346    FINI_G();
     1347
    9901348    return EXIT_SUCCESS;
    9911349}
  • branches/3.3/mindi-busybox/networking/zcip.c

    r3232 r3621  
    3131//usage:     "\n    -q      Quit after obtaining address"
    3232//usage:     "\n    -r 169.254.x.x  Request this address first"
     33//usage:     "\n    -l x.x.0.0  Use this range instead of 169.254"
    3334//usage:     "\n    -v      Verbose"
     35//usage:     "\n"
     36//usage:     "\n$LOGGING=none       Suppress logging"
     37//usage:     "\n$LOGGING=syslog     Log to syslog"
    3438//usage:     "\n"
    3539//usage:     "\nWith no -q, runs continuously monitoring for ARP conflicts,"
     
    3741
    3842#include "libbb.h"
     43#include "common_bufsiz.h"
    3944#include <netinet/ether.h>
    4045#include <net/if.h>
     
    5358
    5459enum {
    55 /* 169.254.0.0 */
    56     LINKLOCAL_ADDR = 0xa9fe0000,
    57 
    58 /* protocol timeout parameters, specified in seconds */
     60    /* 0-1 seconds before sending 1st probe */
    5961    PROBE_WAIT = 1,
     62    /* 1-2 seconds between probes */
    6063    PROBE_MIN = 1,
    6164    PROBE_MAX = 2,
    62     PROBE_NUM = 3,
    63     MAX_CONFLICTS = 10,
    64     RATE_LIMIT_INTERVAL = 60,
    65     ANNOUNCE_WAIT = 2,
    66     ANNOUNCE_NUM = 2,
    67     ANNOUNCE_INTERVAL = 2,
    68     DEFEND_INTERVAL = 10
     65    PROBE_NUM = 3,      /* total probes to send */
     66    ANNOUNCE_INTERVAL = 2,  /* 2 seconds between announces */
     67    ANNOUNCE_NUM = 3,   /* announces to send */
     68    /* if probe/announce sees a conflict, multiply RANDOM(NUM_CONFLICT) by... */
     69    CONFLICT_MULTIPLIER = 2,
     70    /* if we monitor and see a conflict, how long is defend state? */
     71    DEFEND_INTERVAL = 10,
    6972};
    7073
     
    7275enum {
    7376    PROBE = 0,
    74     RATE_LIMIT_PROBE,
    7577    ANNOUNCE,
    7678    MONITOR,
     
    8688
    8789struct globals {
    88     struct sockaddr saddr;
    89     struct ether_addr eth_addr;
     90    struct sockaddr iface_sockaddr;
     91    struct ether_addr our_ethaddr;
     92    uint32_t localnet_ip;
    9093} FIX_ALIASING;
    91 #define G (*(struct globals*)&bb_common_bufsiz1)
    92 #define saddr    (G.saddr   )
    93 #define eth_addr (G.eth_addr)
    94 #define INIT_G() do { } while (0)
     94#define G (*(struct globals*)bb_common_bufsiz1)
     95#define INIT_G() do { setup_common_bufsiz(); } while (0)
    9596
    9697
     
    99100 * the first and last 256 addresses are reserved.
    100101 */
    101 static uint32_t pick(void)
     102static uint32_t pick_nip(void)
    102103{
    103104    unsigned tmp;
     
    106107        tmp = rand() & IN_CLASSB_HOST;
    107108    } while (tmp > (IN_CLASSB_HOST - 0x0200));
    108     return htonl((LINKLOCAL_ADDR + 0x0100) + tmp);
     109    return htonl((G.localnet_ip + 0x0100) + tmp);
     110}
     111
     112static const char *nip_to_a(uint32_t nip)
     113{
     114    struct in_addr in;
     115    in.s_addr = nip;
     116    return inet_ntoa(in);
    109117}
    110118
     
    112120 * Broadcast an ARP packet.
    113121 */
    114 static void arp(
     122static void send_arp_request(
    115123    /* int op, - always ARPOP_REQUEST */
    116     /* const struct ether_addr *source_eth, - always &eth_addr */
    117                     struct in_addr source_ip,
    118     const struct ether_addr *target_eth, struct in_addr target_ip)
     124    /* const struct ether_addr *source_eth, - always &G.our_ethaddr */
     125                    uint32_t source_nip,
     126    const struct ether_addr *target_eth, uint32_t target_nip)
    119127{
    120128    enum { op = ARPOP_REQUEST };
    121 #define source_eth (&eth_addr)
     129#define source_eth (&G.our_ethaddr)
    122130
    123131    struct arp_packet p;
     
    136144    p.arp.arp_op = htons(op);
    137145    memcpy(&p.arp.arp_sha, source_eth, ETH_ALEN);
    138     memcpy(&p.arp.arp_spa, &source_ip, sizeof(p.arp.arp_spa));
     146    memcpy(&p.arp.arp_spa, &source_nip, 4);
    139147    memcpy(&p.arp.arp_tha, target_eth, ETH_ALEN);
    140     memcpy(&p.arp.arp_tpa, &target_ip, sizeof(p.arp.arp_tpa));
     148    memcpy(&p.arp.arp_tpa, &target_nip, 4);
    141149
    142150    // send it
    143     // Even though sock_fd is already bound to saddr, just send()
     151    // Even though sock_fd is already bound to G.iface_sockaddr, just send()
    144152    // won't work, because "socket is not connected"
    145153    // (and connect() won't fix that, "operation not supported").
    146     // Thus we sendto() to saddr. I wonder which sockaddr
     154    // Thus we sendto() to G.iface_sockaddr. I wonder which sockaddr
    147155    // (from bind() or from sendto()?) kernel actually uses
    148156    // to determine iface to emit the packet from...
    149     xsendto(sock_fd, &p, sizeof(p), &saddr, sizeof(saddr));
     157    xsendto(sock_fd, &p, sizeof(p), &G.iface_sockaddr, sizeof(G.iface_sockaddr));
    150158#undef source_eth
    151159}
     
    155163 * argv[0]:intf argv[1]:script_name argv[2]:junk argv[3]:NULL
    156164 */
    157 static int run(char *argv[3], const char *param, struct in_addr *ip)
     165static int run(char *argv[3], const char *param, uint32_t nip)
    158166{
    159167    int status;
    160     char *addr = addr; /* for gcc */
     168    const char *addr = addr; /* for gcc */
    161169    const char *fmt = "%s %s %s" + 3;
    162170
     
    165173    VDBG("%s run %s %s\n", argv[0], argv[1], argv[2]);
    166174
    167     if (ip) {
    168         addr = inet_ntoa(*ip);
     175    if (nip != 0) {
     176        addr = nip_to_a(nip);
    169177        xsetenv("ip", addr);
    170178        fmt -= 3;
    171179    }
    172     bb_info_msg(fmt, argv[2], argv[0], addr);
     180    bb_error_msg(fmt, argv[2], argv[0], addr);
    173181
    174182    status = spawn_and_wait(argv + 1);
     
    187195static ALWAYS_INLINE unsigned random_delay_ms(unsigned secs)
    188196{
    189     return rand() % (secs * 1000);
     197    return (unsigned)rand() % (secs * 1000);
    190198}
    191199
     
    196204int zcip_main(int argc UNUSED_PARAM, char **argv)
    197205{
     206    char *r_opt;
     207    const char *l_opt = "169.254.0.0";
    198208    int state;
    199     char *r_opt;
     209    int nsent;
    200210    unsigned opts;
    201211
    202     // ugly trick, but I want these zeroed in one go
     212    // Ugly trick, but I want these zeroed in one go
    203213    struct {
    204         const struct in_addr null_ip;
    205         const struct ether_addr null_addr;
    206         struct in_addr ip;
     214        const struct ether_addr null_ethaddr;
    207215        struct ifreq ifr;
    208         int timeout_ms; /* must be signed */
    209         unsigned conflicts;
    210         unsigned nprobes;
    211         unsigned nclaims;
    212         int ready;
     216        uint32_t chosen_nip;
     217        int conflicts;
     218        int timeout_ms; // must be signed
    213219        int verbose;
    214220    } L;
    215 #define null_ip    (L.null_ip   )
    216 #define null_addr  (L.null_addr )
    217 #define ip         (L.ip        )
    218 #define ifr        (L.ifr       )
    219 #define timeout_ms (L.timeout_ms)
    220 #define conflicts  (L.conflicts )
    221 #define nprobes    (L.nprobes   )
    222 #define nclaims    (L.nclaims   )
    223 #define ready      (L.ready     )
    224 #define verbose    (L.verbose   )
     221#define null_ethaddr (L.null_ethaddr)
     222#define ifr          (L.ifr         )
     223#define chosen_nip   (L.chosen_nip  )
     224#define conflicts    (L.conflicts   )
     225#define timeout_ms   (L.timeout_ms  )
     226#define verbose      (L.verbose     )
    225227
    226228    memset(&L, 0, sizeof(L));
     
    229231#define FOREGROUND (opts & 1)
    230232#define QUIT       (opts & 2)
    231     // parse commandline: prog [options] ifname script
     233    // Parse commandline: prog [options] ifname script
    232234    // exactly 2 args; -v accumulates and implies -f
    233235    opt_complementary = "=2:vv:vf";
    234     opts = getopt32(argv, "fqr:v", &r_opt, &verbose);
     236    opts = getopt32(argv, "fqr:l:v", &r_opt, &l_opt, &verbose);
    235237#if !BB_MMU
    236238    // on NOMMU reexec early (or else we will rerun things twice)
     
    238240        bb_daemonize_or_rexec(0 /*was: DAEMON_CHDIR_ROOT*/, argv);
    239241#endif
    240     // open an ARP socket
     242    // Open an ARP socket
    241243    // (need to do it before openlog to prevent openlog from taking
    242244    // fd 3 (sock_fd==3))
     
    247249        logmode |= LOGMODE_SYSLOG;
    248250    }
     251    bb_logenv_override();
     252
     253    { // -l n.n.n.n
     254        struct in_addr net;
     255        if (inet_aton(l_opt, &net) == 0
     256         || (net.s_addr & htonl(IN_CLASSB_NET)) != net.s_addr
     257        ) {
     258            bb_error_msg_and_die("invalid network address");
     259        }
     260        G.localnet_ip = ntohl(net.s_addr);
     261    }
    249262    if (opts & 4) { // -r n.n.n.n
     263        struct in_addr ip;
    250264        if (inet_aton(r_opt, &ip) == 0
    251          || (ntohl(ip.s_addr) & IN_CLASSB_NET) != LINKLOCAL_ADDR
     265         || (ntohl(ip.s_addr) & IN_CLASSB_NET) != G.localnet_ip
    252266        ) {
    253267            bb_error_msg_and_die("invalid link address");
    254268        }
     269        chosen_nip = ip.s_addr;
    255270    }
    256271    argv += optind - 1;
     
    265280    xsetenv("interface", argv_intf);
    266281
    267     // initialize the interface (modprobe, ifup, etc)
    268     if (run(argv, "init", NULL))
     282    // Initialize the interface (modprobe, ifup, etc)
     283    if (run(argv, "init", 0))
    269284        return EXIT_FAILURE;
    270285
    271     // initialize saddr
    272     // saddr is: { u16 sa_family; u8 sa_data[14]; }
    273     //memset(&saddr, 0, sizeof(saddr));
     286    // Initialize G.iface_sockaddr
     287    // G.iface_sockaddr is: { u16 sa_family; u8 sa_data[14]; }
     288    //memset(&G.iface_sockaddr, 0, sizeof(G.iface_sockaddr));
    274289    //TODO: are we leaving sa_family == 0 (AF_UNSPEC)?!
    275     safe_strncpy(saddr.sa_data, argv_intf, sizeof(saddr.sa_data));
    276 
    277     // bind to the interface's ARP socket
    278     xbind(sock_fd, &saddr, sizeof(saddr));
    279 
    280     // get the interface's ethernet address
     290    safe_strncpy(G.iface_sockaddr.sa_data, argv_intf, sizeof(G.iface_sockaddr.sa_data));
     291
     292    // Bind to the interface's ARP socket
     293    xbind(sock_fd, &G.iface_sockaddr, sizeof(G.iface_sockaddr));
     294
     295    // Get the interface's ethernet address
    281296    //memset(&ifr, 0, sizeof(ifr));
    282297    strncpy_IFNAMSIZ(ifr.ifr_name, argv_intf);
    283298    xioctl(sock_fd, SIOCGIFHWADDR, &ifr);
    284     memcpy(&eth_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
    285 
    286     // start with some stable ip address, either a function of
     299    memcpy(&G.our_ethaddr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
     300
     301    // Start with some stable ip address, either a function of
    287302    // the hardware address or else the last address we used.
    288303    // we are taking low-order four bytes, as top-order ones
     
    292307    {
    293308        uint32_t t;
    294         move_from_unaligned32(t, ((char *)&eth_addr + 2));
     309        move_from_unaligned32(t, ((char *)&G.our_ethaddr + 2));
    295310        srand(t);
    296311    }
    297     if (ip.s_addr == 0)
    298         ip.s_addr = pick();
    299 
    300312    // FIXME cases to handle:
    301313    //  - zcip already running!
    302314    //  - link already has local address... just defend/update
    303315
    304     // daemonize now; don't delay system startup
     316    // Daemonize now; don't delay system startup
    305317    if (!FOREGROUND) {
    306318#if BB_MMU
    307319        bb_daemonize(0 /*was: DAEMON_CHDIR_ROOT*/);
    308320#endif
    309         bb_info_msg("start, interface %s", argv_intf);
    310     }
    311 
    312     // run the dynamic address negotiation protocol,
     321        bb_error_msg("start, interface %s", argv_intf);
     322    }
     323
     324    // Run the dynamic address negotiation protocol,
    313325    // restarting after address conflicts:
    314326    //  - start with some address we want to try
    315327    //  - short random delay
    316328    //  - arp probes to see if another host uses it
     329    //    00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff arp who-has 169.254.194.171 tell 0.0.0.0
    317330    //  - arp announcements that we're claiming it
     331    //    00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff arp who-has 169.254.194.171 (00:04:e2:64:23:c2) tell 169.254.194.171
    318332    //  - use it
    319333    //  - defend it, within limits
     
    323337    // - poll error (when does this happen?)
    324338    // - read error (when does this happen?)
    325     // - sendto error (in arp()) (when does this happen?)
     339    // - sendto error (in send_arp_request()) (when does this happen?)
    326340    // - revents & POLLERR (link down). run "<script> deconfig" first
     341    if (chosen_nip == 0) {
     342 new_nip_and_PROBE:
     343        chosen_nip = pick_nip();
     344    }
     345    nsent = 0;
    327346    state = PROBE;
    328347    while (1) {
    329348        struct pollfd fds[1];
    330         unsigned deadline_us;
     349        unsigned deadline_us = deadline_us;
    331350        struct arp_packet p;
    332         int source_ip_conflict;
    333         int target_ip_conflict;
     351        int ip_conflict;
     352        int n;
    334353
    335354        fds[0].fd = sock_fd;
     
    337356        fds[0].revents = 0;
    338357
    339         // poll, being ready to adjust current timeout
     358        // Poll, being ready to adjust current timeout
    340359        if (!timeout_ms) {
    341360            timeout_ms = random_delay_ms(PROBE_WAIT);
     
    344363            // ones we'd care about.
    345364        }
    346         // set deadline_us to the point in time when we timeout
    347         deadline_us = MONOTONIC_US() + timeout_ms * 1000;
    348 
    349         VDBG("...wait %d %s nprobes=%u, nclaims=%u\n",
    350                 timeout_ms, argv_intf, nprobes, nclaims);
    351 
    352         switch (safe_poll(fds, 1, timeout_ms)) {
    353 
    354         default:
     365        if (timeout_ms >= 0) {
     366            // Set deadline_us to the point in time when we timeout
     367            deadline_us = MONOTONIC_US() + timeout_ms * 1000;
     368        }
     369
     370        VDBG("...wait %d %s nsent=%u\n",
     371                timeout_ms, argv_intf, nsent);
     372
     373        n = safe_poll(fds, 1, timeout_ms);
     374        if (n < 0) {
    355375            //bb_perror_msg("poll"); - done in safe_poll
    356376            return EXIT_FAILURE;
    357 
    358         // timeout
    359         case 0:
    360             VDBG("state = %d\n", state);
     377        }
     378        if (n == 0) { // timed out?
     379            VDBG("state:%d\n", state);
    361380            switch (state) {
    362381            case PROBE:
    363                 // timeouts in the PROBE state mean no conflicting ARP packets
    364                 // have been received, so we can progress through the states
    365                 if (nprobes < PROBE_NUM) {
    366                     nprobes++;
     382                // No conflicting ARP packets were seen:
     383                // we can progress through the states
     384                if (nsent < PROBE_NUM) {
     385                    nsent++;
    367386                    VDBG("probe/%u %s@%s\n",
    368                             nprobes, argv_intf, inet_ntoa(ip));
    369                     arp(/* ARPOP_REQUEST, */
    370                             /* &eth_addr, */ null_ip,
    371                             &null_addr, ip);
     387                            nsent, argv_intf, nip_to_a(chosen_nip));
    372388                    timeout_ms = PROBE_MIN * 1000;
    373389                    timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN);
     390                    send_arp_request(0, &null_ethaddr, chosen_nip);
     391                    continue;
    374392                }
    375                 else {
    376                     // Switch to announce state.
    377                     state = ANNOUNCE;
    378                     nclaims = 0;
     393                // Switch to announce state
     394                nsent = 0;
     395                state = ANNOUNCE;
     396                goto send_announce;
     397            case ANNOUNCE:
     398                // No conflicting ARP packets were seen:
     399                // we can progress through the states
     400                if (nsent < ANNOUNCE_NUM) {
     401 send_announce:
     402                    nsent++;
    379403                    VDBG("announce/%u %s@%s\n",
    380                             nclaims, argv_intf, inet_ntoa(ip));
    381                     arp(/* ARPOP_REQUEST, */
    382                             /* &eth_addr, */ ip,
    383                             &eth_addr, ip);
     404                            nsent, argv_intf, nip_to_a(chosen_nip));
    384405                    timeout_ms = ANNOUNCE_INTERVAL * 1000;
     406                    send_arp_request(chosen_nip, &G.our_ethaddr, chosen_nip);
     407                    continue;
    385408                }
    386                 break;
    387             case RATE_LIMIT_PROBE:
    388                 // timeouts in the RATE_LIMIT_PROBE state mean no conflicting ARP packets
    389                 // have been received, so we can move immediately to the announce state
    390                 state = ANNOUNCE;
    391                 nclaims = 0;
    392                 VDBG("announce/%u %s@%s\n",
    393                         nclaims, argv_intf, inet_ntoa(ip));
    394                 arp(/* ARPOP_REQUEST, */
    395                         /* &eth_addr, */ ip,
    396                         &eth_addr, ip);
    397                 timeout_ms = ANNOUNCE_INTERVAL * 1000;
    398                 break;
    399             case ANNOUNCE:
    400                 // timeouts in the ANNOUNCE state mean no conflicting ARP packets
    401                 // have been received, so we can progress through the states
    402                 if (nclaims < ANNOUNCE_NUM) {
    403                     nclaims++;
    404                     VDBG("announce/%u %s@%s\n",
    405                             nclaims, argv_intf, inet_ntoa(ip));
    406                     arp(/* ARPOP_REQUEST, */
    407                             /* &eth_addr, */ ip,
    408                             &eth_addr, ip);
    409                     timeout_ms = ANNOUNCE_INTERVAL * 1000;
    410                 }
    411                 else {
    412                     // Switch to monitor state.
    413                     state = MONITOR;
    414                     // link is ok to use earlier
    415                     // FIXME update filters
    416                     run(argv, "config", &ip);
    417                     ready = 1;
    418                     conflicts = 0;
    419                     timeout_ms = -1; // Never timeout in the monitor state.
    420 
    421                     // NOTE: all other exit paths
    422                     // should deconfig ...
    423                     if (QUIT)
    424                         return EXIT_SUCCESS;
    425                 }
    426                 break;
    427             case DEFEND:
    428                 // We won!  No ARP replies, so just go back to monitor.
     409                // Switch to monitor state
     410                // FIXME update filters
     411                run(argv, "config", chosen_nip);
     412                // NOTE: all other exit paths should deconfig...
     413                if (QUIT)
     414                    return EXIT_SUCCESS;
     415                // fall through: switch to MONITOR
     416            default:
     417            // case DEFEND:
     418            // case MONITOR: (shouldn't happen, MONITOR timeout is infinite)
     419                // Defend period ended with no ARP replies - we won
     420                timeout_ms = -1; // never timeout in monitor state
    429421                state = MONITOR;
    430                 timeout_ms = -1;
    431                 conflicts = 0;
    432                 break;
    433             default:
    434                 // Invalid, should never happen.  Restart the whole protocol.
    435                 state = PROBE;
    436                 ip.s_addr = pick();
    437                 timeout_ms = 0;
    438                 nprobes = 0;
    439                 nclaims = 0;
    440                 break;
    441             } // switch (state)
    442             break; // case 0 (timeout)
    443 
    444         // packets arriving, or link went down
    445         case 1:
    446             // We need to adjust the timeout in case we didn't receive
    447             // a conflicting packet.
    448             if (timeout_ms > 0) {
    449                 unsigned diff = deadline_us - MONOTONIC_US();
    450                 if ((int)(diff) < 0) {
    451                     // Current time is greater than the expected timeout time.
    452                     // Should never happen.
    453                     VDBG("missed an expected timeout\n");
    454                     timeout_ms = 0;
    455                 } else {
    456                     VDBG("adjusting timeout\n");
    457                     timeout_ms = (diff / 1000) | 1; /* never 0 */
    458                 }
    459             }
    460 
    461             if ((fds[0].revents & POLLIN) == 0) {
    462                 if (fds[0].revents & POLLERR) {
    463                     // FIXME: links routinely go down;
    464                     // this shouldn't necessarily exit.
    465                     bb_error_msg("iface %s is down", argv_intf);
    466                     if (ready) {
    467                         run(argv, "deconfig", &ip);
    468                     }
    469                     return EXIT_FAILURE;
    470                 }
    471422                continue;
    472423            }
    473 
    474             // read ARP packet
    475             if (safe_read(sock_fd, &p, sizeof(p)) < 0) {
    476                 bb_perror_msg_and_die(bb_msg_read_error);
     424        }
     425
     426        // Packet arrived, or link went down.
     427        // We need to adjust the timeout in case we didn't receive
     428        // a conflicting packet.
     429        if (timeout_ms > 0) {
     430            unsigned diff = deadline_us - MONOTONIC_US();
     431            if ((int)(diff) < 0) {
     432                // Current time is greater than the expected timeout time.
     433                diff = 0;
    477434            }
    478             if (p.eth.ether_type != htons(ETHERTYPE_ARP))
    479                 continue;
     435            VDBG("adjusting timeout\n");
     436            timeout_ms = (diff / 1000) | 1; // never 0
     437        }
     438
     439        if ((fds[0].revents & POLLIN) == 0) {
     440            if (fds[0].revents & POLLERR) {
     441                // FIXME: links routinely go down;
     442                // this shouldn't necessarily exit.
     443                bb_error_msg("iface %s is down", argv_intf);
     444                if (state >= MONITOR) {
     445                    // Only if we are in MONITOR or DEFEND
     446                    run(argv, "deconfig", chosen_nip);
     447                }
     448                return EXIT_FAILURE;
     449            }
     450            continue;
     451        }
     452
     453        // Read ARP packet
     454        if (safe_read(sock_fd, &p, sizeof(p)) < 0) {
     455            bb_perror_msg_and_die(bb_msg_read_error);
     456        }
     457
     458        if (p.eth.ether_type != htons(ETHERTYPE_ARP))
     459            continue;
     460        if (p.arp.arp_op != htons(ARPOP_REQUEST)
     461         && p.arp.arp_op != htons(ARPOP_REPLY)
     462        ) {
     463            continue;
     464        }
    480465#ifdef DEBUG
    481             {
    482                 struct ether_addr *sha = (struct ether_addr *) p.arp.arp_sha;
    483                 struct ether_addr *tha = (struct ether_addr *) p.arp.arp_tha;
    484                 struct in_addr *spa = (struct in_addr *) p.arp.arp_spa;
    485                 struct in_addr *tpa = (struct in_addr *) p.arp.arp_tpa;
    486                 VDBG("%s recv arp type=%d, op=%d,\n",
    487                     argv_intf, ntohs(p.eth.ether_type),
    488                     ntohs(p.arp.arp_op));
    489                 VDBG("\tsource=%s %s\n",
    490                     ether_ntoa(sha),
    491                     inet_ntoa(*spa));
    492                 VDBG("\ttarget=%s %s\n",
    493                     ether_ntoa(tha),
    494                     inet_ntoa(*tpa));
    495             }
     466        {
     467            struct ether_addr *sha = (struct ether_addr *) p.arp.arp_sha;
     468            struct ether_addr *tha = (struct ether_addr *) p.arp.arp_tha;
     469            struct in_addr *spa = (struct in_addr *) p.arp.arp_spa;
     470            struct in_addr *tpa = (struct in_addr *) p.arp.arp_tpa;
     471            VDBG("source=%s %s\n", ether_ntoa(sha), inet_ntoa(*spa));
     472            VDBG("target=%s %s\n", ether_ntoa(tha), inet_ntoa(*tpa));
     473        }
    496474#endif
    497             if (p.arp.arp_op != htons(ARPOP_REQUEST)
    498              && p.arp.arp_op != htons(ARPOP_REPLY))
    499                 continue;
    500 
    501             source_ip_conflict = 0;
    502             target_ip_conflict = 0;
    503 
    504             if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr)) == 0
    505              && memcmp(&p.arp.arp_sha, &eth_addr, ETH_ALEN) != 0
    506             ) {
    507                 source_ip_conflict = 1;
     475        ip_conflict = 0;
     476        if (memcmp(&p.arp.arp_sha, &G.our_ethaddr, ETH_ALEN) != 0) {
     477            if (memcmp(p.arp.arp_spa, &chosen_nip, 4) == 0) {
     478                // A probe or reply with source_ip == chosen ip
     479                ip_conflict = 1;
    508480            }
    509481            if (p.arp.arp_op == htons(ARPOP_REQUEST)
    510              && memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0
    511              && memcmp(&p.arp.arp_tha, &eth_addr, ETH_ALEN) != 0
     482             && memcmp(p.arp.arp_spa, &const_int_0, 4) == 0
     483             && memcmp(p.arp.arp_tpa, &chosen_nip, 4) == 0
    512484            ) {
    513                 target_ip_conflict = 1;
     485                // A probe with source_ip == 0.0.0.0, target_ip == chosen ip:
     486                // another host trying to claim this ip!
     487                ip_conflict |= 2;
    514488            }
    515 
    516             VDBG("state = %d, source ip conflict = %d, target ip conflict = %d\n",
    517                 state, source_ip_conflict, target_ip_conflict);
    518             switch (state) {
    519             case PROBE:
    520             case ANNOUNCE:
    521                 // When probing or announcing, check for source IP conflicts
    522                 // and other hosts doing ARP probes (target IP conflicts).
    523                 if (source_ip_conflict || target_ip_conflict) {
    524                     conflicts++;
    525                     if (conflicts >= MAX_CONFLICTS) {
    526                         VDBG("%s ratelimit\n", argv_intf);
    527                         timeout_ms = RATE_LIMIT_INTERVAL * 1000;
    528                         state = RATE_LIMIT_PROBE;
    529                     }
    530 
    531                     // restart the whole protocol
    532                     ip.s_addr = pick();
    533                     timeout_ms = 0;
    534                     nprobes = 0;
    535                     nclaims = 0;
    536                 }
    537                 break;
    538             case MONITOR:
    539                 // If a conflict, we try to defend with a single ARP probe.
    540                 if (source_ip_conflict) {
    541                     VDBG("monitor conflict -- defending\n");
    542                     state = DEFEND;
    543                     timeout_ms = DEFEND_INTERVAL * 1000;
    544                     arp(/* ARPOP_REQUEST, */
    545                         /* &eth_addr, */ ip,
    546                         &eth_addr, ip);
    547                 }
    548                 break;
    549             case DEFEND:
    550                 // Well, we tried.  Start over (on conflict).
    551                 if (source_ip_conflict) {
    552                     state = PROBE;
    553                     VDBG("defend conflict -- starting over\n");
    554                     ready = 0;
    555                     run(argv, "deconfig", &ip);
    556 
    557                     // restart the whole protocol
    558                     ip.s_addr = pick();
    559                     timeout_ms = 0;
    560                     nprobes = 0;
    561                     nclaims = 0;
    562                 }
    563                 break;
    564             default:
    565                 // Invalid, should never happen.  Restart the whole protocol.
    566                 VDBG("invalid state -- starting over\n");
    567                 state = PROBE;
    568                 ip.s_addr = pick();
    569                 timeout_ms = 0;
    570                 nprobes = 0;
    571                 nclaims = 0;
    572                 break;
    573             } // switch state
    574             break; // case 1 (packets arriving)
    575         } // switch poll
     489        }
     490        VDBG("state:%d ip_conflict:%d\n", state, ip_conflict);
     491        if (!ip_conflict)
     492            continue;
     493
     494        // Either src or target IP conflict exists
     495        if (state <= ANNOUNCE) {
     496            // PROBE or ANNOUNCE
     497            conflicts++;
     498            timeout_ms = PROBE_MIN * 1000
     499                + CONFLICT_MULTIPLIER * random_delay_ms(conflicts);
     500            goto new_nip_and_PROBE;
     501        }
     502
     503        // MONITOR or DEFEND: only src IP conflict is a problem
     504        if (ip_conflict & 1) {
     505            if (state == MONITOR) {
     506                // Src IP conflict, defend with a single ARP probe
     507                VDBG("monitor conflict - defending\n");
     508                timeout_ms = DEFEND_INTERVAL * 1000;
     509                state = DEFEND;
     510                send_arp_request(chosen_nip, &G.our_ethaddr, chosen_nip);
     511                continue;
     512            }
     513            // state == DEFEND
     514            // Another src IP conflict, start over
     515            VDBG("defend conflict - starting over\n");
     516            run(argv, "deconfig", chosen_nip);
     517            conflicts = 0;
     518            timeout_ms = 0;
     519            goto new_nip_and_PROBE;
     520        }
     521        // Note: if we only have a target IP conflict here (ip_conflict & 2),
     522        // IOW: if we just saw this sort of ARP packet:
     523        //  aa:bb:cc:dd:ee:ff > xx:xx:xx:xx:xx:xx arp who-has <chosen_nip> tell 0.0.0.0
     524        // we expect _kernel_ to respond to that, because <chosen_nip>
     525        // is (expected to be) configured on this iface.
    576526    } // while (1)
    577527#undef argv_intf
Note: See TracChangeset for help on using the changeset viewer.