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


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

Legend:

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

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

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

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

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

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

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

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

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

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

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

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

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

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