main.c revision fee9053f6a8a22ff53d59fc7865230ad41fdf760
160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering/* $Id$ */
260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering/***
460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering  This file is part of avahi.
560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering  avahi is free software; you can redistribute it and/or modify it
760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering  under the terms of the GNU Lesser General Public License as
860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering  published by the Free Software Foundation; either version 2.1 of the
960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering  License, or (at your option) any later version.
1060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
1160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering  avahi is distributed in the hope that it will be useful, but WITHOUT
1260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
1460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering  Public License for more details.
1560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
1660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering  You should have received a copy of the GNU Lesser General Public
1760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering  License along with avahi; if not, write to the Free Software
1860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
1960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering  USA.
2060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering***/
2160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
2260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#ifdef HAVE_CONFIG_H
2360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <config.h>
2460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#endif
2560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
2660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <stdlib.h>
2760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <unistd.h>
2860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <sys/socket.h>
2960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <netpacket/packet.h>
3060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <net/ethernet.h>
3160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <fcntl.h>
3260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <time.h>
3360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <assert.h>
3460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <errno.h>
3560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <string.h>
3660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <inttypes.h>
3760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <sys/types.h>
3860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <arpa/inet.h>
3960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <sys/ioctl.h>
4060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <poll.h>
4160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <net/if.h>
4260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
4360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <avahi-common/malloc.h>
4460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <avahi-common/timeval.h>
4560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
4612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering#include <avahi-daemon/setproctitle.h>
4712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
4860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <libdaemon/dfork.h>
4960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <libdaemon/dsignal.h>
5060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <libdaemon/dlog.h>
5160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <libdaemon/dpid.h>
5260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <libdaemon/dexec.h>
5360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
5412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering#include "main.h"
5512874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering#include "iface.h"
5612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
5760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#ifndef __linux__
5860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#error "avahi-autoipd is only available on Linux for now"
5960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#endif
6060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
6160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering/* An implementation of RFC 3927 */
6260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
6360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering/* Constants from the RFC */
6460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define PROBE_WAIT 1
6560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define PROBE_NUM 3
6660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define PROBE_MIN 1
6760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define PROBE_MAX 2
6860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define ANNOUNCE_WAIT 2
6960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define ANNOUNCE_NUM 2
7060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define ANNOUNCE_INTERVAL 2
7160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define MAX_CONFLICTS 10
7260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define RATE_LIMIT_INTERVAL 60
7360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define DEFEND_INTERVAL 10
7460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
7560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define IPV4LL_NETWORK 0xA9FE0000L
7660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define IPV4LL_NETMASK 0xFFFF0000L
7760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define IPV4LL_HOSTMASK 0x0000FFFFL
7860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
7960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define ETHER_ADDRLEN 6
8060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define ARP_PACKET_SIZE (8+4+4+2*ETHER_ADDRLEN)
8160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
8260d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringtypedef enum ArpOperation {
8360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ARP_REQUEST = 1,
8460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ARP_RESPONSE = 2
8560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering} ArpOperation;
8660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
8760d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringtypedef struct ArpPacketInfo {
8860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ArpOperation operation;
8960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
9060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    uint32_t sender_ip_address, target_ip_address;
9160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    uint8_t sender_hw_address[ETHER_ADDRLEN], target_hw_address[ETHER_ADDRLEN];
9260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering} ArpPacketInfo;
9360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
9412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poetteringstatic State state = STATE_START;
9560d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int n_iteration = 0;
9660d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int n_conflict = 0;
9760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
9860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define RANDOM_DEVICE "/dev/urandom"
9960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
10060d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic void init_rand_seed(void) {
10160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    int fd;
10260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    unsigned seed = 0;
10360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
10460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    /* Try to initialize seed from /dev/urandom, to make it a little
10560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering     * less predictable, and to make sure that multiple machines
10660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering     * booted at the same time choose different random seeds.  */
10760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if ((fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) {
10860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        read(fd, &seed, sizeof(seed));
10960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        close(fd);
11060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
11160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
11260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    /* If the initialization failed by some reason, we add the time to the seed */
11360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    seed ^= (unsigned) time(NULL);
11460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
11560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    srand(seed);
11660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
11760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
11860d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic uint32_t pick_addr(uint32_t old_addr) {
11960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    uint32_t addr;
12060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
12160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    do {
12260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        unsigned r = (unsigned) rand();
12360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
12460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        /* Reduce to 16 bits */
12560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        while (r > 0xFFFF)
12660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            r = (r >> 16) ^ (r & 0xFFFF);
12760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
12860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        addr = htonl(IPV4LL_NETWORK | (uint32_t) r);
12960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
13060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    } while (addr == old_addr);
13160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
13260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return addr;
13360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
13460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
13560d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic void* packet_new(const ArpPacketInfo *info, size_t *packet_len) {
13660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    uint8_t *r;
13760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
13860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(info);
13960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(packet_len);
14060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(info->operation == ARP_REQUEST || info->operation == ARP_RESPONSE);
14160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
14260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    *packet_len = ARP_PACKET_SIZE;
14360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    r = avahi_new0(uint8_t, *packet_len);
14460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
14560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    r[1] = 1; /* HTYPE */
14660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    r[2] = 8; /* PTYPE */
14760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    r[4] = ETHER_ADDRLEN; /* HLEN */
14860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    r[5] = 4; /* PLEN */
14960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    r[7] = (uint8_t) info->operation;
15060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
15160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(r+8, info->sender_hw_address, ETHER_ADDRLEN);
15260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(r+14, &info->sender_ip_address, 4);
15360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(r+18, info->target_hw_address, ETHER_ADDRLEN);
15460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(r+24, &info->target_ip_address, 4);
15560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
15660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return r;
15760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
15860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
15960d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic void *packet_new_probe(uint32_t ip_address, const uint8_t*hw_address, size_t *packet_len) {
16060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ArpPacketInfo info;
16160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
16260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(&info, 0, sizeof(info));
16360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    info.operation = ARP_REQUEST;
16460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(info.sender_hw_address, hw_address, ETHER_ADDRLEN);
16560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    info.target_ip_address = ip_address;
16660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
16760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return packet_new(&info, packet_len);
16860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
16960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
17060d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic void *packet_new_announcement(uint32_t ip_address, const uint8_t* hw_address, size_t *packet_len) {
17160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ArpPacketInfo info;
17260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
17360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(&info, 0, sizeof(info));
17460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    info.operation = ARP_REQUEST;
17560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(info.sender_hw_address, hw_address, ETHER_ADDRLEN);
17660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    info.target_ip_address = ip_address;
17760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    info.sender_ip_address = ip_address;
17860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
17960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return packet_new(&info, packet_len);
18060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
18160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
18260d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int packet_parse(const void *data, size_t packet_len, ArpPacketInfo *info) {
18360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    const uint8_t *p = data;
18460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
18560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(data);
18660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
18760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (packet_len < ARP_PACKET_SIZE)
18860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        return -1;
18960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
19060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    /* Check HTYPE and PTYPE */
19160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (p[0] != 0 || p[1] != 1 || p[2] != 8 || p[3] != 0)
19260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        return -1;
19360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
19460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    /* Check HLEN, PLEN, OPERATION */
19560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (p[4] != ETHER_ADDRLEN || p[5] != 4 || p[6] != 0 || (p[7] != 1 && p[7] != 2))
19660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        return -1;
19760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
19860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    info->operation = p[7];
19960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(info->sender_hw_address, p+8, ETHER_ADDRLEN);
20060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(&info->sender_ip_address, p+14, 4);
20160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(info->target_hw_address, p+18, ETHER_ADDRLEN);
20260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(&info->target_ip_address, p+24, 4);
20360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
20460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return 0;
20560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
20660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
20760d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic void set_state(State st, int reset_counter) {
20860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    const char* const state_table[] = {
20912874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        [STATE_START] = "START",
21060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        [STATE_WAITING_PROBE] = "WAITING_PROBE",
21160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        [STATE_PROBING] = "PROBING",
21260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        [STATE_WAITING_ANNOUNCE] = "WAITING_ANNOUNCE",
21360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        [STATE_ANNOUNCING] = "ANNOUNCING",
21460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        [STATE_RUNNING] = "RUNNING",
21560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        [STATE_SLEEPING] = "SLEEPING"
21660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    };
21760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
21860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(st < STATE_MAX);
21960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
22060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (st == state && !reset_counter) {
22160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        n_iteration++;
22260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_DEBUG, "State iteration %s-%i", state_table[state], n_iteration);
22360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    } else {
22460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_DEBUG, "State transition %s-%i -> %s-0", state_table[state], n_iteration, state_table[st]);
22560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        state = st;
22660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        n_iteration = 0;
22760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
22860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
22960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
23060d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int add_address(int iface, uint32_t addr) {
23160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    char buf[64];
23260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
233fee9053f6a8a22ff53d59fc7865230ad41fdf760Lennart Poettering    daemon_log(LOG_INFO, "Configuring address %s", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
23460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return 0;
23560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
23660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
23760d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int remove_address(int iface, uint32_t addr) {
23860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    char buf[64];
23960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
240fee9053f6a8a22ff53d59fc7865230ad41fdf760Lennart Poettering    daemon_log(LOG_INFO, "Unconfiguring address %s", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
24160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return 0;
24260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
24360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
24460d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int open_socket(int iface, uint8_t *hw_address) {
24560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    int fd = -1;
24660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    struct sockaddr_ll sa;
24760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    socklen_t sa_len;
24860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
24960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if ((fd = socket(PF_PACKET, SOCK_DGRAM, 0)) < 0) {
25060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "socket() failed: %s", strerror(errno));
25160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
25260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
25360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
25460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(&sa, 0, sizeof(sa));
25560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_family = AF_PACKET;
25660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_protocol = htons(ETH_P_ARP);
25760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_ifindex = iface;
25860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
25960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (bind(fd, (struct sockaddr*) &sa, sizeof(sa)) < 0) {
26060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "bind() failed: %s", strerror(errno));
26160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
26260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
26360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
26460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa_len = sizeof(sa);
26560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (getsockname(fd, (struct sockaddr*) &sa, &sa_len) < 0) {
26660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "getsockname() failed: %s", strerror(errno));
26760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
26860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
26960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
27060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (sa.sll_halen != ETHER_ADDRLEN) {
27160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "getsockname() returned invalid hardware address.");
27260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
27360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
27460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
27560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(hw_address, sa.sll_addr, ETHER_ADDRLEN);
27660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
27760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return fd;
27860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
27960d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringfail:
28060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (fd >= 0)
28160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        close(fd);
28260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
28360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return -1;
28460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
28560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
28660d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int send_packet(int fd, int iface, void *packet, size_t packet_len) {
28760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    struct sockaddr_ll sa;
28860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
28960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(fd >= 0);
29060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(packet);
29160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(packet_len > 0);
29260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
29360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(&sa, 0, sizeof(sa));
29460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_family = AF_PACKET;
29560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_protocol = htons(ETH_P_ARP);
29660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_ifindex = iface;
29760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_halen = ETHER_ADDRLEN;
29860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(sa.sll_addr, 0xFF, ETHER_ADDRLEN);
29960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
30060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (sendto(fd, packet, packet_len, 0, (struct sockaddr*) &sa, sizeof(sa)) < 0) {
30160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "sendto() failed: %s", strerror(errno));
30260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        return -1;
30360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
30460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
30560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return 0;
30660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
30760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
30860d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int recv_packet(int fd, void **packet, size_t *packet_len) {
30960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    int s;
31060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    struct sockaddr_ll sa;
31160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    socklen_t sa_len;
31260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
31360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(fd >= 0);
31460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(packet);
31560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(packet_len);
31660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
31760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    *packet = NULL;
31860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
31960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (ioctl(fd, FIONREAD, &s) < 0) {
32060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "FIONREAD failed: %s", strerror(errno));
32160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
32260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
32360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
32460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(s > 0);
32560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
32660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    *packet_len = (size_t) s;
32760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    *packet = avahi_new(uint8_t, s);
32860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
32960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa_len = sizeof(sa);
33060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (recvfrom(fd, *packet, s, 0, (struct sockaddr*) &sa, &sa_len) < 0) {
33160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "recvfrom() failed: %s", strerror(errno));
33260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
33360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
33460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
33560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return 0;
33660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
33760d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringfail:
33860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (*packet)
33960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        avahi_free(*packet);
34060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
34160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return -1;
34260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
34360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
34412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poetteringint is_ll_address(uint32_t addr) {
34560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return (ntohl(addr) & IPV4LL_NETMASK) == IPV4LL_NETWORK;
34660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
34760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
34860d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic struct timeval *elapse_time(struct timeval *tv, unsigned msec, unsigned jitter) {
34960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(tv);
35060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
35160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    gettimeofday(tv, NULL);
35260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
35360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (msec)
35460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        avahi_timeval_add(tv, (AvahiUsec) msec*1000);
35560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
35660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (jitter)
35760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        avahi_timeval_add(tv, (AvahiUsec) (jitter*1000.0*rand()/(RAND_MAX+1.0)));
35860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
35960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return tv;
36060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
36160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
36260d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int loop(int iface, uint32_t addr) {
36312874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    enum {
36412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        FD_ARP,
36512874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        FD_IFACE,
36612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        FD_MAX
36712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    };
36812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
36960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    int fd = -1, ret = -1;
37060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    struct timeval next_wakeup;
37160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    int next_wakeup_valid = 0;
37260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    char buf[64];
37360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    void *in_packet = NULL;
37460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    size_t in_packet_len;
37560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    void *out_packet = NULL;
37660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    size_t out_packet_len;
37760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    uint8_t hw_address[ETHER_ADDRLEN];
37812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    struct pollfd pollfds[FD_MAX];
37912874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    int iface_fd;
38012874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    Event event = EVENT_NULL;
38160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
38260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if ((fd = open_socket(iface, hw_address)) < 0)
38360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
38460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
38512874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    if ((iface_fd = iface_init(iface)) < 0)
38612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        goto fail;
38712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
38812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    if (iface_get_initial_state(&state) < 0)
38912874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        goto fail;
39012874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
39160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (addr && !is_ll_address(addr)) {
39260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_WARNING, "Requested address %s is not from IPv4LL range 169.254/16, ignoring.", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
39360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        addr = 0;
39460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
39560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
39660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (!addr) {
39760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        int i;
39860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        uint32_t a = 1;
39960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
40060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        for (i = 0; i < ETHER_ADDRLEN; i++)
40160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            a += hw_address[i]*i;
40260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
40360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        addr = htonl(IPV4LL_NETWORK | (uint32_t) a);
40460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
40560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
40660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    daemon_log(LOG_INFO, "Starting with address %s", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
40760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
40812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    if (state == STATE_SLEEPING)
40912874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        daemon_log(LOG_INFO, "Routable address already assigned, sleeping.");
41012874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
41160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(pollfds, 0, sizeof(pollfds));
41212874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    pollfds[FD_ARP].fd = fd;
41312874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    pollfds[FD_ARP].events = POLLIN;
41412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    pollfds[FD_IFACE].fd = iface_fd;
41512874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    pollfds[FD_IFACE].events = POLLIN;
41660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
41760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    for (;;) {
41860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        int r, timeout;
41960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        AvahiUsec usec;
42060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
42112874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        if (state == STATE_START) {
42260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
42360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            /* First, wait a random time */
42460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            set_state(STATE_WAITING_PROBE, 1);
42560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
42660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            elapse_time(&next_wakeup, 0, PROBE_WAIT*1000);
42760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            next_wakeup_valid = 1;
42860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
42960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else if ((state == STATE_WAITING_PROBE && event == EVENT_TIMEOUT) ||
43060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                   (state == STATE_PROBING && event == EVENT_TIMEOUT && n_iteration < PROBE_NUM-2)) {
43160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
43260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            /* Send a probe */
43360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            out_packet = packet_new_probe(addr, hw_address, &out_packet_len);
43460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            set_state(STATE_PROBING, 0);
43560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
43660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            elapse_time(&next_wakeup, PROBE_MIN*1000, (PROBE_MAX-PROBE_MIN)*1000);
43760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            next_wakeup_valid = 1;
43860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
43960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else if (state == STATE_PROBING && event == EVENT_TIMEOUT && n_iteration >= PROBE_NUM-2) {
44060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
44160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            /* Send the last probe */
44260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            out_packet = packet_new_probe(addr, hw_address, &out_packet_len);
44360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            set_state(STATE_WAITING_ANNOUNCE, 1);
44460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
44560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            elapse_time(&next_wakeup, ANNOUNCE_WAIT*1000, 0);
44660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            next_wakeup_valid = 1;
44760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
44860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else if ((state == STATE_WAITING_ANNOUNCE && event == EVENT_TIMEOUT) ||
44960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                   (state == STATE_ANNOUNCING && event == EVENT_TIMEOUT && n_iteration < ANNOUNCE_NUM-1)) {
45060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
45160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            /* Send announcement packet */
45260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            out_packet = packet_new_announcement(addr, hw_address, &out_packet_len);
45360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            set_state(STATE_ANNOUNCING, 0);
45460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
45560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            elapse_time(&next_wakeup, ANNOUNCE_INTERVAL*1000, 0);
45660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            next_wakeup_valid = 1;
45760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
45860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            if (n_iteration == 0) {
45960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                add_address(iface, addr);
46060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                n_conflict = 0;
46160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            }
46260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
46360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else if ((state == STATE_ANNOUNCING && event == EVENT_TIMEOUT && n_iteration >= ANNOUNCE_NUM-1)) {
46460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
46560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            daemon_log(LOG_INFO, "Successfully claimed IP address %s", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
46660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            set_state(STATE_RUNNING, 0);
467fee9053f6a8a22ff53d59fc7865230ad41fdf760Lennart Poettering
468fee9053f6a8a22ff53d59fc7865230ad41fdf760Lennart Poettering            next_wakeup_valid = 0;
46960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
47060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else if (event == EVENT_PACKET) {
47160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            ArpPacketInfo info;
47260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
47360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            assert(in_packet);
47460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
47560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            if (packet_parse(in_packet, in_packet_len, &info) < 0)
47660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                daemon_log(LOG_WARNING, "Failed to parse incoming ARP packet.");
47760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            else {
47860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                int conflict = 0;
47960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
48060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                if (info.sender_ip_address == addr) {
48160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    /* Normal conflict */
48260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    conflict = 1;
48360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    daemon_log(LOG_INFO, "Recieved conflicting normal ARP packet.");
48460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                } else if (state == STATE_WAITING_PROBE || state == STATE_PROBING || state == STATE_WAITING_ANNOUNCE) {
48560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    /* Probe conflict */
48660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    conflict = info.target_ip_address == addr && memcmp(hw_address, info.sender_hw_address, ETHER_ADDRLEN);
48760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    daemon_log(LOG_INFO, "Recieved conflicting probe ARP packet.");
48860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                }
48960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
49060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                if (conflict) {
49160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
49260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    if (state == STATE_RUNNING || state == STATE_ANNOUNCING)
49360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                        remove_address(iface, addr);
49460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
49560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    /* Pick a new address */
49660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    addr = pick_addr(addr);
49760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
49860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    daemon_log(LOG_INFO, "Trying address %s", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
49960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
50060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    n_conflict++;
50160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
50212874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering                    set_state(STATE_WAITING_PROBE, 1);
50312874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
50460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    if (n_conflict >= MAX_CONFLICTS) {
50560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                        daemon_log(LOG_WARNING, "Got too many conflicts, rate limiting new probes.");
50660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                        elapse_time(&next_wakeup, RATE_LIMIT_INTERVAL*1000, PROBE_WAIT*1000);
50760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    } else
50860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                        elapse_time(&next_wakeup, 0, PROBE_WAIT*1000);
50960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
51060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    next_wakeup_valid = 1;
51160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                } else
51260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    daemon_log(LOG_DEBUG, "Ignoring ARP packet.");
51360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            }
51412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
51512874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        } else if (event == EVENT_ROUTABLE_ADDR_CONFIGURED) {
51612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
51712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            daemon_log(LOG_INFO, "A routable address has been configured.");
51812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
51912874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            if (state == STATE_RUNNING || state == STATE_ANNOUNCING)
52012874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering                remove_address(iface, addr);
521fee9053f6a8a22ff53d59fc7865230ad41fdf760Lennart Poettering
522fee9053f6a8a22ff53d59fc7865230ad41fdf760Lennart Poettering            set_state(STATE_SLEEPING, 1);
523fee9053f6a8a22ff53d59fc7865230ad41fdf760Lennart Poettering            next_wakeup_valid = 0;
52412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
52512874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        } else if (event == EVENT_ROUTABLE_ADDR_UNCONFIGURED && state == STATE_SLEEPING) {
52612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
52712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            daemon_log(LOG_INFO, "No longer a routable address configured, restarting probe process.");
52812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
52912874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            set_state(STATE_WAITING_PROBE, 1);
53012874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
53112874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            elapse_time(&next_wakeup, 0, PROBE_WAIT*1000);
53212874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            next_wakeup_valid = 1;
53312874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
53460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        }
53560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
53660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        if (out_packet) {
53760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            daemon_log(LOG_DEBUG, "sending...");
53860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
53960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            if (send_packet(fd, iface, out_packet, out_packet_len) < 0)
54060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                goto fail;
54160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
54260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            avahi_free(out_packet);
54360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            out_packet = NULL;
54460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        }
54560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
54660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        if (in_packet) {
54760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            avahi_free(in_packet);
54860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            in_packet = NULL;
54960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        }
55060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
55112874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        event = EVENT_NULL;
55260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        timeout = -1;
55360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
55460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        if (next_wakeup_valid) {
55560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            usec = avahi_age(&next_wakeup);
55660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            timeout = usec < 0 ? (int) (-usec/1000) : 0;
55760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        }
55860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
55960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_DEBUG, "sleeping %ims", timeout);
56060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
56112874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        while ((r = poll(pollfds, FD_MAX, timeout)) < 0 && errno == EINTR)
56260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            ;
56360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
56460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        if (r < 0) {
56560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            daemon_log(LOG_ERR, "poll() failed: %s", strerror(r));
56660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            break;
56760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else if (r == 0) {
56860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            event = EVENT_TIMEOUT;
56960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            next_wakeup_valid = 0;
57060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else {
57160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
57212874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            if (pollfds[FD_ARP].revents == POLLIN) {
57312874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering                if (recv_packet(fd, &in_packet, &in_packet_len) < 0)
57412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering                    goto fail;
57512874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
57612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering                if (in_packet)
57712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering                    event = EVENT_PACKET;
57812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            }
57960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
58012874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            if (event == EVENT_NULL &&
58112874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering                pollfds[FD_IFACE].revents == POLLIN) {
58212874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
58312874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering                if (iface_process(&event) < 0)
58412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering                    goto fail;
58512874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            }
58660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        }
58760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
58860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
58960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ret = 0;
59060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
59160d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringfail:
59260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
59360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    avahi_free(out_packet);
59460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    avahi_free(in_packet);
59560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
59660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (fd >= 0)
59760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        close(fd);
59812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
59912874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    if (iface_fd >= 0)
60012874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        iface_done();
60160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
60260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return ret;
60360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
60460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
60560d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int get_ifindex(const char *name) {
60660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    int fd = -1;
60760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    struct ifreq ifreq;
60860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
60960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
61060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "socket() failed: %s", strerror(errno));
61160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
61260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
61360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
61460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(&ifreq, 0, sizeof(ifreq));
61560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    strncpy(ifreq.ifr_name, name, IFNAMSIZ-1);
61660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ifreq.ifr_name[IFNAMSIZ-1] = 0;
61760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
61860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (ioctl(fd, SIOCGIFINDEX, &ifreq) < 0) {
61960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "SIOCGIFINDEX failed: %s", strerror(errno));
62060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
62160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
62260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
62360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return ifreq.ifr_ifindex;
62460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
62560d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringfail:
62660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
62760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (fd >= 0)
62860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        close(fd);
62960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
63060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return -1;
63160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
63260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
63360d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringint main(int argc, char*argv[]) {
63460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    int ret = 1;
63560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    int ifindex;
63660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    uint32_t addr = 0;
63760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
63812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    avahi_init_proc_title(argc, argv);
63912874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
64060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    init_rand_seed();
64160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
64260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if ((ifindex = get_ifindex(argc >= 2 ? argv[1] : "eth0")) < 0)
64360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
64460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
64560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (argc >= 3)
64660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        addr = inet_addr(argv[2]);
64760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
64860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (loop(ifindex, addr) < 0)
64960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
65060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
65160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ret = 0;
65260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
65360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
65460d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringfail:
65560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
65660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return ret;
65760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
65860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
65960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering/* TODO:
66060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
66160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering- man page
66260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering- user script
66360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering- chroot/drop privs/caps
66460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering- daemonize
66560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering- defend
66660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering- signals
66760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering- store last used address
66860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering- cmdline
66912874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering- setproctitle
67060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
67160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering*/
672