Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.9/mindi-busybox/networking/zcip.c

    r1765 r2725  
    77 * Copyright (C) 2004 by David Brownell
    88 *
    9  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1010 */
    1111
     
    2424// - link status monitoring (restart on link-up; stop on link-down)
    2525
    26 #include <syslog.h>
    27 #include <poll.h>
    28 #include <sys/wait.h>
    2926#include <netinet/ether.h>
    3027#include <net/ethernet.h>
     
    3532
    3633#include "libbb.h"
     34#include <syslog.h>
    3735
    3836/* We don't need more than 32 bits of the counter */
     
    4038
    4139struct arp_packet {
    42     struct ether_header hdr;
     40    struct ether_header eth;
    4341    struct ether_arp arp;
    44 } ATTRIBUTE_PACKED;
     42} PACKED;
    4543
    4644enum {
     
    7068};
    7169
    72 #define VDBG(fmt,args...) \
    73     do { } while (0)
     70#define VDBG(...) do { } while (0)
     71
     72
     73enum {
     74    sock_fd = 3
     75};
     76
     77struct globals {
     78    struct sockaddr saddr;
     79    struct ether_addr eth_addr;
     80} FIX_ALIASING;
     81#define G (*(struct globals*)&bb_common_bufsiz1)
     82#define saddr    (G.saddr   )
     83#define eth_addr (G.eth_addr)
     84
    7485
    7586/**
     
    7788 * the first and last 256 addresses are reserved.
    7889 */
    79 static void pick(struct in_addr *ip)
     90static uint32_t pick(void)
    8091{
    8192    unsigned tmp;
     
    8495        tmp = rand() & IN_CLASSB_HOST;
    8596    } while (tmp > (IN_CLASSB_HOST - 0x0200));
    86     ip->s_addr = htonl((LINKLOCAL_ADDR + 0x0100) + tmp);
     97    return htonl((LINKLOCAL_ADDR + 0x0100) + tmp);
    8798}
    8899
     
    90101 * Broadcast an ARP packet.
    91102 */
    92 static void arp(int fd, struct sockaddr *saddr, int op,
    93     const struct ether_addr *source_addr, struct in_addr source_ip,
    94     const struct ether_addr *target_addr, struct in_addr target_ip)
     103static void arp(
     104    /* int op, - always ARPOP_REQUEST */
     105    /* const struct ether_addr *source_eth, - always &eth_addr */
     106                    struct in_addr source_ip,
     107    const struct ether_addr *target_eth, struct in_addr target_ip)
    95108{
     109    enum { op = ARPOP_REQUEST };
     110#define source_eth (&eth_addr)
     111
    96112    struct arp_packet p;
    97113    memset(&p, 0, sizeof(p));
    98114
    99115    // ether header
    100     p.hdr.ether_type = htons(ETHERTYPE_ARP);
    101     memcpy(p.hdr.ether_shost, source_addr, ETH_ALEN);
    102     memset(p.hdr.ether_dhost, 0xff, ETH_ALEN);
     116    p.eth.ether_type = htons(ETHERTYPE_ARP);
     117    memcpy(p.eth.ether_shost, source_eth, ETH_ALEN);
     118    memset(p.eth.ether_dhost, 0xff, ETH_ALEN);
    103119
    104120    // arp request
     
    108124    p.arp.arp_pln = 4;
    109125    p.arp.arp_op = htons(op);
    110     memcpy(&p.arp.arp_sha, source_addr, ETH_ALEN);
     126    memcpy(&p.arp.arp_sha, source_eth, ETH_ALEN);
    111127    memcpy(&p.arp.arp_spa, &source_ip, sizeof(p.arp.arp_spa));
    112     memcpy(&p.arp.arp_tha, target_addr, ETH_ALEN);
     128    memcpy(&p.arp.arp_tha, target_eth, ETH_ALEN);
    113129    memcpy(&p.arp.arp_tpa, &target_ip, sizeof(p.arp.arp_tpa));
    114130
    115131    // send it
    116     xsendto(fd, &p, sizeof(p), saddr, sizeof(*saddr));
    117 
    118     // Currently all callers ignore errors, that's why returns are
    119     // commented out...
    120     //return 0;
     132    // Even though sock_fd is already bound to saddr, just send()
     133    // won't work, because "socket is not connected"
     134    // (and connect() won't fix that, "operation not supported").
     135    // Thus we sendto() to saddr. I wonder which sockaddr
     136    // (from bind() or from sendto()?) kernel actually uses
     137    // to determine iface to emit the packet from...
     138    xsendto(sock_fd, &p, sizeof(p), &saddr, sizeof(saddr));
     139#undef source_eth
    121140}
    122141
    123142/**
    124  * Run a script. argv[2] is already NULL.
    125  */
    126 static int run(char *argv[3], const char *intf, struct in_addr *ip)
     143 * Run a script.
     144 * argv[0]:intf argv[1]:script_name argv[2]:junk argv[3]:NULL
     145 */
     146static int run(char *argv[3], const char *param, struct in_addr *ip)
    127147{
    128148    int status;
    129 
    130     VDBG("%s run %s %s\n", intf, argv[0], argv[1]);
     149    char *addr = addr; /* for gcc */
     150    const char *fmt = "%s %s %s" + 3;
     151
     152    argv[2] = (char*)param;
     153
     154    VDBG("%s run %s %s\n", argv[0], argv[1], argv[2]);
    131155
    132156    if (ip) {
    133         char *addr = inet_ntoa(*ip);
    134         setenv("ip", addr, 1);
    135         bb_info_msg("%s %s %s", argv[1], intf, addr);
     157        addr = inet_ntoa(*ip);
     158        xsetenv("ip", addr);
     159        fmt -= 3;
    136160    }
    137 
    138     status = wait4pid(spawn(argv));
     161    bb_info_msg(fmt, argv[2], argv[0], addr);
     162
     163    status = spawn_and_wait(argv + 1);
    139164    if (status < 0) {
    140         bb_perror_msg("%s %s", argv[1], intf);
     165        bb_perror_msg("%s %s %s" + 3, argv[2], argv[0]);
    141166        return -errno;
    142167    }
    143168    if (status != 0)
    144         bb_error_msg("script %s %s failed, exitcode=%d", argv[0], argv[1], status);
     169        bb_error_msg("script %s %s failed, exitcode=%d", argv[1], argv[2], status & 0xff);
    145170    return status;
    146171}
     
    149174 * Return milliseconds of random delay, up to "secs" seconds.
    150175 */
    151 static unsigned ALWAYS_INLINE ms_rdelay(unsigned secs)
     176static ALWAYS_INLINE unsigned random_delay_ms(unsigned secs)
    152177{
    153178    return rand() % (secs * 1000);
     
    157182 * main program
    158183 */
    159 int zcip_main(int argc, char **argv);
    160 int zcip_main(int argc, char **argv)
     184int zcip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     185int zcip_main(int argc UNUSED_PARAM, char **argv)
    161186{
    162     int state = PROBE;
    163     struct ether_addr eth_addr;
    164     const char *why;
    165     int fd;
     187    int state;
    166188    char *r_opt;
    167189    unsigned opts;
    168190
    169     /* Ugly trick, but I want these zeroed in one go */
     191    // ugly trick, but I want these zeroed in one go
    170192    struct {
    171193        const struct in_addr null_ip;
    172194        const struct ether_addr null_addr;
    173         struct sockaddr saddr;
    174195        struct in_addr ip;
    175196        struct ifreq ifr;
    176         char *intf;
    177         char *script_av[3];
    178197        int timeout_ms; /* must be signed */
    179198        unsigned conflicts;
     
    185204#define null_ip    (L.null_ip   )
    186205#define null_addr  (L.null_addr )
    187 #define saddr      (L.saddr     )
    188206#define ip         (L.ip        )
    189207#define ifr        (L.ifr       )
    190 #define intf       (L.intf      )
    191 #define script_av  (L.script_av )
    192208#define timeout_ms (L.timeout_ms)
    193209#define conflicts  (L.conflicts )
     
    205221    opt_complementary = "=2:vv:vf";
    206222    opts = getopt32(argv, "fqr:v", &r_opt, &verbose);
     223#if !BB_MMU
     224    // on NOMMU reexec early (or else we will rerun things twice)
     225    if (!FOREGROUND)
     226        bb_daemonize_or_rexec(0 /*was: DAEMON_CHDIR_ROOT*/, argv);
     227#endif
     228    // open an ARP socket
     229    // (need to do it before openlog to prevent openlog from taking
     230    // fd 3 (sock_fd==3))
     231    xmove_fd(xsocket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)), sock_fd);
    207232    if (!FOREGROUND) {
    208         /* Do it early, before all bb_xx_msg calls */
     233        // do it before all bb_xx_msg calls
    209234        openlog(applet_name, 0, LOG_DAEMON);
    210235        logmode |= LOGMODE_SYSLOG;
     
    217242        }
    218243    }
    219     // On NOMMU reexec early (or else we will rerun things twice)
    220 #if !BB_MMU
    221     if (!FOREGROUND)
    222         bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv);
    223 #endif
    224     argc -= optind;
    225     argv += optind;
    226 
    227     intf = argv[0];
    228     script_av[0] = argv[1];
    229     setenv("interface", intf, 1);
     244    argv += optind - 1;
     245
     246    /* Now: argv[0]:junk argv[1]:intf argv[2]:script argv[3]:NULL */
     247    /* We need to make space for script argument: */
     248    argv[0] = argv[1];
     249    argv[1] = argv[2];
     250    /* Now: argv[0]:intf argv[1]:script argv[2]:junk argv[3]:NULL */
     251#define argv_intf (argv[0])
     252
     253    xsetenv("interface", argv_intf);
    230254
    231255    // initialize the interface (modprobe, ifup, etc)
    232     script_av[1] = (char*)"init";
    233     if (run(script_av, intf, NULL))
     256    if (run(argv, "init", NULL))
    234257        return EXIT_FAILURE;
    235258
    236259    // initialize saddr
     260    // saddr is: { u16 sa_family; u8 sa_data[14]; }
    237261    //memset(&saddr, 0, sizeof(saddr));
    238     safe_strncpy(saddr.sa_data, intf, sizeof(saddr.sa_data));
    239 
    240     // open an ARP socket
    241     fd = xsocket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP));
     262    //TODO: are we leaving sa_family == 0 (AF_UNSPEC)?!
     263    safe_strncpy(saddr.sa_data, argv_intf, sizeof(saddr.sa_data));
     264
    242265    // bind to the interface's ARP socket
    243     xbind(fd, &saddr, sizeof(saddr));
     266    xbind(sock_fd, &saddr, sizeof(saddr));
    244267
    245268    // get the interface's ethernet address
    246269    //memset(&ifr, 0, sizeof(ifr));
    247     strncpy(ifr.ifr_name, intf, sizeof(ifr.ifr_name));
    248     xioctl(fd, SIOCGIFHWADDR, &ifr);
     270    strncpy_IFNAMSIZ(ifr.ifr_name, argv_intf);
     271    xioctl(sock_fd, SIOCGIFHWADDR, &ifr);
    249272    memcpy(&eth_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
    250273
    251274    // start with some stable ip address, either a function of
    252275    // the hardware address or else the last address we used.
     276    // we are taking low-order four bytes, as top-order ones
     277    // aren't random enough.
    253278    // NOTE: the sequence of addresses we try changes only
    254279    // depending on when we detect conflicts.
    255     srand(*(unsigned*)&ifr.ifr_hwaddr.sa_data);
     280    {
     281        uint32_t t;
     282        move_from_unaligned32(t, ((char *)&eth_addr + 2));
     283        srand(t);
     284    }
    256285    if (ip.s_addr == 0)
    257         pick(&ip);
     286        ip.s_addr = pick();
    258287
    259288    // FIXME cases to handle:
     
    264293    if (!FOREGROUND) {
    265294#if BB_MMU
    266         bb_daemonize(DAEMON_CHDIR_ROOT);
     295        bb_daemonize(0 /*was: DAEMON_CHDIR_ROOT*/);
    267296#endif
    268         bb_info_msg("start, interface %s", intf);
     297        bb_info_msg("start, interface %s", argv_intf);
    269298    }
    270299
     
    273302    //  - start with some address we want to try
    274303    //  - short random delay
    275     //  - arp probes to see if another host else uses it
     304    //  - arp probes to see if another host uses it
    276305    //  - arp announcements that we're claiming it
    277306    //  - use it
    278307    //  - defend it, within limits
     308    // exit if:
     309    // - address is successfully obtained and -q was given:
     310    //   run "<script> config", then exit with exitcode 0
     311    // - poll error (when does this happen?)
     312    // - read error (when does this happen?)
     313    // - sendto error (in arp()) (when does this happen?)
     314    // - revents & POLLERR (link down). run "<script> deconfig" first
     315    state = PROBE;
    279316    while (1) {
    280317        struct pollfd fds[1];
    281318        unsigned deadline_us;
    282319        struct arp_packet p;
    283 
    284         int source_ip_conflict = 0;
    285         int target_ip_conflict = 0;
    286 
    287         fds[0].fd = fd;
     320        int source_ip_conflict;
     321        int target_ip_conflict;
     322
     323        fds[0].fd = sock_fd;
    288324        fds[0].events = POLLIN;
    289325        fds[0].revents = 0;
     
    291327        // poll, being ready to adjust current timeout
    292328        if (!timeout_ms) {
    293             timeout_ms = ms_rdelay(PROBE_WAIT);
    294             // FIXME setsockopt(fd, SO_ATTACH_FILTER, ...) to
     329            timeout_ms = random_delay_ms(PROBE_WAIT);
     330            // FIXME setsockopt(sock_fd, SO_ATTACH_FILTER, ...) to
    295331            // make the kernel filter out all packets except
    296332            // ones we'd care about.
     
    300336
    301337        VDBG("...wait %d %s nprobes=%u, nclaims=%u\n",
    302                 timeout_ms, intf, nprobes, nclaims);
    303         switch (poll(fds, 1, timeout_ms)) {
     338                timeout_ms, argv_intf, nprobes, nclaims);
     339
     340        switch (safe_poll(fds, 1, timeout_ms)) {
     341
     342        default:
     343            //bb_perror_msg("poll"); - done in safe_poll
     344            return EXIT_FAILURE;
    304345
    305346        // timeout
     
    313354                    nprobes++;
    314355                    VDBG("probe/%u %s@%s\n",
    315                             nprobes, intf, inet_ntoa(ip));
    316                     arp(fd, &saddr, ARPOP_REQUEST,
    317                             &eth_addr, null_ip,
     356                            nprobes, argv_intf, inet_ntoa(ip));
     357                    arp(/* ARPOP_REQUEST, */
     358                            /* &eth_addr, */ null_ip,
    318359                            &null_addr, ip);
    319360                    timeout_ms = PROBE_MIN * 1000;
    320                     timeout_ms += ms_rdelay(PROBE_MAX - PROBE_MIN);
     361                    timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN);
    321362                }
    322363                else {
     
    325366                    nclaims = 0;
    326367                    VDBG("announce/%u %s@%s\n",
    327                             nclaims, intf, inet_ntoa(ip));
    328                     arp(fd, &saddr, ARPOP_REQUEST,
    329                             &eth_addr, ip,
     368                            nclaims, argv_intf, inet_ntoa(ip));
     369                    arp(/* ARPOP_REQUEST, */
     370                            /* &eth_addr, */ ip,
    330371                            &eth_addr, ip);
    331372                    timeout_ms = ANNOUNCE_INTERVAL * 1000;
     
    338379                nclaims = 0;
    339380                VDBG("announce/%u %s@%s\n",
    340                         nclaims, intf, inet_ntoa(ip));
    341                 arp(fd, &saddr, ARPOP_REQUEST,
    342                         &eth_addr, ip,
     381                        nclaims, argv_intf, inet_ntoa(ip));
     382                arp(/* ARPOP_REQUEST, */
     383                        /* &eth_addr, */ ip,
    343384                        &eth_addr, ip);
    344385                timeout_ms = ANNOUNCE_INTERVAL * 1000;
     
    350391                    nclaims++;
    351392                    VDBG("announce/%u %s@%s\n",
    352                             nclaims, intf, inet_ntoa(ip));
    353                     arp(fd, &saddr, ARPOP_REQUEST,
    354                             &eth_addr, ip,
     393                            nclaims, argv_intf, inet_ntoa(ip));
     394                    arp(/* ARPOP_REQUEST, */
     395                            /* &eth_addr, */ ip,
    355396                            &eth_addr, ip);
    356397                    timeout_ms = ANNOUNCE_INTERVAL * 1000;
     
    361402                    // link is ok to use earlier
    362403                    // FIXME update filters
    363                     script_av[1] = (char*)"config";
    364                     run(script_av, intf, &ip);
     404                    run(argv, "config", &ip);
    365405                    ready = 1;
    366406                    conflicts = 0;
     
    382422                // Invalid, should never happen.  Restart the whole protocol.
    383423                state = PROBE;
    384                 pick(&ip);
     424                ip.s_addr = pick();
    385425                timeout_ms = 0;
    386426                nprobes = 0;
     
    389429            } // switch (state)
    390430            break; // case 0 (timeout)
    391         // packets arriving
     431
     432        // packets arriving, or link went down
    392433        case 1:
    393434            // We need to adjust the timeout in case we didn't receive
     
    402443                } else {
    403444                    VDBG("adjusting timeout\n");
    404                     timeout_ms = diff / 1000;
    405                     if (!timeout_ms) timeout_ms = 1;
     445                    timeout_ms = (diff / 1000) | 1; /* never 0 */
    406446                }
    407447            }
     
    411451                    // FIXME: links routinely go down;
    412452                    // this shouldn't necessarily exit.
    413                     bb_error_msg("%s: poll error", intf);
     453                    bb_error_msg("iface %s is down", argv_intf);
    414454                    if (ready) {
    415                         script_av[1] = (char*)"deconfig";
    416                         run(script_av, intf, &ip);
     455                        run(argv, "deconfig", &ip);
    417456                    }
    418457                    return EXIT_FAILURE;
     
    422461
    423462            // read ARP packet
    424             if (recv(fd, &p, sizeof(p), 0) < 0) {
    425                 why = "recv";
    426                 goto bad;
     463            if (safe_read(sock_fd, &p, sizeof(p)) < 0) {
     464                bb_perror_msg_and_die(bb_msg_read_error);
    427465            }
    428             if (p.hdr.ether_type != htons(ETHERTYPE_ARP))
     466            if (p.eth.ether_type != htons(ETHERTYPE_ARP))
    429467                continue;
    430 
    431468#ifdef DEBUG
    432469            {
    433                 struct ether_addr * sha = (struct ether_addr *) p.arp.arp_sha;
    434                 struct ether_addr * tha = (struct ether_addr *) p.arp.arp_tha;
    435                 struct in_addr * spa = (struct in_addr *) p.arp.arp_spa;
    436                 struct in_addr * tpa = (struct in_addr *) p.arp.arp_tpa;
     470                struct ether_addr *sha = (struct ether_addr *) p.arp.arp_sha;
     471                struct ether_addr *tha = (struct ether_addr *) p.arp.arp_tha;
     472                struct in_addr *spa = (struct in_addr *) p.arp.arp_spa;
     473                struct in_addr *tpa = (struct in_addr *) p.arp.arp_tpa;
    437474                VDBG("%s recv arp type=%d, op=%d,\n",
    438                     intf, ntohs(p.hdr.ether_type),
     475                    argv_intf, ntohs(p.eth.ether_type),
    439476                    ntohs(p.arp.arp_op));
    440477                VDBG("\tsource=%s %s\n",
     
    447484#endif
    448485            if (p.arp.arp_op != htons(ARPOP_REQUEST)
    449                     && p.arp.arp_op != htons(ARPOP_REPLY))
     486             && p.arp.arp_op != htons(ARPOP_REPLY))
    450487                continue;
    451488
    452             if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr)) == 0 &&
    453                 memcmp(&eth_addr, &p.arp.arp_sha, ETH_ALEN) != 0) {
     489            source_ip_conflict = 0;
     490            target_ip_conflict = 0;
     491
     492            if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr)) == 0
     493             && memcmp(&p.arp.arp_sha, &eth_addr, ETH_ALEN) != 0
     494            ) {
    454495                source_ip_conflict = 1;
    455496            }
    456             if (memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0 &&
    457                 p.arp.arp_op == htons(ARPOP_REQUEST) &&
    458                 memcmp(&eth_addr, &p.arp.arp_tha, ETH_ALEN) != 0) {
     497            if (p.arp.arp_op == htons(ARPOP_REQUEST)
     498             && memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0
     499             && memcmp(&p.arp.arp_tha, &eth_addr, ETH_ALEN) != 0
     500            ) {
    459501                target_ip_conflict = 1;
    460502            }
     
    470512                    conflicts++;
    471513                    if (conflicts >= MAX_CONFLICTS) {
    472                         VDBG("%s ratelimit\n", intf);
     514                        VDBG("%s ratelimit\n", argv_intf);
    473515                        timeout_ms = RATE_LIMIT_INTERVAL * 1000;
    474516                        state = RATE_LIMIT_PROBE;
     
    476518
    477519                    // restart the whole protocol
    478                     pick(&ip);
     520                    ip.s_addr = pick();
    479521                    timeout_ms = 0;
    480522                    nprobes = 0;
     
    488530                    state = DEFEND;
    489531                    timeout_ms = DEFEND_INTERVAL * 1000;
    490                     arp(fd, &saddr,
    491                             ARPOP_REQUEST,
    492                             &eth_addr, ip,
    493                             &eth_addr, ip);
     532                    arp(/* ARPOP_REQUEST, */
     533                        /* &eth_addr, */ ip,
     534                        &eth_addr, ip);
    494535                }
    495536                break;
     
    500541                    VDBG("defend conflict -- starting over\n");
    501542                    ready = 0;
    502                     script_av[1] = (char*)"deconfig";
    503                     run(script_av, intf, &ip);
     543                    run(argv, "deconfig", &ip);
    504544
    505545                    // restart the whole protocol
    506                     pick(&ip);
     546                    ip.s_addr = pick();
    507547                    timeout_ms = 0;
    508548                    nprobes = 0;
     
    514554                VDBG("invalid state -- starting over\n");
    515555                state = PROBE;
    516                 pick(&ip);
     556                ip.s_addr = pick();
    517557                timeout_ms = 0;
    518558                nprobes = 0;
     
    520560                break;
    521561            } // switch state
    522 
    523562            break; // case 1 (packets arriving)
    524         default:
    525             why = "poll";
    526             goto bad;
    527563        } // switch poll
    528     }
    529  bad:
    530     bb_perror_msg("%s, %s", intf, why);
    531     return EXIT_FAILURE;
     564    } // while (1)
     565#undef argv_intf
    532566}
Note: See TracChangeset for help on using the changeset viewer.