X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=avahi-autoipd%2Fmain.c;h=60fc8aa01719cf7a971060d0984d8f57935e8e2e;hb=1d4f819072e901518309aff781f9f1e7272dca87;hp=4c3b0ebe5adeb7dd1c1da8026ce3a564a651eb16;hpb=9ce608107192e885eb8de93290f7faf0bf9176a2;p=catta diff --git a/avahi-autoipd/main.c b/avahi-autoipd/main.c index 4c3b0eb..60fc8aa 100644 --- a/avahi-autoipd/main.c +++ b/avahi-autoipd/main.c @@ -81,6 +81,7 @@ #define IPV4LL_NETWORK 0xA9FE0000L #define IPV4LL_NETMASK 0xFFFF0000L #define IPV4LL_HOSTMASK 0x0000FFFFL +#define IPV4LL_BROADCAST 0xA9FEFFFFL #define ETHER_ADDRLEN 6 #define ARP_PACKET_SIZE (8+4+4+2*ETHER_ADDRLEN) @@ -185,11 +186,69 @@ static uint32_t pick_addr(uint32_t old_addr) { addr = htonl(IPV4LL_NETWORK | (uint32_t) r); - } while (addr == old_addr); + } while (addr == old_addr || !is_ll_address(addr)); return addr; } +static int load_address(const char *fn, uint32_t *addr) { + FILE *f; + unsigned a, b, c, d; + + assert(fn); + assert(addr); + + if (!(f = fopen(fn, "r"))) { + + if (errno == ENOENT) { + *addr = 0; + return 0; + } + + daemon_log(LOG_ERR, "fopen() failed: %s", strerror(errno)); + goto fail; + } + + if (fscanf(f, "%u.%u.%u.%u\n", &a, &b, &c, &d) != 4) { + daemon_log(LOG_ERR, "Parse failure"); + goto fail; + } + + fclose(f); + + *addr = htonl((a << 24) | (b << 16) | (c << 8) | d); + return 0; + +fail: + if (f) + fclose(f); + + return -1; +} + +static int save_address(const char *fn, uint32_t addr) { + FILE *f; + char buf[32]; + + assert(fn); + + if (!(f = fopen(fn, "w"))) { + daemon_log(LOG_ERR, "fopen() failed: %s", strerror(errno)); + goto fail; + } + + fprintf(f, "%s\n", inet_ntop(AF_INET, &addr, buf, sizeof (buf))); + fclose(f); + + return 0; + +fail: + if (f) + fclose(f); + + return -1; +} + static void* packet_new(const ArpPacketInfo *info, size_t *packet_len) { uint8_t *r; @@ -442,7 +501,10 @@ fail: } int is_ll_address(uint32_t addr) { - return (ntohl(addr) & IPV4LL_NETMASK) == IPV4LL_NETWORK; + return + (ntohl(addr) & IPV4LL_NETMASK) == IPV4LL_NETWORK && + ntohl(addr) != IPV4LL_NETWORK && + ntohl(addr) != IPV4LL_BROADCAST; } static struct timeval *elapse_time(struct timeval *tv, unsigned msec, unsigned jitter) { @@ -729,6 +791,8 @@ static int loop(int iface, uint32_t addr) { int retval_sent = !daemonize; State st; FILE *dispatcher = NULL; + char *address_fn = NULL; + const char *p; daemon_signal_init(SIGINT, SIGTERM, SIGCHLD, SIGHUP,0); @@ -749,6 +813,22 @@ static int loop(int iface, uint32_t addr) { else if (iface_get_initial_state(&st) < 0) goto fail; +#ifdef HAVE_CHROOT + if (!no_chroot) + p = ""; + else +#endif + p = AVAHI_IPDATA_DIR; + + address_fn = avahi_strdup_printf( + "%s/%02x:%02x:%02x:%02x:%02x:%02x", p, + hw_address[0], hw_address[1], + hw_address[2], hw_address[3], + hw_address[4], hw_address[5]); + + if (!addr) + load_address(address_fn, &addr); + if (addr && !is_ll_address(addr)) { daemon_log(LOG_WARNING, "Requested address %s is not from IPv4LL range 169.254/16, ignoring.", inet_ntop(AF_INET, &addr, buf, sizeof(buf))); addr = 0; @@ -830,11 +910,6 @@ static int loop(int iface, uint32_t addr) { goto fail; n_conflict = 0; - - if (!retval_sent) { - daemon_retval_send(0); - retval_sent = 1; - } } } else if ((state == STATE_ANNOUNCING && event == EVENT_TIMEOUT && n_iteration >= ANNOUNCE_NUM-1)) { @@ -843,7 +918,14 @@ static int loop(int iface, uint32_t addr) { set_state(STATE_RUNNING, 0, addr); next_wakeup_valid = 0; + + save_address(address_fn, addr); + if (!retval_sent) { + daemon_retval_send(0); + retval_sent = 1; + } + } else if (event == EVENT_PACKET) { ArpPacketInfo info; @@ -861,7 +943,9 @@ static int loop(int iface, uint32_t addr) { } else if (state == STATE_WAITING_PROBE || state == STATE_PROBING || state == STATE_WAITING_ANNOUNCE) { /* Probe conflict */ conflict = info.target_ip_address == addr && memcmp(hw_address, info.sender_hw_address, ETHER_ADDRLEN); - daemon_log(LOG_INFO, "Recieved conflicting probe ARP packet."); + + if (conflict) + daemon_log(LOG_INFO, "Recieved conflicting probe ARP packet."); } if (conflict) { @@ -1050,6 +1134,9 @@ fail: if (dispatcher) fclose(dispatcher); + + if (address_fn) + avahi_free(address_fn); return ret; } @@ -1069,7 +1156,7 @@ static void help(FILE *f, const char *a0) { " 169.254.0.0/16\n" " -w --wait Wait until an address has been acquired before\n" " daemonizing\n" - " --force-bind Assign an IPv4LL address even if routable address\n" + " --force-bind Assign an IPv4LL address even if a routable address\n" " is already assigned\n" " --no-drop-root Don't drop privileges\n" #ifdef HAVE_CHROOT @@ -1172,7 +1259,7 @@ static int parse_command_line(int argc, char *argv[]) { #endif default: - fprintf(stderr, "Invalid command line argument: %c\n", c); + fprintf(stderr, "Invalid command line argument: %s\n", argv[optind-1]); return -1; } } @@ -1328,10 +1415,3 @@ finish: return r; } - -/* TODO: - -- store last used address -- man page - -*/