Remove [AP]F_* comment from netcslisten.
[doldaconnect.git] / daemon / net.c
CommitLineData
d3372da9 1/*
2 * Dolda Connect - Modular multiuser Direct Connect-style client
3 * Copyright (C) 2004 Fredrik Tolf (fredrik@dolda2000.com)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18*/
19/* XXX: Implement SOCKS proxyability */
20
21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24#include <string.h>
25#include <stdlib.h>
26#include <unistd.h>
27#include <fcntl.h>
28#include <sys/ioctl.h>
29#include <sys/socket.h>
30#include <sys/un.h>
31#include <sys/poll.h>
32#include <arpa/inet.h>
33#include <netinet/in.h>
34#include <netdb.h>
35#include <sys/signal.h>
d3372da9 36#ifdef HAVE_LINUX_SOCKIOS_H
37#include <linux/sockios.h>
38#endif
39#include <errno.h>
40#include <net/if.h>
41
42#include "conf.h"
43#include "net.h"
44#include "module.h"
45#include "log.h"
46#include "utils.h"
47#include "sysevents.h"
48
49static struct configvar myvars[] =
50{
51 /* 0 = Direct mode, 1 = Passive mode, 2 = SOCKS proxy */
52 {CONF_VAR_INT, "mode", {.num = 0}},
347d6d76 53 {CONF_VAR_BOOL, "reuseaddr", {.num = 0}},
d3372da9 54 /* Only for direct mode */
55 {CONF_VAR_IPV4, "visibleipv4", {.ipv4 = {0}}},
56 {CONF_VAR_STRING, "publicif", {.str = L""}},
b020fb3d 57 /* Diffserv should be supported on IPv4, too, but I don't know the
58 * API to do that. */
59 {CONF_VAR_INT, "diffserv-mincost", {.num = 0}},
60 {CONF_VAR_INT, "diffserv-maxrel", {.num = 0}},
61 {CONF_VAR_INT, "diffserv-maxtp", {.num = 0}},
62 {CONF_VAR_INT, "diffserv-mindelay", {.num = 0}},
d3372da9 63 {CONF_VAR_END}
64};
65
66static struct socket *sockets = NULL;
67int numsocks = 0;
68
69/* XXX: Get autoconf for all this... */
70int getpublicaddr(int af, struct sockaddr **addr, socklen_t *lenbuf)
71{
72 struct sockaddr_in *ipv4;
73 struct configvar *var;
74 void *bufend;
75 int sock;
76 struct ifconf conf;
77 struct ifreq *ifr, req;
78 char *pif;
79
80 if(af == AF_INET)
81 {
82 var = confgetvar("net", "visibleipv4");
83 if(var->val.ipv4.s_addr != 0)
84 {
85 ipv4 = smalloc(sizeof(*ipv4));
86 ipv4->sin_family = AF_INET;
87 ipv4->sin_addr.s_addr = var->val.ipv4.s_addr;
88 *addr = (struct sockaddr *)ipv4;
89 *lenbuf = sizeof(*ipv4);
90 return(0);
91 }
bcb73bb3 92 if((pif = icswcstombs(confgetstr("net", "publicif"), NULL, NULL)) == NULL)
d3372da9 93 {
94 flog(LOG_ERR, "could not convert net.publicif into local charset: %s", strerror(errno));
95 return(-1);
96 }
97 if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
98 return(-1);
99 conf.ifc_buf = smalloc(conf.ifc_len = 65536);
100 if(ioctl(sock, SIOCGIFCONF, &conf) < 0)
101 {
102 free(conf.ifc_buf);
103 close(sock);
104 return(-1);
105 }
106 bufend = ((char *)conf.ifc_buf) + conf.ifc_len;
107 ipv4 = NULL;
108 for(ifr = conf.ifc_ifcu.ifcu_req; (void *)ifr < bufend; ifr++)
109 {
110 memset(&req, 0, sizeof(req));
111 memcpy(req.ifr_name, ifr->ifr_name, sizeof(ifr->ifr_name));
112 if(ioctl(sock, SIOCGIFFLAGS, &req) < 0)
113 {
114 free(conf.ifc_buf);
115 close(sock);
116 return(-1);
117 }
118 if(!(req.ifr_flags & IFF_UP))
119 continue;
120 if(ifr->ifr_addr.sa_family == AF_INET)
121 {
122 if(ntohl(((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr) == 0x7f000001)
123 continue;
124 if(ipv4 == NULL)
125 {
126 ipv4 = smalloc(sizeof(*ipv4));
127 memcpy(ipv4, &ifr->ifr_addr, sizeof(ifr->ifr_addr));
128 } else {
129 free(ipv4);
bcb73bb3 130 free(conf.ifc_buf);
d3372da9 131 flog(LOG_WARNING, "could not locate an unambiguous interface for determining your public IP address - set net.publicif");
132 errno = ENFILE; /* XXX: There's no appropriate one for this... */
133 return(-1);
134 }
135 }
136 }
bcb73bb3 137 free(conf.ifc_buf);
d3372da9 138 close(sock);
139 if(ipv4 != NULL)
140 {
141 *addr = (struct sockaddr *)ipv4;
142 *lenbuf = sizeof(*ipv4);
143 return(0);
144 }
145 errno = ENETDOWN;
146 return(-1);
147 }
148 errno = EPFNOSUPPORT;
149 return(-1);
150}
151
152static struct socket *newsock(int type)
153{
154 struct socket *new;
155
156 new = smalloc(sizeof(*new));
157 new->refcount = 2;
158 new->fd = -1;
159 new->isrealsocket = 1;
160 new->family = -1;
161 new->tos = 0;
162 new->type = type;
163 new->state = -1;
164 new->ignread = 0;
165 new->close = 0;
166 new->remote = NULL;
167 new->remotelen = 0;
168 switch(type)
169 {
170 case SOCK_STREAM:
171 new->outbuf.s.buf = NULL;
172 new->outbuf.s.bufsize = 0;
173 new->outbuf.s.datasize = 0;
174 new->inbuf.s.buf = NULL;
175 new->inbuf.s.bufsize = 0;
176 new->inbuf.s.datasize = 0;
177 break;
178 case SOCK_DGRAM:
179 new->outbuf.d.f = new->outbuf.d.l = NULL;
180 new->inbuf.d.f = new->inbuf.d.l = NULL;
181 break;
182 }
183 new->conncb = NULL;
184 new->errcb = NULL;
185 new->readcb = NULL;
186 new->writecb = NULL;
187 new->acceptcb = NULL;
188 new->next = sockets;
189 new->prev = NULL;
190 if(sockets != NULL)
191 sockets->prev = new;
192 sockets = new;
193 numsocks++;
194 return(new);
195}
196
197static struct socket *mksock(int domain, int type)
198{
199 int fd;
200 struct socket *new;
201
202 if((fd = socket(domain, type, 0)) < 0)
203 {
204 flog(LOG_CRIT, "could not create socket: %s", strerror(errno));
205 return(NULL);
206 }
207 new = newsock(type);
208 new->fd = fd;
209 new->family = domain;
210 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
211 return(new);
212}
213
214struct socket *wrapsock(int fd)
215{
216 struct socket *new;
217
218 new = newsock(SOCK_STREAM);
219 new->fd = fd;
220 new->state = SOCK_EST;
221 new->isrealsocket = 0;
222 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
223 return(new);
224}
225
226static void unlinksock(struct socket *sk)
227{
228 if(sk->prev != NULL)
229 sk->prev->next = sk->next;
230 if(sk->next != NULL)
231 sk->next->prev = sk->prev;
232 if(sk == sockets)
233 sockets = sk->next;
234 putsock(sk);
235 numsocks--;
236}
237
238void getsock(struct socket *sk)
239{
240 sk->refcount++;
241}
242
243void putsock(struct socket *sk)
244{
245 struct dgrambuf *buf;
246
247 if(--(sk->refcount) == 0)
248 {
249 switch(sk->type)
250 {
251 case SOCK_STREAM:
252 if(sk->outbuf.s.buf != NULL)
253 free(sk->outbuf.s.buf);
254 if(sk->inbuf.s.buf != NULL)
255 free(sk->inbuf.s.buf);
256 break;
257 case SOCK_DGRAM:
258 while((buf = sk->outbuf.d.f) != NULL)
259 {
260 sk->outbuf.d.f = buf->next;
261 free(buf->data);
262 free(buf);
263 }
264 while((buf = sk->inbuf.d.f) != NULL)
265 {
266 sk->inbuf.d.f = buf->next;
267 free(buf->data);
268 free(buf);
269 }
270 break;
271 }
272 if(sk->fd >= 0)
273 close(sk->fd);
274 if(sk->remote != NULL)
275 free(sk->remote);
276 free(sk);
277 }
278}
279
336539c2 280void sockpushdata(struct socket *sk, void *buf, size_t size)
281{
282 switch(sk->type)
283 {
284 case SOCK_STREAM:
285 sizebuf(&sk->inbuf.s.buf, &sk->inbuf.s.bufsize, sk->inbuf.s.datasize + size, 1, 1);
286 memmove(sk->inbuf.s.buf + size, sk->inbuf.s.buf, sk->inbuf.s.datasize);
287 memcpy(sk->inbuf.s.buf, buf, size);
288 sk->inbuf.s.datasize += size;
289 break;
290 case SOCK_DGRAM:
291 /* XXX */
292 break;
293 }
294 return;
295}
296
d3372da9 297void *sockgetinbuf(struct socket *sk, size_t *size)
298{
299 void *buf;
300 struct dgrambuf *dbuf;
301
302 switch(sk->type)
303 {
304 case SOCK_STREAM:
305 if((sk->inbuf.s.buf == NULL) || (sk->inbuf.s.datasize == 0))
306 {
307 *size = 0;
308 return(NULL);
309 }
310 buf = sk->inbuf.s.buf;
311 *size = sk->inbuf.s.datasize;
312 sk->inbuf.s.buf = NULL;
313 sk->inbuf.s.bufsize = sk->inbuf.s.datasize = 0;
314 return(buf);
315 case SOCK_DGRAM:
316 if((dbuf = sk->inbuf.d.f) == NULL)
317 return(NULL);
318 sk->inbuf.d.f = dbuf->next;
319 if(dbuf->next == NULL)
320 sk->inbuf.d.l = NULL;
321 buf = dbuf->data;
322 *size = dbuf->size;
323 free(dbuf->addr);
324 free(dbuf);
325 return(buf);
326 }
327 return(NULL);
328}
329
330static void sockrecv(struct socket *sk)
331{
332 int ret, inq;
333 struct dgrambuf *dbuf;
334
335 switch(sk->type)
336 {
337 case SOCK_STREAM:
338#if defined(HAVE_LINUX_SOCKIOS_H) && defined(SIOCINQ)
339 /* SIOCINQ is Linux-specific AFAIK, but I really have no idea
340 * how to read the inqueue size on other OSs */
341 if(ioctl(sk->fd, SIOCINQ, &inq))
342 {
343 /* I don't really know what could go wrong here, so let's
344 * assume it's transient. */
345 flog(LOG_WARNING, "SIOCINQ return %s on socket %i, falling back to 2048 bytes", strerror(errno), sk->fd);
346 inq = 2048;
347 }
348#else
349 inq = 2048;
350#endif
351 if(inq > 65536)
352 inq = 65536;
353 sizebuf(&sk->inbuf.s.buf, &sk->inbuf.s.bufsize, sk->inbuf.s.datasize + inq, 1, 1);
354 ret = read(sk->fd, sk->inbuf.s.buf + sk->inbuf.s.datasize, inq);
355 if(ret < 0)
356 {
357 if((errno == EINTR) || (errno == EAGAIN))
358 return;
359 if(sk->errcb != NULL)
360 sk->errcb(sk, errno, sk->data);
361 closesock(sk);
362 return;
363 }
364 if(ret == 0)
365 {
366 if(sk->errcb != NULL)
367 sk->errcb(sk, 0, sk->data);
368 closesock(sk);
369 return;
370 }
371 sk->inbuf.s.datasize += ret;
372 if(sk->readcb != NULL)
373 sk->readcb(sk, sk->data);
374 break;
375 case SOCK_DGRAM:
376 if(ioctl(sk->fd, SIOCINQ, &inq))
377 {
378 /* I don't really know what could go wrong here, so let's
379 * assume it's transient. */
380 flog(LOG_WARNING, "SIOCINQ return %s on socket %i", strerror(errno), sk->fd);
381 return;
382 }
383 dbuf = smalloc(sizeof(*dbuf));
384 dbuf->data = smalloc(inq);
385 dbuf->addr = smalloc(dbuf->addrlen = sizeof(struct sockaddr_storage));
386 ret = recvfrom(sk->fd, dbuf->data, inq, 0, dbuf->addr, &dbuf->addrlen);
387 if(ret < 0)
388 {
389 free(dbuf->addr);
390 free(dbuf->data);
391 free(dbuf);
392 if((errno == EINTR) || (errno == EAGAIN))
393 return;
394 if(sk->errcb != NULL)
395 sk->errcb(sk, errno, sk->data);
396 closesock(sk);
397 return;
398 }
399 /* On UDP/IPv[46], ret == 0 doesn't mean EOF (since UDP can't
400 * have EOF), but rather an empty packet. I don't know if any
401 * other potential DGRAM protocols might have an EOF
402 * condition, so let's play safe. */
403 if(ret == 0)
404 {
405 free(dbuf->addr);
406 free(dbuf->data);
407 free(dbuf);
408 if(!((sk->family == AF_INET) || (sk->family == AF_INET6)))
409 {
410 if(sk->errcb != NULL)
411 sk->errcb(sk, 0, sk->data);
412 closesock(sk);
413 }
414 return;
415 }
416 dbuf->addr = srealloc(dbuf->addr, dbuf->addrlen);
417 dbuf->data = srealloc(dbuf->data, dbuf->size = ret);
418 dbuf->next = NULL;
419 if(sk->inbuf.d.l != NULL)
420 sk->inbuf.d.l->next = dbuf;
421 else
422 sk->inbuf.d.f = dbuf;
423 sk->inbuf.d.l = dbuf;
424 if(sk->readcb != NULL)
425 sk->readcb(sk, sk->data);
426 break;
427 }
428}
429
430static void sockflush(struct socket *sk)
431{
432 int ret;
433 struct dgrambuf *dbuf;
434
435 switch(sk->type)
436 {
437 case SOCK_STREAM:
438 if(sk->isrealsocket)
439 ret = send(sk->fd, sk->outbuf.s.buf, sk->outbuf.s.datasize, MSG_DONTWAIT | MSG_NOSIGNAL);
440 else
441 ret = write(sk->fd, sk->outbuf.s.buf, sk->outbuf.s.datasize);
442 if(ret < 0)
443 {
444 /* For now, assume transient error, since
445 * the socket is polled for errors */
446 break;
447 }
448 if(ret > 0)
449 {
450 memmove(sk->outbuf.s.buf, ((char *)sk->outbuf.s.buf) + ret, sk->outbuf.s.datasize -= ret);
451 if(sk->writecb != NULL)
452 sk->writecb(sk, sk->data);
453 }
454 break;
455 case SOCK_DGRAM:
456 dbuf = sk->outbuf.d.f;
457 if((sk->outbuf.d.f = dbuf->next) == NULL)
458 sk->outbuf.d.l = NULL;
459 sendto(sk->fd, dbuf->data, dbuf->size, MSG_DONTWAIT | MSG_NOSIGNAL, dbuf->addr, dbuf->addrlen);
460 free(dbuf->data);
461 free(dbuf->addr);
462 free(dbuf);
463 if(sk->writecb != NULL)
464 sk->writecb(sk, sk->data);
465 break;
466 }
467}
468
469void closesock(struct socket *sk)
470{
471 sk->state = SOCK_STL;
472 close(sk->fd);
473 sk->fd = -1;
474 sk->close = 0;
475}
476
477void sockqueue(struct socket *sk, void *data, size_t size)
478{
479 struct dgrambuf *new;
480
481 if(sk->state == SOCK_STL)
482 return;
483 switch(sk->type)
484 {
485 case SOCK_STREAM:
486 sizebuf(&(sk->outbuf.s.buf), &(sk->outbuf.s.bufsize), sk->outbuf.s.datasize + size, 1, 1);
487 memcpy(sk->outbuf.s.buf + sk->outbuf.s.datasize, data, size);
488 sk->outbuf.s.datasize += size;
489 break;
490 case SOCK_DGRAM:
491 if(sk->remote == NULL)
492 return;
493 new = smalloc(sizeof(*new));
494 new->next = NULL;
495 memcpy(new->data = smalloc(size), data, new->size = size);
496 memcpy(new->addr = smalloc(sk->remotelen), sk->remote, new->addrlen = sk->remotelen);
497 if(sk->outbuf.d.l == NULL)
498 {
499 sk->outbuf.d.l = sk->outbuf.d.f = new;
500 } else {
501 sk->outbuf.d.l->next = new;
502 sk->outbuf.d.l = new;
503 }
504 break;
505 }
506}
507
508size_t sockgetdatalen(struct socket *sk)
509{
510 struct dgrambuf *b;
511 size_t ret;
512
513 switch(sk->type)
514 {
515 case SOCK_STREAM:
516 ret = sk->inbuf.s.datasize;
517 break;
518 case SOCK_DGRAM:
519 ret = 0;
520 for(b = sk->inbuf.d.f; b != NULL; b = b->next)
521 ret += b->size;
522 break;
523 }
524 return(ret);
525}
526
527size_t sockqueuesize(struct socket *sk)
528{
529 struct dgrambuf *b;
530 size_t ret;
531
532 switch(sk->type)
533 {
534 case SOCK_STREAM:
535 ret = sk->outbuf.s.datasize;
536 break;
537 case SOCK_DGRAM:
538 ret = 0;
539 for(b = sk->outbuf.d.f; b != NULL; b = b->next)
540 ret += b->size;
541 break;
542 }
543 return(ret);
544}
545
d3372da9 546/*
547 * The difference between netcslisten() and netcslistenlocal() is that
548 * netcslistenlocal() always listens on the local host, instead of
549 * following proxy/passive mode directions. It is suitable for eg. the
550 * UI channel, while the file sharing networks should, naturally, use
551 * netcslisten() instead.
552*/
553
554struct socket *netcslistenlocal(int type, struct sockaddr *name, socklen_t namelen, void (*func)(struct socket *, struct socket *, void *), void *data)
555{
556 struct socket *sk;
66c517d2 557 int intbuf;
d3372da9 558
559 /* I don't know if this is actually correct (it probably isn't),
560 * but since, at on least Linux systems, PF_* are specifically
561 * #define'd to their AF_* counterparts, it allows for a severely
562 * smoother implementation. If it breaks something on your
563 * platform, please tell me so.
564 */
565 if((sk = mksock(name->sa_family, type)) == NULL)
566 return(NULL);
567 sk->state = SOCK_LST;
687b2ee2 568 if(confgetint("net", "reuseaddr"))
569 {
570 intbuf = 1;
571 setsockopt(sk->fd, SOL_SOCKET, SO_REUSEADDR, &intbuf, sizeof(intbuf));
572 }
d3372da9 573 if(bind(sk->fd, name, namelen) < 0)
574 {
575 putsock(sk);
576 return(NULL);
577 }
578 if(listen(sk->fd, 16) < 0)
579 {
580 putsock(sk);
581 return(NULL);
582 }
583 sk->acceptcb = func;
584 sk->data = data;
585 return(sk);
586}
587
c23acc61 588struct socket *netcslisten(int type, struct sockaddr *name, socklen_t namelen, void (*func)(struct socket *, struct socket *, void *), void *data)
589{
590 if(confgetint("net", "mode") == 1)
591 {
592 errno = EOPNOTSUPP;
593 return(NULL);
594 }
c23acc61 595 if(confgetint("net", "mode") == 0)
596 return(netcslistenlocal(type, name, namelen, func, data));
597 errno = EOPNOTSUPP;
598 return(NULL);
599}
600
0a1bc5b1 601struct socket *netcstcplisten(int port, int local, void (*func)(struct socket *, struct socket *, void *), void *data)
602{
603 struct sockaddr_in addr;
604#ifdef HAVE_IPV6
605 struct sockaddr_in6 addr6;
606#endif
607 struct socket *(*csfunc)(int, struct sockaddr *, socklen_t, void (*)(struct socket *, struct socket *, void *), void *);
608 struct socket *ret;
609
610 if(local)
611 csfunc = netcslistenlocal;
612 else
613 csfunc = netcslisten;
614#ifdef HAVE_IPV6
615 memset(&addr6, 0, sizeof(addr6));
616 addr6.sin6_family = AF_INET6;
617 addr6.sin6_port = htons(port);
618 addr6.sin6_addr = in6addr_any;
619 if((ret = csfunc(SOCK_STREAM, (struct sockaddr *)&addr6, sizeof(addr6), func, data)) != NULL)
620 return(ret);
621 if((ret == NULL) && (errno != EAFNOSUPPORT))
622 return(NULL);
623#endif
624 memset(&addr, 0, sizeof(addr));
625 addr.sin_family = AF_INET;
626 addr.sin_port = htons(port);
627 return(csfunc(SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr), func, data));
628}
629
d3372da9 630struct socket *netcsdgram(struct sockaddr *name, socklen_t namelen)
631{
632 struct socket *sk;
633 int mode;
634
635 mode = confgetint("net", "mode");
636 if((mode == 0) || (mode == 1))
637 {
638 if((sk = mksock(name->sa_family, SOCK_DGRAM)) == NULL)
639 return(NULL);
640 if(bind(sk->fd, name, namelen) < 0)
641 {
642 putsock(sk);
643 return(NULL);
644 }
645 sk->state = SOCK_EST;
646 return(sk);
647 }
648 errno = EOPNOTSUPP;
649 return(NULL);
650}
651
652struct socket *netdupsock(struct socket *sk)
653{
654 struct socket *newsk;
655
656 newsk = newsock(sk->type);
657 if((newsk->fd = dup(sk->fd)) < 0)
658 {
659 flog(LOG_WARNING, "could not dup() socket: %s", strerror(errno));
660 putsock(newsk);
661 return(NULL);
662 }
663 newsk->state = sk->state;
664 newsk->ignread = sk->ignread;
665 if(sk->remote != NULL)
666 memcpy(newsk->remote = smalloc(sk->remotelen), sk->remote, newsk->remotelen = sk->remotelen);
667 return(newsk);
668}
669
670void netdgramconn(struct socket *sk, struct sockaddr *addr, socklen_t addrlen)
671{
672 if(sk->remote != NULL)
673 free(sk->remote);
674 memcpy(sk->remote = smalloc(addrlen), addr, sk->remotelen = addrlen);
675 sk->ignread = 1;
676}
677
678struct socket *netcsconn(struct sockaddr *addr, socklen_t addrlen, void (*func)(struct socket *, int, void *), void *data)
679{
680 struct socket *sk;
681 int mode;
682
683 mode = confgetint("net", "mode");
684 if((mode == 0) || (mode == 1))
685 {
686 if((sk = mksock(addr->sa_family, SOCK_STREAM)) == NULL)
687 return(NULL);
688 memcpy(sk->remote = smalloc(addrlen), addr, sk->remotelen = addrlen);
689 if(!connect(sk->fd, addr, addrlen))
690 {
691 sk->state = SOCK_EST;
692 func(sk, 0, data);
693 return(sk);
694 }
695 if(errno == EINPROGRESS)
696 {
697 sk->state = SOCK_SYN;
698 sk->conncb = func;
699 sk->data = data;
700 return(sk);
701 }
702 putsock(sk);
703 return(NULL);
704 }
705 errno = EOPNOTSUPP;
706 return(NULL);
707}
708
709int pollsocks(int timeout)
710{
711 int i, num, ret, retlen;
712 int newfd;
713 struct pollfd *pfds;
714 struct socket *sk, *next, *newsk;
715 struct sockaddr_storage ss;
716 socklen_t sslen;
717
718 pfds = smalloc(sizeof(*pfds) * (num = numsocks));
719 for(i = 0, sk = sockets; i < num; sk = sk->next)
720 {
721 if(sk->state == SOCK_STL)
722 {
723 num--;
724 continue;
725 }
726 pfds[i].fd = sk->fd;
727 pfds[i].events = 0;
728 if(!sk->ignread)
729 pfds[i].events |= POLLIN;
730 if((sk->state == SOCK_SYN) || (sockqueuesize(sk) > 0))
731 pfds[i].events |= POLLOUT;
732 pfds[i].revents = 0;
733 i++;
734 }
735 ret = poll(pfds, num, timeout);
736 if(ret < 0)
737 {
738 if(errno != EINTR)
739 {
740 flog(LOG_CRIT, "pollsocks: poll errored out: %s", strerror(errno));
741 /* To avoid CPU hogging in case it's bad, which it
742 * probably is. */
743 sleep(1);
744 }
745 free(pfds);
746 return(1);
747 }
748 for(sk = sockets; sk != NULL; sk = next)
749 {
750 next = sk->next;
751 for(i = 0; i < num; i++)
752 {
753 if(pfds[i].fd == sk->fd)
754 break;
755 }
756 if(i == num)
757 continue;
758 switch(sk->state)
759 {
760 case SOCK_LST:
761 if(pfds[i].revents & POLLIN)
762 {
763 sslen = sizeof(ss);
764 if((newfd = accept(sk->fd, (struct sockaddr *)&ss, &sslen)) < 0)
765 {
766 if(sk->errcb != NULL)
767 sk->errcb(sk, errno, sk->data);
768 }
769 newsk = newsock(sk->type);
770 newsk->fd = newfd;
771 newsk->family = sk->family;
772 newsk->state = SOCK_EST;
773 memcpy(newsk->remote = smalloc(sslen), &ss, sslen);
774 newsk->remotelen = sslen;
775 putsock(newsk);
776 if(sk->acceptcb != NULL)
777 sk->acceptcb(sk, newsk, sk->data);
778 }
779 if(pfds[i].revents & POLLERR)
780 {
781 retlen = sizeof(ret);
782 getsockopt(sk->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
783 if(sk->errcb != NULL)
784 sk->errcb(sk, ret, sk->data);
785 continue;
786 }
787 break;
788 case SOCK_SYN:
789 if(pfds[i].revents & POLLERR)
790 {
791 retlen = sizeof(ret);
792 getsockopt(sk->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
793 if(sk->conncb != NULL)
794 sk->conncb(sk, ret, sk->data);
795 closesock(sk);
796 continue;
797 }
798 if(pfds[i].revents & (POLLIN | POLLOUT))
799 {
800 sk->state = SOCK_EST;
801 if(sk->conncb != NULL)
802 sk->conncb(sk, 0, sk->data);
803 }
804 break;
805 case SOCK_EST:
806 if(pfds[i].revents & POLLERR)
807 {
808 retlen = sizeof(ret);
809 getsockopt(sk->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
810 if(sk->errcb != NULL)
811 sk->errcb(sk, ret, sk->data);
812 closesock(sk);
813 continue;
814 }
815 if(pfds[i].revents & POLLIN)
816 sockrecv(sk);
817 if(pfds[i].revents & POLLOUT)
818 {
819 if(sockqueuesize(sk) > 0)
820 sockflush(sk);
821 }
822 break;
823 }
824 if(pfds[i].revents & POLLNVAL)
825 {
826 flog(LOG_CRIT, "BUG: stale socket struct on fd %i", sk->fd);
827 sk->state = SOCK_STL;
828 unlinksock(sk);
829 continue;
830 }
831 if(pfds[i].revents & POLLHUP)
832 {
833 if(sk->errcb != NULL)
834 sk->errcb(sk, 0, sk->data);
835 closesock(sk);
836 unlinksock(sk);
837 continue;
838 }
839 }
840 free(pfds);
841 for(sk = sockets; sk != NULL; sk = next)
842 {
843 next = sk->next;
844 if(sk->refcount == 1 && (sockqueuesize(sk) == 0))
845 {
846 unlinksock(sk);
847 continue;
848 }
849 if(sk->close && (sockqueuesize(sk) == 0))
850 closesock(sk);
851 if(sk->state == SOCK_STL)
852 {
853 unlinksock(sk);
854 continue;
855 }
856 }
857 return(1);
858}
859
860int socksettos(struct socket *sk, int tos)
861{
b020fb3d 862 int buf;
863
d3372da9 864 if(sk->family == AF_INET)
865 {
b020fb3d 866 switch(tos)
867 {
b198bed6 868 case 0:
869 buf = 0;
870 break;
b020fb3d 871 case SOCK_TOS_MINCOST:
18c1ae1d 872 buf = 0x02;
b020fb3d 873 break;
874 case SOCK_TOS_MAXREL:
18c1ae1d 875 buf = 0x04;
b020fb3d 876 break;
877 case SOCK_TOS_MAXTP:
18c1ae1d 878 buf = 0x08;
b020fb3d 879 break;
880 case SOCK_TOS_MINDELAY:
18c1ae1d 881 buf = 0x10;
b020fb3d 882 break;
883 default:
884 flog(LOG_WARNING, "attempted to set unknown TOS value %i to IPv4 sock", tos);
885 return(-1);
886 }
887 if(setsockopt(sk->fd, SOL_IP, IP_TOS, &buf, sizeof(buf)) < 0)
d3372da9 888 {
889 flog(LOG_WARNING, "could not set sock TOS to %i: %s", tos, strerror(errno));
890 return(-1);
891 }
892 return(0);
893 }
b020fb3d 894 if(sk->family == AF_INET6)
895 {
896 switch(tos)
897 {
b198bed6 898 case 0:
899 buf = 0;
b020fb3d 900 case SOCK_TOS_MINCOST:
901 buf = confgetint("net", "diffserv-mincost");
902 break;
903 case SOCK_TOS_MAXREL:
904 buf = confgetint("net", "diffserv-maxrel");
905 break;
906 case SOCK_TOS_MAXTP:
907 buf = confgetint("net", "diffserv-maxtp");
908 break;
909 case SOCK_TOS_MINDELAY:
910 buf = confgetint("net", "diffserv-mindelay");
911 break;
912 default:
913 flog(LOG_WARNING, "attempted to set unknown TOS value %i to IPv4 sock", tos);
914 return(-1);
915 }
916 /*
917 On Linux, the API IPv6 flow label management doesn't seem to
918 be entirely complete, so I guess this will have to wait.
919
920 if(setsockopt(...) < 0)
921 {
922 flog(LOG_WARNING, "could not set sock traffic class to %i: %s", tos, strerror(errno));
923 return(-1);
924 }
925 */
926 return(0);
927 }
d3372da9 928 flog(LOG_WARNING, "could not set TOS on sock of family %i", sk->family);
929 return(1);
930}
931
932struct resolvedata
933{
934 int fd;
935 void (*callback)(struct sockaddr *addr, int addrlen, void *data);
936 void *data;
937 struct sockaddr_storage addr;
938 int addrlen;
939};
940
941static void resolvecb(pid_t pid, int status, struct resolvedata *data)
942{
943 static char buf[80];
944 int ret;
945 struct sockaddr_in *ipv4;
946
947 if(!status)
948 {
949 if((ret = read(data->fd, buf, sizeof(buf))) != 4)
950 {
951 errno = ENONET;
952 data->callback(NULL, 0, data->data);
953 } else {
954 ipv4 = (struct sockaddr_in *)&data->addr;
955 memcpy(&ipv4->sin_addr, buf, 4);
956 data->callback((struct sockaddr *)ipv4, sizeof(*ipv4), data->data);
957 }
958 } else {
959 errno = ENONET;
960 data->callback(NULL, 0, data->data);
961 }
962 close(data->fd);
963 free(data);
964}
965
966int netresolve(char *addr, void (*callback)(struct sockaddr *addr, int addrlen, void *data), void *data)
967{
968 int i;
969 char *p;
970 int port;
971 int pfd[2];
972 pid_t child;
973 struct resolvedata *rdata;
974 struct sockaddr_in ipv4;
975 struct hostent *he;
976 sigset_t sigset;
977
978 /* IPv4 */
979 port = -1;
980 if((p = strchr(addr, ':')) != NULL)
981 {
982 *p = 0;
983 port = atoi(p + 1);
984 }
985 ipv4.sin_family = AF_INET;
986 ipv4.sin_port = htons(port);
987 if(inet_aton(addr, &ipv4.sin_addr))
988 {
989 callback((struct sockaddr *)&ipv4, sizeof(ipv4), data);
990 } else {
991 sigemptyset(&sigset);
992 sigaddset(&sigset, SIGCHLD);
993 sigprocmask(SIG_BLOCK, &sigset, NULL);
994 if((pipe(pfd) < 0) || ((child = fork()) < 0))
995 {
996 sigprocmask(SIG_UNBLOCK, &sigset, NULL);
997 return(-1);
998 }
999 if(child == 0)
1000 {
1001 sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1002 for(i = 3; i < FD_SETSIZE; i++)
1003 {
1004 if(i != pfd[1])
1005 close(i);
1006 }
1007 signal(SIGALRM, SIG_DFL);
1008 alarm(30);
1009 if((he = gethostbyname(addr)) == NULL)
1010 exit(1);
1011 write(pfd[1], he->h_addr_list[0], 4);
1012 exit(0);
1013 } else {
1014 close(pfd[1]);
1015 fcntl(pfd[0], F_SETFL, fcntl(pfd[0], F_GETFL) | O_NONBLOCK);
1016 rdata = smalloc(sizeof(*rdata));
1017 rdata->fd = pfd[0];
1018 rdata->callback = callback;
1019 rdata->data = data;
1020 memcpy(&rdata->addr, &ipv4, rdata->addrlen = sizeof(ipv4));
1021 childcallback(child, (void (*)(pid_t, int, void *))resolvecb, rdata);
1022 sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1023 return(1);
1024 }
1025 }
1026 return(0);
1027}
1028
1029int sockgetlocalname(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf)
1030{
1031 socklen_t len;
1032 struct sockaddr_storage name;
1033
1034 *namebuf = NULL;
1035 if((sk->state == SOCK_STL) || (sk->fd < 0))
1036 return(-1);
1037 len = sizeof(name);
1038 if(getsockname(sk->fd, (struct sockaddr *)&name, &len) < 0)
1039 {
1040 flog(LOG_ERR, "BUG: alive socket with dead fd in sockgetlocalname");
1041 return(-1);
1042 }
1043 *namebuf = memcpy(smalloc(len), &name, len);
1044 *lenbuf = len;
1045 return(0);
1046}
1047
1048int sockgetremotename(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf)
1049{
1050 socklen_t len;
1051 struct sockaddr_storage name;
1052 struct sockaddr_in *ipv4;
1053 struct sockaddr *pname;
1054 socklen_t pnamelen;
1055
1056 switch(confgetint("net", "mode"))
1057 {
1058 case 0:
1059 *namebuf = NULL;
1060 if((sk->state == SOCK_STL) || (sk->fd < 0))
1061 return(-1);
1062 len = sizeof(name);
1063 if(getsockname(sk->fd, (struct sockaddr *)&name, &len) < 0)
1064 {
1065 flog(LOG_ERR, "BUG: alive socket with dead fd in sockgetremotename");
1066 return(-1);
1067 }
1068 if(name.ss_family == AF_INET)
1069 {
1070 ipv4 = (struct sockaddr_in *)&name;
1071 if(getpublicaddr(AF_INET, &pname, &pnamelen) < 0)
1072 {
1073 flog(LOG_WARNING, "could not determine public IP address - strange things may happen");
1074 return(-1);
1075 }
1076 ipv4->sin_addr.s_addr = ((struct sockaddr_in *)pname)->sin_addr.s_addr;
1077 free(pname);
1078 }
1079 *namebuf = memcpy(smalloc(len), &name, len);
1080 *lenbuf = len;
1081 return(0);
1082 case 1:
1083 errno = EOPNOTSUPP;
1084 return(-1);
1085 default:
1086 flog(LOG_CRIT, "unknown net mode %i active", confgetint("net", "mode"));
1087 errno = EOPNOTSUPP;
1088 return(-1);
1089 }
1090}
1091
99a28d47 1092int addreq(struct sockaddr *x, struct sockaddr *y)
1093{
1094 struct sockaddr_un *u1, *u2;
1095 struct sockaddr_in *n1, *n2;
1096#ifdef HAVE_IPV6
1097 struct sockaddr_in6 *s1, *s2;
1098#endif
1099
1100 if(x->sa_family != y->sa_family)
1101 return(0);
1102 switch(x->sa_family) {
1103 case AF_UNIX:
1104 u1 = (struct sockaddr_un *)x; u2 = (struct sockaddr_un *)y;
1105 if(strncmp(u1->sun_path, u2->sun_path, sizeof(u1->sun_path)))
1106 return(0);
1107 break;
1108 case AF_INET:
1109 n1 = (struct sockaddr_in *)x; n2 = (struct sockaddr_in *)y;
1110 if(n1->sin_port != n2->sin_port)
1111 return(0);
1112 if(n1->sin_addr.s_addr != n2->sin_addr.s_addr)
1113 return(0);
1114 break;
1115 case AF_INET6:
1116 s1 = (struct sockaddr_in6 *)x; s2 = (struct sockaddr_in6 *)y;
1117 if(s1->sin6_port != s2->sin6_port)
1118 return(0);
1119 if(memcmp(s1->sin6_addr.s6_addr, s2->sin6_addr.s6_addr, sizeof(s1->sin6_addr.s6_addr)))
1120 return(0);
1121 break;
1122 }
1123 return(1);
1124}
1125
d3372da9 1126char *formataddress(struct sockaddr *arg, socklen_t arglen)
1127{
1128 struct sockaddr_un *UNIX; /* Some wise guy has #defined unix with
1129 * lowercase letters to 1, so I do this
1130 * instead. */
1131 struct sockaddr_in *ipv4;
1132#ifdef HAVE_IPV6
1133 struct sockaddr_in6 *ipv6;
1134#endif
1135 static char *ret = NULL;
1136 char buf[1024];
1137
1138 if(ret != NULL)
1139 free(ret);
1140 ret = NULL;
1141 switch(arg->sa_family)
1142 {
1143 case AF_UNIX:
1144 UNIX = (struct sockaddr_un *)arg;
1145 ret = sprintf2("%s", UNIX->sun_path);
1146 break;
1147 case AF_INET:
1148 ipv4 = (struct sockaddr_in *)arg;
1149 if(inet_ntop(AF_INET, &ipv4->sin_addr, buf, sizeof(buf)) == NULL)
1150 return(NULL);
1151 ret = sprintf2("%s:%i", buf, (int)ntohs(ipv4->sin_port));
1152 break;
1153#ifdef HAVE_IPV6
1154 case AF_INET6:
1155 ipv6 = (struct sockaddr_in6 *)arg;
1156 if(inet_ntop(AF_INET6, &ipv6->sin6_addr, buf, sizeof(buf)) == NULL)
1157 return(NULL);
fc7f7735 1158 ret = sprintf2("[%s]:%i", buf, (int)ntohs(ipv6->sin6_port));
d3372da9 1159 break;
1160#endif
1161 default:
1162 errno = EPFNOSUPPORT;
1163 break;
1164 }
1165 return(ret);
1166}
1167
1168#if 0
1169
1170/*
1171 * It was very nice to use this, but it seems
1172 * to mess things up, so I guess it has to go... :-(
1173 */
1174
1175static int formataddress(FILE *stream, const struct printf_info *info, const void *const *args)
1176{
1177 struct sockaddr *arg;
1178 socklen_t arglen;
1179 struct sockaddr_un *UNIX; /* Some wise guy has #defined unix with
1180 * lowercase letters to 1, so I do this
1181 * instead. */
1182 struct sockaddr_in *ipv4;
1183 int ret;
1184
1185 arg = *(struct sockaddr **)(args[0]);
1186 arglen = *(socklen_t *)(args[1]);
1187 switch(arg->sa_family)
1188 {
1189 case AF_UNIX:
1190 UNIX = (struct sockaddr_un *)arg;
1191 ret = fprintf(stream, "%s", UNIX->sun_path);
1192 break;
1193 case AF_INET:
1194 ipv4 = (struct sockaddr_in *)arg;
1195 ret = fprintf(stream, "%s:%i", inet_ntoa(ipv4->sin_addr), (int)ntohs(ipv4->sin_port));
1196 break;
1197 default:
1198 ret = -1;
1199 errno = EPFNOSUPPORT;
1200 break;
1201 }
1202 return(ret);
1203}
1204
1205static int formataddress_arginfo(const struct printf_info *info, size_t n, int *argtypes)
1206{
1207 if(n > 0)
1208 argtypes[0] = PA_POINTER;
1209 if(n > 1)
1210 argtypes[1] = PA_INT; /* Sources tell me that socklen_t _must_
1211 * be an int, so I guess this should be
1212 * safe. */
1213 return(2);
1214}
1215#endif
1216
1217static int init(int hup)
1218{
1219 if(!hup)
1220 {
1221 /*
1222 if(register_printf_function('N', formataddress, formataddress_arginfo))
1223 {
1224 flog(LOG_CRIT, "could not register printf handler %%N: %s", strerror(errno));
1225 return(1);
1226 }
1227 */
1228 }
1229 return(0);
1230}
1231
1232static void terminate(void)
1233{
1234 while(sockets != NULL)
1235 unlinksock(sockets);
1236}
1237
1238static struct module me =
1239{
1240 .name = "net",
1241 .conf =
1242 {
1243 .vars = myvars
1244 },
1245 .init = init,
1246 .terminate = terminate
1247};
1248
1249MODULE(me)