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


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

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

Location:
branches/3.3
Files:
1 edited
1 copied

Legend:

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

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