main.c revision 5ea98f8caf0e163ad1f51039b8a2d13e3fe0e86c
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>
425ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering#include <stdio.h>
435ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering#include <getopt.h>
445ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering#include <signal.h>
455ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering#include <sys/wait.h>
4660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
4760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <avahi-common/malloc.h>
4860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <avahi-common/timeval.h>
4960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
5012874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering#include <avahi-daemon/setproctitle.h>
5112874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
5260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <libdaemon/dfork.h>
5360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <libdaemon/dsignal.h>
5460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <libdaemon/dlog.h>
5560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <libdaemon/dpid.h>
5660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <libdaemon/dexec.h>
5760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
5812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering#include "main.h"
5912874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering#include "iface.h"
6012874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
6160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#ifndef __linux__
6260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#error "avahi-autoipd is only available on Linux for now"
6360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#endif
6460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
6560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering/* An implementation of RFC 3927 */
6660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
6760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering/* Constants from the RFC */
6860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define PROBE_WAIT 1
6960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define PROBE_NUM 3
7060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define PROBE_MIN 1
7160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define PROBE_MAX 2
7260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define ANNOUNCE_WAIT 2
7360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define ANNOUNCE_NUM 2
7460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define ANNOUNCE_INTERVAL 2
7560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define MAX_CONFLICTS 10
7660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define RATE_LIMIT_INTERVAL 60
7760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define DEFEND_INTERVAL 10
7860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
7960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define IPV4LL_NETWORK 0xA9FE0000L
8060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define IPV4LL_NETMASK 0xFFFF0000L
8160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define IPV4LL_HOSTMASK 0x0000FFFFL
8260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
8360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define ETHER_ADDRLEN 6
8460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define ARP_PACKET_SIZE (8+4+4+2*ETHER_ADDRLEN)
8560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
8660d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringtypedef enum ArpOperation {
8760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ARP_REQUEST = 1,
8860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ARP_RESPONSE = 2
8960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering} ArpOperation;
9060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
9160d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringtypedef struct ArpPacketInfo {
9260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ArpOperation operation;
9360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
9460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    uint32_t sender_ip_address, target_ip_address;
9560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    uint8_t sender_hw_address[ETHER_ADDRLEN], target_hw_address[ETHER_ADDRLEN];
9660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering} ArpPacketInfo;
9760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
9812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poetteringstatic State state = STATE_START;
9960d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int n_iteration = 0;
10060d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int n_conflict = 0;
10160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
1025ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic char *interface_name = NULL;
1035ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic char *pid_file_name = NULL;
1045ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic uint32_t start_address = 0;
1055ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic char *argv0 = NULL;
1065ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic int daemonize = 0;
1075ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic int wait_for_address = 0;
1085ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic int use_syslog = 0;
1095ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic int debug = 0;
1105ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic int modify_proc_title = 1;
1115ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
1125ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic enum {
1135ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    DAEMON_RUN,
1145ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    DAEMON_KILL,
1155ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    DAEMON_REFRESH,
1165ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    DAEMON_VERSION,
1175ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    DAEMON_HELP,
1185ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    DAEMON_CHECK
1195ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering} command = DAEMON_RUN;
1205ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
1215ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringtypedef enum CalloutEvent {
1225ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    CALLOUT_BIND,
1235ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    CALLOUT_CONFLICT,
1245ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    CALLOUT_UNBIND,
1255ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    CALLOUT_STOP,
1265ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    CALLOUT_MAX
1275ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering} CalloutEvent;
1285ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
12960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define RANDOM_DEVICE "/dev/urandom"
13060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
1315ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering#define DEBUG(x) do {\
1325ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringif (debug) { \
1335ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    x; \
1345ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering} \
1355ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering} while (0)
1365ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
13760d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic void init_rand_seed(void) {
13860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    int fd;
13960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    unsigned seed = 0;
14060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
14160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    /* Try to initialize seed from /dev/urandom, to make it a little
14260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering     * less predictable, and to make sure that multiple machines
14360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering     * booted at the same time choose different random seeds.  */
14460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if ((fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) {
14560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        read(fd, &seed, sizeof(seed));
14660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        close(fd);
14760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
14860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
14960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    /* If the initialization failed by some reason, we add the time to the seed */
15060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    seed ^= (unsigned) time(NULL);
15160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
15260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    srand(seed);
15360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
15460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
15560d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic uint32_t pick_addr(uint32_t old_addr) {
15660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    uint32_t addr;
15760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
15860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    do {
15960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        unsigned r = (unsigned) rand();
16060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
16160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        /* Reduce to 16 bits */
16260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        while (r > 0xFFFF)
16360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            r = (r >> 16) ^ (r & 0xFFFF);
16460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
16560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        addr = htonl(IPV4LL_NETWORK | (uint32_t) r);
16660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
16760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    } while (addr == old_addr);
16860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
16960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return addr;
17060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
17160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
17260d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic void* packet_new(const ArpPacketInfo *info, size_t *packet_len) {
17360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    uint8_t *r;
17460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
17560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(info);
17660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(packet_len);
17760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(info->operation == ARP_REQUEST || info->operation == ARP_RESPONSE);
17860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
17960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    *packet_len = ARP_PACKET_SIZE;
18060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    r = avahi_new0(uint8_t, *packet_len);
18160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
18260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    r[1] = 1; /* HTYPE */
18360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    r[2] = 8; /* PTYPE */
18460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    r[4] = ETHER_ADDRLEN; /* HLEN */
18560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    r[5] = 4; /* PLEN */
18660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    r[7] = (uint8_t) info->operation;
18760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
18860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(r+8, info->sender_hw_address, ETHER_ADDRLEN);
18960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(r+14, &info->sender_ip_address, 4);
19060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(r+18, info->target_hw_address, ETHER_ADDRLEN);
19160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(r+24, &info->target_ip_address, 4);
19260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
19360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return r;
19460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
19560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
19660d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic void *packet_new_probe(uint32_t ip_address, const uint8_t*hw_address, size_t *packet_len) {
19760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ArpPacketInfo info;
19860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
19960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(&info, 0, sizeof(info));
20060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    info.operation = ARP_REQUEST;
20160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(info.sender_hw_address, hw_address, ETHER_ADDRLEN);
20260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    info.target_ip_address = ip_address;
20360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
20460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return packet_new(&info, packet_len);
20560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
20660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
20760d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic void *packet_new_announcement(uint32_t ip_address, const uint8_t* hw_address, size_t *packet_len) {
20860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ArpPacketInfo info;
20960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
21060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(&info, 0, sizeof(info));
21160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    info.operation = ARP_REQUEST;
21260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(info.sender_hw_address, hw_address, ETHER_ADDRLEN);
21360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    info.target_ip_address = ip_address;
21460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    info.sender_ip_address = ip_address;
21560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
21660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return packet_new(&info, packet_len);
21760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
21860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
21960d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int packet_parse(const void *data, size_t packet_len, ArpPacketInfo *info) {
22060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    const uint8_t *p = data;
22160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
22260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(data);
22360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
22460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (packet_len < ARP_PACKET_SIZE)
22560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        return -1;
22660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
22760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    /* Check HTYPE and PTYPE */
22860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (p[0] != 0 || p[1] != 1 || p[2] != 8 || p[3] != 0)
22960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        return -1;
23060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
23160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    /* Check HLEN, PLEN, OPERATION */
23260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (p[4] != ETHER_ADDRLEN || p[5] != 4 || p[6] != 0 || (p[7] != 1 && p[7] != 2))
23360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        return -1;
23460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
23560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    info->operation = p[7];
23660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(info->sender_hw_address, p+8, ETHER_ADDRLEN);
23760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(&info->sender_ip_address, p+14, 4);
23860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(info->target_hw_address, p+18, ETHER_ADDRLEN);
23960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(&info->target_ip_address, p+24, 4);
24060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
24160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return 0;
24260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
24360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
2445ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic void set_state(State st, int reset_counter, uint32_t address) {
24560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    const char* const state_table[] = {
24612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        [STATE_START] = "START",
24760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        [STATE_WAITING_PROBE] = "WAITING_PROBE",
24860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        [STATE_PROBING] = "PROBING",
24960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        [STATE_WAITING_ANNOUNCE] = "WAITING_ANNOUNCE",
25060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        [STATE_ANNOUNCING] = "ANNOUNCING",
25160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        [STATE_RUNNING] = "RUNNING",
25260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        [STATE_SLEEPING] = "SLEEPING"
25360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    };
2545ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    char buf[64];
25560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
25660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(st < STATE_MAX);
25760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
25860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (st == state && !reset_counter) {
25960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        n_iteration++;
2605ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        DEBUG(daemon_log(LOG_DEBUG, "State iteration %s-%i", state_table[state], n_iteration));
26160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    } else {
2625ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        DEBUG(daemon_log(LOG_DEBUG, "State transition %s-%i -> %s-0", state_table[state], n_iteration, state_table[st]));
26360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        state = st;
26460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        n_iteration = 0;
26560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
26660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
2675ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (modify_proc_title) {
2685ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if (state == STATE_SLEEPING)
2695ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            avahi_set_proc_title("%s: sleeping", argv0);
2705ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        else if (state == STATE_ANNOUNCING)
2715ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            avahi_set_proc_title("%s: announcing %s", argv0, inet_ntop(AF_INET, &address, buf, sizeof(buf)));
2725ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        else if (state == STATE_RUNNING)
2735ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            avahi_set_proc_title("%s: bound %s", argv0, inet_ntop(AF_INET, &address, buf, sizeof(buf)));
2745ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        else
2755ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            avahi_set_proc_title("%s: probing %s", argv0, inet_ntop(AF_INET, &address, buf, sizeof(buf)));
2765ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    }
27760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
27860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
2795ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic int do_callout(CalloutEvent event, int iface, uint32_t addr) {
2805ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    char buf[64], ifname[IFNAMSIZ];
2815ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    const char * const event_table[CALLOUT_MAX] = {
2825ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        [CALLOUT_BIND] = "BIND",
2835ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        [CALLOUT_CONFLICT] = "CONFLICT",
2845ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        [CALLOUT_UNBIND] = "UNBIND",
2855ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        [CALLOUT_STOP] = "STOP"
2865ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    };
2875ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
2885ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    daemon_log(LOG_INFO, "Callout %s, address %s on interface %s",
2895ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering               event_table[event],
2905ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering               inet_ntop(AF_INET, &addr, buf, sizeof(buf)),
2915ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering               if_indextoname(iface, ifname));
29260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
29360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return 0;
29460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
29560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
29660d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int open_socket(int iface, uint8_t *hw_address) {
29760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    int fd = -1;
29860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    struct sockaddr_ll sa;
29960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    socklen_t sa_len;
30060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
30160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if ((fd = socket(PF_PACKET, SOCK_DGRAM, 0)) < 0) {
30260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "socket() failed: %s", strerror(errno));
30360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
30460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
30560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
30660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(&sa, 0, sizeof(sa));
30760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_family = AF_PACKET;
30860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_protocol = htons(ETH_P_ARP);
30960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_ifindex = iface;
31060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
31160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (bind(fd, (struct sockaddr*) &sa, sizeof(sa)) < 0) {
31260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "bind() failed: %s", strerror(errno));
31360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
31460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
31560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
31660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa_len = sizeof(sa);
31760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (getsockname(fd, (struct sockaddr*) &sa, &sa_len) < 0) {
31860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "getsockname() failed: %s", strerror(errno));
31960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
32060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
32160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
32260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (sa.sll_halen != ETHER_ADDRLEN) {
32360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "getsockname() returned invalid hardware address.");
32460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
32560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
32660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
32760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(hw_address, sa.sll_addr, ETHER_ADDRLEN);
32860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
32960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return fd;
33060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
33160d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringfail:
33260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (fd >= 0)
33360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        close(fd);
33460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
33560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return -1;
33660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
33760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
33860d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int send_packet(int fd, int iface, void *packet, size_t packet_len) {
33960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    struct sockaddr_ll sa;
34060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
34160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(fd >= 0);
34260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(packet);
34360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(packet_len > 0);
34460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
34560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(&sa, 0, sizeof(sa));
34660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_family = AF_PACKET;
34760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_protocol = htons(ETH_P_ARP);
34860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_ifindex = iface;
34960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_halen = ETHER_ADDRLEN;
35060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(sa.sll_addr, 0xFF, ETHER_ADDRLEN);
35160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
35260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (sendto(fd, packet, packet_len, 0, (struct sockaddr*) &sa, sizeof(sa)) < 0) {
35360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "sendto() failed: %s", strerror(errno));
35460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        return -1;
35560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
35660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
35760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return 0;
35860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
35960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
36060d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int recv_packet(int fd, void **packet, size_t *packet_len) {
36160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    int s;
36260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    struct sockaddr_ll sa;
36360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    socklen_t sa_len;
36460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
36560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(fd >= 0);
36660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(packet);
36760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(packet_len);
36860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
36960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    *packet = NULL;
37060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
37160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (ioctl(fd, FIONREAD, &s) < 0) {
37260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "FIONREAD failed: %s", strerror(errno));
37360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
37460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
37560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
37660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(s > 0);
37760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
37860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    *packet_len = (size_t) s;
37960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    *packet = avahi_new(uint8_t, s);
38060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
38160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa_len = sizeof(sa);
38260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (recvfrom(fd, *packet, s, 0, (struct sockaddr*) &sa, &sa_len) < 0) {
38360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "recvfrom() failed: %s", strerror(errno));
38460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
38560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
38660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
38760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return 0;
38860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
38960d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringfail:
39060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (*packet)
39160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        avahi_free(*packet);
39260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
39360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return -1;
39460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
39560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
39612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poetteringint is_ll_address(uint32_t addr) {
39760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return (ntohl(addr) & IPV4LL_NETMASK) == IPV4LL_NETWORK;
39860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
39960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
40060d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic struct timeval *elapse_time(struct timeval *tv, unsigned msec, unsigned jitter) {
40160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(tv);
40260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
40360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    gettimeofday(tv, NULL);
40460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
40560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (msec)
40660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        avahi_timeval_add(tv, (AvahiUsec) msec*1000);
40760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
40860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (jitter)
40960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        avahi_timeval_add(tv, (AvahiUsec) (jitter*1000.0*rand()/(RAND_MAX+1.0)));
41060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
41160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return tv;
41260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
41360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
41460d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int loop(int iface, uint32_t addr) {
41512874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    enum {
41612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        FD_ARP,
41712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        FD_IFACE,
4185ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        FD_SIGNAL,
4195ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        FD_MAX,
42012874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    };
42112874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
42260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    int fd = -1, ret = -1;
42360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    struct timeval next_wakeup;
42460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    int next_wakeup_valid = 0;
42560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    char buf[64];
42660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    void *in_packet = NULL;
42760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    size_t in_packet_len;
42860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    void *out_packet = NULL;
42960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    size_t out_packet_len;
43060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    uint8_t hw_address[ETHER_ADDRLEN];
43112874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    struct pollfd pollfds[FD_MAX];
43212874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    int iface_fd;
43312874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    Event event = EVENT_NULL;
4345ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    int retval_sent = !daemonize;
4355ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    State st;
4365ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
4375ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    daemon_signal_init(SIGINT, SIGTERM, SIGCHLD, SIGHUP,0);
43860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
43960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if ((fd = open_socket(iface, hw_address)) < 0)
44060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
44160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
44212874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    if ((iface_fd = iface_init(iface)) < 0)
44312874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        goto fail;
44412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
4455ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (iface_get_initial_state(&st) < 0)
44612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        goto fail;
4475ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
44860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (addr && !is_ll_address(addr)) {
44960d86f779725e78ae3d295380f15208859cc06ebLennart 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)));
45060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        addr = 0;
45160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
45260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
45360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (!addr) {
45460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        int i;
45560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        uint32_t a = 1;
45660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
45760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        for (i = 0; i < ETHER_ADDRLEN; i++)
45860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            a += hw_address[i]*i;
45960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
46060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        addr = htonl(IPV4LL_NETWORK | (uint32_t) a);
46160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
46260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
4635ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    set_state(st, 1, addr);
4645ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
46560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    daemon_log(LOG_INFO, "Starting with address %s", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
46660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
46712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    if (state == STATE_SLEEPING)
46812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        daemon_log(LOG_INFO, "Routable address already assigned, sleeping.");
46912874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
4705ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (!retval_sent && (!wait_for_address || state == STATE_SLEEPING)) {
4715ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        daemon_retval_send(0);
4725ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        retval_sent = 1;
4735ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    }
4745ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
47560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(pollfds, 0, sizeof(pollfds));
47612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    pollfds[FD_ARP].fd = fd;
47712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    pollfds[FD_ARP].events = POLLIN;
47812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    pollfds[FD_IFACE].fd = iface_fd;
47912874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    pollfds[FD_IFACE].events = POLLIN;
4805ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    pollfds[FD_SIGNAL].fd = daemon_signal_fd();
4815ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    pollfds[FD_SIGNAL].events = POLLIN;
48260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
48360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    for (;;) {
48460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        int r, timeout;
48560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        AvahiUsec usec;
48660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
48712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        if (state == STATE_START) {
48860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
48960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            /* First, wait a random time */
4905ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            set_state(STATE_WAITING_PROBE, 1, addr);
49160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
49260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            elapse_time(&next_wakeup, 0, PROBE_WAIT*1000);
49360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            next_wakeup_valid = 1;
49460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
49560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else if ((state == STATE_WAITING_PROBE && event == EVENT_TIMEOUT) ||
49660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                   (state == STATE_PROBING && event == EVENT_TIMEOUT && n_iteration < PROBE_NUM-2)) {
49760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
49860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            /* Send a probe */
49960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            out_packet = packet_new_probe(addr, hw_address, &out_packet_len);
5005ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            set_state(STATE_PROBING, 0, addr);
50160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
50260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            elapse_time(&next_wakeup, PROBE_MIN*1000, (PROBE_MAX-PROBE_MIN)*1000);
50360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            next_wakeup_valid = 1;
50460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
50560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else if (state == STATE_PROBING && event == EVENT_TIMEOUT && n_iteration >= PROBE_NUM-2) {
50660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
50760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            /* Send the last probe */
50860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            out_packet = packet_new_probe(addr, hw_address, &out_packet_len);
5095ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            set_state(STATE_WAITING_ANNOUNCE, 1, addr);
51060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
51160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            elapse_time(&next_wakeup, ANNOUNCE_WAIT*1000, 0);
51260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            next_wakeup_valid = 1;
51360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
51460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else if ((state == STATE_WAITING_ANNOUNCE && event == EVENT_TIMEOUT) ||
51560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                   (state == STATE_ANNOUNCING && event == EVENT_TIMEOUT && n_iteration < ANNOUNCE_NUM-1)) {
51660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
51760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            /* Send announcement packet */
51860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            out_packet = packet_new_announcement(addr, hw_address, &out_packet_len);
5195ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            set_state(STATE_ANNOUNCING, 0, addr);
52060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
52160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            elapse_time(&next_wakeup, ANNOUNCE_INTERVAL*1000, 0);
52260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            next_wakeup_valid = 1;
52360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
52460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            if (n_iteration == 0) {
5255ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                do_callout(CALLOUT_BIND, iface, addr);
52660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                n_conflict = 0;
5275ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
5285ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                if (!retval_sent) {
5295ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    daemon_retval_send(0);
5305ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    retval_sent = 1;
5315ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                }
53260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            }
53360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
53460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else if ((state == STATE_ANNOUNCING && event == EVENT_TIMEOUT && n_iteration >= ANNOUNCE_NUM-1)) {
53560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
53660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            daemon_log(LOG_INFO, "Successfully claimed IP address %s", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
5375ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            set_state(STATE_RUNNING, 0, addr);
538fee9053f6a8a22ff53d59fc7865230ad41fdf760Lennart Poettering
539fee9053f6a8a22ff53d59fc7865230ad41fdf760Lennart Poettering            next_wakeup_valid = 0;
54060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
54160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else if (event == EVENT_PACKET) {
54260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            ArpPacketInfo info;
54360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
54460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            assert(in_packet);
54560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
54660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            if (packet_parse(in_packet, in_packet_len, &info) < 0)
54760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                daemon_log(LOG_WARNING, "Failed to parse incoming ARP packet.");
54860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            else {
54960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                int conflict = 0;
55060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
55160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                if (info.sender_ip_address == addr) {
55260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    /* Normal conflict */
55360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    conflict = 1;
55460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    daemon_log(LOG_INFO, "Recieved conflicting normal ARP packet.");
55560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                } else if (state == STATE_WAITING_PROBE || state == STATE_PROBING || state == STATE_WAITING_ANNOUNCE) {
55660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    /* Probe conflict */
55760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    conflict = info.target_ip_address == addr && memcmp(hw_address, info.sender_hw_address, ETHER_ADDRLEN);
55860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    daemon_log(LOG_INFO, "Recieved conflicting probe ARP packet.");
55960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                }
56060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
56160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                if (conflict) {
56260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
56360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    if (state == STATE_RUNNING || state == STATE_ANNOUNCING)
5645ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                        do_callout(CALLOUT_CONFLICT, iface, addr);
56560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
56660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    /* Pick a new address */
56760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    addr = pick_addr(addr);
56860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
56960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    daemon_log(LOG_INFO, "Trying address %s", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
57060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
57160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    n_conflict++;
57260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
5735ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    set_state(STATE_WAITING_PROBE, 1, addr);
57412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
57560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    if (n_conflict >= MAX_CONFLICTS) {
57660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                        daemon_log(LOG_WARNING, "Got too many conflicts, rate limiting new probes.");
57760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                        elapse_time(&next_wakeup, RATE_LIMIT_INTERVAL*1000, PROBE_WAIT*1000);
57860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    } else
57960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                        elapse_time(&next_wakeup, 0, PROBE_WAIT*1000);
58060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
58160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    next_wakeup_valid = 1;
58260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                } else
5835ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    DEBUG(daemon_log(LOG_DEBUG, "Ignoring irrelevant ARP packet."));
58460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            }
58512874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
58612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        } else if (event == EVENT_ROUTABLE_ADDR_CONFIGURED) {
58712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
58812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            daemon_log(LOG_INFO, "A routable address has been configured.");
58912874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
59012874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            if (state == STATE_RUNNING || state == STATE_ANNOUNCING)
5915ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                do_callout(CALLOUT_UNBIND, iface, addr);
592fee9053f6a8a22ff53d59fc7865230ad41fdf760Lennart Poettering
5935ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            if (!retval_sent) {
5945ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                daemon_retval_send(0);
5955ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                retval_sent = 1;
5965ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            }
5975ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
5985ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            set_state(STATE_SLEEPING, 1, addr);
599fee9053f6a8a22ff53d59fc7865230ad41fdf760Lennart Poettering            next_wakeup_valid = 0;
60012874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
60112874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        } else if (event == EVENT_ROUTABLE_ADDR_UNCONFIGURED && state == STATE_SLEEPING) {
60212874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
60312874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            daemon_log(LOG_INFO, "No longer a routable address configured, restarting probe process.");
60412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
6055ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            set_state(STATE_WAITING_PROBE, 1, addr);
60612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
60712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            elapse_time(&next_wakeup, 0, PROBE_WAIT*1000);
60812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            next_wakeup_valid = 1;
6095ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
6105ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        } else if (event == EVENT_REFRESH_REQUEST && state == STATE_RUNNING) {
6115ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
6125ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            /* The user requested a reannouncing of the address by a SIGHUP */
6135ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            daemon_log(LOG_INFO, "Reannouncing address.");
61412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
6155ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            /* Send announcement packet */
6165ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            out_packet = packet_new_announcement(addr, hw_address, &out_packet_len);
6175ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            set_state(STATE_ANNOUNCING, 1, addr);
6185ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
6195ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            elapse_time(&next_wakeup, ANNOUNCE_INTERVAL*1000, 0);
6205ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            next_wakeup_valid = 1;
62160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        }
62260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
62360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        if (out_packet) {
6245ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            DEBUG(daemon_log(LOG_DEBUG, "sending..."));
62560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
62660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            if (send_packet(fd, iface, out_packet, out_packet_len) < 0)
62760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                goto fail;
62860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
62960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            avahi_free(out_packet);
63060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            out_packet = NULL;
63160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        }
63260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
63360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        if (in_packet) {
63460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            avahi_free(in_packet);
63560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            in_packet = NULL;
63660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        }
63760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
63812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        event = EVENT_NULL;
63960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        timeout = -1;
64060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
64160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        if (next_wakeup_valid) {
64260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            usec = avahi_age(&next_wakeup);
64360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            timeout = usec < 0 ? (int) (-usec/1000) : 0;
64460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        }
64560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
6465ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        DEBUG(daemon_log(LOG_DEBUG, "sleeping %ims", timeout));
64760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
64812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        while ((r = poll(pollfds, FD_MAX, timeout)) < 0 && errno == EINTR)
64960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            ;
65060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
65160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        if (r < 0) {
65260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            daemon_log(LOG_ERR, "poll() failed: %s", strerror(r));
6535ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            goto fail;
65460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else if (r == 0) {
65560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            event = EVENT_TIMEOUT;
65660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            next_wakeup_valid = 0;
65760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else {
65860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
65912874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            if (pollfds[FD_ARP].revents == POLLIN) {
66012874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering                if (recv_packet(fd, &in_packet, &in_packet_len) < 0)
66112874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering                    goto fail;
66212874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
66312874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering                if (in_packet)
66412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering                    event = EVENT_PACKET;
66512874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            }
66660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
66712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            if (event == EVENT_NULL &&
66812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering                pollfds[FD_IFACE].revents == POLLIN) {
66912874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
67012874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering                if (iface_process(&event) < 0)
67112874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering                    goto fail;
67212874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            }
6735ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
6745ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            if (event == EVENT_NULL &&
6755ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                pollfds[FD_SIGNAL].revents == POLLIN) {
6765ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
6775ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                int sig;
6785ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
6795ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                if ((sig = daemon_signal_next()) <= 0) {
6805ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    daemon_log(LOG_ERR, "daemon_signal_next() failed");
6815ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    goto fail;
6825ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                }
6835ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
6845ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                switch(sig) {
6855ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    case SIGINT:
6865ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    case SIGTERM:
6875ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                        daemon_log(LOG_INFO, "Got %s, quitting.", sig == SIGINT ? "SIGINT" : "SIGTERM");
6885ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                        ret = 0;
6895ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                        goto fail;
6905ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
6915ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    case SIGCHLD:
6925ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                        waitpid(-1, NULL, WNOHANG);
6935ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                        break;
6945ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
6955ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    case SIGHUP:
6965ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                        event = EVENT_REFRESH_REQUEST;
6975ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                        break;
6985ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                }
6995ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
7005ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            }
70160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        }
70260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
70360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
70460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ret = 0;
70560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
70660d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringfail:
70760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
7085ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (state == STATE_RUNNING || state == STATE_ANNOUNCING)
7095ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        do_callout(CALLOUT_STOP, iface, addr);
7105ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
71160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    avahi_free(out_packet);
71260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    avahi_free(in_packet);
71360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
71460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (fd >= 0)
71560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        close(fd);
71612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
71712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    if (iface_fd >= 0)
71812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        iface_done();
7195ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
7205ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (daemonize && !retval_sent)
7215ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        daemon_retval_send(ret);
72260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
72360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return ret;
72460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
72560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
72660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
7275ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic void help(FILE *f, const char *a0) {
7285ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    fprintf(f,
7295ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "%s [options] INTERFACE\n"
7305ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "    -h --help           Show this help\n"
7315ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "    -D --daemonize      Daemonize after startup\n"
7325ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "    -s --syslog         Write log messages to syslog(3) instead of STDERR\n"
7335ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "    -k --kill           Kill a running daemon\n"
7345ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "    -r --refresh        Request a running daemon to refresh it's IP address\n"
7355ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "    -c --check          Return 0 if a daemon is already running\n"
7365ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "    -V --version        Show version\n"
7375ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "    -S --start=ADDRESS  Start with this address from the IPv4LL range 169.254.0.0/16\n"
7385ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "    -w --wait           Wait until an address has been acquired before daemonizing\n"
7395ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "       --no-proc-title  Don't modify process title\n"
7405ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "       --debug          Increase verbosity\n",
7415ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            a0);
7425ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering}
7435ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
7445ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic int parse_command_line(int argc, char *argv[]) {
7455ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    int c;
7465ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
7475ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    enum {
7485ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        OPTION_NO_PROC_TITLE = 256,
7495ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        OPTION_DEBUG
7505ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    };
7515ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
7525ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    static const struct option long_options[] = {
7535ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "help",          no_argument,       NULL, 'h' },
7545ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "daemonize",     no_argument,       NULL, 'D' },
7555ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "syslog",        no_argument,       NULL, 's' },
7565ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "kill",          no_argument,       NULL, 'k' },
7575ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "refresh",       no_argument,       NULL, 'r' },
7585ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "check",         no_argument,       NULL, 'c' },
7595ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "version",       no_argument,       NULL, 'V' },
7605ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "start",         required_argument, NULL, 'S' },
7615ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "wait",          no_argument,       NULL, 'w' },
7625ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "no-proc-title", no_argument,       NULL, OPTION_NO_PROC_TITLE },
7635ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "debug",         no_argument,       NULL, OPTION_DEBUG },
7645ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { NULL, 0, NULL, 0 }
7655ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    };
76660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
7675ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    opterr = 0;
7685ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    while ((c = getopt_long(argc, argv, "hDkVrcS:", long_options, NULL)) >= 0) {
7695ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
7705ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        switch(c) {
7715ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case 's':
7725ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                use_syslog = 1;
7735ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
7745ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case 'h':
7755ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                command = DAEMON_HELP;
7765ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
7775ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case 'D':
7785ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                daemonize = 1;
7795ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
7805ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case 'k':
7815ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                command = DAEMON_KILL;
7825ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
7835ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case 'V':
7845ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                command = DAEMON_VERSION;
7855ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
7865ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case 'r':
7875ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                command = DAEMON_REFRESH;
7885ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
7895ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case 'c':
7905ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                command = DAEMON_CHECK;
7915ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
7925ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case 'S':
7935ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
7945ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                if ((start_address = inet_addr(optarg)) == (uint32_t) -1) {
7955ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    fprintf(stderr, "Failed to parse IP address '%s'.", optarg);
7965ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    return -1;
7975ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                }
7985ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
7995ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case 'w':
8005ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                wait_for_address = 1;
8015ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
8025ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
8035ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case OPTION_NO_PROC_TITLE:
8045ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                modify_proc_title = 0;
8055ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
80660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
8075ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case OPTION_DEBUG:
8085ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                debug = 1;
8095ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
8105ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
8115ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            default:
8125ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                fprintf(stderr, "Invalid command line argument: %c\n", c);
8135ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                return -1;
8145ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        }
81560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
81660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
8175ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (command == DAEMON_RUN ||
8185ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        command == DAEMON_KILL ||
8195ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        command == DAEMON_REFRESH ||
8205ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        command == DAEMON_CHECK) {
82160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
8225ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if (optind >= argc) {
8235ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            fprintf(stderr, "Missing interface name.\n");
8245ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            return -1;
8255ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        }
82660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
8275ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        interface_name = argv[optind++];
8285ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    }
8295ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
8305ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (optind != argc) {
8315ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        fprintf(stderr, "Too many arguments\n");
8325ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        return -1;
8335ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    }
8345ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
8355ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    return 0;
8365ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering}
8375ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
8385ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic const char* pid_file_proc(void) {
8395ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    return pid_file_name;
84060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
84160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
84260d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringint main(int argc, char*argv[]) {
8435ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    int r = 1;
8445ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    int wrote_pid_file = 0;
84560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
84612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    avahi_init_proc_title(argc, argv);
84760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
8485ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if ((argv0 = strrchr(argv[0], '/')))
8495ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        argv0++;
8505ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    else
8515ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        argv0 = argv[0];
85260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
8535ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    daemon_pid_file_ident = daemon_log_ident = argv0;
8545ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    daemon_pid_file_proc = pid_file_proc;
85560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
8565ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (parse_command_line(argc, argv) < 0)
8575ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        goto finish;
85860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
8595ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    pid_file_name = avahi_strdup_printf(AVAHI_RUNTIME_DIR"/avahi-autoipd.%s.pid", interface_name);
8605ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
8615ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (command == DAEMON_RUN) {
8625ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        pid_t pid;
8635ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        int ifindex;
8645ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
8655ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        init_rand_seed();
8665ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
8675ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if ((ifindex = if_nametoindex(interface_name)) <= 0) {
8685ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            daemon_log(LOG_ERR, "Failed to get index for interface name '%s': %s", interface_name, strerror(errno));
8695ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            goto finish;
8705ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        }
8715ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
8725ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if (getuid() != 0) {
8735ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            daemon_log(LOG_ERR, "This program is intended to be run as root.");
8745ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            goto finish;
8755ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        }
8765ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
8775ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if ((pid = daemon_pid_file_is_running()) >= 0) {
8785ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            daemon_log(LOG_ERR, "Daemon already running on PID %u", pid);
8795ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            goto finish;
8805ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        }
8815ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
8825ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if (daemonize) {
8835ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            daemon_retval_init();
8845ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
8855ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            if ((pid = daemon_fork()) < 0)
8865ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                goto finish;
8875ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            else if (pid != 0) {
8885ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                int ret;
8895ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                /** Parent **/
8905ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
8915ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                if ((ret = daemon_retval_wait(20)) < 0) {
8925ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    daemon_log(LOG_ERR, "Could not receive return value from daemon process.");
8935ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    goto finish;
8945ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                }
8955ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
8965ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                r = ret;
8975ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                goto finish;
8985ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            }
8995ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
9005ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            /* Child */
9015ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        }
9025ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
9035ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if (use_syslog || daemonize)
9045ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            daemon_log_use = DAEMON_LOG_SYSLOG;
9055ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
9065ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        chdir("/");
9075ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
9085ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if (daemon_pid_file_create() < 0) {
9095ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            daemon_log(LOG_ERR, "Failed to create PID file: %s", strerror(errno));
9105ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
9115ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            if (daemonize)
9125ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                daemon_retval_send(1);
9135ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            goto finish;
9145ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        } else
9155ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            wrote_pid_file = 1;
9165ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
9175ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if (loop(ifindex, start_address) < 0)
9185ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            goto finish;
9195ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
9205ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        r = 0;
9215ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    } else if (command == DAEMON_HELP) {
9225ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        help(stdout, argv0);
9235ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
9245ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        r = 0;
9255ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    } else if (command == DAEMON_VERSION) {
9265ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        printf("%s "PACKAGE_VERSION"\n", argv0);
9275ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
9285ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        r = 0;
9295ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    } else if (command == DAEMON_KILL) {
9305ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if (daemon_pid_file_kill_wait(SIGTERM, 5) < 0) {
9315ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            daemon_log(LOG_WARNING, "Failed to kill daemon: %s", strerror(errno));
9325ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            goto finish;
9335ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        }
9345ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
9355ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        r = 0;
9365ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    } else if (command == DAEMON_REFRESH) {
9375ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if (daemon_pid_file_kill(SIGHUP) < 0) {
9385ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            daemon_log(LOG_WARNING, "Failed to kill daemon: %s", strerror(errno));
9395ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            goto finish;
9405ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        }
9415ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
9425ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        r = 0;
9435ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    } else if (command == DAEMON_CHECK)
9445ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        r = (daemon_pid_file_is_running() >= 0) ? 0 : 1;
9455ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
9465ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
9475ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringfinish:
9485ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
9495ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (daemonize)
9505ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        daemon_retval_done();
95160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
9525ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (wrote_pid_file)
9535ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        daemon_pid_file_remove();
9545ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
9555ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    return r;
95660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
95760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
95860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering/* TODO:
95960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
96060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering- chroot/drop privs/caps
9615ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering- user script
96260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering- store last used address
9635ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering- man page
96460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
96560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering*/
966