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