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