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