• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 
usage()77 void usage()
78 {
79 	fprintf(stderr, "Usage: rarpd [ -dveaA ] [ -b tftpdir ] [ interface]\n");
80 	exit(1);
81 }
82 
load_db(void)83 void load_db(void)
84 {
85 }
86 
load_if(void)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 
configure(void)213 void configure(void)
214 {
215 	load_if();
216 	load_db();
217 }
218 
bootable(__u32 addr)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 
select_ipaddr(int ifindex,__u32 * sel_addr,__u32 ** alist)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 
rarp_lookup(int ifindex,int hatype,int halen,unsigned char * lladdr)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 
load_arp_bpflet(int fd)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 
put_mylladdr(unsigned char ** ptr_p,int ifindex,int alen)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 
put_myipaddr(unsigned char ** ptr_p,int ifindex,__u32 hisipaddr)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 
arp_advise(int ifindex,unsigned char * lladdr,int lllen,__u32 ipaddr)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 
serve_it(int fd)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 
catch_signal(int sig,void (* handler)(int))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 
sig_alarm(int signo)554 void sig_alarm(int signo)
555 {
556 }
557 
sig_hup(int signo)558 void sig_hup(int signo)
559 {
560 	do_reload = 1;
561 }
562 
main(int argc,char ** argv)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