1 /*
2 Copyright (c) 2003-2006 by Juliusz Chroboczek
3 
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10 
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 */
22 
23 #include "polipo.h"
24 
25 #ifdef HAVE_IPv6
26 #ifdef IPV6_PREFER_TEMPADDR
27 #define HAVE_IPV6_PREFER_TEMPADDR 1
28 #endif
29 #endif
30 
31 #ifdef HAVE_IPV6_PREFER_TEMPADDR
32 int useTemporarySourceAddress = 1;
33 #endif
34 
35 void
preinitIo()36 preinitIo()
37 {
38 #ifdef HAVE_IPV6_PREFER_TEMPADDR
39     CONFIG_VARIABLE_SETTABLE(useTemporarySourceAddress, CONFIG_TRISTATE,
40                              configIntSetter,
41                              "Prefer IPv6 temporary source address.");
42 #endif
43 
44 #ifdef HAVE_WINSOCK
45     /* Load the winsock dll */
46     WSADATA wsaData;
47     WORD wVersionRequested = MAKEWORD(2, 2);
48     int err = WSAStartup( wVersionRequested, &wsaData );
49     if (err != 0) {
50         do_log_error(L_ERROR, err, "Couldn't load winsock dll");
51         exit(-1);
52     }
53 #endif
54     return;
55 }
56 
57 void
initIo()58 initIo()
59 {
60     return;
61 }
62 
63 FdEventHandlerPtr
do_stream(int operation,int fd,int offset,char * buf,int len,int (* handler)(int,FdEventHandlerPtr,StreamRequestPtr),void * data)64 do_stream(int operation, int fd, int offset, char *buf, int len,
65           int (*handler)(int, FdEventHandlerPtr, StreamRequestPtr),
66           void *data)
67 {
68     assert(len > offset || (operation & (IO_END | IO_IMMEDIATE)));
69     return schedule_stream(operation, fd, offset,
70                            NULL, 0, buf, len, NULL, 0, NULL, 0, NULL,
71                            handler, data);
72 }
73 
74 FdEventHandlerPtr
do_stream_2(int operation,int fd,int offset,char * buf,int len,char * buf2,int len2,int (* handler)(int,FdEventHandlerPtr,StreamRequestPtr),void * data)75 do_stream_2(int operation, int fd, int offset,
76             char *buf, int len, char *buf2, int len2,
77             int (*handler)(int, FdEventHandlerPtr, StreamRequestPtr),
78             void *data)
79 {
80     assert(len + len2 > offset || (operation & (IO_END | IO_IMMEDIATE)));
81     return schedule_stream(operation, fd, offset,
82                            NULL, 0, buf, len, buf2, len2, NULL, 0, NULL,
83                            handler, data);
84 }
85 
86 FdEventHandlerPtr
do_stream_3(int operation,int fd,int offset,char * buf,int len,char * buf2,int len2,char * buf3,int len3,int (* handler)(int,FdEventHandlerPtr,StreamRequestPtr),void * data)87 do_stream_3(int operation, int fd, int offset,
88             char *buf, int len, char *buf2, int len2, char *buf3, int len3,
89             int (*handler)(int, FdEventHandlerPtr, StreamRequestPtr),
90             void *data)
91 {
92     assert(len + len2 > offset || (operation & (IO_END | IO_IMMEDIATE)));
93     return schedule_stream(operation, fd, offset,
94                            NULL, 0, buf, len, buf2, len2, buf3, len3, NULL,
95                            handler, data);
96 }
97 
98 FdEventHandlerPtr
do_stream_h(int operation,int fd,int offset,char * header,int hlen,char * buf,int len,int (* handler)(int,FdEventHandlerPtr,StreamRequestPtr),void * data)99 do_stream_h(int operation, int fd, int offset,
100             char *header, int hlen, char *buf, int len,
101             int (*handler)(int, FdEventHandlerPtr, StreamRequestPtr),
102             void *data)
103 {
104     assert(hlen + len > offset || (operation & (IO_END | IO_IMMEDIATE)));
105     return schedule_stream(operation, fd, offset,
106                            header, hlen, buf, len, NULL, 0, NULL, 0, NULL,
107                            handler, data);
108 }
109 
110 FdEventHandlerPtr
do_stream_buf(int operation,int fd,int offset,char ** buf_location,int len,int (* handler)(int,FdEventHandlerPtr,StreamRequestPtr),void * data)111 do_stream_buf(int operation, int fd, int offset, char **buf_location, int len,
112               int (*handler)(int, FdEventHandlerPtr, StreamRequestPtr),
113               void *data)
114 {
115     assert((len > offset || (operation & (IO_END | IO_IMMEDIATE)))
116            && len <= CHUNK_SIZE);
117     return schedule_stream(operation, fd, offset,
118                            NULL, 0, *buf_location, len,
119                            NULL, 0, NULL, 0, buf_location,
120                            handler, data);
121 }
122 
123 static int
chunkHeaderLen(int i)124 chunkHeaderLen(int i)
125 {
126     if(i <= 0)
127         return 0;
128     if(i < 0x10)
129         return 3;
130     else if(i < 0x100)
131         return 4;
132     else if(i < 0x1000)
133         return 5;
134     else if(i < 0x10000)
135         return 6;
136     else
137         abort();
138 }
139 
140 static int
chunkHeader(char * buf,int buflen,int i)141 chunkHeader(char *buf, int buflen, int i)
142 {
143     int n;
144     if(i <= 0)
145         return 0;
146     n = snprintf(buf, buflen, "%x\r\n", i);
147     return n;
148 }
149 
150 
151 FdEventHandlerPtr
schedule_stream(int operation,int fd,int offset,char * header,int hlen,char * buf,int len,char * buf2,int len2,char * buf3,int len3,char ** buf_location,int (* handler)(int,FdEventHandlerPtr,StreamRequestPtr),void * data)152 schedule_stream(int operation, int fd, int offset,
153                 char *header, int hlen,
154                 char *buf, int len, char *buf2, int len2, char *buf3, int len3,
155                 char **buf_location,
156                 int (*handler)(int, FdEventHandlerPtr, StreamRequestPtr),
157                 void *data)
158 {
159     StreamRequestRec request;
160     FdEventHandlerPtr event;
161     int done;
162 
163     request.operation = operation;
164     request.fd = fd;
165     if(len3) {
166         assert(hlen == 0 && buf_location == NULL);
167         request.u.b.len3 = len3;
168         request.u.b.buf3 = buf3;
169         request.operation |= IO_BUF3;
170     } else if(buf_location) {
171         assert(hlen == 0);
172         request.u.l.buf_location = buf_location;
173         request.operation |= IO_BUF_LOCATION;
174     } else {
175         request.u.h.hlen = hlen;
176         request.u.h.header = header;
177     }
178     request.buf = buf;
179     request.len = len;
180     request.buf2 = buf2;
181     request.len2 = len2;
182     if((operation & IO_CHUNKED) ||
183        (!(request.operation & (IO_BUF3 | IO_BUF_LOCATION)) && hlen > 0)) {
184         assert(offset == 0);
185         request.offset = -hlen;
186         if(operation & IO_CHUNKED)
187             request.offset += -chunkHeaderLen(len + len2);
188     } else {
189         request.offset = offset;
190     }
191     request.handler = handler;
192     request.data = data;
193     event = makeFdEvent(fd,
194                         (operation & IO_MASK) == IO_WRITE ?
195                         POLLOUT : POLLIN,
196                         do_scheduled_stream,
197                         sizeof(StreamRequestRec), &request);
198     if(!event) {
199         done = (*handler)(-ENOMEM, NULL, &request);
200         assert(done);
201         return NULL;
202     }
203 
204     if(!(operation & IO_NOTNOW)) {
205         done = event->handler(0, event);
206         if(done) {
207             free(event);
208             return NULL;
209         }
210     }
211 
212     if(operation & IO_IMMEDIATE) {
213         assert(hlen == 0 && !(operation & IO_CHUNKED));
214         done = (*handler)(0, event, &request);
215         if(done) {
216             free(event);
217             return NULL;
218         }
219     }
220     event = registerFdEventHelper(event);
221     return event;
222 }
223 
224 static const char *endChunkTrailer = "\r\n0\r\n\r\n";
225 
226 int
do_scheduled_stream(int status,FdEventHandlerPtr event)227 do_scheduled_stream(int status, FdEventHandlerPtr event)
228 {
229     StreamRequestPtr request = (StreamRequestPtr)&event->data;
230     int rc, done, i;
231     struct iovec iov[6];
232     int chunk_header_len;
233     char chunk_header[10];
234     int len12 = request->len + request->len2;
235     int len123 =
236         request->len + request->len2 +
237         ((request->operation & IO_BUF3) ? request->u.b.len3 : 0);
238 
239     if(status) {
240         done = request->handler(status, event, request);
241         return done;
242     }
243 
244     i = 0;
245 
246     if(request->offset < 0) {
247         assert((request->operation & (IO_MASK | IO_BUF3 | IO_BUF_LOCATION)) ==
248                IO_WRITE);
249         if(request->operation & IO_CHUNKED) {
250             chunk_header_len = chunkHeaderLen(len123);
251         } else {
252             chunk_header_len = 0;
253         }
254 
255         if(request->offset < -chunk_header_len) {
256             assert(request->offset >= -(request->u.h.hlen + chunk_header_len));
257             iov[i].iov_base = request->u.h.header;
258             iov[i].iov_len = -request->offset - chunk_header_len;
259             i++;
260         }
261 
262         if(chunk_header_len > 0) {
263             chunkHeader(chunk_header, 10, len123);
264             if(request->offset < -chunk_header_len) {
265                 iov[i].iov_base = chunk_header;
266                 iov[i].iov_len = chunk_header_len;
267             } else {
268                 iov[i].iov_base = chunk_header +
269                     chunk_header_len + request->offset;
270                 iov[i].iov_len = -request->offset;
271             }
272             i++;
273         }
274     }
275 
276     if(request->len > 0) {
277         if(request->buf == NULL &&
278            (request->operation & IO_BUF_LOCATION)) {
279             assert(*request->u.l.buf_location == NULL);
280             request->buf = *request->u.l.buf_location = get_chunk();
281             if(request->buf == NULL) {
282                 done = request->handler(-ENOMEM, event, request);
283                 return done;
284             }
285         }
286         if(request->offset <= 0) {
287             iov[i].iov_base = request->buf;
288             iov[i].iov_len = request->len;
289             i++;
290         } else if(request->offset < request->len) {
291             iov[i].iov_base = request->buf + request->offset;
292             iov[i].iov_len = request->len - request->offset;
293             i++;
294         }
295     }
296 
297     if(request->len2 > 0) {
298         if(request->offset <= request->len) {
299             iov[i].iov_base = request->buf2;
300             iov[i].iov_len = request->len2;
301             i++;
302         } else if(request->offset < request->len + request->len2) {
303             iov[i].iov_base = request->buf2 + request->offset - request->len;
304             iov[i].iov_len = request->len2 - request->offset + request->len;
305             i++;
306         }
307     }
308 
309     if((request->operation & IO_BUF3) && request->u.b.len3 > 0) {
310         if(request->offset <= len12) {
311             iov[i].iov_base = request->u.b.buf3;
312             iov[i].iov_len = request->u.b.len3;
313             i++;
314         } else if(request->offset < len12 + request->u.b.len3) {
315             iov[i].iov_base = request->u.b.buf3 + request->offset - len12;
316             iov[i].iov_len = request->u.b.len3 - request->offset + len12;
317             i++;
318         }
319     }
320 
321     if((request->operation & IO_CHUNKED)) {
322         int l;
323         const char *trailer;
324         if(request->operation & IO_END) {
325             if(len123 == 0) {
326                 trailer = endChunkTrailer + 2;
327                 l = 5;
328             } else {
329                 trailer = endChunkTrailer;
330                 l = 7;
331             }
332         } else {
333             trailer = endChunkTrailer;
334             l = 2;
335         }
336 
337         if(request->offset <= len123) {
338             iov[i].iov_base = (char*)trailer;
339             iov[i].iov_len = l;
340             i++;
341         } else if(request->offset < len123 + l) {
342             iov[i].iov_base =
343                 (char*)endChunkTrailer + request->offset - len123;
344             iov[i].iov_len = l - request->offset + len123;
345             i++;
346         }
347     }
348 
349     assert(i > 0);
350 
351     if((request->operation & IO_MASK) == IO_WRITE) {
352         if(i > 1)
353             rc = WRITEV(request->fd, iov, i);
354         else
355             rc = WRITE(request->fd, iov[0].iov_base, iov[0].iov_len);
356     } else {
357         if(i > 1)
358             rc = READV(request->fd, iov, i);
359         else
360             rc = READ(request->fd, iov[0].iov_base, iov[0].iov_len);
361     }
362 
363     if(rc > 0) {
364         request->offset += rc;
365         if(request->offset < 0) return 0;
366         done = request->handler(0, event, request);
367         return done;
368     } else if(rc == 0 || errno == EPIPE) {
369         done = request->handler(1, event, request);
370     } else if(errno == EAGAIN || errno == EINTR) {
371         return 0;
372     } else if(errno == EFAULT || errno == EBADF) {
373         abort();
374     } else {
375         done = request->handler(-errno, event, request);
376     }
377     assert(done);
378     return done;
379 }
380 
381 int
streamRequestDone(StreamRequestPtr request)382 streamRequestDone(StreamRequestPtr request)
383 {
384     int len123 =
385         request->len + request->len2 +
386         ((request->operation & IO_BUF3) ? request->u.b.len3 : 0);
387 
388     if(request->offset < 0)
389         return 0;
390     else if(request->offset < len123)
391         return 0;
392     else if(request->operation & IO_CHUNKED) {
393         if(request->operation & IO_END) {
394             if(request->offset < len123 + (len123 ? 7 : 5))
395                 return 0;
396         } else {
397             if(request->offset < len123 + 2)
398                 return 0;
399         }
400     }
401 
402     return 1;
403 }
404 
405 static int
serverSocket(int af)406 serverSocket(int af)
407 {
408     int fd, rc;
409     if(af == 4) {
410         fd = socket(PF_INET, SOCK_STREAM, 0);
411     } else if(af == 6) {
412 #ifdef HAVE_IPv6
413         fd = socket(PF_INET6, SOCK_STREAM, 0);
414 #else
415         fd = -1;
416         errno = EAFNOSUPPORT;
417 #endif
418     } else {
419         abort();
420     }
421 
422     if(fd >= 0) {
423         rc = setNonblocking(fd, 1);
424         if(rc < 0) {
425             int errno_save = errno;
426             CLOSE(fd);
427             errno = errno_save;
428             return -1;
429         }
430 #ifdef HAVE_IPV6_PREFER_TEMPADDR
431 	if (af == 6 && useTemporarySourceAddress != 1) {
432             int value;
433             value = (useTemporarySourceAddress == 2) ? 1 : 0;
434             rc = setsockopt(fd, IPPROTO_IPV6, IPV6_PREFER_TEMPADDR,
435                             &value, sizeof(value));
436             if (rc < 0) {
437                 /* no error, warning only */
438                 do_log_error(L_WARN, errno, "Couldn't set IPV6CTL_USETEMPADDR");
439             }
440 	}
441 
442 #endif
443     }
444     return fd;
445 }
446 
447 FdEventHandlerPtr
do_connect(AtomPtr addr,int index,int port,int (* handler)(int,FdEventHandlerPtr,ConnectRequestPtr),void * data)448 do_connect(AtomPtr addr, int index, int port,
449            int (*handler)(int, FdEventHandlerPtr, ConnectRequestPtr),
450            void *data)
451 {
452     ConnectRequestRec request;
453     FdEventHandlerPtr event;
454     int done, fd, af;
455 
456     assert(addr->length > 0 && addr->string[0] == DNS_A);
457     assert(addr->length % sizeof(HostAddressRec) == 1);
458 
459     if(index >= (addr->length - 1)/ sizeof(HostAddressRec))
460         index = 0;
461 
462     request.firstindex = index;
463     request.port = port;
464     request.handler = handler;
465     request.data = data;
466  again:
467     af = addr->string[1 + index * sizeof(HostAddressRec)];
468     fd = serverSocket(af);
469 
470     request.fd = fd;
471     request.af = af;
472     request.addr = addr;
473     request.index = index;
474 
475     if(fd < 0) {
476         int n = (addr->length - 1) / sizeof(HostAddressRec);
477         if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
478             if((index + 1) % n != request.firstindex) {
479                 index = (index + 1) % n;
480                 goto again;
481             }
482         }
483         do_log_error(L_ERROR, errno, "Couldn't create socket");
484         done = (*handler)(-errno, NULL, &request);
485         assert(done);
486         return NULL;
487     }
488 
489     /* POLLIN is apparently needed on Windows */
490     event = registerFdEvent(fd, POLLIN | POLLOUT,
491                             do_scheduled_connect,
492                             sizeof(ConnectRequestRec), &request);
493     if(event == NULL) {
494         done = (*handler)(-ENOMEM, NULL, &request);
495         assert(done);
496         return NULL;
497     }
498 
499     done = event->handler(0, event);
500     if(done) {
501         unregisterFdEvent(event);
502         return NULL;
503     }
504     return event;
505 }
506 
507 int
do_scheduled_connect(int status,FdEventHandlerPtr event)508 do_scheduled_connect(int status, FdEventHandlerPtr event)
509 {
510     ConnectRequestPtr request = (ConnectRequestPtr)&event->data;
511     AtomPtr addr = request->addr;
512     int done;
513     int rc;
514     HostAddressPtr host;
515     struct sockaddr_in servaddr;
516 #ifdef HAVE_IPv6
517     struct sockaddr_in6 servaddr6;
518 #endif
519 
520     assert(addr->length > 0 && addr->string[0] == DNS_A);
521     assert(addr->length % sizeof(HostAddressRec) == 1);
522     assert(request->index < (addr->length - 1) / sizeof(HostAddressRec));
523 
524     if(status) {
525         done = request->handler(status, event, request);
526         if(done) {
527             releaseAtom(addr);
528             request->addr = NULL;
529             return 1;
530         }
531         return 0;
532     }
533 
534  again:
535     host = (HostAddressPtr)&addr->string[1 +
536                                          request->index *
537                                          sizeof(HostAddressRec)];
538     if(host->af != request->af) {
539         int newfd;
540         /* Ouch.  Our socket has a different protocol than the host
541            address. */
542         CLOSE(request->fd);
543         newfd = serverSocket(host->af);
544         if(newfd < 0) {
545             if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
546                 int n = request->addr->length / sizeof(HostAddressRec);
547                 if((request->index + 1) % n != request->firstindex) {
548                     request->index = (request->index + 1) % n;
549                     goto again;
550                 }
551             }
552             request->fd = -1;
553             done = request->handler(-errno, event, request);
554             assert(done);
555             return 1;
556         }
557         if(newfd != request->fd) {
558             request->fd = dup2(newfd, request->fd);
559             CLOSE(newfd);
560             if(request->fd < 0) {
561                 done = request->handler(-errno, event, request);
562                 assert(done);
563                 return 1;
564             }
565         }
566         request->af = host->af;
567     }
568     switch(host->af) {
569     case 4:
570         memset(&servaddr, 0, sizeof(servaddr));
571         servaddr.sin_family = AF_INET;
572         servaddr.sin_port = htons(request->port);
573         memcpy(&servaddr.sin_addr, &host->data, sizeof(struct in_addr));
574         rc = connect(request->fd,
575                      (struct sockaddr*)&servaddr, sizeof(servaddr));
576         break;
577     case 6:
578 #ifdef HAVE_IPv6
579         memset(&servaddr6, 0, sizeof(servaddr6));
580         servaddr6.sin6_family = AF_INET6;
581         servaddr6.sin6_port = htons(request->port);
582         memcpy(&servaddr6.sin6_addr, &host->data, sizeof(struct in6_addr));
583         rc = connect(request->fd,
584                      (struct sockaddr*)&servaddr6, sizeof(servaddr6));
585 #else
586         rc = -1;
587         errno = EAFNOSUPPORT;
588 #endif
589         break;
590     default:
591         abort();
592     }
593 
594     if(rc >= 0 || errno == EISCONN) {
595         done = request->handler(1, event, request);
596         assert(done);
597         releaseAtom(request->addr);
598         request->addr = NULL;
599         return 1;
600     }
601 
602     if(errno == EINPROGRESS || errno == EINTR) {
603         return 0;
604     } else if(errno == EFAULT || errno == EBADF) {
605         abort();
606     } else {
607         int n = request->addr->length / sizeof(HostAddressRec);
608         if((request->index + 1) % n != request->firstindex) {
609             request->index = (request->index + 1) % n;
610             goto again;
611         }
612         done = request->handler(-errno, event, request);
613         assert(done);
614         releaseAtom(request->addr);
615         request->addr = NULL;
616         return 1;
617     }
618 }
619 
620 FdEventHandlerPtr
do_accept(int fd,int (* handler)(int,FdEventHandlerPtr,AcceptRequestPtr),void * data)621 do_accept(int fd,
622           int (*handler)(int, FdEventHandlerPtr, AcceptRequestPtr),
623           void *data)
624 {
625     FdEventHandlerPtr event;
626     int done;
627 
628     event = schedule_accept(fd, handler, data);
629     if(event == NULL) {
630         done = (*handler)(-ENOMEM, NULL, NULL);
631         assert(done);
632     }
633 
634     /* But don't invoke it now - this will delay accept if under load. */
635     return event;
636 }
637 
638 FdEventHandlerPtr
schedule_accept(int fd,int (* handler)(int,FdEventHandlerPtr,AcceptRequestPtr),void * data)639 schedule_accept(int fd,
640                 int (*handler)(int, FdEventHandlerPtr, AcceptRequestPtr),
641                 void *data)
642 {
643     FdEventHandlerPtr event;
644     AcceptRequestRec request;
645     int done;
646 
647     request.fd = fd;
648     request.handler = handler;
649     request.data = data;
650     event = registerFdEvent(fd, POLLIN,
651                             do_scheduled_accept, sizeof(request), &request);
652     if(!event) {
653         done = (*handler)(-ENOMEM, NULL, NULL);
654         assert(done);
655     }
656     return event;
657 }
658 
659 int
do_scheduled_accept(int status,FdEventHandlerPtr event)660 do_scheduled_accept(int status, FdEventHandlerPtr event)
661 {
662     AcceptRequestPtr request = (AcceptRequestPtr)&event->data;
663     int rc, done;
664     unsigned len;
665     struct sockaddr_in addr;
666 
667     if(status) {
668         done = request->handler(status, event, request);
669         if(done) return done;
670     }
671 
672     len = sizeof(struct sockaddr_in);
673 
674     rc = accept(request->fd, (struct sockaddr*)&addr, &len);
675 
676     if(rc >= 0)
677         done = request->handler(rc, event, request);
678     else
679         done = request->handler(-errno, event, request);
680     return done;
681 }
682 
683 FdEventHandlerPtr
create_listener(char * address,int port,int (* handler)(int,FdEventHandlerPtr,AcceptRequestPtr),void * data)684 create_listener(char *address, int port,
685                 int (*handler)(int, FdEventHandlerPtr, AcceptRequestPtr),
686                 void *data)
687 {
688     int fd, rc;
689     int one = 1;
690     int done;
691     struct sockaddr_in addr;
692 #ifdef HAVE_IPv6
693     int inet6 = 1;
694     struct sockaddr_in6 addr6;
695 #else
696     int inet6 = 0;
697 #endif
698 
699     if(inet6 && address) {
700         struct in_addr buf;
701         rc = inet_aton(address, &buf);
702         if(rc == 1)
703             inet6 = 0;
704     }
705     fd = -1;
706     errno = EAFNOSUPPORT;
707 
708 #ifdef HAVE_IPv6
709     if(inet6) {
710         fd = socket(PF_INET6, SOCK_STREAM, 0);
711     }
712 #endif
713 
714     if(fd < 0 && (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT)) {
715         inet6 = 0;
716         fd = socket(PF_INET, SOCK_STREAM, 0);
717     }
718 
719     if(fd < 0) {
720         done = (*handler)(-errno, NULL, NULL);
721         assert(done);
722         return NULL;
723     }
724 
725 #ifndef WIN32
726     /* on WIN32 SO_REUSEADDR allows two sockets bind to the same port */
727     rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one));
728     if(rc < 0) do_log_error(L_WARN, errno, "Couldn't set SO_REUSEADDR");
729 #endif
730 
731     if(inet6) {
732 #ifdef HAVE_IPv6
733         rc = setV6only(fd, 0);
734         if(rc < 0)
735             /* Reportedly OpenBSD returns an error for that.  So only
736                log it as a debugging message. */
737             do_log_error(D_CLIENT_CONN, errno, "Couldn't reset IPV6_V6ONLY");
738 
739         memset(&addr6, 0, sizeof(addr6));
740         rc = inet_pton(AF_INET6, address, &addr6.sin6_addr);
741         if(rc != 1) {
742             done = (*handler)(rc == 0 ? -ESYNTAX : -errno, NULL, NULL);
743             assert(done);
744             return NULL;
745         }
746         addr6.sin6_family = AF_INET6;
747         addr6.sin6_port = htons(port);
748         rc = bind(fd, (struct sockaddr*)&addr6, sizeof(addr6));
749 #else
750         rc = -1;
751         errno = EAFNOSUPPORT;
752 #endif
753     } else {
754         memset(&addr, 0, sizeof(addr));
755         rc = inet_aton(address, &addr.sin_addr);
756         if(rc != 1) {
757             done = (*handler)(rc == 0 ? -ESYNTAX : -errno, NULL, NULL);
758             assert(done);
759             return NULL;
760         }
761         addr.sin_family = AF_INET;
762         addr.sin_port = htons(port);
763         rc = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
764     }
765 
766     if(rc < 0) {
767         do_log_error(L_ERROR, errno, "Couldn't bind");
768         CLOSE(fd);
769         done = (*handler)(-errno, NULL, NULL);
770         assert(done);
771         return NULL;
772     }
773 
774     rc = setNonblocking(fd, 1);
775     if(rc < 0) {
776         do_log_error(L_ERROR, errno, "Couldn't set non blocking mode");
777         CLOSE(fd);
778         done = (*handler)(-errno, NULL, NULL);
779         assert(done);
780         return NULL;
781     }
782 
783     rc = listen(fd, 1024);
784     if(rc < 0) {
785         do_log_error(L_ERROR, errno, "Couldn't listen");
786         CLOSE(fd);
787         done = (*handler)(-errno, NULL, NULL);
788         assert(done);
789         return NULL;
790     }
791 
792     do_log(L_INFO, "Established listening socket on port %d.\n", port);
793 
794     return schedule_accept(fd, handler, data);
795 }
796 
797 #ifndef SOL_TCP
798 /* BSD */
799 #define SOL_TCP IPPROTO_TCP
800 #endif
801 
802 int
setNonblocking(int fd,int nonblocking)803 setNonblocking(int fd, int nonblocking)
804 {
805 #ifdef WIN32 /*MINGW*/
806     return win32_setnonblocking(fd, nonblocking);
807 #else
808     int rc;
809     rc = fcntl(fd, F_GETFL, 0);
810     if(rc < 0)
811         return -1;
812 
813     rc = fcntl(fd, F_SETFL, nonblocking?(rc | O_NONBLOCK):(rc & ~O_NONBLOCK));
814     if(rc < 0)
815         return -1;
816 
817     return 0;
818 #endif
819 }
820 
821 int
setNodelay(int fd,int nodelay)822 setNodelay(int fd, int nodelay)
823 {
824     int val = nodelay ? 1 : 0;
825     int rc;
826     rc = setsockopt(fd, SOL_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
827     if(rc < 0)
828         return -1;
829     return 0;
830 }
831 
832 #ifdef IPV6_V6ONLY
833 int
setV6only(int fd,int v6only)834 setV6only(int fd, int v6only)
835 {
836     int val = v6only ? 1 : 0;
837     int rc;
838     rc = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&val, sizeof(val));
839     if(rc < 0)
840         return -1;
841     return 0;
842 }
843 #else
844 int
setV6only(int fd,int v6only)845 setV6only(int fd, int v6only)
846 {
847     return 0;
848 }
849 #endif
850 
851 typedef struct _LingeringClose {
852     int fd;
853     FdEventHandlerPtr handler;
854     TimeEventHandlerPtr timeout;
855 } LingeringCloseRec, *LingeringClosePtr;
856 
857 static int
lingeringCloseTimeoutHandler(TimeEventHandlerPtr event)858 lingeringCloseTimeoutHandler(TimeEventHandlerPtr event)
859 {
860     LingeringClosePtr l = *(LingeringClosePtr*)event->data;
861     assert(l->timeout == event);
862     l->timeout = NULL;
863     if(l->handler)
864         pokeFdEvent(l->fd, -ESHUTDOWN, POLLIN | POLLOUT);
865     else {
866         CLOSE(l->fd);
867         free(l);
868     }
869     return 1;
870 }
871 
872 static int
lingeringCloseHandler(int status,FdEventHandlerPtr event)873 lingeringCloseHandler(int status, FdEventHandlerPtr event)
874 {
875     LingeringClosePtr l = *(LingeringClosePtr*)event->data;
876     char buf[17];
877     int rc;
878 
879     assert(l->handler == event);
880 
881     l->handler = NULL;
882     if(status && status != -EDOGRACEFUL)
883         goto done;
884 
885     rc = READ(l->fd, &buf, 17);
886     if(rc == 0 || (rc < 0 && errno != EAGAIN && errno != EINTR))
887         goto done;
888 
889     /* The client is still sending data.  Ignore it in order to let
890        TCP's flow control do its work.  The timeout will close the
891        connection. */
892     return 1;
893 
894  done:
895     if(l->timeout) {
896         cancelTimeEvent(l->timeout);
897         l->timeout = NULL;
898     }
899     CLOSE(l->fd);
900     free(l);
901     return 1;
902 }
903 
904 int
lingeringClose(int fd)905 lingeringClose(int fd)
906 {
907     int rc;
908     LingeringClosePtr l;
909 
910     rc = shutdown(fd, 1);
911     if(rc < 0) {
912         if(errno != ENOTCONN) {
913             do_log_error(L_ERROR, errno, "Shutdown failed");
914         } else if(errno == EFAULT || errno == EBADF) {
915             abort();
916         }
917         CLOSE(fd);
918         return 1;
919     }
920 
921     l = malloc(sizeof(LingeringCloseRec));
922     if(l == NULL)
923         goto fail;
924     l->fd = fd;
925     l->handler = NULL;
926     l->timeout = NULL;
927 
928     l->timeout = scheduleTimeEvent(10, lingeringCloseTimeoutHandler,
929                                    sizeof(LingeringClosePtr), &l);
930     if(l->timeout == NULL) {
931         free(l);
932         goto fail;
933     }
934 
935     l->handler = registerFdEvent(fd, POLLIN,
936                                  lingeringCloseHandler,
937                                  sizeof(LingeringClosePtr), &l);
938     if(l->handler == NULL) {
939         do_log(L_ERROR, "Couldn't schedule lingering close handler.\n");
940         /* But don't close -- the timeout will do its work. */
941     }
942     return 1;
943 
944  fail:
945     do_log(L_ERROR, "Couldn't schedule lingering close.\n");
946     CLOSE(fd);
947     return 1;
948 }
949 
950 NetAddressPtr
parseNetAddress(AtomListPtr list)951 parseNetAddress(AtomListPtr list)
952 {
953     NetAddressPtr nl;
954     int i, rc, rc6;
955     char buf[100];
956     struct in_addr ina;
957 #ifdef HAVE_IPv6
958     struct in6_addr ina6;
959 #endif
960 
961     nl = malloc((list->length + 1) * sizeof(NetAddressRec));
962     if(nl == NULL) {
963         do_log(L_ERROR, "Couldn't allocate network list.\n");
964         return NULL;
965     }
966 
967     for(i = 0; i < list->length; i++) {
968         int prefix;
969         char *s = list->list[i]->string, *p;
970         int n = list->list[i]->length;
971         char *suffix;
972 
973         while(*s == ' ' || *s == '\t') {
974             s++;
975             n--;
976         }
977 
978         if(n >= 100) {
979             do_log(L_ERROR, "Network name too long.\n");
980             goto fail;
981         }
982         p = memchr(s, '/', n);
983         if(p) {
984             memcpy(buf, s, p - s);
985             buf[p - s] = '\0';
986             prefix = strtol(p + 1, &suffix, 10);
987         } else {
988             char *s1, *s2;
989             prefix = -1;
990             strcpy(buf, s);
991             s1 = strchr(s, ' ');
992             s2 = strchr(s, '\t');
993             if(s1 == NULL) suffix = s2;
994             else if(s2 == NULL) suffix = s1;
995             else if(s1 < s2) suffix = s1;
996             else suffix = s2;
997             if(suffix == NULL)
998                 suffix = s + n;
999         }
1000 
1001         if(!isWhitespace(suffix)) {
1002             do_log(L_ERROR, "Couldn't parse network %s.\n", buf);
1003             goto fail;
1004         }
1005 
1006         rc = 0; rc6 = 0;
1007         rc = inet_aton(buf, &ina);
1008 #ifdef HAVE_IPv6
1009         if(rc == 0) {
1010             rc6 = inet_pton(AF_INET6, buf, &ina6);
1011         }
1012 #endif
1013         if(rc == 0 && rc6 == 0) {
1014             do_log(L_ERROR, "Couldn't parse network %s.\n", buf);
1015             goto fail;
1016         }
1017         nl[i].prefix = prefix;
1018         if(rc) {
1019             nl[i].af = 4;
1020             memcpy(nl[i].data, &ina, 4);
1021         } else {
1022 #ifdef HAVE_IPv6
1023             nl[i].af = 6;
1024             memcpy(nl[i].data, &ina6, 16);
1025 #else
1026             abort();
1027 #endif
1028         }
1029     }
1030     nl[i].af = 0;
1031     return nl;
1032 
1033  fail:
1034     free(nl);
1035     return NULL;
1036 }
1037 
1038 /* Returns 1 if the first n bits of a and b are equal */
1039 static int
bitmatch(const unsigned char * a,const unsigned char * b,int n)1040 bitmatch(const unsigned char *a, const unsigned char *b, int n)
1041 {
1042     if(n >= 8) {
1043         if(memcmp(a, b, n / 8) != 0)
1044             return 0;
1045     }
1046 
1047     if(n % 8 != 0) {
1048         int mask = (~0) << (8 - n % 8);
1049         if((a[n / 8] & mask) != (b[n / 8] & mask))
1050             return 0;
1051     }
1052 
1053     return 1;
1054 }
1055 
1056 /* Returns 1 if the address in data is in list */
1057 static int
match(int af,unsigned char * data,NetAddressPtr list)1058 match(int af, unsigned char *data, NetAddressPtr list)
1059 {
1060     int i;
1061 #ifdef HAVE_IPv6
1062     static const unsigned char v6mapped[] =
1063         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF };
1064 #endif
1065 
1066     i = 0;
1067     while(list[i].af != 0) {
1068         if(af == 4 && list[i].af == 4) {
1069             if(bitmatch(data, list[i].data,
1070                         list[i].prefix >= 0 ? list[i].prefix : 32))
1071                 return 1;
1072 #ifdef HAVE_IPv6
1073         } else if(af == 6 && list[i].af == 6) {
1074             if(bitmatch(data, list[i].data,
1075                         list[i].prefix >= 0 ? list[i].prefix : 128))
1076                 return 1;
1077         } else if(af == 6 && list[i].af == 4) {
1078             if(bitmatch(data, v6mapped, 96)) {
1079                 if(bitmatch(data + 12, list[i].data,
1080                             list[i].prefix >= 0 ? list[i].prefix : 32))
1081                     return 1;
1082             }
1083         } else if(af == 4 && list[i].af == 6) {
1084             if(bitmatch(list[i].data, v6mapped, 96)) {
1085                 if(bitmatch(data, list[i].data + 12,
1086                             list[i].prefix >= 96 ?
1087                             list[i].prefix - 96 : 32))
1088                     return 1;
1089             }
1090 #endif
1091         } else {
1092             abort();
1093         }
1094         i++;
1095     }
1096     return 0;
1097 }
1098 
1099 int
netAddressMatch(int fd,NetAddressPtr list)1100 netAddressMatch(int fd, NetAddressPtr list)
1101 {
1102     int rc;
1103     unsigned int len;
1104     struct sockaddr_in sain;
1105 #ifdef HAVE_IPv6
1106     struct sockaddr_in6 sain6;
1107 #endif
1108 
1109     len = sizeof(sain);
1110     rc = getpeername(fd, (struct sockaddr*)&sain, &len);
1111     if(rc < 0) {
1112         do_log_error(L_ERROR, errno, "Couldn't get peer name");
1113         return -1;
1114     }
1115 
1116     if(sain.sin_family == AF_INET) {
1117         return match(4, (unsigned char*)&sain.sin_addr, list);
1118 #ifdef HAVE_IPv6
1119     } else if(sain.sin_family == AF_INET6) {
1120         len = sizeof(sain6);
1121         rc = getpeername(fd, (struct sockaddr*)&sain6, &len);
1122         if(rc < 0) {
1123             do_log_error(L_ERROR, errno, "Couldn't get peer name");
1124             return -1;
1125         }
1126         if(sain6.sin6_family != AF_INET6) {
1127             do_log(L_ERROR, "Inconsistent peer name");
1128             return -1;
1129         }
1130         return match(6, (unsigned char*)&sain6.sin6_addr, list);
1131 #endif
1132     } else {
1133         do_log(L_ERROR, "Unknown address family %d\n", sain.sin_family);
1134         return -1;
1135     }
1136     return 0;
1137 }
1138 
1139 
1140 
1141 
1142 
1143 
1144