160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering/***
2872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    This file is part of avahi.
3872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
4872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    avahi is free software; you can redistribute it and/or modify it
5872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    under the terms of the GNU Lesser General Public License as
6872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    published by the Free Software Foundation; either version 2.1 of the
7872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    License, or (at your option) any later version.
8872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
9872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    avahi is distributed in the hope that it will be useful, but WITHOUT
10872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    Public License for more details.
13872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
14872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    You should have received a copy of the GNU Lesser General Public
15872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    License along with avahi; if not, write to the Free Software
16872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    USA.
1860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering***/
1960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
2060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#ifdef HAVE_CONFIG_H
2160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <config.h>
2260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#endif
2360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
24f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <sys/param.h>
25f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <sys/types.h>
26f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <sys/stat.h>
27f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <sys/ioctl.h>
2860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <sys/socket.h>
29f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <sys/wait.h>
30f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#ifdef __FreeBSD__
31f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <sys/sysctl.h>
32f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#endif
33f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
34f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#ifdef __linux__
3560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <netpacket/packet.h>
36f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#endif
3760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <net/ethernet.h>
38f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <net/if.h>
39f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#ifdef __FreeBSD__
40f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <net/if_dl.h>
41f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <net/route.h>
42f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#endif
43f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <arpa/inet.h>
44f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
4560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <assert.h>
4660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <errno.h>
4760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <inttypes.h>
48f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <fcntl.h>
49f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <stdlib.h>
505ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering#include <stdio.h>
515ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering#include <signal.h>
52f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <string.h>
53f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <time.h>
54f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <getopt.h>
55f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
569ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#include <grp.h>
57f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <poll.h>
58f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <pwd.h>
59f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <unistd.h>
60f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
61f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#ifndef __linux__
62f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#include <pcap.h>
63cf1f05215e3651ed47ea530edc7e924787de1bc6Lennart Poettering
64cf1f05215e3651ed47ea530edc7e924787de1bc6Lennart Poettering/* Old versions of PCAP defined it as D_IN */
65cf1f05215e3651ed47ea530edc7e924787de1bc6Lennart Poettering#ifndef PCAP_D_IN
66cf1f05215e3651ed47ea530edc7e924787de1bc6Lennart Poettering#define PCAP_D_IN D_IN
67cf1f05215e3651ed47ea530edc7e924787de1bc6Lennart Poettering#endif
68cf1f05215e3651ed47ea530edc7e924787de1bc6Lennart Poettering
69f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#endif
7060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
718e46e738cae449bf44232c66e973c8e9e15fbcb5Robert Ginda#include "avahi-common/avahi-malloc.h"
7260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <avahi-common/timeval.h>
7312874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering#include <avahi-daemon/setproctitle.h>
7412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
7560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <libdaemon/dfork.h>
7660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <libdaemon/dsignal.h>
7760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <libdaemon/dlog.h>
7860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <libdaemon/dpid.h>
7960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#include <libdaemon/dexec.h>
8060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
8112874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering#include "main.h"
8212874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering#include "iface.h"
8312874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
8460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering/* An implementation of RFC 3927 */
8560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
8660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering/* Constants from the RFC */
8760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define PROBE_WAIT 1
8860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define PROBE_NUM 3
8960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define PROBE_MIN 1
9060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define PROBE_MAX 2
9160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define ANNOUNCE_WAIT 2
9260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define ANNOUNCE_NUM 2
9360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define ANNOUNCE_INTERVAL 2
9460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define MAX_CONFLICTS 10
9560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define RATE_LIMIT_INTERVAL 60
9660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define DEFEND_INTERVAL 10
9760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
9860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define IPV4LL_NETWORK 0xA9FE0000L
9960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define IPV4LL_NETMASK 0xFFFF0000L
10060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define IPV4LL_HOSTMASK 0x0000FFFFL
101c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering#define IPV4LL_BROADCAST 0xA9FEFFFFL
10260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
10360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define ETHER_ADDRLEN 6
104f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#define ETHER_HDR_SIZE (2+2*ETHER_ADDRLEN)
10560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define ARP_PACKET_SIZE (8+4+4+2*ETHER_ADDRLEN)
10660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
10760d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringtypedef enum ArpOperation {
10860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ARP_REQUEST = 1,
10960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ARP_RESPONSE = 2
11060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering} ArpOperation;
11160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
11260d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringtypedef struct ArpPacketInfo {
11360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ArpOperation operation;
11460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
11560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    uint32_t sender_ip_address, target_ip_address;
11660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    uint8_t sender_hw_address[ETHER_ADDRLEN], target_hw_address[ETHER_ADDRLEN];
11760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering} ArpPacketInfo;
11860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
119f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poetteringtypedef struct ArpPacket {
120f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    uint8_t *ether_header;
121f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    uint8_t *ether_payload;
122f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering} ArpPacket;
123f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
12412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poetteringstatic State state = STATE_START;
12560d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int n_iteration = 0;
12660d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int n_conflict = 0;
12760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
1285ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic char *interface_name = NULL;
1295ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic char *pid_file_name = NULL;
1305ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic uint32_t start_address = 0;
1315ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic char *argv0 = NULL;
1325ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic int daemonize = 0;
1335ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic int wait_for_address = 0;
1345ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic int use_syslog = 0;
1355ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic int debug = 0;
1365ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic int modify_proc_title = 1;
1375b67d0bbb21412bcdf7a271ddf34823f8776dc06Lennart Poetteringstatic int force_bind = 0;
1389ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#ifdef HAVE_CHROOT
1399ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poetteringstatic int no_chroot = 0;
1409ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#endif
1419ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poetteringstatic int no_drop_root = 0;
1429ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poetteringstatic int wrote_pid_file = 0;
143b54a67fe8a7da842fd086a289e5b61c5b518b03eLennart Poetteringstatic char *action_script = NULL;
1445ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
1455ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic enum {
1465ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    DAEMON_RUN,
1475ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    DAEMON_KILL,
1485ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    DAEMON_REFRESH,
1495ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    DAEMON_VERSION,
1505ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    DAEMON_HELP,
1515ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    DAEMON_CHECK
1525ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering} command = DAEMON_RUN;
1535ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
1545ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringtypedef enum CalloutEvent {
1555ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    CALLOUT_BIND,
1565ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    CALLOUT_CONFLICT,
1575ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    CALLOUT_UNBIND,
1585ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    CALLOUT_STOP,
1595ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    CALLOUT_MAX
1605ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering} CalloutEvent;
1615ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
1627bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poetteringstatic const char * const callout_event_table[CALLOUT_MAX] = {
1637bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    [CALLOUT_BIND] = "BIND",
1647bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    [CALLOUT_CONFLICT] = "CONFLICT",
1657bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    [CALLOUT_UNBIND] = "UNBIND",
1667bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    [CALLOUT_STOP] = "STOP"
1677bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering};
1687bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
1697bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poetteringtypedef struct CalloutEventInfo {
1707bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    CalloutEvent event;
1717bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    uint32_t address;
1727bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    int ifindex;
1737bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering} CalloutEventInfo;
1747bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
17560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering#define RANDOM_DEVICE "/dev/urandom"
17660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
177872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering#define DEBUG(x)                                \
178872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    do {                                        \
179872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        if (debug) {                            \
180872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering            x;                                  \
181872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        }                                       \
182872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    } while (0)
1835ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
18460d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic void init_rand_seed(void) {
18560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    int fd;
18660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    unsigned seed = 0;
18760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
18860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    /* Try to initialize seed from /dev/urandom, to make it a little
18960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering     * less predictable, and to make sure that multiple machines
19060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering     * booted at the same time choose different random seeds.  */
19160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if ((fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) {
19260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        read(fd, &seed, sizeof(seed));
19360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        close(fd);
19460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
19560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
19660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    /* If the initialization failed by some reason, we add the time to the seed */
19760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    seed ^= (unsigned) time(NULL);
19860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
19960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    srand(seed);
20060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
20160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
20260d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic uint32_t pick_addr(uint32_t old_addr) {
20360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    uint32_t addr;
20460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
20560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    do {
20660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        unsigned r = (unsigned) rand();
20760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
20860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        /* Reduce to 16 bits */
20960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        while (r > 0xFFFF)
21060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            r = (r >> 16) ^ (r & 0xFFFF);
211872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
21260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        addr = htonl(IPV4LL_NETWORK | (uint32_t) r);
21360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
214c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    } while (addr == old_addr || !is_ll_address(addr));
21560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
21660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return addr;
21760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
21860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
219c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poetteringstatic int load_address(const char *fn, uint32_t *addr) {
220c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    FILE *f;
221c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    unsigned a, b, c, d;
222c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering
223c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    assert(fn);
224c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    assert(addr);
225872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
226c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    if (!(f = fopen(fn, "r"))) {
227c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering
228c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering        if (errno == ENOENT) {
229c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering            *addr = 0;
230c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering            return 0;
231c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering        }
232872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
233c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering        daemon_log(LOG_ERR, "fopen() failed: %s", strerror(errno));
234c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering        goto fail;
235c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    }
236c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering
237c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    if (fscanf(f, "%u.%u.%u.%u\n", &a, &b, &c, &d) != 4) {
238c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering        daemon_log(LOG_ERR, "Parse failure");
239c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering        goto fail;
240c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    }
241c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering
242c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    fclose(f);
243c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering
244c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    *addr = htonl((a << 24) | (b << 16) | (c << 8) | d);
245c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    return 0;
246872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
247c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poetteringfail:
248c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    if (f)
249c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering        fclose(f);
250c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering
251c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    return -1;
252c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering}
253c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering
254c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poetteringstatic int save_address(const char *fn, uint32_t addr) {
255c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    FILE *f;
256c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    char buf[32];
257747f75372063371865bf5fc9857982defcffdca4Lennart Poettering    mode_t u;
258c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering
259c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    assert(fn);
260747f75372063371865bf5fc9857982defcffdca4Lennart Poettering
261747f75372063371865bf5fc9857982defcffdca4Lennart Poettering    u = umask(0033);
262c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    if (!(f = fopen(fn, "w"))) {
263c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering        daemon_log(LOG_ERR, "fopen() failed: %s", strerror(errno));
264c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering        goto fail;
265c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    }
266747f75372063371865bf5fc9857982defcffdca4Lennart Poettering    umask(u);
267c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering
268c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    fprintf(f, "%s\n", inet_ntop(AF_INET, &addr, buf, sizeof (buf)));
269c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    fclose(f);
270c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering
271c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    return 0;
272872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
273c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poetteringfail:
274c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    if (f)
275c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering        fclose(f);
276c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering
277747f75372063371865bf5fc9857982defcffdca4Lennart Poettering    umask(u);
278872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
279c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    return -1;
280c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering}
281c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering
282f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering/*
283f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering * Allocate a buffer with two pointers in front, one of which is
284f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering * guaranteed to point ETHER_HDR_SIZE bytes into it.
285f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering */
286f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poetteringstatic ArpPacket* packet_new(size_t packet_len) {
287f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    ArpPacket *p;
288f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    uint8_t *b;
289f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
290f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    assert(packet_len > 0);
291f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
292f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#ifdef __linux__
293f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    b = avahi_new0(uint8_t, sizeof(struct ArpPacket) + packet_len);
294f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    p = (ArpPacket*) b;
295f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    p->ether_header = NULL;
296f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    p->ether_payload = b + sizeof(struct ArpPacket);
297872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
298f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#else
299f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    b = avahi_new0(uint8_t, sizeof(struct ArpPacket) + ETHER_HDR_SIZE + packet_len);
300f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    p = (ArpPacket*) b;
301f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    p->ether_header = b + sizeof(struct ArpPacket);
302f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    p->ether_payload = b + sizeof(struct ArpPacket) + ETHER_HDR_SIZE;
303f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#endif
304f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
305f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    return p;
306f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering}
307f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
308f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poetteringstatic ArpPacket* packet_new_with_info(const ArpPacketInfo *info, size_t *packet_len) {
309f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    ArpPacket *p = NULL;
31060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    uint8_t *r;
31160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
31260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(info);
31360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(info->operation == ARP_REQUEST || info->operation == ARP_RESPONSE);
314f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    assert(packet_len != NULL);
31560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
31660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    *packet_len = ARP_PACKET_SIZE;
317f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    p = packet_new(*packet_len);
318f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    r = p->ether_payload;
319f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
32060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    r[1] = 1; /* HTYPE */
32160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    r[2] = 8; /* PTYPE */
32260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    r[4] = ETHER_ADDRLEN; /* HLEN */
32360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    r[5] = 4; /* PLEN */
32460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    r[7] = (uint8_t) info->operation;
32560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
32660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(r+8, info->sender_hw_address, ETHER_ADDRLEN);
32760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(r+14, &info->sender_ip_address, 4);
32860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(r+18, info->target_hw_address, ETHER_ADDRLEN);
32960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(r+24, &info->target_ip_address, 4);
33060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
331f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    return p;
33260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
33360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
334f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poetteringstatic ArpPacket *packet_new_probe(uint32_t ip_address, const uint8_t*hw_address, size_t *packet_len) {
33560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ArpPacketInfo info;
336872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
33760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(&info, 0, sizeof(info));
33860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    info.operation = ARP_REQUEST;
33960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(info.sender_hw_address, hw_address, ETHER_ADDRLEN);
34060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    info.target_ip_address = ip_address;
34160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
342f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    return packet_new_with_info(&info, packet_len);
34360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
34460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
345f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poetteringstatic ArpPacket *packet_new_announcement(uint32_t ip_address, const uint8_t* hw_address, size_t *packet_len) {
34660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ArpPacketInfo info;
34760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
34860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(&info, 0, sizeof(info));
34960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    info.operation = ARP_REQUEST;
35060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(info.sender_hw_address, hw_address, ETHER_ADDRLEN);
35160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    info.target_ip_address = ip_address;
35260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    info.sender_ip_address = ip_address;
35360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
354f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    return packet_new_with_info(&info, packet_len);
35560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
35660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
357f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poetteringstatic int packet_parse(const ArpPacket *packet, size_t packet_len, ArpPacketInfo *info) {
358f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    const uint8_t *p;
359872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
360f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    assert(packet);
361f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    p = (uint8_t *)packet->ether_payload;
362f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    assert(p);
36360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
36460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (packet_len < ARP_PACKET_SIZE)
36560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        return -1;
36660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
36760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    /* Check HTYPE and PTYPE */
36860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (p[0] != 0 || p[1] != 1 || p[2] != 8 || p[3] != 0)
36960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        return -1;
37060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
37160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    /* Check HLEN, PLEN, OPERATION */
37260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (p[4] != ETHER_ADDRLEN || p[5] != 4 || p[6] != 0 || (p[7] != 1 && p[7] != 2))
37360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        return -1;
374872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
37560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    info->operation = p[7];
37660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(info->sender_hw_address, p+8, ETHER_ADDRLEN);
37760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(&info->sender_ip_address, p+14, 4);
37860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(info->target_hw_address, p+18, ETHER_ADDRLEN);
37960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(&info->target_ip_address, p+24, 4);
38060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
38160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return 0;
38260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
38360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
3845ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic void set_state(State st, int reset_counter, uint32_t address) {
3857bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    static const char* const state_table[] = {
38612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        [STATE_START] = "START",
38760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        [STATE_WAITING_PROBE] = "WAITING_PROBE",
38860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        [STATE_PROBING] = "PROBING",
389872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        [STATE_WAITING_ANNOUNCE] = "WAITING_ANNOUNCE",
39060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        [STATE_ANNOUNCING] = "ANNOUNCING",
39160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        [STATE_RUNNING] = "RUNNING",
39260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        [STATE_SLEEPING] = "SLEEPING"
39360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    };
3945ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    char buf[64];
395872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
39660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(st < STATE_MAX);
39760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
39860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (st == state && !reset_counter) {
39960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        n_iteration++;
4005ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        DEBUG(daemon_log(LOG_DEBUG, "State iteration %s-%i", state_table[state], n_iteration));
40160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    } else {
4025ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        DEBUG(daemon_log(LOG_DEBUG, "State transition %s-%i -> %s-0", state_table[state], n_iteration, state_table[st]));
40360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        state = st;
40460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        n_iteration = 0;
40560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
40660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
407872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    if (state == STATE_SLEEPING)
4089ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        avahi_set_proc_title(argv0, "%s: [%s] sleeping", argv0, interface_name);
4099ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    else if (state == STATE_ANNOUNCING)
4109ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        avahi_set_proc_title(argv0, "%s: [%s] announcing %s", argv0, interface_name, inet_ntop(AF_INET, &address, buf, sizeof(buf)));
4119ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    else if (state == STATE_RUNNING)
4129ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        avahi_set_proc_title(argv0, "%s: [%s] bound %s", argv0, interface_name, inet_ntop(AF_INET, &address, buf, sizeof(buf)));
4139ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    else
4149ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        avahi_set_proc_title(argv0, "%s: [%s] probing %s", argv0, interface_name, inet_ntop(AF_INET, &address, buf, sizeof(buf)));
41560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
41660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
41725ae811f3393baed4930f30278a7595dd8122dfbLennart Poetteringstatic int interface_up(int iface) {
41825ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    int fd = -1;
41925ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    struct ifreq ifreq;
42025ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering
42125ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
42225ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering        daemon_log(LOG_ERR, "socket() failed: %s", strerror(errno));
42325ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering        goto fail;
42425ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    }
42525ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering
42625ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    memset(&ifreq, 0, sizeof(ifreq));
42725ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    if (!if_indextoname(iface, ifreq.ifr_name)) {
42825ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering        daemon_log(LOG_ERR, "if_indextoname() failed: %s", strerror(errno));
42925ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering        goto fail;
43025ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    }
431872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
43225ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    if (ioctl(fd, SIOCGIFFLAGS, &ifreq) < 0) {
43325ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering        daemon_log(LOG_ERR, "SIOCGIFFLAGS failed: %s", strerror(errno));
43425ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering        goto fail;
43525ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    }
43625ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering
43725ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    ifreq.ifr_flags |= IFF_UP;
43825ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering
43925ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    if (ioctl(fd, SIOCSIFFLAGS, &ifreq) < 0) {
44025ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering        daemon_log(LOG_ERR, "SIOCSIFFLAGS failed: %s", strerror(errno));
44125ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering        goto fail;
44225ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    }
44325ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering
44425ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    close(fd);
44525ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering
44625ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    return 0;
447872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
44825ae811f3393baed4930f30278a7595dd8122dfbLennart Poetteringfail:
44925ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    if (fd >= 0)
45025ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering        close(fd);
451872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
45225ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    return -1;
45325ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering}
45425ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering
455f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#ifdef __linux__
456f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
457f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering/* Linux 'packet socket' specific implementation */
458f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
45960d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int open_socket(int iface, uint8_t *hw_address) {
46060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    int fd = -1;
46160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    struct sockaddr_ll sa;
46260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    socklen_t sa_len;
46325ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering
46425ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    if (interface_up(iface) < 0)
46525ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering        goto fail;
466872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
46760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if ((fd = socket(PF_PACKET, SOCK_DGRAM, 0)) < 0) {
46860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "socket() failed: %s", strerror(errno));
46960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
47060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
47160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
47260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(&sa, 0, sizeof(sa));
47360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_family = AF_PACKET;
47460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_protocol = htons(ETH_P_ARP);
47560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_ifindex = iface;
476872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
47760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (bind(fd, (struct sockaddr*) &sa, sizeof(sa)) < 0) {
47860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "bind() failed: %s", strerror(errno));
47960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
48060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
481872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
48260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa_len = sizeof(sa);
48360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (getsockname(fd, (struct sockaddr*) &sa, &sa_len) < 0) {
48460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "getsockname() failed: %s", strerror(errno));
48560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
48660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
487872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
48860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (sa.sll_halen != ETHER_ADDRLEN) {
48960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "getsockname() returned invalid hardware address.");
49060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
49160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
49260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
49360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memcpy(hw_address, sa.sll_addr, ETHER_ADDRLEN);
49460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
49560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return fd;
496872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
49760d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringfail:
49860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (fd >= 0)
49960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        close(fd);
50060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
50160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return -1;
50260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
50360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
504f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poetteringstatic int send_packet(int fd, int iface, ArpPacket *packet, size_t packet_len) {
50560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    struct sockaddr_ll sa;
506872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
50760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(fd >= 0);
50860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(packet);
50960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(packet_len > 0);
51060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
51160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(&sa, 0, sizeof(sa));
51260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_family = AF_PACKET;
51360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_protocol = htons(ETH_P_ARP);
51460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_ifindex = iface;
51560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa.sll_halen = ETHER_ADDRLEN;
51660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(sa.sll_addr, 0xFF, ETHER_ADDRLEN);
51760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
5189247d610deb3842f28ca81a9b9aad2f4ec2ff2f1Lennart Poettering    if (sendto(fd, packet->ether_payload, packet_len, 0, (struct sockaddr*) &sa, sizeof(sa)) < 0) {
51960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "sendto() failed: %s", strerror(errno));
52060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        return -1;
52160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
52260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
52360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return 0;
52460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
52560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
526f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poetteringstatic int recv_packet(int fd, ArpPacket **packet, size_t *packet_len) {
52760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    int s;
52860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    struct sockaddr_ll sa;
52960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    socklen_t sa_len;
53025ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    ssize_t r;
531872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
53260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(fd >= 0);
53360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(packet);
53460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(packet_len);
53560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
53660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    *packet = NULL;
53760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
53860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (ioctl(fd, FIONREAD, &s) < 0) {
53960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "FIONREAD failed: %s", strerror(errno));
54060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
54160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
54260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
54325ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    if (s <= 0)
54425ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering        s = 4096;
54560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
546f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    *packet = packet_new(s);
54760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
54860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    sa_len = sizeof(sa);
549f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    if ((r = recvfrom(fd, (*packet)->ether_payload, s, 0, (struct sockaddr*) &sa, &sa_len)) < 0) {
55060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        daemon_log(LOG_ERR, "recvfrom() failed: %s", strerror(errno));
55160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
55260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
553872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
55425ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    *packet_len = (size_t) r;
555872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
55660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return 0;
557872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
55860d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringfail:
55925ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    if (*packet) {
56060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        avahi_free(*packet);
56125ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering        *packet = NULL;
56225ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering    }
56360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
56460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return -1;
56560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
566f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
5672f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poetteringstatic void close_socket(int fd) {
568f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    close(fd);
569f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering}
570f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
571f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#else /* !__linux__ */
572f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering/* PCAP-based implementation */
573f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
574f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poetteringstatic pcap_t *__pp;
575f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poetteringstatic char __pcap_errbuf[PCAP_ERRBUF_SIZE];
576f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poetteringstatic uint8_t __lladdr[ETHER_ADDRLEN];
577f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
578f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#ifndef elementsof
579872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering#define elementsof(array)       (sizeof(array)/sizeof(array[0]))
580f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#endif
581f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
5822f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poetteringstatic int __get_ether_addr(int ifindex, u_char *lladdr) {
5832f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    int mib[6];
5842f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    char *buf;
5852f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    struct if_msghdr *ifm;
5862f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    char *lim;
5872f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    char *next;
5882f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    struct sockaddr_dl *sdl;
5892f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    size_t len;
590872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
591872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    mib[0] = CTL_NET;
592872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    mib[1] = PF_ROUTE;
593872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    mib[2] = 0;
594872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    mib[3] = 0;
595872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    mib[4] = NET_RT_IFLIST;
596872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    mib[5] = ifindex;
597872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
598872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    if (sysctl(mib, elementsof(mib), NULL, &len, NULL, 0) != 0) {
599872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        daemon_log(LOG_ERR, "sysctl(NET_RT_IFLIST): %s",
600872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering                   strerror(errno));
6012f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering        return -1;
602872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    }
603872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
6042f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    buf = avahi_malloc(len);
605872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    if (sysctl(mib, elementsof(mib), buf, &len, NULL, 0) != 0) {
606872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        daemon_log(LOG_ERR, "sysctl(NET_RT_IFLIST): %s",
607872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering                   strerror(errno));
608872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        free(buf);
6092f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering        return -1;
610872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    }
611872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
612872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    lim = buf + len;
613872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    for (next = buf; next < lim; next += ifm->ifm_msglen) {
614872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        ifm = (struct if_msghdr *)next;
615872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        if (ifm->ifm_type == RTM_IFINFO) {
616872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering            sdl = (struct sockaddr_dl *)(ifm + 1);
617872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering            memcpy(lladdr, LLADDR(sdl), ETHER_ADDRLEN);
618872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        }
619872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    }
6202f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    avahi_free(buf);
621872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
6222f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    return 0;
623f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering}
624f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
625872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering#define PCAP_TIMEOUT 500 /* 0.5s */
626872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
6272f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poetteringstatic int open_socket(int iface, uint8_t *hw_address) {
6282f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    struct bpf_program bpf;
6292f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    char *filter;
6302f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    char ifname[IFNAMSIZ];
6312f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    pcap_t *pp;
6322f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    int err;
6332f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    int fd;
634872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
635872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    assert(__pp == NULL);
636872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
6372f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    if (interface_up(iface) < 0)
6382f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering        return -1;
6392f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering
6402f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    if (__get_ether_addr(iface, __lladdr) == -1)
6412f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering        return -1;
6422f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering
6432f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    if (if_indextoname(iface, ifname) == NULL)
6442f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering        return -1;
645872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
646872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    /*
647872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering     * Using a timeout for BPF is fairly portable across BSDs. On most
648872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering     * modern versions, using the timeout/nonblock/poll method results in
649872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering     * fairly sane behavior, with the timeout only coming into play during
650872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering     * the next_ex() call itself (so, for us, that's only when there's
651872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering     * data). On older versions, it may result in a PCAP_TIMEOUT busy-wait
652872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering     * on some versions, though, as the poll() may terminate at the
653872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering     * PCAP_TIMEOUT instead of the poll() timeout.
654872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering     */
655872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    pp = pcap_open_live(ifname, 1500, 0, PCAP_TIMEOUT, __pcap_errbuf);
656872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    if (pp == NULL) {
657872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        return (-1);
658872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    }
659872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    err = pcap_set_datalink(pp, DLT_EN10MB);
660872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    if (err == -1) {
661872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        daemon_log(LOG_ERR, "pcap_set_datalink: %s", pcap_geterr(pp));
662872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        pcap_close(pp);
663872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        return (-1);
664872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    }
665872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    err = pcap_setdirection(pp, PCAP_D_IN);
666872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    if (err == -1) {
667872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        daemon_log(LOG_ERR, "pcap_setdirection: %s", pcap_geterr(pp));
668872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        pcap_close(pp);
669872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        return (-1);
670872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    }
671872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
672872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    fd = pcap_get_selectable_fd(pp);
673872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    if (fd == -1) {
674872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        pcap_close(pp);
675872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        return (-1);
676872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    }
677872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
678872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    /*
679872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering     * Using setnonblock is a portability stop-gap. Using the timeout in
680872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering     * combination with setnonblock will ensure on most BSDs that the
681872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering     * next_ex call returns in a timely fashion.
682872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering     */
683872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    err = pcap_setnonblock(pp, 1, __pcap_errbuf);
684872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    if (err == -1) {
685872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        pcap_close(pp);
686872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        return (-1);
687872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    }
688872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
689872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    filter = avahi_strdup_printf("arp and (ether dst ff:ff:ff:ff:ff:ff or "
690872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering                                 "%02x:%02x:%02x:%02x:%02x:%02x)",
691872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering                                 __lladdr[0], __lladdr[1],
692872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering                                 __lladdr[2], __lladdr[3],
693872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering                                 __lladdr[4], __lladdr[5]);
694872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    DEBUG(daemon_log(LOG_DEBUG, "Using pcap filter '%s'", filter));
695872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
696872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    err = pcap_compile(pp, &bpf, filter, 1, 0);
697872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    avahi_free(filter);
698872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    if (err == -1) {
699872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        daemon_log(LOG_ERR, "pcap_compile: %s", pcap_geterr(pp));
700872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        pcap_close(pp);
701872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        return (-1);
702872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    }
703872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    err = pcap_setfilter(pp, &bpf);
704872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    if (err == -1) {
705872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        daemon_log(LOG_ERR, "pcap_setfilter: %s", pcap_geterr(pp));
706872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        pcap_close(pp);
707872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        return (-1);
708872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    }
709872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    pcap_freecode(&bpf);
710872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
711872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    /* Stash pcap-specific context away. */
712872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    memcpy(hw_address, __lladdr, ETHER_ADDRLEN);
713872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    __pp = pp;
714f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
715872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    return (fd);
716f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering}
717f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
7182f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poetteringstatic void close_socket(int fd AVAHI_GCC_UNUSED) {
719872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    assert(__pp != NULL);
720872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    pcap_close(__pp);
721872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    __pp = NULL;
722f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering}
723f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
724f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering/*
725f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering * We trick avahi into allocating sizeof(packet) + sizeof(ether_header),
726f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering * and prepend the required ethernet header information before sending.
727f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering */
7282f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poetteringstatic int send_packet(int fd AVAHI_GCC_UNUSED, int iface AVAHI_GCC_UNUSED, ArpPacket *packet, size_t packet_len) {
729872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    struct ether_header *eh;
730f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
731872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    assert(__pp != NULL);
732872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    assert(packet != NULL);
733f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
734872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    eh = (struct ether_header *)packet->ether_header;
735872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    memset(eh->ether_dhost, 0xFF, ETHER_ADDRLEN);
736872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    memcpy(eh->ether_shost, __lladdr, ETHER_ADDRLEN);
737872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    eh->ether_type = htons(0x0806);
738f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
739872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    return (pcap_inject(__pp, (void *)eh, packet_len + sizeof(*eh)));
740f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering}
741f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
7422f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poetteringstatic int recv_packet(int fd AVAHI_GCC_UNUSED, ArpPacket **packet, size_t *packet_len) {
7432f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    struct pcap_pkthdr *ph;
7442f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    u_char *pd;
7452f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    ArpPacket *ap;
7462f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    int err;
7472f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    int retval;
748872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
749872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    assert(__pp != NULL);
750872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    assert(packet != NULL);
751872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    assert(packet_len != NULL);
752872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
753872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    *packet = NULL;
754872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    *packet_len = 0;
755872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    retval = -1;
756872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
757872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    err = pcap_next_ex(__pp, &ph, (const u_char **)&pd);
758872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    if (err == 1 && ph->caplen <= ph->len) {
759872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        ap = packet_new(ph->caplen);
760872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        memcpy(ap->ether_header, pd, ph->caplen);
761872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        *packet = ap;
762872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        *packet_len = (ph->caplen - sizeof(struct ether_header));
763872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        retval = 0;
764872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    } else if (err >= 0) {
765872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        /*
766872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering         * err == 1: Just drop bogus packets (>1500 for an arp packet!?)
767872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering         * on the floor.
768872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering         *
769872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering         * err == 0: We might have had traffic on the pcap fd that
770872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering         * didn't match the filter, in which case we'll get 0 packets.
771872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering         */
772872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        retval = 0;
7732f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    } else
774872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        daemon_log(LOG_ERR, "pcap_next_ex(%d): %s",
775872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering                   err, pcap_geterr(__pp));
776872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
777872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering    return (retval);
778f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering}
779f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering#endif /* __linux__ */
780f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
78112874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poetteringint is_ll_address(uint32_t addr) {
782c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    return
7830e1ff7b80d77fa1fb0a3ccb3c4b047e25c04afddLennart Poettering        ((ntohl(addr) & IPV4LL_NETMASK) == IPV4LL_NETWORK) &&
7840e1ff7b80d77fa1fb0a3ccb3c4b047e25c04afddLennart Poettering        ((ntohl(addr) & 0x0000FF00) != 0x0000) &&
7850e1ff7b80d77fa1fb0a3ccb3c4b047e25c04afddLennart Poettering        ((ntohl(addr) & 0x0000FF00) != 0xFF00);
78660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
78760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
78860d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic struct timeval *elapse_time(struct timeval *tv, unsigned msec, unsigned jitter) {
78960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    assert(tv);
79060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
79160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    gettimeofday(tv, NULL);
79260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
79360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (msec)
79460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        avahi_timeval_add(tv, (AvahiUsec) msec*1000);
79560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
79660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (jitter)
79760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        avahi_timeval_add(tv, (AvahiUsec) (jitter*1000.0*rand()/(RAND_MAX+1.0)));
798872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
79960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return tv;
80060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
80160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
8027bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poetteringstatic FILE* fork_dispatcher(void) {
8037bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    FILE *ret;
8047bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    int fds[2];
8057bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    pid_t pid;
8067bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
8077bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    if (pipe(fds) < 0) {
8087bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        daemon_log(LOG_ERR, "pipe() failed: %s", strerror(errno));
8097bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        goto fail;
8107bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    }
8117bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
8127bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    if ((pid = fork()) < 0)
8137bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        goto fail;
8147bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    else if (pid == 0) {
815872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering        FILE *f = NULL;
8167bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        int r = 1;
8177bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
8187bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        /* Please note that the signal pipe is not closed at this
8197bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering         * point, signals will thus be dispatched in the main
8207bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering         * process. */
8217bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
8227bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        daemon_retval_done();
823872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
824287f9866c923e6afe8ffbbc03b90be64acf395e1Lennart Poettering        avahi_set_proc_title(argv0, "%s: [%s] callout dispatcher", argv0, interface_name);
8257bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
8267bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        close(fds[1]);
8277bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
8287bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        if (!(f = fdopen(fds[0], "r"))) {
8297bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering            daemon_log(LOG_ERR, "fdopen() failed: %s", strerror(errno));
8307bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering            goto dispatcher_fail;
8317bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        }
832872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
8337bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        for (;;) {
8347bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering            CalloutEventInfo info;
8357bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering            char name[IFNAMSIZ], buf[64];
8367bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering            int k;
8377bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
8387bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering            if (fread(&info, sizeof(info), 1, f) != 1) {
8397bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering                if (feof(f))
8407bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering                    break;
8417bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
8427bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering                daemon_log(LOG_ERR, "fread() failed: %s", strerror(errno));
8437bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering                goto dispatcher_fail;
8447bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering            }
8457bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
8467bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering            assert(info.event <= CALLOUT_MAX);
8477bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
8487bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering            if (!if_indextoname(info.ifindex, name)) {
8497bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering                daemon_log(LOG_ERR, "if_indextoname() failed: %s", strerror(errno));
8507bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering                continue;
8517bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering            }
852872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
8537bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering            if (daemon_exec("/", &k,
854b54a67fe8a7da842fd086a289e5b61c5b518b03eLennart Poettering                            action_script, action_script,
8557bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering                            callout_event_table[info.event],
8567bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering                            name,
8577bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering                            inet_ntop(AF_INET, &info.address, buf, sizeof(buf)), NULL) < 0) {
858872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
8597bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering                daemon_log(LOG_ERR, "Failed to run script: %s", strerror(errno));
8607bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering                continue;
8617bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering            }
8627bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
8637bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering            if (k != 0)
8647bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering                daemon_log(LOG_WARNING, "Script execution failed with return value %i", k);
8657bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        }
8667bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
8677bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        r = 0;
8687bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
8697bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    dispatcher_fail:
8707bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
8717bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        if (f)
8727bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering            fclose(f);
8739ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering
8749ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#ifdef HAVE_CHROOT
8759ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        /* If the main process is trapped inside a chroot() we have to
8769ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering         * remove the PID file for it */
877872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
8789ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        if (!no_chroot && wrote_pid_file)
8799ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            daemon_pid_file_remove();
8809ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#endif
881872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
8827bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        _exit(r);
8837bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    }
8847bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
8857bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    /* parent */
8867bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
8877bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    close(fds[0]);
8887bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    fds[0] = -1;
8897bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
8907bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    if (!(ret = fdopen(fds[1], "w"))) {
8917bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        daemon_log(LOG_ERR, "fdopen() failed: %s", strerror(errno));
8927bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        goto fail;
8937bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    }
894872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
8957bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    return ret;
8967bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
8977bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poetteringfail:
8987bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    if (fds[0] >= 0)
8997bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        close(fds[0]);
9007bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    if (fds[1] >= 0)
9017bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        close(fds[1]);
9027bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
9037bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    return NULL;
9047bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering}
9057bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
9067bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poetteringstatic int do_callout(FILE *f, CalloutEvent event, int iface, uint32_t addr) {
9077bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    CalloutEventInfo info;
9087bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    char buf[64], ifname[IFNAMSIZ];
9097bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
9107bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    daemon_log(LOG_INFO, "Callout %s, address %s on interface %s",
9117bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering               callout_event_table[event],
9127bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering               inet_ntop(AF_INET, &addr, buf, sizeof(buf)),
9137bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering               if_indextoname(iface, ifname));
9147bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
9157bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    info.event = event;
9167bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    info.ifindex = iface;
9177bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    info.address = addr;
9187bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
9197bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    if (fwrite(&info, sizeof(info), 1, f) != 1 || fflush(f) != 0) {
9207bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        daemon_log(LOG_ERR, "Failed to write callout event: %s", strerror(errno));
9217bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        return -1;
9227bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    }
923872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
9247bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    return 0;
9257bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering}
9267bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
9279ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#define set_env(key, value) putenv(avahi_strdup_printf("%s=%s", (key), (value)))
9289ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering
9299ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poetteringstatic int drop_privs(void) {
9309ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    struct passwd *pw;
9319ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    struct group * gr;
9329ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    int r;
9339ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    mode_t u;
9349ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering
935f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    pw = NULL;
936f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    gr = NULL;
937f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering
9389ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    /* Get user/group ID */
939872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
9409ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    if (!no_drop_root) {
941872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
9429ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        if (!(pw = getpwnam(AVAHI_AUTOIPD_USER))) {
9439ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            daemon_log(LOG_ERR, "Failed to find user '"AVAHI_AUTOIPD_USER"'.");
9449ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            return -1;
9459ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        }
946872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
9479ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        if (!(gr = getgrnam(AVAHI_AUTOIPD_GROUP))) {
9489ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            daemon_log(LOG_ERR, "Failed to find group '"AVAHI_AUTOIPD_GROUP"'.");
9499ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            return -1;
9509ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        }
951872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
9529ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        daemon_log(LOG_INFO, "Found user '"AVAHI_AUTOIPD_USER"' (UID %lu) and group '"AVAHI_AUTOIPD_GROUP"' (GID %lu).", (unsigned long) pw->pw_uid, (unsigned long) gr->gr_gid);
9539ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    }
9549ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering
9559ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    /* Create directory */
9569ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    u = umask(0000);
9579ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    r = mkdir(AVAHI_IPDATA_DIR, 0755);
9589ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    umask(u);
959872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
9609ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    if (r < 0 && errno != EEXIST) {
9619ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        daemon_log(LOG_ERR, "mkdir(\""AVAHI_IPDATA_DIR"\"): %s", strerror(errno));
9629ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        return -1;
9639ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    }
9649ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering
9659ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    /* Convey working directory */
966872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
9679ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    if (!no_drop_root) {
9689ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        struct stat st;
969872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
9709ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        chown(AVAHI_IPDATA_DIR, pw->pw_uid, gr->gr_gid);
971872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
9729ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        if (stat(AVAHI_IPDATA_DIR, &st) < 0) {
9739ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            daemon_log(LOG_ERR, "stat(): %s\n", strerror(errno));
9749ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            return -1;
9759ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        }
976872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
9779ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        if (!S_ISDIR(st.st_mode) || st.st_uid != pw->pw_uid || st.st_gid != gr->gr_gid) {
9789ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            daemon_log(LOG_ERR, "Failed to create runtime directory "AVAHI_IPDATA_DIR".");
9799ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            return -1;
9809ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        }
9819ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    }
9829ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering
9839ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#ifdef HAVE_CHROOT
9849ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering
9859ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    if (!no_chroot) {
9869ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        if (chroot(AVAHI_IPDATA_DIR) < 0) {
9879ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            daemon_log(LOG_ERR, "Failed to chroot(): %s", strerror(errno));
9889ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            return -1;
9899ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        }
9909ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering
9919ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        daemon_log(LOG_INFO, "Successfully called chroot().");
9929ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        chdir("/");
9939ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering
9949ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        /* Since we are now trapped inside a chroot we cannot remove
9959ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering         * the pid file anymore, the helper process will do that for us. */
9969ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        wrote_pid_file = 0;
9979ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    }
998872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
9999ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#endif
10009ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering
10019ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    if (!no_drop_root) {
10029ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering
10039ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        if (initgroups(AVAHI_AUTOIPD_USER, gr->gr_gid) != 0) {
10049ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            daemon_log(LOG_ERR, "Failed to change group list: %s", strerror(errno));
10059ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            return -1;
10069ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        }
1007872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
10089ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#if defined(HAVE_SETRESGID)
10099ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        r = setresgid(gr->gr_gid, gr->gr_gid, gr->gr_gid);
10109ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#elif defined(HAVE_SETEGID)
10119ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        if ((r = setgid(gr->gr_gid)) >= 0)
10129ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            r = setegid(gr->gr_gid);
10139ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#elif defined(HAVE_SETREGID)
10149ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        r = setregid(gr->gr_gid, gr->gr_gid);
10159ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#else
10160fa82e3aca0b80504e50016d1661bdcb4b429360Ted Percival#error "No API to drop privileges"
10179ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#endif
10189ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering
10199ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        if (r < 0) {
10209ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            daemon_log(LOG_ERR, "Failed to change GID: %s", strerror(errno));
10219ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            return -1;
10229ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        }
1023872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
10249ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#if defined(HAVE_SETRESUID)
10259ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        r = setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid);
10269ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#elif defined(HAVE_SETEUID)
10279ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        if ((r = setuid(pw->pw_uid)) >= 0)
10289ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            r = seteuid(pw->pw_uid);
10299ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#elif defined(HAVE_SETREUID)
10309ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        r = setreuid(pw->pw_uid, pw->pw_uid);
10319ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#else
10320fa82e3aca0b80504e50016d1661bdcb4b429360Ted Percival#error "No API to drop privileges"
10339ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#endif
1034872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
10359ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        if (r < 0) {
10369ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            daemon_log(LOG_ERR, "Failed to change UID: %s", strerror(errno));
10379ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            return -1;
10389ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        }
10399ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering
10409ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        set_env("USER", pw->pw_name);
10419ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        set_env("LOGNAME", pw->pw_name);
10429ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        set_env("HOME", pw->pw_dir);
1043872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
10442bbdbf1155cca40d5c89ef4fcd4db40f655b0a93Lennart Poettering        daemon_log(LOG_INFO, "Successfully dropped root privileges.");
10459ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    }
1046747f75372063371865bf5fc9857982defcffdca4Lennart Poettering
10479ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    return 0;
10489ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering}
10499ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering
105060d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringstatic int loop(int iface, uint32_t addr) {
105112874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    enum {
105212874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        FD_ARP,
105312874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        FD_IFACE,
10545ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        FD_SIGNAL,
1055648db528f5cc197c38f7b17bb09dd53958df6302Lennart Poettering        FD_MAX
105612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    };
105712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
105860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    int fd = -1, ret = -1;
105960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    struct timeval next_wakeup;
106060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    int next_wakeup_valid = 0;
106160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    char buf[64];
1062f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    ArpPacket *in_packet = NULL;
10632462c966a241720518f612a62a56f55bb8e4b1d6Lennart Poettering    size_t in_packet_len = 0;
1064f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    ArpPacket *out_packet = NULL;
106560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    size_t out_packet_len;
106660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    uint8_t hw_address[ETHER_ADDRLEN];
106712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    struct pollfd pollfds[FD_MAX];
1068f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering    int iface_fd = -1;
106912874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    Event event = EVENT_NULL;
10705ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    int retval_sent = !daemonize;
10715ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    State st;
10727bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    FILE *dispatcher = NULL;
1073c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    char *address_fn = NULL;
1074c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    const char *p;
10755ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
10762f56f8a0943f92d430c8f395880ace8f5922f85bLennart Poettering    daemon_signal_init(SIGINT, SIGTERM, SIGCHLD, SIGHUP, 0);
107760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
10787bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    if (!(dispatcher = fork_dispatcher()))
10797bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        goto fail;
10807bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
108160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if ((fd = open_socket(iface, hw_address)) < 0)
108260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        goto fail;
108360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
108412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    if ((iface_fd = iface_init(iface)) < 0)
108512874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        goto fail;
108612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
10879ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    if (drop_privs() < 0)
10889ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        goto fail;
10897bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
10905b67d0bbb21412bcdf7a271ddf34823f8776dc06Lennart Poettering    if (force_bind)
10915b67d0bbb21412bcdf7a271ddf34823f8776dc06Lennart Poettering        st = STATE_START;
10925b67d0bbb21412bcdf7a271ddf34823f8776dc06Lennart Poettering    else if (iface_get_initial_state(&st) < 0)
109312874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        goto fail;
10945ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
1095c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering#ifdef HAVE_CHROOT
1096c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    if (!no_chroot)
1097c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering        p = "";
1098c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    else
1099c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering#endif
1100c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering        p = AVAHI_IPDATA_DIR;
1101872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
1102c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    address_fn = avahi_strdup_printf(
1103c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering            "%s/%02x:%02x:%02x:%02x:%02x:%02x", p,
1104c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering            hw_address[0], hw_address[1],
1105c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering            hw_address[2], hw_address[3],
1106c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering            hw_address[4], hw_address[5]);
1107872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
1108c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    if (!addr)
1109c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering        load_address(address_fn, &addr);
1110c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering
111160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (addr && !is_ll_address(addr)) {
11120e1ff7b80d77fa1fb0a3ccb3c4b047e25c04afddLennart Poettering        daemon_log(LOG_WARNING, "Requested address %s is not from IPv4LL range 169.254/16 or a reserved address, ignoring.", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
111360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        addr = 0;
111460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
111560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
111660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (!addr) {
111760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        int i;
111860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        uint32_t a = 1;
111960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
112060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        for (i = 0; i < ETHER_ADDRLEN; i++)
112160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            a += hw_address[i]*i;
112260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
1123d6ce91c0b5258c2e107415704413f42edfab2c30Lennart Poettering        a = (a % 0xFE00) + 0x0100;
1124d6ce91c0b5258c2e107415704413f42edfab2c30Lennart Poettering
112560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        addr = htonl(IPV4LL_NETWORK | (uint32_t) a);
112660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
112760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
1128d6ce91c0b5258c2e107415704413f42edfab2c30Lennart Poettering    assert(is_ll_address(addr));
1129d6ce91c0b5258c2e107415704413f42edfab2c30Lennart Poettering
11305ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    set_state(st, 1, addr);
1131872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
113260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    daemon_log(LOG_INFO, "Starting with address %s", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
113360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
113412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    if (state == STATE_SLEEPING)
113512874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        daemon_log(LOG_INFO, "Routable address already assigned, sleeping.");
113612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
11375ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (!retval_sent && (!wait_for_address || state == STATE_SLEEPING)) {
11385ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        daemon_retval_send(0);
11395ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        retval_sent = 1;
11405ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    }
11415ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
114260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    memset(pollfds, 0, sizeof(pollfds));
114312874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    pollfds[FD_ARP].fd = fd;
114412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    pollfds[FD_ARP].events = POLLIN;
114512874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    pollfds[FD_IFACE].fd = iface_fd;
114612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    pollfds[FD_IFACE].events = POLLIN;
11475ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    pollfds[FD_SIGNAL].fd = daemon_signal_fd();
11485ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    pollfds[FD_SIGNAL].events = POLLIN;
1149872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
115060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    for (;;) {
115160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        int r, timeout;
115260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        AvahiUsec usec;
115360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
115412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        if (state == STATE_START) {
115560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
115660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            /* First, wait a random time */
11575ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            set_state(STATE_WAITING_PROBE, 1, addr);
115860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
115960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            elapse_time(&next_wakeup, 0, PROBE_WAIT*1000);
116060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            next_wakeup_valid = 1;
116160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
116260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else if ((state == STATE_WAITING_PROBE && event == EVENT_TIMEOUT) ||
116360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                   (state == STATE_PROBING && event == EVENT_TIMEOUT && n_iteration < PROBE_NUM-2)) {
116460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
116560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            /* Send a probe */
116660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            out_packet = packet_new_probe(addr, hw_address, &out_packet_len);
11675ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            set_state(STATE_PROBING, 0, addr);
116860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
116960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            elapse_time(&next_wakeup, PROBE_MIN*1000, (PROBE_MAX-PROBE_MIN)*1000);
117060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            next_wakeup_valid = 1;
1171872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
117260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else if (state == STATE_PROBING && event == EVENT_TIMEOUT && n_iteration >= PROBE_NUM-2) {
117360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
117460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            /* Send the last probe */
117560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            out_packet = packet_new_probe(addr, hw_address, &out_packet_len);
11765ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            set_state(STATE_WAITING_ANNOUNCE, 1, addr);
117760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
117860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            elapse_time(&next_wakeup, ANNOUNCE_WAIT*1000, 0);
117960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            next_wakeup_valid = 1;
1180872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
118160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else if ((state == STATE_WAITING_ANNOUNCE && event == EVENT_TIMEOUT) ||
118260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                   (state == STATE_ANNOUNCING && event == EVENT_TIMEOUT && n_iteration < ANNOUNCE_NUM-1)) {
118360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
118460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            /* Send announcement packet */
118560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            out_packet = packet_new_announcement(addr, hw_address, &out_packet_len);
11865ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            set_state(STATE_ANNOUNCING, 0, addr);
118760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
118860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            elapse_time(&next_wakeup, ANNOUNCE_INTERVAL*1000, 0);
118960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            next_wakeup_valid = 1;
1190872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
119160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            if (n_iteration == 0) {
11927bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering                if (do_callout(dispatcher, CALLOUT_BIND, iface, addr) < 0)
11937bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering                    goto fail;
1194872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
119560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                n_conflict = 0;
119660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            }
119760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
119860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else if ((state == STATE_ANNOUNCING && event == EVENT_TIMEOUT && n_iteration >= ANNOUNCE_NUM-1)) {
119960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
120060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            daemon_log(LOG_INFO, "Successfully claimed IP address %s", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
12015ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            set_state(STATE_RUNNING, 0, addr);
1202fee9053f6a8a22ff53d59fc7865230ad41fdf760Lennart Poettering
1203fee9053f6a8a22ff53d59fc7865230ad41fdf760Lennart Poettering            next_wakeup_valid = 0;
1204c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering
1205c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering            save_address(address_fn, addr);
1206872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
1207c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering            if (!retval_sent) {
1208c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering                daemon_retval_send(0);
1209c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering                retval_sent = 1;
1210c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering            }
1211c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering
121260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else if (event == EVENT_PACKET) {
121360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            ArpPacketInfo info;
121460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
121560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            assert(in_packet);
1216872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
121760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            if (packet_parse(in_packet, in_packet_len, &info) < 0)
121860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                daemon_log(LOG_WARNING, "Failed to parse incoming ARP packet.");
121960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            else {
122060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                int conflict = 0;
122160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
122260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                if (info.sender_ip_address == addr) {
1223c5ef344e39fd7e169a31e2353ba09a8870768502Nathaniel McCallum
1224c5ef344e39fd7e169a31e2353ba09a8870768502Nathaniel McCallum                    if (memcmp(hw_address, info.sender_hw_address, ETHER_ADDRLEN)) {
1225c5ef344e39fd7e169a31e2353ba09a8870768502Nathaniel McCallum                        /* Normal conflict */
1226c5ef344e39fd7e169a31e2353ba09a8870768502Nathaniel McCallum                        conflict = 1;
1227c5ef344e39fd7e169a31e2353ba09a8870768502Nathaniel McCallum                        daemon_log(LOG_INFO, "Received conflicting normal ARP packet.");
1228c5ef344e39fd7e169a31e2353ba09a8870768502Nathaniel McCallum                    } else
1229c5ef344e39fd7e169a31e2353ba09a8870768502Nathaniel McCallum                        daemon_log(LOG_DEBUG, "Received ARP packet back on source interface. Ignoring.");
1230c5ef344e39fd7e169a31e2353ba09a8870768502Nathaniel McCallum
123160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                } else if (state == STATE_WAITING_PROBE || state == STATE_PROBING || state == STATE_WAITING_ANNOUNCE) {
123260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    /* Probe conflict */
123360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    conflict = info.target_ip_address == addr && memcmp(hw_address, info.sender_hw_address, ETHER_ADDRLEN);
12344638c9afcb14dffca2d0f1749660c68a14f9f65dLennart Poettering
12354638c9afcb14dffca2d0f1749660c68a14f9f65dLennart Poettering                    if (conflict)
1236b59779facaa64e00286478d5417ae98ce6981664Ted Percival                        daemon_log(LOG_INFO, "Received conflicting probe ARP packet.");
123760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                }
123860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
123960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                if (conflict) {
1240872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
124160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    if (state == STATE_RUNNING || state == STATE_ANNOUNCING)
12427bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering                        if (do_callout(dispatcher, CALLOUT_CONFLICT, iface, addr) < 0)
12437bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering                            goto fail;
1244872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
124560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    /* Pick a new address */
124660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    addr = pick_addr(addr);
124760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
124860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    daemon_log(LOG_INFO, "Trying address %s", inet_ntop(AF_INET, &addr, buf, sizeof(buf)));
124960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
125060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    n_conflict++;
125160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
12525ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    set_state(STATE_WAITING_PROBE, 1, addr);
1253872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
125460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    if (n_conflict >= MAX_CONFLICTS) {
125560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                        daemon_log(LOG_WARNING, "Got too many conflicts, rate limiting new probes.");
125660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                        elapse_time(&next_wakeup, RATE_LIMIT_INTERVAL*1000, PROBE_WAIT*1000);
125760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    } else
125860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                        elapse_time(&next_wakeup, 0, PROBE_WAIT*1000);
125960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
126060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                    next_wakeup_valid = 1;
126160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                } else
12625ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    DEBUG(daemon_log(LOG_DEBUG, "Ignoring irrelevant ARP packet."));
126360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            }
1264872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
1265f8ef650e9d7b633c67509666599c15f205fa5bafLennart Poettering        } else if (event == EVENT_ROUTABLE_ADDR_CONFIGURED && !force_bind) {
126612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
126712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            daemon_log(LOG_INFO, "A routable address has been configured.");
126812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
126912874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            if (state == STATE_RUNNING || state == STATE_ANNOUNCING)
12707bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering                if (do_callout(dispatcher, CALLOUT_UNBIND, iface, addr) < 0)
12717bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering                    goto fail;
1272fee9053f6a8a22ff53d59fc7865230ad41fdf760Lennart Poettering
12735ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            if (!retval_sent) {
12745ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                daemon_retval_send(0);
12755ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                retval_sent = 1;
12765ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            }
1277872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
12785ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            set_state(STATE_SLEEPING, 1, addr);
1279fee9053f6a8a22ff53d59fc7865230ad41fdf760Lennart Poettering            next_wakeup_valid = 0;
1280872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
12815b67d0bbb21412bcdf7a271ddf34823f8776dc06Lennart Poettering        } else if (event == EVENT_ROUTABLE_ADDR_UNCONFIGURED && state == STATE_SLEEPING && !force_bind) {
128212874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
128312874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            daemon_log(LOG_INFO, "No longer a routable address configured, restarting probe process.");
128412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
12855ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            set_state(STATE_WAITING_PROBE, 1, addr);
128612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
128712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            elapse_time(&next_wakeup, 0, PROBE_WAIT*1000);
128812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            next_wakeup_valid = 1;
12895ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
1290f8ef650e9d7b633c67509666599c15f205fa5bafLennart Poettering        } else if (event == EVENT_REFRESH_REQUEST && state == STATE_RUNNING) {
12915ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
12925ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            /* The user requested a reannouncing of the address by a SIGHUP */
12935ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            daemon_log(LOG_INFO, "Reannouncing address.");
1294872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
12955ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            /* Send announcement packet */
12965ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            out_packet = packet_new_announcement(addr, hw_address, &out_packet_len);
12975ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            set_state(STATE_ANNOUNCING, 1, addr);
12985ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
12995ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            elapse_time(&next_wakeup, ANNOUNCE_INTERVAL*1000, 0);
13005ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            next_wakeup_valid = 1;
130160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        }
1302872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
130360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        if (out_packet) {
13045ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            DEBUG(daemon_log(LOG_DEBUG, "sending..."));
1305872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
130660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            if (send_packet(fd, iface, out_packet, out_packet_len) < 0)
130760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering                goto fail;
1308872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
130960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            avahi_free(out_packet);
131060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            out_packet = NULL;
131160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        }
131260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
131360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        if (in_packet) {
131460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            avahi_free(in_packet);
131560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            in_packet = NULL;
131660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        }
131760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
131812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        event = EVENT_NULL;
131960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        timeout = -1;
1320872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
132160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        if (next_wakeup_valid) {
132260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            usec = avahi_age(&next_wakeup);
132360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            timeout = usec < 0 ? (int) (-usec/1000) : 0;
132460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        }
132560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
13265ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        DEBUG(daemon_log(LOG_DEBUG, "sleeping %ims", timeout));
1327872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
132812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        while ((r = poll(pollfds, FD_MAX, timeout)) < 0 && errno == EINTR)
132960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            ;
133060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
133160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        if (r < 0) {
133260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            daemon_log(LOG_ERR, "poll() failed: %s", strerror(r));
13335ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            goto fail;
133460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else if (r == 0) {
133560d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            event = EVENT_TIMEOUT;
133660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering            next_wakeup_valid = 0;
133760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        } else {
1338872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
1339872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
134025ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering            if (pollfds[FD_ARP].revents) {
134160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
134225ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering                if (pollfds[FD_ARP].revents == POLLERR) {
134325ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering                    /* The interface is probably down, let's recreate our socket */
1344872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
1345f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering                    close_socket(fd);
134625ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering
134725ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering                    if ((fd = open_socket(iface, hw_address)) < 0)
134825ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering                        goto fail;
134925ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering
135025ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering                    pollfds[FD_ARP].fd = fd;
1351872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
135225ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering                } else {
1353872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
135425ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering                    assert(pollfds[FD_ARP].revents == POLLIN);
1355872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
135625ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering                    if (recv_packet(fd, &in_packet, &in_packet_len) < 0)
135725ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering                        goto fail;
1358872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
135925ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering                    if (in_packet)
136025ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering                        event = EVENT_PACKET;
136125ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering                }
136212874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            }
136360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
136412874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            if (event == EVENT_NULL &&
136525ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering                pollfds[FD_IFACE].revents) {
1366872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
136725ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering                assert(pollfds[FD_IFACE].revents == POLLIN);
136825ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering
136912874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering                if (iface_process(&event) < 0)
137012874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering                    goto fail;
137112874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering            }
13725ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
13735ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            if (event == EVENT_NULL &&
137425ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering                pollfds[FD_SIGNAL].revents) {
13755ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
13765ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                int sig;
137725ae811f3393baed4930f30278a7595dd8122dfbLennart Poettering                assert(pollfds[FD_SIGNAL].revents == POLLIN);
13785ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
13795ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                if ((sig = daemon_signal_next()) <= 0) {
13805ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    daemon_log(LOG_ERR, "daemon_signal_next() failed");
13815ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    goto fail;
13825ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                }
13835ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
13845ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                switch(sig) {
13855ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    case SIGINT:
13865ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    case SIGTERM:
13875ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                        daemon_log(LOG_INFO, "Got %s, quitting.", sig == SIGINT ? "SIGINT" : "SIGTERM");
13885ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                        ret = 0;
13895ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                        goto fail;
13905ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
13915ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    case SIGCHLD:
13925ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                        waitpid(-1, NULL, WNOHANG);
13935ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                        break;
1394872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
13955ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    case SIGHUP:
13965ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                        event = EVENT_REFRESH_REQUEST;
13975ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                        break;
13985ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                }
1399872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
14005ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            }
140160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering        }
140260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
140360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
140460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    ret = 0;
1405872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
140660d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringfail:
140760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
14085ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (state == STATE_RUNNING || state == STATE_ANNOUNCING)
14097bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        do_callout(dispatcher, CALLOUT_STOP, iface, addr);
14105ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
141160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    avahi_free(out_packet);
141260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    avahi_free(in_packet);
1413872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
141460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    if (fd >= 0)
1415f10b82b26456f44d03d0c28d93c5118b859d3891Lennart Poettering        close_socket(fd);
141612874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering
141712874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering    if (iface_fd >= 0)
141812874f5d761b4b80ac27c1fc758a93b69d92c34cLennart Poettering        iface_done();
14195ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
14205ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (daemonize && !retval_sent)
14215ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        daemon_retval_send(ret);
14227bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering
14237bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    if (dispatcher)
14247bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering        fclose(dispatcher);
1425c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering
1426c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering    if (address_fn)
1427c09e09d8d0c17c12979d84fdf66b2b595f399051Lennart Poettering        avahi_free(address_fn);
1428872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
142960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    return ret;
143060d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
143160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
143260d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
14335ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic void help(FILE *f, const char *a0) {
14345ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    fprintf(f,
14355ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "%s [options] INTERFACE\n"
14365ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "    -h --help           Show this help\n"
14375ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "    -D --daemonize      Daemonize after startup\n"
14385ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "    -s --syslog         Write log messages to syslog(3) instead of STDERR\n"
14395ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "    -k --kill           Kill a running daemon\n"
1440b59779facaa64e00286478d5417ae98ce6981664Ted Percival            "    -r --refresh        Request a running daemon refresh its IP address\n"
14415ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "    -c --check          Return 0 if a daemon is already running\n"
14425ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "    -V --version        Show version\n"
14435b67d0bbb21412bcdf7a271ddf34823f8776dc06Lennart Poettering            "    -S --start=ADDRESS  Start with this address from the IPv4LL range\n"
14445b67d0bbb21412bcdf7a271ddf34823f8776dc06Lennart Poettering            "                        169.254.0.0/16\n"
1445b54a67fe8a7da842fd086a289e5b61c5b518b03eLennart Poettering            "    -t --script=script  Action script to run (defaults to\n"
1446fb11678ae2b71101a641a4050797a98229430d03Ted Percival            "                        "AVAHI_IPCONF_SCRIPT")\n"
14475b67d0bbb21412bcdf7a271ddf34823f8776dc06Lennart Poettering            "    -w --wait           Wait until an address has been acquired before\n"
14485b67d0bbb21412bcdf7a271ddf34823f8776dc06Lennart Poettering            "                        daemonizing\n"
14490ab5eaa3fa41c910204b801cbe030fafc4c29ba2Lennart Poettering            "       --force-bind     Assign an IPv4LL address even if a routable address\n"
14505b67d0bbb21412bcdf7a271ddf34823f8776dc06Lennart Poettering            "                        is already assigned\n"
14519ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            "       --no-drop-root   Don't drop privileges\n"
1452872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering#ifdef HAVE_CHROOT
14539ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            "       --no-chroot      Don't chroot()\n"
1454872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering#endif
14559ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            "       --no-proc-title  Don't modify process title\n"
14565ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            "       --debug          Increase verbosity\n",
14575ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            a0);
14585ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering}
14595ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
14605ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic int parse_command_line(int argc, char *argv[]) {
14615ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    int c;
1462872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
14635ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    enum {
14645ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        OPTION_NO_PROC_TITLE = 256,
14655b67d0bbb21412bcdf7a271ddf34823f8776dc06Lennart Poettering        OPTION_FORCE_BIND,
14669ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        OPTION_DEBUG,
14679ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        OPTION_NO_DROP_ROOT,
14689ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#ifdef HAVE_CHROOT
14699ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        OPTION_NO_CHROOT
1470872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering#endif
14715ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    };
1472872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
14735ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    static const struct option long_options[] = {
14745ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "help",          no_argument,       NULL, 'h' },
14755ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "daemonize",     no_argument,       NULL, 'D' },
14765ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "syslog",        no_argument,       NULL, 's' },
14775ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "kill",          no_argument,       NULL, 'k' },
14785ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "refresh",       no_argument,       NULL, 'r' },
14795ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "check",         no_argument,       NULL, 'c' },
14805ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "version",       no_argument,       NULL, 'V' },
14815ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "start",         required_argument, NULL, 'S' },
1482b54a67fe8a7da842fd086a289e5b61c5b518b03eLennart Poettering        { "script",        required_argument, NULL, 't' },
14835ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "wait",          no_argument,       NULL, 'w' },
14845b67d0bbb21412bcdf7a271ddf34823f8776dc06Lennart Poettering        { "force-bind",    no_argument,       NULL, OPTION_FORCE_BIND },
14859ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        { "no-drop-root",  no_argument,       NULL, OPTION_NO_DROP_ROOT },
1486872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering#ifdef HAVE_CHROOT
14879ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        { "no-chroot",     no_argument,       NULL, OPTION_NO_CHROOT },
1488872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering#endif
14899ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        { "no-proc-title", no_argument,       NULL, OPTION_NO_PROC_TITLE },
14905ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { "debug",         no_argument,       NULL, OPTION_DEBUG },
14915ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        { NULL, 0, NULL, 0 }
14925ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    };
149360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
1494b54a67fe8a7da842fd086a289e5b61c5b518b03eLennart Poettering    while ((c = getopt_long(argc, argv, "hDskrcVS:t:w", long_options, NULL)) >= 0) {
14955ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
14965ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        switch(c) {
14975ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case 's':
14985ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                use_syslog = 1;
14995ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
15005ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case 'h':
15015ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                command = DAEMON_HELP;
15025ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
15035ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case 'D':
15045ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                daemonize = 1;
15055ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
15065ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case 'k':
15075ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                command = DAEMON_KILL;
15085ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
15095ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case 'V':
15105ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                command = DAEMON_VERSION;
15115ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
15125ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case 'r':
15135ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                command = DAEMON_REFRESH;
15145ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
15155ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case 'c':
15165ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                command = DAEMON_CHECK;
15175ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
15185ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case 'S':
1519872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
15205ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                if ((start_address = inet_addr(optarg)) == (uint32_t) -1) {
15215ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    fprintf(stderr, "Failed to parse IP address '%s'.", optarg);
15225ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    return -1;
15235ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                }
15245ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
1525b54a67fe8a7da842fd086a289e5b61c5b518b03eLennart Poettering            case 't':
1526b54a67fe8a7da842fd086a289e5b61c5b518b03eLennart Poettering                avahi_free(action_script);
1527b54a67fe8a7da842fd086a289e5b61c5b518b03eLennart Poettering                action_script = avahi_strdup(optarg);
1528b54a67fe8a7da842fd086a289e5b61c5b518b03eLennart Poettering                break;
15295ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case 'w':
15305ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                wait_for_address = 1;
15315ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
1532872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
15335ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case OPTION_NO_PROC_TITLE:
15345ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                modify_proc_title = 0;
15355ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
153660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
15375ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            case OPTION_DEBUG:
15385ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                debug = 1;
15395ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                break;
15405ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
15415b67d0bbb21412bcdf7a271ddf34823f8776dc06Lennart Poettering            case OPTION_FORCE_BIND:
15425b67d0bbb21412bcdf7a271ddf34823f8776dc06Lennart Poettering                force_bind = 1;
15435b67d0bbb21412bcdf7a271ddf34823f8776dc06Lennart Poettering                break;
15445b67d0bbb21412bcdf7a271ddf34823f8776dc06Lennart Poettering
15459ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            case OPTION_NO_DROP_ROOT:
15469ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering                no_drop_root = 1;
15479ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering                break;
15489ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering
15499ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#ifdef HAVE_CHROOT
15509ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering            case OPTION_NO_CHROOT:
15519ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering                no_chroot = 1;
15529ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering                break;
15539ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering#endif
15549ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering
15555ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            default:
15565ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                return -1;
15575ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        }
155860d86f779725e78ae3d295380f15208859cc06ebLennart Poettering    }
155960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
15605ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (command == DAEMON_RUN ||
15615ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        command == DAEMON_KILL ||
15625ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        command == DAEMON_REFRESH ||
15635ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        command == DAEMON_CHECK) {
156460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
15655ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if (optind >= argc) {
15665ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            fprintf(stderr, "Missing interface name.\n");
15675ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            return -1;
15685ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        }
156960d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
15709d709a294b81066a0942a7a642df1b3d4940ad26Lennart Poettering        interface_name = avahi_strdup(argv[optind++]);
15715ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    }
15725ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
15735ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (optind != argc) {
15745ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        fprintf(stderr, "Too many arguments\n");
15755ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        return -1;
15765ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    }
1577b54a67fe8a7da842fd086a289e5b61c5b518b03eLennart Poettering
1578b54a67fe8a7da842fd086a289e5b61c5b518b03eLennart Poettering    if (!action_script)
1579b54a67fe8a7da842fd086a289e5b61c5b518b03eLennart Poettering        action_script = avahi_strdup(AVAHI_IPCONF_SCRIPT);
1580872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
15815ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    return 0;
15825ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering}
15835ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
15845ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringstatic const char* pid_file_proc(void) {
15855ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    return pid_file_name;
158660d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
158760d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
158860d86f779725e78ae3d295380f15208859cc06ebLennart Poetteringint main(int argc, char*argv[]) {
15895ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    int r = 1;
15909d709a294b81066a0942a7a642df1b3d4940ad26Lennart Poettering    char *log_ident = NULL;
159160d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
15927bf6b7b95b7c3327000794a24e104242598a9f3fLennart Poettering    signal(SIGPIPE, SIG_IGN);
1593872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
15945ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if ((argv0 = strrchr(argv[0], '/')))
15959ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        argv0 = avahi_strdup(argv0 + 1);
15965ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    else
15979ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        argv0 = avahi_strdup(argv[0]);
15989d709a294b81066a0942a7a642df1b3d4940ad26Lennart Poettering
15999d709a294b81066a0942a7a642df1b3d4940ad26Lennart Poettering    daemon_log_ident = argv0;
1600872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
16015ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (parse_command_line(argc, argv) < 0)
16025ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        goto finish;
160360d86f779725e78ae3d295380f15208859cc06ebLennart Poettering
16049ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering    if (modify_proc_title)
16059ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering        avahi_init_proc_title(argc, argv);
16069ce608107192e885eb8de93290f7faf0bf9176a2Lennart Poettering
16079d709a294b81066a0942a7a642df1b3d4940ad26Lennart Poettering    daemon_log_ident = log_ident = avahi_strdup_printf("%s(%s)", argv0, interface_name);
16089d709a294b81066a0942a7a642df1b3d4940ad26Lennart Poettering    daemon_pid_file_proc = pid_file_proc;
16095ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    pid_file_name = avahi_strdup_printf(AVAHI_RUNTIME_DIR"/avahi-autoipd.%s.pid", interface_name);
16105ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
16115ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (command == DAEMON_RUN) {
16125ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        pid_t pid;
16135ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        int ifindex;
16145ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
16155ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        init_rand_seed();
1616872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
16175ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if ((ifindex = if_nametoindex(interface_name)) <= 0) {
16185ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            daemon_log(LOG_ERR, "Failed to get index for interface name '%s': %s", interface_name, strerror(errno));
16195ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            goto finish;
16205ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        }
16215ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
16225ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if (getuid() != 0) {
16235ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            daemon_log(LOG_ERR, "This program is intended to be run as root.");
16245ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            goto finish;
16255ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        }
16265ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
16275ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if ((pid = daemon_pid_file_is_running()) >= 0) {
16285ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            daemon_log(LOG_ERR, "Daemon already running on PID %u", pid);
16295ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            goto finish;
16305ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        }
16315ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
16325ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if (daemonize) {
16335ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            daemon_retval_init();
1634872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
16355ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            if ((pid = daemon_fork()) < 0)
16365ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                goto finish;
16375ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            else if (pid != 0) {
16385ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                int ret;
16395ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                /** Parent **/
16405ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
16415ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                if ((ret = daemon_retval_wait(20)) < 0) {
16425ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    daemon_log(LOG_ERR, "Could not receive return value from daemon process.");
16435ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                    goto finish;
16445ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                }
16455ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
16465ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                r = ret;
16475ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                goto finish;
16485ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            }
16495ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
16505ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            /* Child */
16515ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        }
16525ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
16535ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if (use_syslog || daemonize)
16545ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            daemon_log_use = DAEMON_LOG_SYSLOG;
16555ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
16565ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        chdir("/");
16575ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
16585ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if (daemon_pid_file_create() < 0) {
16595ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            daemon_log(LOG_ERR, "Failed to create PID file: %s", strerror(errno));
16605ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
16615ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            if (daemonize)
16625ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering                daemon_retval_send(1);
16635ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            goto finish;
16645ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        } else
16655ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            wrote_pid_file = 1;
16665ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
1667287f9866c923e6afe8ffbbc03b90be64acf395e1Lennart Poettering        avahi_set_proc_title(argv0, "%s: [%s] starting up", argv0, interface_name);
1668872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
16695ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if (loop(ifindex, start_address) < 0)
16705ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            goto finish;
16715ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
16725ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        r = 0;
16735ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    } else if (command == DAEMON_HELP) {
16745ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        help(stdout, argv0);
1675872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
16765ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        r = 0;
16775ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    } else if (command == DAEMON_VERSION) {
16785ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        printf("%s "PACKAGE_VERSION"\n", argv0);
1679872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
16805ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        r = 0;
16815ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    } else if (command == DAEMON_KILL) {
16825ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if (daemon_pid_file_kill_wait(SIGTERM, 5) < 0) {
16835ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            daemon_log(LOG_WARNING, "Failed to kill daemon: %s", strerror(errno));
16845ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            goto finish;
16855ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        }
1686872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
16875ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        r = 0;
16885ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    } else if (command == DAEMON_REFRESH) {
16895ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        if (daemon_pid_file_kill(SIGHUP) < 0) {
16905ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            daemon_log(LOG_WARNING, "Failed to kill daemon: %s", strerror(errno));
16915ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering            goto finish;
16925ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        }
16935ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
16945ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        r = 0;
16955ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    } else if (command == DAEMON_CHECK)
16965ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        r = (daemon_pid_file_is_running() >= 0) ? 0 : 1;
16975ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
16985ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
16995ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poetteringfinish:
17005ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
17015ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (daemonize)
17025ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        daemon_retval_done();
1703872947dffb0d1e5b23658ef118799c0ed55d8b27Lennart Poettering
17045ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    if (wrote_pid_file)
17055ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering        daemon_pid_file_remove();
17065ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering
17079d709a294b81066a0942a7a642df1b3d4940ad26Lennart Poettering    avahi_free(log_ident);
17089d709a294b81066a0942a7a642df1b3d4940ad26Lennart Poettering    avahi_free(pid_file_name);
17099d709a294b81066a0942a7a642df1b3d4940ad26Lennart Poettering    avahi_free(argv0);
17109d709a294b81066a0942a7a642df1b3d4940ad26Lennart Poettering    avahi_free(interface_name);
1711b54a67fe8a7da842fd086a289e5b61c5b518b03eLennart Poettering    avahi_free(action_script);
17129d709a294b81066a0942a7a642df1b3d4940ad26Lennart Poettering
17135ea98f8caf0e163ad1f51039b8a2d13e3fe0e86cLennart Poettering    return r;
171460d86f779725e78ae3d295380f15208859cc06ebLennart Poettering}
1715