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