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