Ignore:
Timestamp:
Nov 6, 2007, 11:01:53 AM (13 years ago)
Author:
Bruno Cornec
Message:
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod? silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian? keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René? Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

File:
1 edited

Legend:

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

    r902 r1770  
     1/* vi: set sw=4 ts=4: */
    12/*
    23 * RFC3927 ZeroConf IPv4 Link-Local addressing
     
    2324// - link status monitoring (restart on link-up; stop on link-down)
    2425
    25 #include "busybox.h"
    26 #include <errno.h>
    27 #include <string.h>
    2826#include <syslog.h>
    2927#include <poll.h>
    30 #include <time.h>
    31 
    3228#include <sys/wait.h>
    33 
    3429#include <netinet/ether.h>
    3530#include <net/ethernet.h>
    3631#include <net/if.h>
    3732#include <net/if_arp.h>
    38 
    3933#include <linux/if_packet.h>
    4034#include <linux/sockios.h>
    4135
     36#include "libbb.h"
     37
     38/* We don't need more than 32 bits of the counter */
     39#define MONOTONIC_US() ((unsigned)monotonic_us())
    4240
    4341struct arp_packet {
     
    7270};
    7371
    74 /* Implicitly zero-initialized */
    75 static const struct in_addr null_ip;
    76 static const struct ether_addr null_addr;
    77 static int verbose;
    78 
    79 #define DBG(fmt,args...) \
     72#define VDBG(fmt,args...) \
    8073    do { } while (0)
    81 #define VDBG    DBG
    8274
    8375/**
     
    8779static void pick(struct in_addr *ip)
    8880{
    89     unsigned    tmp;
    90 
    91     /* use cheaper math than lrand48() mod N */
     81    unsigned tmp;
     82
    9283    do {
    93         tmp = (lrand48() >> 16) & IN_CLASSB_HOST;
     84        tmp = rand() & IN_CLASSB_HOST;
    9485    } while (tmp > (IN_CLASSB_HOST - 0x0200));
    9586    ip->s_addr = htonl((LINKLOCAL_ADDR + 0x0100) + tmp);
     
    9990 * Broadcast an ARP packet.
    10091 */
    101 static int arp(int fd, struct sockaddr *saddr, int op,
     92static void arp(int fd, struct sockaddr *saddr, int op,
    10293    const struct ether_addr *source_addr, struct in_addr source_ip,
    10394    const struct ether_addr *target_addr, struct in_addr target_ip)
     
    118109    p.arp.arp_op = htons(op);
    119110    memcpy(&p.arp.arp_sha, source_addr, ETH_ALEN);
    120     memcpy(&p.arp.arp_spa, &source_ip, sizeof (p.arp.arp_spa));
     111    memcpy(&p.arp.arp_spa, &source_ip, sizeof(p.arp.arp_spa));
    121112    memcpy(&p.arp.arp_tha, target_addr, ETH_ALEN);
    122     memcpy(&p.arp.arp_tpa, &target_ip, sizeof (p.arp.arp_tpa));
     113    memcpy(&p.arp.arp_tpa, &target_ip, sizeof(p.arp.arp_tpa));
    123114
    124115    // send it
    125     if (sendto(fd, &p, sizeof (p), 0, saddr, sizeof (*saddr)) < 0) {
    126         perror("sendto");
     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;
     121}
     122
     123/**
     124 * Run a script. argv[2] is already NULL.
     125 */
     126static int run(char *argv[3], const char *intf, struct in_addr *ip)
     127{
     128    int status;
     129
     130    VDBG("%s run %s %s\n", intf, argv[0], argv[1]);
     131
     132    if (ip) {
     133        char *addr = inet_ntoa(*ip);
     134        setenv("ip", addr, 1);
     135        bb_info_msg("%s %s %s", argv[1], intf, addr);
     136    }
     137
     138    status = wait4pid(spawn(argv));
     139    if (status < 0) {
     140        bb_perror_msg("%s %s", argv[1], intf);
    127141        return -errno;
    128142    }
    129     return 0;
     143    if (status != 0)
     144        bb_error_msg("script %s %s failed, exitcode=%d", argv[0], argv[1], status);
     145    return status;
    130146}
    131147
    132148/**
    133  * Run a script.
    134  */
    135 static int run(char *script, char *arg, char *intf, struct in_addr *ip)
     149 * Return milliseconds of random delay, up to "secs" seconds.
     150 */
     151static unsigned ALWAYS_INLINE ms_rdelay(unsigned secs)
    136152{
    137     int pid, status;
    138     char *why;
    139 
    140     if (script != NULL) {
    141         VDBG("%s run %s %s\n", intf, script, arg);
    142         if (ip != NULL) {
    143             char *addr = inet_ntoa(*ip);
    144             setenv("ip", addr, 1);
    145             syslog(LOG_INFO, "%s %s %s", arg, intf, addr);
    146         }
    147 
    148         pid = vfork();
    149         if (pid < 0) {          // error
    150             why = "vfork";
    151             goto bad;
    152         } else if (pid == 0) {      // child
    153             execl(script, script, arg, NULL);
    154             perror("execl");
    155             _exit(EXIT_FAILURE);
    156         }
    157 
    158         if (waitpid(pid, &status, 0) <= 0) {
    159             why = "waitpid";
    160             goto bad;
    161         }
    162         if (WEXITSTATUS(status) != 0) {
    163             bb_error_msg("script %s failed, exit=%d\n",
    164                     script, WEXITSTATUS(status));
    165             return -errno;
     153    return rand() % (secs * 1000);
     154}
     155
     156/**
     157 * main program
     158 */
     159int zcip_main(int argc, char **argv);
     160int zcip_main(int argc, char **argv)
     161{
     162    int state = PROBE;
     163    struct ether_addr eth_addr;
     164    const char *why;
     165    int fd;
     166    char *r_opt;
     167    unsigned opts;
     168
     169    /* Ugly trick, but I want these zeroed in one go */
     170    struct {
     171        const struct in_addr null_ip;
     172        const struct ether_addr null_addr;
     173        struct sockaddr saddr;
     174        struct in_addr ip;
     175        struct ifreq ifr;
     176        char *intf;
     177        char *script_av[3];
     178        int timeout_ms; /* must be signed */
     179        unsigned conflicts;
     180        unsigned nprobes;
     181        unsigned nclaims;
     182        int ready;
     183        int verbose;
     184    } L;
     185#define null_ip    (L.null_ip   )
     186#define null_addr  (L.null_addr )
     187#define saddr      (L.saddr     )
     188#define ip         (L.ip        )
     189#define ifr        (L.ifr       )
     190#define intf       (L.intf      )
     191#define script_av  (L.script_av )
     192#define timeout_ms (L.timeout_ms)
     193#define conflicts  (L.conflicts )
     194#define nprobes    (L.nprobes   )
     195#define nclaims    (L.nclaims   )
     196#define ready      (L.ready     )
     197#define verbose    (L.verbose   )
     198
     199    memset(&L, 0, sizeof(L));
     200
     201#define FOREGROUND (opts & 1)
     202#define QUIT       (opts & 2)
     203    // parse commandline: prog [options] ifname script
     204    // exactly 2 args; -v accumulates and implies -f
     205    opt_complementary = "=2:vv:vf";
     206    opts = getopt32(argv, "fqr:v", &r_opt, &verbose);
     207    if (!FOREGROUND) {
     208        /* Do it early, before all bb_xx_msg calls */
     209        openlog(applet_name, 0, LOG_DAEMON);
     210        logmode |= LOGMODE_SYSLOG;
     211    }
     212    if (opts & 4) { // -r n.n.n.n
     213        if (inet_aton(r_opt, &ip) == 0
     214         || (ntohl(ip.s_addr) & IN_CLASSB_NET) != LINKLOCAL_ADDR
     215        ) {
     216            bb_error_msg_and_die("invalid link address");
    166217        }
    167218    }
    168     return 0;
    169 bad:
    170     status = -errno;
    171     syslog(LOG_ERR, "%s %s, %s error: %s",
    172         arg, intf, why, strerror(errno));
    173     return status;
    174 }
    175 
    176 
    177 /**
    178  * Return milliseconds of random delay, up to "secs" seconds.
    179  */
    180 static inline unsigned ms_rdelay(unsigned secs)
    181 {
    182     return lrand48() % (secs * 1000);
    183 }
    184 
    185 /**
    186  * main program
    187  */
    188 
    189 int zcip_main(int argc, char *argv[])
    190 {
    191     char *intf = NULL;
    192     char *script = NULL;
    193     int quit = 0;
    194     int foreground = 0;
    195 
    196     char *why;
    197     struct sockaddr saddr;
    198     struct ether_addr addr;
    199     struct in_addr ip = { 0 };
    200     int fd;
    201     int ready = 0;
    202     suseconds_t timeout = 0;    // milliseconds
    203     unsigned conflicts = 0;
    204     unsigned nprobes = 0;
    205     unsigned nclaims = 0;
    206     int t;
    207     int state = PROBE;
    208 
    209     // parse commandline: prog [options] ifname script
    210     while ((t = getopt(argc, argv, "fqr:v")) != EOF) {
    211         switch (t) {
    212         case 'f':
    213             foreground = 1;
    214             continue;
    215         case 'q':
    216             quit = 1;
    217             continue;
    218         case 'r':
    219             if (inet_aton(optarg, &ip) == 0
    220                     || (ntohl(ip.s_addr) & IN_CLASSB_NET)
    221                         != LINKLOCAL_ADDR) {
    222                 bb_error_msg_and_die("invalid link address");
    223             }
    224             continue;
    225         case 'v':
    226             verbose++;
    227             foreground = 1;
    228             continue;
    229         default:
    230             bb_error_msg_and_die("bad option");
    231         }
    232     }
    233     if (optind < argc - 1) {
    234         intf = argv[optind++];
    235         setenv("interface", intf, 1);
    236         script = argv[optind++];
    237     }
    238     if (optind != argc || !intf)
    239         bb_show_usage();
    240     openlog(bb_applet_name, 0, LOG_DAEMON);
     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);
    241230
    242231    // initialize the interface (modprobe, ifup, etc)
    243     if (run(script, "init", intf, NULL) < 0)
     232    script_av[1] = (char*)"init";
     233    if (run(script_av, intf, NULL))
    244234        return EXIT_FAILURE;
    245235
    246236    // initialize saddr
    247     memset(&saddr, 0, sizeof (saddr));
    248     safe_strncpy(saddr.sa_data, intf, sizeof (saddr.sa_data));
     237    //memset(&saddr, 0, sizeof(saddr));
     238    safe_strncpy(saddr.sa_data, intf, sizeof(saddr.sa_data));
    249239
    250240    // open an ARP socket
    251     if ((fd = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))) < 0) {
    252         why = "open";
    253 fail:
    254         foreground = 1;
    255         goto bad;
    256     }
     241    fd = xsocket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP));
    257242    // bind to the interface's ARP socket
    258     if (bind(fd, &saddr, sizeof (saddr)) < 0) {
    259         why = "bind";
    260         goto fail;
    261     } else {
    262         struct ifreq ifr;
    263         unsigned short seed[3];
    264 
    265         // get the interface's ethernet address
    266         memset(&ifr, 0, sizeof (ifr));
    267         strncpy(ifr.ifr_name, intf, sizeof (ifr.ifr_name));
    268         if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
    269             why = "get ethernet address";
    270             goto fail;
    271         }
    272         memcpy(&addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
    273 
    274         // start with some stable ip address, either a function of
    275         // the hardware address or else the last address we used.
    276         // NOTE: the sequence of addresses we try changes only
    277         // depending on when we detect conflicts.
    278         memcpy(seed, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
    279         seed48(seed);
    280         if (ip.s_addr == 0)
    281             pick(&ip);
    282     }
     243    xbind(fd, &saddr, sizeof(saddr));
     244
     245    // get the interface's ethernet address
     246    //memset(&ifr, 0, sizeof(ifr));
     247    strncpy(ifr.ifr_name, intf, sizeof(ifr.ifr_name));
     248    xioctl(fd, SIOCGIFHWADDR, &ifr);
     249    memcpy(&eth_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
     250
     251    // start with some stable ip address, either a function of
     252    // the hardware address or else the last address we used.
     253    // NOTE: the sequence of addresses we try changes only
     254    // depending on when we detect conflicts.
     255    srand(*(unsigned*)&ifr.ifr_hwaddr.sa_data);
     256    if (ip.s_addr == 0)
     257        pick(&ip);
    283258
    284259    // FIXME cases to handle:
     
    287262
    288263    // daemonize now; don't delay system startup
    289     if (!foreground) {
    290         if (daemon(0, verbose) < 0) {
    291             why = "daemon";
    292             goto bad;
    293         }
    294         syslog(LOG_INFO, "start, interface %s", intf);
     264    if (!FOREGROUND) {
     265#if BB_MMU
     266        bb_daemonize(DAEMON_CHDIR_ROOT);
     267#endif
     268        bb_info_msg("start, interface %s", intf);
    295269    }
    296270
     
    305279    while (1) {
    306280        struct pollfd fds[1];
    307         struct timeval tv1;
     281        unsigned deadline_us;
    308282        struct arp_packet p;
     283
     284        int source_ip_conflict = 0;
     285        int target_ip_conflict = 0;
    309286
    310287        fds[0].fd = fd;
     
    312289        fds[0].revents = 0;
    313290
    314         int source_ip_conflict = 0;
    315         int target_ip_conflict = 0;
    316 
    317291        // poll, being ready to adjust current timeout
    318         if (!timeout) {
    319             timeout = ms_rdelay(PROBE_WAIT);
     292        if (!timeout_ms) {
     293            timeout_ms = ms_rdelay(PROBE_WAIT);
    320294            // FIXME setsockopt(fd, SO_ATTACH_FILTER, ...) to
    321295            // make the kernel filter out all packets except
    322296            // ones we'd care about.
    323297        }
    324         // set tv1 to the point in time when we timeout
    325         gettimeofday(&tv1, NULL);
    326         tv1.tv_usec += (timeout % 1000) * 1000;
    327         while (tv1.tv_usec > 1000000) {
    328             tv1.tv_usec -= 1000000;
    329             tv1.tv_sec++;
    330         }
    331         tv1.tv_sec += timeout / 1000;
    332    
    333         VDBG("...wait %ld %s nprobes=%d, nclaims=%d\n",
    334                 timeout, intf, nprobes, nclaims);
    335         switch (poll(fds, 1, timeout)) {
     298        // set deadline_us to the point in time when we timeout
     299        deadline_us = MONOTONIC_US() + timeout_ms * 1000;
     300
     301        VDBG("...wait %d %s nprobes=%u, nclaims=%u\n",
     302                timeout_ms, intf, nprobes, nclaims);
     303        switch (poll(fds, 1, timeout_ms)) {
    336304
    337305        // timeout
     
    340308            switch (state) {
    341309            case PROBE:
    342                 // timeouts in the PROBE state means no conflicting ARP packets
     310                // timeouts in the PROBE state mean no conflicting ARP packets
    343311                // have been received, so we can progress through the states
    344312                if (nprobes < PROBE_NUM) {
    345313                    nprobes++;
    346                     VDBG("probe/%d %s@%s\n",
     314                    VDBG("probe/%u %s@%s\n",
    347315                            nprobes, intf, inet_ntoa(ip));
    348                     (void)arp(fd, &saddr, ARPOP_REQUEST,
    349                             &addr, null_ip,
     316                    arp(fd, &saddr, ARPOP_REQUEST,
     317                            &eth_addr, null_ip,
    350318                            &null_addr, ip);
    351                     timeout = PROBE_MIN * 1000;
    352                     timeout += ms_rdelay(PROBE_MAX
    353                             - PROBE_MIN);
     319                    timeout_ms = PROBE_MIN * 1000;
     320                    timeout_ms += ms_rdelay(PROBE_MAX - PROBE_MIN);
    354321                }
    355322                else {
     
    357324                    state = ANNOUNCE;
    358325                    nclaims = 0;
    359                     VDBG("announce/%d %s@%s\n",
     326                    VDBG("announce/%u %s@%s\n",
    360327                            nclaims, intf, inet_ntoa(ip));
    361                     (void)arp(fd, &saddr, ARPOP_REQUEST,
    362                             &addr, ip,
    363                             &addr, ip);
    364                     timeout = ANNOUNCE_INTERVAL * 1000;
     328                    arp(fd, &saddr, ARPOP_REQUEST,
     329                            &eth_addr, ip,
     330                            &eth_addr, ip);
     331                    timeout_ms = ANNOUNCE_INTERVAL * 1000;
    365332                }
    366333                break;
    367334            case RATE_LIMIT_PROBE:
    368                 // timeouts in the RATE_LIMIT_PROBE state means no conflicting ARP packets
     335                // timeouts in the RATE_LIMIT_PROBE state mean no conflicting ARP packets
    369336                // have been received, so we can move immediately to the announce state
    370337                state = ANNOUNCE;
    371338                nclaims = 0;
    372                 VDBG("announce/%d %s@%s\n",
     339                VDBG("announce/%u %s@%s\n",
    373340                        nclaims, intf, inet_ntoa(ip));
    374                 (void)arp(fd, &saddr, ARPOP_REQUEST,
    375                         &addr, ip,
    376                         &addr, ip);
    377                 timeout = ANNOUNCE_INTERVAL * 1000;
     341                arp(fd, &saddr, ARPOP_REQUEST,
     342                        &eth_addr, ip,
     343                        &eth_addr, ip);
     344                timeout_ms = ANNOUNCE_INTERVAL * 1000;
    378345                break;
    379346            case ANNOUNCE:
    380                 // timeouts in the ANNOUNCE state means no conflicting ARP packets
     347                // timeouts in the ANNOUNCE state mean no conflicting ARP packets
    381348                // have been received, so we can progress through the states
    382349                if (nclaims < ANNOUNCE_NUM) {
    383350                    nclaims++;
    384                     VDBG("announce/%d %s@%s\n",
     351                    VDBG("announce/%u %s@%s\n",
    385352                            nclaims, intf, inet_ntoa(ip));
    386                     (void)arp(fd, &saddr, ARPOP_REQUEST,
    387                             &addr, ip,
    388                             &addr, ip);
    389                     timeout = ANNOUNCE_INTERVAL * 1000;
     353                    arp(fd, &saddr, ARPOP_REQUEST,
     354                            &eth_addr, ip,
     355                            &eth_addr, ip);
     356                    timeout_ms = ANNOUNCE_INTERVAL * 1000;
    390357                }
    391358                else {
     
    394361                    // link is ok to use earlier
    395362                    // FIXME update filters
    396                     run(script, "config", intf, &ip);
     363                    script_av[1] = (char*)"config";
     364                    run(script_av, intf, &ip);
    397365                    ready = 1;
    398366                    conflicts = 0;
    399                     timeout = -1; // Never timeout in the monitor state.
    400 
    401                     // NOTE:  all other exit paths
     367                    timeout_ms = -1; // Never timeout in the monitor state.
     368
     369                    // NOTE: all other exit paths
    402370                    // should deconfig ...
    403                     if (quit)
     371                    if (QUIT)
    404372                        return EXIT_SUCCESS;
    405373                }
     
    408376                // We won!  No ARP replies, so just go back to monitor.
    409377                state = MONITOR;
    410                 timeout = -1;
     378                timeout_ms = -1;
    411379                conflicts = 0;
    412380                break;
     
    415383                state = PROBE;
    416384                pick(&ip);
    417                 timeout = 0;
     385                timeout_ms = 0;
    418386                nprobes = 0;
    419387                nclaims = 0;
     
    425393            // We need to adjust the timeout in case we didn't receive
    426394            // a conflicting packet.
    427             if (timeout > 0) {
    428                 struct timeval tv2;
    429 
    430                 gettimeofday(&tv2, NULL);
    431                 if (timercmp(&tv1, &tv2, <)) {
     395            if (timeout_ms > 0) {
     396                unsigned diff = deadline_us - MONOTONIC_US();
     397                if ((int)(diff) < 0) {
    432398                    // Current time is greater than the expected timeout time.
    433399                    // Should never happen.
    434400                    VDBG("missed an expected timeout\n");
    435                     timeout = 0;
     401                    timeout_ms = 0;
    436402                } else {
    437403                    VDBG("adjusting timeout\n");
    438                     timersub(&tv1, &tv2, &tv1);
    439                     timeout = 1000 * tv1.tv_sec
    440                             + tv1.tv_usec / 1000;
     404                    timeout_ms = diff / 1000;
     405                    if (!timeout_ms) timeout_ms = 1;
    441406                }
    442407            }
     
    446411                    // FIXME: links routinely go down;
    447412                    // this shouldn't necessarily exit.
    448                     bb_error_msg("%s: poll error\n", intf);
     413                    bb_error_msg("%s: poll error", intf);
    449414                    if (ready) {
    450                         run(script, "deconfig",
    451                                 intf, &ip);
     415                        script_av[1] = (char*)"deconfig";
     416                        run(script_av, intf, &ip);
    452417                    }
    453418                    return EXIT_FAILURE;
     
    457422
    458423            // read ARP packet
    459             if (recv(fd, &p, sizeof (p), 0) < 0) {
     424            if (recv(fd, &p, sizeof(p), 0) < 0) {
    460425                why = "recv";
    461426                goto bad;
     
    486451
    487452            if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr)) == 0 &&
    488                 memcmp(&addr, &p.arp.arp_sha, ETH_ALEN) != 0) {
     453                memcmp(&eth_addr, &p.arp.arp_sha, ETH_ALEN) != 0) {
    489454                source_ip_conflict = 1;
    490455            }
    491456            if (memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0 &&
    492457                p.arp.arp_op == htons(ARPOP_REQUEST) &&
    493                 memcmp(&addr, &p.arp.arp_tha, ETH_ALEN) != 0) {
     458                memcmp(&eth_addr, &p.arp.arp_tha, ETH_ALEN) != 0) {
    494459                target_ip_conflict = 1;
    495460            }
    496461
    497             VDBG("state = %d, source ip conflict = %d, target ip conflict = %d\n", 
     462            VDBG("state = %d, source ip conflict = %d, target ip conflict = %d\n",
    498463                state, source_ip_conflict, target_ip_conflict);
    499464            switch (state) {
     
    506471                    if (conflicts >= MAX_CONFLICTS) {
    507472                        VDBG("%s ratelimit\n", intf);
    508                         timeout = RATE_LIMIT_INTERVAL * 1000;
     473                        timeout_ms = RATE_LIMIT_INTERVAL * 1000;
    509474                        state = RATE_LIMIT_PROBE;
    510475                    }
     
    512477                    // restart the whole protocol
    513478                    pick(&ip);
    514                     timeout = 0;
     479                    timeout_ms = 0;
    515480                    nprobes = 0;
    516481                    nclaims = 0;
     
    522487                    VDBG("monitor conflict -- defending\n");
    523488                    state = DEFEND;
    524                     timeout = DEFEND_INTERVAL * 1000;
    525                     (void)arp(fd, &saddr,
     489                    timeout_ms = DEFEND_INTERVAL * 1000;
     490                    arp(fd, &saddr,
    526491                            ARPOP_REQUEST,
    527                             &addr, ip,
    528                             &addr, ip);
     492                            &eth_addr, ip,
     493                            &eth_addr, ip);
    529494                }
    530495                break;
     
    535500                    VDBG("defend conflict -- starting over\n");
    536501                    ready = 0;
    537                     run(script, "deconfig", intf, &ip);
     502                    script_av[1] = (char*)"deconfig";
     503                    run(script_av, intf, &ip);
    538504
    539505                    // restart the whole protocol
    540506                    pick(&ip);
    541                     timeout = 0;
     507                    timeout_ms = 0;
    542508                    nprobes = 0;
    543509                    nclaims = 0;
     
    549515                state = PROBE;
    550516                pick(&ip);
    551                 timeout = 0;
     517                timeout_ms = 0;
    552518                nprobes = 0;
    553519                nclaims = 0;
     
    561527        } // switch poll
    562528    }
    563 bad:
    564     if (foreground)
    565         perror(why);
    566     else
    567         syslog(LOG_ERR, "%s %s, %s error: %s",
    568             bb_applet_name, intf, why, strerror(errno));
     529 bad:
     530    bb_perror_msg("%s, %s", intf, why);
    569531    return EXIT_FAILURE;
    570532}
Note: See TracChangeset for help on using the changeset viewer.