Home | History | Annotate | Download | only in iputils
      1 /*
      2  * rarpd.c	RARP daemon.
      3  *
      4  *		This program is free software; you can redistribute it and/or
      5  *		modify it under the terms of the GNU General Public License
      6  *		as published by the Free Software Foundation; either version
      7  *		2 of the License, or (at your option) any later version.
      8  *
      9  * Authors:	Alexey Kuznetsov, <kuznet (at) ms2.inr.ac.ru>
     10  */
     11 
     12 #include <stdio.h>
     13 #include <syslog.h>
     14 #include <dirent.h>
     15 #include <malloc.h>
     16 #include <string.h>
     17 #include <unistd.h>
     18 #include <stdlib.h>
     19 #include <netdb.h>
     20 #include <arpa/inet.h>
     21 #include <sys/ioctl.h>
     22 #include <sys/poll.h>
     23 #include <sys/errno.h>
     24 #include <sys/fcntl.h>
     25 #include <sys/socket.h>
     26 #include <sys/signal.h>
     27 #include <linux/if.h>
     28 #include <linux/if_arp.h>
     29 #include <netinet/in.h>
     30 #include <linux/if_packet.h>
     31 #include <linux/filter.h>
     32 
     33 int do_reload = 1;
     34 
     35 int debug;
     36 int verbose;
     37 int ifidx;
     38 int allow_offlink;
     39 int only_ethers;
     40 int all_ifaces;
     41 int listen_arp;
     42 char *ifname;
     43 char *tftp_dir = "/etc/tftpboot";
     44 
     45 extern int ether_ntohost(char *name, unsigned char *ea);
     46 void usage(void) __attribute__((noreturn));
     47 
     48 struct iflink
     49 {
     50 	struct iflink	*next;
     51 	int	       	index;
     52 	int		hatype;
     53 	unsigned char	lladdr[16];
     54 	char		name[IFNAMSIZ];
     55 	struct ifaddr 	*ifa_list;
     56 } *ifl_list;
     57 
     58 struct ifaddr
     59 {
     60 	struct ifaddr 	*next;
     61 	__u32		prefix;
     62 	__u32		mask;
     63 	__u32		local;
     64 };
     65 
     66 struct rarp_map
     67 {
     68 	struct rarp_map *next;
     69 
     70 	int		ifindex;
     71 	int		arp_type;
     72 	int		lladdr_len;
     73 	unsigned char	lladdr[16];
     74 	__u32		ipaddr;
     75 } *rarp_db;
     76 
     77 void usage()
     78 {
     79 	fprintf(stderr, "Usage: rarpd [ -dveaA ] [ -b tftpdir ] [ interface]\n");
     80 	exit(1);
     81 }
     82 
     83 void load_db(void)
     84 {
     85 }
     86 
     87 void load_if(void)
     88 {
     89 	int fd;
     90 	struct ifreq *ifrp, *ifend;
     91 	struct iflink *ifl;
     92 	struct ifaddr *ifa;
     93 	struct ifconf ifc;
     94 	struct ifreq ibuf[256];
     95 
     96 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
     97 		syslog(LOG_ERR, "socket: %m");
     98 		return;
     99 	}
    100 
    101 	ifc.ifc_len = sizeof ibuf;
    102 	ifc.ifc_buf = (caddr_t)ibuf;
    103 	if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
    104 	    ifc.ifc_len < (int)sizeof(struct ifreq)) {
    105 		syslog(LOG_ERR, "SIOCGIFCONF: %m");
    106 		close(fd);
    107 		return;
    108 	}
    109 
    110 	while ((ifl = ifl_list) != NULL) {
    111 		while ((ifa = ifl->ifa_list) != NULL) {
    112 			ifl->ifa_list = ifa->next;
    113 			free(ifa);
    114 		}
    115 		ifl_list = ifl->next;
    116 		free(ifl);
    117 	}
    118 
    119 	ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
    120 	for (ifrp = ibuf; ifrp < ifend; ifrp++) {
    121 		__u32 addr;
    122 		__u32 mask;
    123 		__u32 prefix;
    124 
    125 		if (ifrp->ifr_addr.sa_family != AF_INET)
    126 			continue;
    127 		addr = ((struct sockaddr_in*)&ifrp->ifr_addr)->sin_addr.s_addr;
    128 		if (addr == 0)
    129 			continue;
    130 		if (ioctl(fd, SIOCGIFINDEX, ifrp)) {
    131 			syslog(LOG_ERR, "ioctl(SIOCGIFNAME): %m");
    132 			continue;
    133 		}
    134 		if (ifidx && ifrp->ifr_ifindex != ifidx)
    135 			continue;
    136 		for (ifl = ifl_list; ifl; ifl = ifl->next)
    137 			if (ifl->index == ifrp->ifr_ifindex)
    138 				break;
    139 		if (ifl == NULL) {
    140 			char *p;
    141 			int index = ifrp->ifr_ifindex;
    142 
    143 			if (ioctl(fd, SIOCGIFHWADDR, ifrp)) {
    144 				syslog(LOG_ERR, "ioctl(SIOCGIFHWADDR): %m");
    145 				continue;
    146 			}
    147 
    148 			ifl = (struct iflink*)malloc(sizeof(*ifl));
    149 			if (ifl == NULL)
    150 				continue;
    151 			memset(ifl, 0, sizeof(*ifl));
    152 			ifl->next = ifl_list;
    153 			ifl_list = ifl;
    154 			ifl->index = index;
    155 			ifl->hatype = ifrp->ifr_hwaddr.sa_family;
    156 			memcpy(ifl->lladdr, ifrp->ifr_hwaddr.sa_data, 14);
    157 			strncpy(ifl->name, ifrp->ifr_name, IFNAMSIZ);
    158 			p = strchr(ifl->name, ':');
    159 			if (p)
    160 				*p = 0;
    161 			if (verbose)
    162 				syslog(LOG_INFO, "link %s", ifl->name);
    163 		}
    164 		if (ioctl(fd, SIOCGIFNETMASK, ifrp)) {
    165 			syslog(LOG_ERR, "ioctl(SIOCGIFMASK): %m");
    166 			continue;
    167 		}
    168 		mask = ((struct sockaddr_in*)&ifrp->ifr_netmask)->sin_addr.s_addr;
    169 		if (ioctl(fd, SIOCGIFDSTADDR, ifrp)) {
    170 			syslog(LOG_ERR, "ioctl(SIOCGIFDSTADDR): %m");
    171 			continue;
    172 		}
    173 		prefix = ((struct sockaddr_in*)&ifrp->ifr_dstaddr)->sin_addr.s_addr;
    174 		for (ifa = ifl->ifa_list; ifa; ifa = ifa->next) {
    175 			if (ifa->local == addr &&
    176 			    ifa->prefix == prefix &&
    177 			    ifa->mask == mask)
    178 				break;
    179 		}
    180 		if (ifa == NULL) {
    181 			if (mask == 0 || prefix == 0)
    182 				continue;
    183 			ifa = (struct ifaddr*)malloc(sizeof(*ifa));
    184 			memset(ifa, 0, sizeof(*ifa));
    185 			ifa->local = addr;
    186 			ifa->prefix = prefix;
    187 			ifa->mask = mask;
    188 			ifa->next = ifl->ifa_list;
    189 			ifl->ifa_list = ifa;
    190 
    191 			if (verbose) {
    192 				int i;
    193 				__u32 m = ~0U;
    194 				for (i=32; i>=0; i--) {
    195 					if (htonl(m) == mask)
    196 						break;
    197 					m <<= 1;
    198 				}
    199 				if (addr == prefix) {
    200 					syslog(LOG_INFO, "  addr %s/%d on %s\n",
    201 					       inet_ntoa(*(struct in_addr*)&addr), i, ifl->name);
    202 				} else {
    203 					char tmpa[64];
    204 					sprintf(tmpa, "%s", inet_ntoa(*(struct in_addr*)&addr));
    205 					syslog(LOG_INFO, "  addr %s %s/%d on %s\n", tmpa,
    206 					       inet_ntoa(*(struct in_addr*)&prefix), i, ifl->name);
    207 				}
    208 			}
    209 		}
    210 	}
    211 }
    212 
    213 void configure(void)
    214 {
    215 	load_if();
    216 	load_db();
    217 }
    218 
    219 int bootable(__u32 addr)
    220 {
    221 	struct dirent *dent;
    222 	DIR *d;
    223 	char name[9];
    224 
    225 	sprintf(name, "%08X", (__u32)ntohl(addr));
    226 	d = opendir(tftp_dir);
    227 	if (d == NULL) {
    228 		syslog(LOG_ERR, "opendir: %m");
    229 		return 0;
    230 	}
    231 	while ((dent = readdir(d)) != NULL) {
    232 		if (strncmp(dent->d_name, name, 8) == 0)
    233 			break;
    234 	}
    235 	closedir(d);
    236 	return dent != NULL;
    237 }
    238 
    239 struct ifaddr *select_ipaddr(int ifindex, __u32 *sel_addr, __u32 **alist)
    240 {
    241 	struct iflink *ifl;
    242 	struct ifaddr *ifa;
    243 	int retry = 0;
    244 	int i;
    245 
    246 retry:
    247 	for (ifl=ifl_list; ifl; ifl=ifl->next)
    248 		if (ifl->index == ifindex)
    249 			break;
    250 	if (ifl == NULL && !retry) {
    251 		retry++;
    252 		load_if();
    253 		goto retry;
    254 	}
    255 	if (ifl == NULL)
    256 		return NULL;
    257 
    258 	for (i=0; alist[i]; i++) {
    259 		__u32 addr = *(alist[i]);
    260 		for (ifa=ifl->ifa_list; ifa; ifa=ifa->next) {
    261 			if (!((ifa->prefix^addr)&ifa->mask)) {
    262 				*sel_addr = addr;
    263 				return ifa;
    264 			}
    265 		}
    266 		if (ifa == NULL && retry==0) {
    267 			retry++;
    268 			load_if();
    269 			goto retry;
    270 		}
    271 	}
    272 	if (i==1 && allow_offlink) {
    273 		*sel_addr = *(alist[0]);
    274 		return ifl->ifa_list;
    275 	}
    276 	syslog(LOG_ERR, "Off-link request on %s", ifl->name);
    277 	return NULL;
    278 }
    279 
    280 struct rarp_map *rarp_lookup(int ifindex, int hatype,
    281 			     int halen, unsigned char *lladdr)
    282 {
    283 	struct rarp_map *r;
    284 
    285 	for (r=rarp_db; r; r=r->next) {
    286 		if (r->arp_type != hatype && r->arp_type != -1)
    287 			continue;
    288 		if (r->lladdr_len != halen)
    289 			continue;
    290 		if (r->ifindex != ifindex && r->ifindex != 0)
    291 			continue;
    292 		if (memcmp(r->lladdr, lladdr, halen) == 0)
    293 			break;
    294 	}
    295 
    296 	if (r == NULL) {
    297 		if (hatype == ARPHRD_ETHER && halen == 6) {
    298 			struct ifaddr *ifa;
    299 			struct hostent *hp;
    300 			char ename[256];
    301 			static struct rarp_map emap = {
    302 				NULL,
    303 				0,
    304 				ARPHRD_ETHER,
    305 				6,
    306 			};
    307 
    308 			if (ether_ntohost(ename, lladdr) != 0 ||
    309 			    (hp = gethostbyname(ename)) == NULL) {
    310 				if (verbose)
    311 					syslog(LOG_INFO, "not found in /etc/ethers");
    312 				return NULL;
    313 			}
    314 			if (hp->h_addrtype != AF_INET) {
    315 				syslog(LOG_ERR, "no IP address");
    316 				return NULL;
    317 			}
    318 			ifa = select_ipaddr(ifindex, &emap.ipaddr, (__u32 **)hp->h_addr_list);
    319 			if (ifa) {
    320 				memcpy(emap.lladdr, lladdr, 6);
    321 				if (only_ethers || bootable(emap.ipaddr))
    322 					return &emap;
    323 				if (verbose)
    324 					syslog(LOG_INFO, "not bootable");
    325 			}
    326 		}
    327 	}
    328 	return r;
    329 }
    330 
    331 static int load_arp_bpflet(int fd)
    332 {
    333 	static struct sock_filter insns[] = {
    334 		BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 6),
    335 		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, ARPOP_RREQUEST, 0, 1),
    336 		BPF_STMT(BPF_RET|BPF_K, 1024),
    337 		BPF_STMT(BPF_RET|BPF_K, 0),
    338 	};
    339 	static struct sock_fprog filter = {
    340 		sizeof insns / sizeof(insns[0]),
    341 		insns
    342 	};
    343 
    344 	return setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter));
    345 }
    346 
    347 int put_mylladdr(unsigned char **ptr_p, int ifindex, int alen)
    348 {
    349 	struct iflink *ifl;
    350 
    351 	for (ifl=ifl_list; ifl; ifl = ifl->next)
    352 		if (ifl->index == ifindex)
    353 			break;
    354 
    355 	if (ifl==NULL)
    356 		return -1;
    357 
    358 	memcpy(*ptr_p, ifl->lladdr, alen);
    359 	*ptr_p += alen;
    360 	return 0;
    361 }
    362 
    363 int put_myipaddr(unsigned char **ptr_p, int ifindex, __u32 hisipaddr)
    364 {
    365 	__u32 laddr = 0;
    366 	struct iflink *ifl;
    367 	struct ifaddr *ifa;
    368 
    369 	for (ifl=ifl_list; ifl; ifl = ifl->next)
    370 		if (ifl->index == ifindex)
    371 			break;
    372 
    373 	if (ifl==NULL)
    374 		return -1;
    375 
    376 	for (ifa=ifl->ifa_list; ifa; ifa=ifa->next) {
    377 		if (!((ifa->prefix^hisipaddr)&ifa->mask)) {
    378 			laddr = ifa->local;
    379 			break;
    380 		}
    381 	}
    382 	memcpy(*ptr_p, &laddr, 4);
    383 	*ptr_p += 4;
    384 	return 0;
    385 }
    386 
    387 void arp_advise(int ifindex, unsigned char *lladdr, int lllen, __u32 ipaddr)
    388 {
    389 	int fd;
    390 	struct arpreq req;
    391 	struct sockaddr_in *sin;
    392 	struct iflink *ifl;
    393 
    394 	for (ifl=ifl_list; ifl; ifl = ifl->next)
    395 		if (ifl->index == ifindex)
    396 			break;
    397 
    398 	if (ifl == NULL)
    399 		return;
    400 
    401 	fd = socket(AF_INET, SOCK_DGRAM, 0);
    402 	memset(&req, 0, sizeof(req));
    403 	req.arp_flags = ATF_COM;
    404 	sin = (struct sockaddr_in *)&req.arp_pa;
    405 	sin->sin_family = AF_INET;
    406 	sin->sin_addr.s_addr = ipaddr;
    407 	req.arp_ha.sa_family = ifl->hatype;
    408 	memcpy(req.arp_ha.sa_data, lladdr, lllen);
    409 	memcpy(req.arp_dev, ifl->name, IFNAMSIZ);
    410 
    411 	if (ioctl(fd, SIOCSARP, &req))
    412 		syslog(LOG_ERR, "SIOCSARP: %m");
    413 	close(fd);
    414 }
    415 
    416 void serve_it(int fd)
    417 {
    418 	unsigned char buf[1024];
    419 	struct sockaddr_ll sll;
    420 	socklen_t sll_len = sizeof(sll);
    421 	struct arphdr *a = (struct arphdr*)buf;
    422 	struct rarp_map *rmap;
    423 	unsigned char *ptr;
    424 	int n;
    425 
    426 	n = recvfrom(fd, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr*)&sll, &sll_len);
    427 	if (n<0) {
    428 		if (errno != EINTR && errno != EAGAIN)
    429 			syslog(LOG_ERR, "recvfrom: %m");
    430 		return;
    431 	}
    432 
    433 	/* Do not accept packets for other hosts and our own ones */
    434 	if (sll.sll_pkttype != PACKET_BROADCAST &&
    435 	    sll.sll_pkttype != PACKET_MULTICAST &&
    436 	    sll.sll_pkttype != PACKET_HOST)
    437 		return;
    438 
    439 	if (ifidx && sll.sll_ifindex != ifidx)
    440 		return;
    441 
    442 	if (n<sizeof(*a)) {
    443 		syslog(LOG_ERR, "truncated arp packet; len=%d", n);
    444 		return;
    445 	}
    446 
    447 	/* Accept only RARP requests */
    448 	if (a->ar_op != htons(ARPOP_RREQUEST))
    449 		return;
    450 
    451 	if (verbose) {
    452 		int i;
    453 		char tmpbuf[16*3];
    454 		char *ptr = tmpbuf;
    455 		for (i=0; i<sll.sll_halen; i++) {
    456 			if (i) {
    457 				sprintf(ptr, ":%02x", sll.sll_addr[i]);
    458 				ptr++;
    459 			} else
    460 				sprintf(ptr, "%02x", sll.sll_addr[i]);
    461 			ptr += 2;
    462 		}
    463 		syslog(LOG_INFO, "RARP request from %s on if%d", tmpbuf, sll.sll_ifindex);
    464 	}
    465 
    466 	/* Sanity checks */
    467 
    468 	/* 1. IP only -> pln==4 */
    469 	if (a->ar_pln != 4) {
    470 		syslog(LOG_ERR, "interesting rarp_req plen=%d", a->ar_pln);
    471 		return;
    472 	}
    473 	/* 2. ARP protocol must be IP */
    474 	if (a->ar_pro != htons(ETH_P_IP)) {
    475 		syslog(LOG_ERR, "rarp protocol is not IP %04x", ntohs(a->ar_pro));
    476 		return;
    477 	}
    478 	/* 3. ARP types must match */
    479 	if (htons(sll.sll_hatype) != a->ar_hrd) {
    480 		switch (sll.sll_hatype) {
    481 		case ARPHRD_FDDI:
    482 			if (a->ar_hrd == htons(ARPHRD_ETHER) ||
    483 			    a->ar_hrd == htons(ARPHRD_IEEE802))
    484 				break;
    485 		default:
    486 			syslog(LOG_ERR, "rarp htype mismatch");
    487 			return;
    488 		}
    489 	}
    490 	/* 3. LL address lengths must be equal */
    491 	if (a->ar_hln != sll.sll_halen) {
    492 		syslog(LOG_ERR, "rarp hlen mismatch");
    493 		return;
    494 	}
    495 	/* 4. Check packet length */
    496 	if (sizeof(*a) + 2*4 + 2*a->ar_hln > n) {
    497 		syslog(LOG_ERR, "truncated rarp request; len=%d", n);
    498 		return;
    499 	}
    500 	/* 5. Silly check: if this guy set different source
    501 	      addresses in MAC header and in ARP, he is insane
    502 	 */
    503 	if (memcmp(sll.sll_addr, a+1, sll.sll_halen)) {
    504 		syslog(LOG_ERR, "this guy set different his lladdrs in arp and header");
    505 		return;
    506 	}
    507 	/* End of sanity checks */
    508 
    509 	/* Lookup requested target in our database */
    510 	rmap = rarp_lookup(sll.sll_ifindex, sll.sll_hatype,
    511 			   sll.sll_halen, (unsigned char*)(a+1) + sll.sll_halen + 4);
    512 	if (rmap == NULL)
    513 		return;
    514 
    515 	/* Prepare reply. It is almost ready, we only
    516 	   replace ARP packet type, put our lladdr and
    517 	   IP address to source fileds,
    518 	   and fill target IP address.
    519 	 */
    520 	a->ar_op = htons(ARPOP_RREPLY);
    521 	ptr = (unsigned char*)(a+1);
    522 	if (put_mylladdr(&ptr, sll.sll_ifindex, rmap->lladdr_len))
    523 		return;
    524 	if (put_myipaddr(&ptr, sll.sll_ifindex, rmap->ipaddr))
    525 		return;
    526 	/* It is already filled */
    527 	ptr += rmap->lladdr_len;
    528 	memcpy(ptr, &rmap->ipaddr, 4);
    529 	ptr += 4;
    530 
    531 	/* Update our ARP cache. Probably, this guy
    532 	   will not able to make ARP (if it is broken)
    533 	 */
    534 	arp_advise(sll.sll_ifindex, rmap->lladdr, rmap->lladdr_len, rmap->ipaddr);
    535 
    536 	/* Sendto is blocking, but with 5sec timeout */
    537 	alarm(5);
    538 	sendto(fd, buf, ptr - buf, 0, (struct sockaddr*)&sll, sizeof(sll));
    539 	alarm(0);
    540 }
    541 
    542 void catch_signal(int sig, void (*handler)(int))
    543 {
    544 	struct sigaction sa;
    545 
    546 	memset(&sa, 0, sizeof(sa));
    547 	sa.sa_handler = handler;
    548 #ifdef SA_INTERRUPT
    549 	sa.sa_flags = SA_INTERRUPT;
    550 #endif
    551 	sigaction(sig, &sa, NULL);
    552 }
    553 
    554 void sig_alarm(int signo)
    555 {
    556 }
    557 
    558 void sig_hup(int signo)
    559 {
    560 	do_reload = 1;
    561 }
    562 
    563 int main(int argc, char **argv)
    564 {
    565 	struct pollfd pset[2];
    566 	int psize;
    567 	int opt;
    568 
    569 
    570 	opterr = 0;
    571 	while ((opt = getopt(argc, argv, "aAb:dvoe")) != EOF) {
    572 		switch (opt) {
    573 		case 'a':
    574 			++all_ifaces;
    575 			break;
    576 
    577 		case 'A':
    578 			++listen_arp;
    579 			break;
    580 
    581 		case 'd':
    582 			++debug;
    583 			break;
    584 
    585 		case 'v':
    586 			++verbose;
    587 			break;
    588 
    589 		case 'o':
    590 			++allow_offlink;
    591 			break;
    592 
    593 		case 'e':
    594 			++only_ethers;
    595 			break;
    596 
    597 		case 'b':
    598 			tftp_dir = optarg;
    599 			break;
    600 
    601 		default:
    602 			usage();
    603 		}
    604 	}
    605 	if (argc > optind) {
    606 		if (argc > optind+1)
    607 			usage();
    608 		ifname = argv[optind];
    609 	}
    610 
    611 	psize = 1;
    612 	pset[0].fd = socket(PF_PACKET, SOCK_DGRAM, 0);
    613 
    614 	if (ifname) {
    615 		struct ifreq ifr;
    616 		memset(&ifr, 0, sizeof(ifr));
    617 		strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
    618 		if (ioctl(pset[0].fd, SIOCGIFINDEX, &ifr)) {
    619 			perror("ioctl(SIOCGIFINDEX)");
    620 			usage();
    621 		}
    622 		ifidx = ifr.ifr_ifindex;
    623 	}
    624 
    625 	pset[1].fd = -1;
    626 	if (listen_arp) {
    627 		pset[1].fd = socket(PF_PACKET, SOCK_DGRAM, 0);
    628 		if (pset[1].fd >= 0) {
    629 			load_arp_bpflet(pset[1].fd);
    630 			psize = 1;
    631 		}
    632 	}
    633 
    634 	if (pset[1].fd >= 0) {
    635 		struct sockaddr_ll sll;
    636 		memset(&sll, 0, sizeof(sll));
    637 		sll.sll_family = AF_PACKET;
    638 		sll.sll_protocol = htons(ETH_P_ARP);
    639 		sll.sll_ifindex = all_ifaces ? 0 : ifidx;
    640 		if (bind(pset[1].fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) {
    641 			close(pset[1].fd);
    642 			pset[1].fd = -1;
    643 			psize = 1;
    644 		}
    645 	}
    646 	if (pset[0].fd >= 0) {
    647 		struct sockaddr_ll sll;
    648 		memset(&sll, 0, sizeof(sll));
    649 		sll.sll_family = AF_PACKET;
    650 		sll.sll_protocol = htons(ETH_P_RARP);
    651 		sll.sll_ifindex = all_ifaces ? 0 : ifidx;
    652 		if (bind(pset[0].fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) {
    653 			close(pset[0].fd);
    654 			pset[0].fd = -1;
    655 		}
    656 	}
    657 	if (pset[0].fd < 0) {
    658 		pset[0] = pset[1];
    659 		psize--;
    660 	}
    661 	if (psize == 0) {
    662 		fprintf(stderr, "failed to bind any socket. Aborting.\n");
    663 		exit(1);
    664 	}
    665 
    666 	if (!debug) {
    667 		int fd;
    668 		pid_t pid = fork();
    669 
    670 		if (pid > 0)
    671 			exit(0);
    672 		else if (pid == -1) {
    673 			perror("rarpd: fork");
    674 			exit(1);
    675 		}
    676 
    677 		if (chdir("/") < 0) {
    678 			perror("rarpd: chdir");
    679 			exit(1);
    680 		}
    681 
    682 		fd = open("/dev/null", O_RDWR);
    683 		if (fd >= 0) {
    684 			dup2(fd, 0);
    685 			dup2(fd, 1);
    686 			dup2(fd, 2);
    687 			if (fd > 2)
    688 				close(fd);
    689 		}
    690 		setsid();
    691 	}
    692 
    693 	openlog("rarpd", LOG_PID | LOG_CONS, LOG_DAEMON);
    694 	catch_signal(SIGALRM, sig_alarm);
    695 	catch_signal(SIGHUP, sig_hup);
    696 
    697 	for (;;) {
    698 		int i;
    699 
    700 		if (do_reload) {
    701 			configure();
    702 			do_reload = 0;
    703 		}
    704 
    705 #define EVENTS (POLLIN|POLLPRI|POLLERR|POLLHUP)
    706 		pset[0].events = EVENTS;
    707 		pset[0].revents = 0;
    708 		pset[1].events = EVENTS;
    709 		pset[1].revents = 0;
    710 
    711 		i = poll(pset, psize, -1);
    712 		if (i <= 0) {
    713 			if (errno != EINTR && i<0) {
    714 				syslog(LOG_ERR, "poll returned some crap: %m\n");
    715 				sleep(10);
    716 			}
    717 			continue;
    718 		}
    719 		for (i=0; i<psize; i++) {
    720 			if (pset[i].revents&EVENTS)
    721 				serve_it(pset[i].fd);
    722 		}
    723 	}
    724 }
    725