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