Remove printf.h, since it is no longer used.
[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 }
595 /* I don't know if this is actually correct (it probably isn't),
596 * but since, at on least Linux systems, PF_* are specifically
597 * #define'd to their AF_* counterparts, it allows for a severely
598 * smoother implementation. If it breaks something on your
599 * platform, please tell me so.
600 */
601 if(confgetint("net", "mode") == 0)
602 return(netcslistenlocal(type, name, namelen, func, data));
603 errno = EOPNOTSUPP;
604 return(NULL);
605}
606
0a1bc5b1 607struct socket *netcstcplisten(int port, int local, void (*func)(struct socket *, struct socket *, void *), void *data)
608{
609 struct sockaddr_in addr;
610#ifdef HAVE_IPV6
611 struct sockaddr_in6 addr6;
612#endif
613 struct socket *(*csfunc)(int, struct sockaddr *, socklen_t, void (*)(struct socket *, struct socket *, void *), void *);
614 struct socket *ret;
615
616 if(local)
617 csfunc = netcslistenlocal;
618 else
619 csfunc = netcslisten;
620#ifdef HAVE_IPV6
621 memset(&addr6, 0, sizeof(addr6));
622 addr6.sin6_family = AF_INET6;
623 addr6.sin6_port = htons(port);
624 addr6.sin6_addr = in6addr_any;
625 if((ret = csfunc(SOCK_STREAM, (struct sockaddr *)&addr6, sizeof(addr6), func, data)) != NULL)
626 return(ret);
627 if((ret == NULL) && (errno != EAFNOSUPPORT))
628 return(NULL);
629#endif
630 memset(&addr, 0, sizeof(addr));
631 addr.sin_family = AF_INET;
632 addr.sin_port = htons(port);
633 return(csfunc(SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr), func, data));
634}
635
d3372da9 636struct socket *netcsdgram(struct sockaddr *name, socklen_t namelen)
637{
638 struct socket *sk;
639 int mode;
640
641 mode = confgetint("net", "mode");
642 if((mode == 0) || (mode == 1))
643 {
644 if((sk = mksock(name->sa_family, SOCK_DGRAM)) == NULL)
645 return(NULL);
646 if(bind(sk->fd, name, namelen) < 0)
647 {
648 putsock(sk);
649 return(NULL);
650 }
651 sk->state = SOCK_EST;
652 return(sk);
653 }
654 errno = EOPNOTSUPP;
655 return(NULL);
656}
657
658struct socket *netdupsock(struct socket *sk)
659{
660 struct socket *newsk;
661
662 newsk = newsock(sk->type);
663 if((newsk->fd = dup(sk->fd)) < 0)
664 {
665 flog(LOG_WARNING, "could not dup() socket: %s", strerror(errno));
666 putsock(newsk);
667 return(NULL);
668 }
669 newsk->state = sk->state;
670 newsk->ignread = sk->ignread;
671 if(sk->remote != NULL)
672 memcpy(newsk->remote = smalloc(sk->remotelen), sk->remote, newsk->remotelen = sk->remotelen);
673 return(newsk);
674}
675
676void netdgramconn(struct socket *sk, struct sockaddr *addr, socklen_t addrlen)
677{
678 if(sk->remote != NULL)
679 free(sk->remote);
680 memcpy(sk->remote = smalloc(addrlen), addr, sk->remotelen = addrlen);
681 sk->ignread = 1;
682}
683
684struct socket *netcsconn(struct sockaddr *addr, socklen_t addrlen, void (*func)(struct socket *, int, void *), void *data)
685{
686 struct socket *sk;
687 int mode;
688
689 mode = confgetint("net", "mode");
690 if((mode == 0) || (mode == 1))
691 {
692 if((sk = mksock(addr->sa_family, SOCK_STREAM)) == NULL)
693 return(NULL);
694 memcpy(sk->remote = smalloc(addrlen), addr, sk->remotelen = addrlen);
695 if(!connect(sk->fd, addr, addrlen))
696 {
697 sk->state = SOCK_EST;
698 func(sk, 0, data);
699 return(sk);
700 }
701 if(errno == EINPROGRESS)
702 {
703 sk->state = SOCK_SYN;
704 sk->conncb = func;
705 sk->data = data;
706 return(sk);
707 }
708 putsock(sk);
709 return(NULL);
710 }
711 errno = EOPNOTSUPP;
712 return(NULL);
713}
714
715int pollsocks(int timeout)
716{
717 int i, num, ret, retlen;
718 int newfd;
719 struct pollfd *pfds;
720 struct socket *sk, *next, *newsk;
721 struct sockaddr_storage ss;
722 socklen_t sslen;
723
724 pfds = smalloc(sizeof(*pfds) * (num = numsocks));
725 for(i = 0, sk = sockets; i < num; sk = sk->next)
726 {
727 if(sk->state == SOCK_STL)
728 {
729 num--;
730 continue;
731 }
732 pfds[i].fd = sk->fd;
733 pfds[i].events = 0;
734 if(!sk->ignread)
735 pfds[i].events |= POLLIN;
736 if((sk->state == SOCK_SYN) || (sockqueuesize(sk) > 0))
737 pfds[i].events |= POLLOUT;
738 pfds[i].revents = 0;
739 i++;
740 }
741 ret = poll(pfds, num, timeout);
742 if(ret < 0)
743 {
744 if(errno != EINTR)
745 {
746 flog(LOG_CRIT, "pollsocks: poll errored out: %s", strerror(errno));
747 /* To avoid CPU hogging in case it's bad, which it
748 * probably is. */
749 sleep(1);
750 }
751 free(pfds);
752 return(1);
753 }
754 for(sk = sockets; sk != NULL; sk = next)
755 {
756 next = sk->next;
757 for(i = 0; i < num; i++)
758 {
759 if(pfds[i].fd == sk->fd)
760 break;
761 }
762 if(i == num)
763 continue;
764 switch(sk->state)
765 {
766 case SOCK_LST:
767 if(pfds[i].revents & POLLIN)
768 {
769 sslen = sizeof(ss);
770 if((newfd = accept(sk->fd, (struct sockaddr *)&ss, &sslen)) < 0)
771 {
772 if(sk->errcb != NULL)
773 sk->errcb(sk, errno, sk->data);
774 }
775 newsk = newsock(sk->type);
776 newsk->fd = newfd;
777 newsk->family = sk->family;
778 newsk->state = SOCK_EST;
779 memcpy(newsk->remote = smalloc(sslen), &ss, sslen);
780 newsk->remotelen = sslen;
781 putsock(newsk);
782 if(sk->acceptcb != NULL)
783 sk->acceptcb(sk, newsk, sk->data);
784 }
785 if(pfds[i].revents & POLLERR)
786 {
787 retlen = sizeof(ret);
788 getsockopt(sk->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
789 if(sk->errcb != NULL)
790 sk->errcb(sk, ret, sk->data);
791 continue;
792 }
793 break;
794 case SOCK_SYN:
795 if(pfds[i].revents & POLLERR)
796 {
797 retlen = sizeof(ret);
798 getsockopt(sk->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
799 if(sk->conncb != NULL)
800 sk->conncb(sk, ret, sk->data);
801 closesock(sk);
802 continue;
803 }
804 if(pfds[i].revents & (POLLIN | POLLOUT))
805 {
806 sk->state = SOCK_EST;
807 if(sk->conncb != NULL)
808 sk->conncb(sk, 0, sk->data);
809 }
810 break;
811 case SOCK_EST:
812 if(pfds[i].revents & POLLERR)
813 {
814 retlen = sizeof(ret);
815 getsockopt(sk->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
816 if(sk->errcb != NULL)
817 sk->errcb(sk, ret, sk->data);
818 closesock(sk);
819 continue;
820 }
821 if(pfds[i].revents & POLLIN)
822 sockrecv(sk);
823 if(pfds[i].revents & POLLOUT)
824 {
825 if(sockqueuesize(sk) > 0)
826 sockflush(sk);
827 }
828 break;
829 }
830 if(pfds[i].revents & POLLNVAL)
831 {
832 flog(LOG_CRIT, "BUG: stale socket struct on fd %i", sk->fd);
833 sk->state = SOCK_STL;
834 unlinksock(sk);
835 continue;
836 }
837 if(pfds[i].revents & POLLHUP)
838 {
839 if(sk->errcb != NULL)
840 sk->errcb(sk, 0, sk->data);
841 closesock(sk);
842 unlinksock(sk);
843 continue;
844 }
845 }
846 free(pfds);
847 for(sk = sockets; sk != NULL; sk = next)
848 {
849 next = sk->next;
850 if(sk->refcount == 1 && (sockqueuesize(sk) == 0))
851 {
852 unlinksock(sk);
853 continue;
854 }
855 if(sk->close && (sockqueuesize(sk) == 0))
856 closesock(sk);
857 if(sk->state == SOCK_STL)
858 {
859 unlinksock(sk);
860 continue;
861 }
862 }
863 return(1);
864}
865
866int socksettos(struct socket *sk, int tos)
867{
b020fb3d 868 int buf;
869
d3372da9 870 if(sk->family == AF_INET)
871 {
b020fb3d 872 switch(tos)
873 {
b198bed6 874 case 0:
875 buf = 0;
876 break;
b020fb3d 877 case SOCK_TOS_MINCOST:
18c1ae1d 878 buf = 0x02;
b020fb3d 879 break;
880 case SOCK_TOS_MAXREL:
18c1ae1d 881 buf = 0x04;
b020fb3d 882 break;
883 case SOCK_TOS_MAXTP:
18c1ae1d 884 buf = 0x08;
b020fb3d 885 break;
886 case SOCK_TOS_MINDELAY:
18c1ae1d 887 buf = 0x10;
b020fb3d 888 break;
889 default:
890 flog(LOG_WARNING, "attempted to set unknown TOS value %i to IPv4 sock", tos);
891 return(-1);
892 }
893 if(setsockopt(sk->fd, SOL_IP, IP_TOS, &buf, sizeof(buf)) < 0)
d3372da9 894 {
895 flog(LOG_WARNING, "could not set sock TOS to %i: %s", tos, strerror(errno));
896 return(-1);
897 }
898 return(0);
899 }
b020fb3d 900 if(sk->family == AF_INET6)
901 {
902 switch(tos)
903 {
b198bed6 904 case 0:
905 buf = 0;
b020fb3d 906 case SOCK_TOS_MINCOST:
907 buf = confgetint("net", "diffserv-mincost");
908 break;
909 case SOCK_TOS_MAXREL:
910 buf = confgetint("net", "diffserv-maxrel");
911 break;
912 case SOCK_TOS_MAXTP:
913 buf = confgetint("net", "diffserv-maxtp");
914 break;
915 case SOCK_TOS_MINDELAY:
916 buf = confgetint("net", "diffserv-mindelay");
917 break;
918 default:
919 flog(LOG_WARNING, "attempted to set unknown TOS value %i to IPv4 sock", tos);
920 return(-1);
921 }
922 /*
923 On Linux, the API IPv6 flow label management doesn't seem to
924 be entirely complete, so I guess this will have to wait.
925
926 if(setsockopt(...) < 0)
927 {
928 flog(LOG_WARNING, "could not set sock traffic class to %i: %s", tos, strerror(errno));
929 return(-1);
930 }
931 */
932 return(0);
933 }
d3372da9 934 flog(LOG_WARNING, "could not set TOS on sock of family %i", sk->family);
935 return(1);
936}
937
938struct resolvedata
939{
940 int fd;
941 void (*callback)(struct sockaddr *addr, int addrlen, void *data);
942 void *data;
943 struct sockaddr_storage addr;
944 int addrlen;
945};
946
947static void resolvecb(pid_t pid, int status, struct resolvedata *data)
948{
949 static char buf[80];
950 int ret;
951 struct sockaddr_in *ipv4;
952
953 if(!status)
954 {
955 if((ret = read(data->fd, buf, sizeof(buf))) != 4)
956 {
957 errno = ENONET;
958 data->callback(NULL, 0, data->data);
959 } else {
960 ipv4 = (struct sockaddr_in *)&data->addr;
961 memcpy(&ipv4->sin_addr, buf, 4);
962 data->callback((struct sockaddr *)ipv4, sizeof(*ipv4), data->data);
963 }
964 } else {
965 errno = ENONET;
966 data->callback(NULL, 0, data->data);
967 }
968 close(data->fd);
969 free(data);
970}
971
972int netresolve(char *addr, void (*callback)(struct sockaddr *addr, int addrlen, void *data), void *data)
973{
974 int i;
975 char *p;
976 int port;
977 int pfd[2];
978 pid_t child;
979 struct resolvedata *rdata;
980 struct sockaddr_in ipv4;
981 struct hostent *he;
982 sigset_t sigset;
983
984 /* IPv4 */
985 port = -1;
986 if((p = strchr(addr, ':')) != NULL)
987 {
988 *p = 0;
989 port = atoi(p + 1);
990 }
991 ipv4.sin_family = AF_INET;
992 ipv4.sin_port = htons(port);
993 if(inet_aton(addr, &ipv4.sin_addr))
994 {
995 callback((struct sockaddr *)&ipv4, sizeof(ipv4), data);
996 } else {
997 sigemptyset(&sigset);
998 sigaddset(&sigset, SIGCHLD);
999 sigprocmask(SIG_BLOCK, &sigset, NULL);
1000 if((pipe(pfd) < 0) || ((child = fork()) < 0))
1001 {
1002 sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1003 return(-1);
1004 }
1005 if(child == 0)
1006 {
1007 sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1008 for(i = 3; i < FD_SETSIZE; i++)
1009 {
1010 if(i != pfd[1])
1011 close(i);
1012 }
1013 signal(SIGALRM, SIG_DFL);
1014 alarm(30);
1015 if((he = gethostbyname(addr)) == NULL)
1016 exit(1);
1017 write(pfd[1], he->h_addr_list[0], 4);
1018 exit(0);
1019 } else {
1020 close(pfd[1]);
1021 fcntl(pfd[0], F_SETFL, fcntl(pfd[0], F_GETFL) | O_NONBLOCK);
1022 rdata = smalloc(sizeof(*rdata));
1023 rdata->fd = pfd[0];
1024 rdata->callback = callback;
1025 rdata->data = data;
1026 memcpy(&rdata->addr, &ipv4, rdata->addrlen = sizeof(ipv4));
1027 childcallback(child, (void (*)(pid_t, int, void *))resolvecb, rdata);
1028 sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1029 return(1);
1030 }
1031 }
1032 return(0);
1033}
1034
1035int sockgetlocalname(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf)
1036{
1037 socklen_t len;
1038 struct sockaddr_storage name;
1039
1040 *namebuf = NULL;
1041 if((sk->state == SOCK_STL) || (sk->fd < 0))
1042 return(-1);
1043 len = sizeof(name);
1044 if(getsockname(sk->fd, (struct sockaddr *)&name, &len) < 0)
1045 {
1046 flog(LOG_ERR, "BUG: alive socket with dead fd in sockgetlocalname");
1047 return(-1);
1048 }
1049 *namebuf = memcpy(smalloc(len), &name, len);
1050 *lenbuf = len;
1051 return(0);
1052}
1053
1054int sockgetremotename(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf)
1055{
1056 socklen_t len;
1057 struct sockaddr_storage name;
1058 struct sockaddr_in *ipv4;
1059 struct sockaddr *pname;
1060 socklen_t pnamelen;
1061
1062 switch(confgetint("net", "mode"))
1063 {
1064 case 0:
1065 *namebuf = NULL;
1066 if((sk->state == SOCK_STL) || (sk->fd < 0))
1067 return(-1);
1068 len = sizeof(name);
1069 if(getsockname(sk->fd, (struct sockaddr *)&name, &len) < 0)
1070 {
1071 flog(LOG_ERR, "BUG: alive socket with dead fd in sockgetremotename");
1072 return(-1);
1073 }
1074 if(name.ss_family == AF_INET)
1075 {
1076 ipv4 = (struct sockaddr_in *)&name;
1077 if(getpublicaddr(AF_INET, &pname, &pnamelen) < 0)
1078 {
1079 flog(LOG_WARNING, "could not determine public IP address - strange things may happen");
1080 return(-1);
1081 }
1082 ipv4->sin_addr.s_addr = ((struct sockaddr_in *)pname)->sin_addr.s_addr;
1083 free(pname);
1084 }
1085 *namebuf = memcpy(smalloc(len), &name, len);
1086 *lenbuf = len;
1087 return(0);
1088 case 1:
1089 errno = EOPNOTSUPP;
1090 return(-1);
1091 default:
1092 flog(LOG_CRIT, "unknown net mode %i active", confgetint("net", "mode"));
1093 errno = EOPNOTSUPP;
1094 return(-1);
1095 }
1096}
1097
99a28d47 1098int addreq(struct sockaddr *x, struct sockaddr *y)
1099{
1100 struct sockaddr_un *u1, *u2;
1101 struct sockaddr_in *n1, *n2;
1102#ifdef HAVE_IPV6
1103 struct sockaddr_in6 *s1, *s2;
1104#endif
1105
1106 if(x->sa_family != y->sa_family)
1107 return(0);
1108 switch(x->sa_family) {
1109 case AF_UNIX:
1110 u1 = (struct sockaddr_un *)x; u2 = (struct sockaddr_un *)y;
1111 if(strncmp(u1->sun_path, u2->sun_path, sizeof(u1->sun_path)))
1112 return(0);
1113 break;
1114 case AF_INET:
1115 n1 = (struct sockaddr_in *)x; n2 = (struct sockaddr_in *)y;
1116 if(n1->sin_port != n2->sin_port)
1117 return(0);
1118 if(n1->sin_addr.s_addr != n2->sin_addr.s_addr)
1119 return(0);
1120 break;
1121 case AF_INET6:
1122 s1 = (struct sockaddr_in6 *)x; s2 = (struct sockaddr_in6 *)y;
1123 if(s1->sin6_port != s2->sin6_port)
1124 return(0);
1125 if(memcmp(s1->sin6_addr.s6_addr, s2->sin6_addr.s6_addr, sizeof(s1->sin6_addr.s6_addr)))
1126 return(0);
1127 break;
1128 }
1129 return(1);
1130}
1131
d3372da9 1132char *formataddress(struct sockaddr *arg, socklen_t arglen)
1133{
1134 struct sockaddr_un *UNIX; /* Some wise guy has #defined unix with
1135 * lowercase letters to 1, so I do this
1136 * instead. */
1137 struct sockaddr_in *ipv4;
1138#ifdef HAVE_IPV6
1139 struct sockaddr_in6 *ipv6;
1140#endif
1141 static char *ret = NULL;
1142 char buf[1024];
1143
1144 if(ret != NULL)
1145 free(ret);
1146 ret = NULL;
1147 switch(arg->sa_family)
1148 {
1149 case AF_UNIX:
1150 UNIX = (struct sockaddr_un *)arg;
1151 ret = sprintf2("%s", UNIX->sun_path);
1152 break;
1153 case AF_INET:
1154 ipv4 = (struct sockaddr_in *)arg;
1155 if(inet_ntop(AF_INET, &ipv4->sin_addr, buf, sizeof(buf)) == NULL)
1156 return(NULL);
1157 ret = sprintf2("%s:%i", buf, (int)ntohs(ipv4->sin_port));
1158 break;
1159#ifdef HAVE_IPV6
1160 case AF_INET6:
1161 ipv6 = (struct sockaddr_in6 *)arg;
1162 if(inet_ntop(AF_INET6, &ipv6->sin6_addr, buf, sizeof(buf)) == NULL)
1163 return(NULL);
fc7f7735 1164 ret = sprintf2("[%s]:%i", buf, (int)ntohs(ipv6->sin6_port));
d3372da9 1165 break;
1166#endif
1167 default:
1168 errno = EPFNOSUPPORT;
1169 break;
1170 }
1171 return(ret);
1172}
1173
1174#if 0
1175
1176/*
1177 * It was very nice to use this, but it seems
1178 * to mess things up, so I guess it has to go... :-(
1179 */
1180
1181static int formataddress(FILE *stream, const struct printf_info *info, const void *const *args)
1182{
1183 struct sockaddr *arg;
1184 socklen_t arglen;
1185 struct sockaddr_un *UNIX; /* Some wise guy has #defined unix with
1186 * lowercase letters to 1, so I do this
1187 * instead. */
1188 struct sockaddr_in *ipv4;
1189 int ret;
1190
1191 arg = *(struct sockaddr **)(args[0]);
1192 arglen = *(socklen_t *)(args[1]);
1193 switch(arg->sa_family)
1194 {
1195 case AF_UNIX:
1196 UNIX = (struct sockaddr_un *)arg;
1197 ret = fprintf(stream, "%s", UNIX->sun_path);
1198 break;
1199 case AF_INET:
1200 ipv4 = (struct sockaddr_in *)arg;
1201 ret = fprintf(stream, "%s:%i", inet_ntoa(ipv4->sin_addr), (int)ntohs(ipv4->sin_port));
1202 break;
1203 default:
1204 ret = -1;
1205 errno = EPFNOSUPPORT;
1206 break;
1207 }
1208 return(ret);
1209}
1210
1211static int formataddress_arginfo(const struct printf_info *info, size_t n, int *argtypes)
1212{
1213 if(n > 0)
1214 argtypes[0] = PA_POINTER;
1215 if(n > 1)
1216 argtypes[1] = PA_INT; /* Sources tell me that socklen_t _must_
1217 * be an int, so I guess this should be
1218 * safe. */
1219 return(2);
1220}
1221#endif
1222
1223static int init(int hup)
1224{
1225 if(!hup)
1226 {
1227 /*
1228 if(register_printf_function('N', formataddress, formataddress_arginfo))
1229 {
1230 flog(LOG_CRIT, "could not register printf handler %%N: %s", strerror(errno));
1231 return(1);
1232 }
1233 */
1234 }
1235 return(0);
1236}
1237
1238static void terminate(void)
1239{
1240 while(sockets != NULL)
1241 unlinksock(sockets);
1242}
1243
1244static struct module me =
1245{
1246 .name = "net",
1247 .conf =
1248 {
1249 .vars = myvars
1250 },
1251 .init = init,
1252 .terminate = terminate
1253};
1254
1255MODULE(me)