Initial work on the new implementation
[doldaconnect.git] / daemon / net.c
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/select.h>
32 #include <arpa/inet.h>
33 #include <netinet/in.h>
34 #include <netdb.h>
35 #include <sys/signal.h>
36 #include <sys/stat.h>       /* For rebindunix() */
37 #ifdef HAVE_LINUX_SOCKIOS_H
38 #include <linux/sockios.h>
39 #endif
40 #include <errno.h>
41 #include <net/if.h>
42
43 #include "conf.h"
44 #include "net.h"
45 #include "module.h"
46 #include "log.h"
47 #include "utils.h"
48 #include "sysevents.h"
49
50 static struct configvar myvars[] =
51 {
52     /** The network mode to use. Currently supported values are 0 for
53      * active mode and 1 for passive mode. In the future, SOCKS5 proxy
54      * support may be added. */
55     {CONF_VAR_INT, "mode", {.num = 0}},
56     /** Set the SO_REUSEADDR socket option on listening sockets, so
57      * that dead TCP connections waiting for timeout are ignored. */
58     {CONF_VAR_BOOL, "reuseaddr", {.num = 0}},
59     /** Overrides the IPv4 address reported to other clients in active
60      * mode. Useful for servers behind NAT routers. If both this and
61      * net.publicif are unspecified the address of the hub connection
62      * is used. */
63     {CONF_VAR_IPV4, "visibleipv4", {.ipv4 = {0}}},
64     /** Specifies an interface name from which to fetch the IPv4
65      * address reported to other clients in active mode. If both this
66      * and net.visibleipv4 are unspecified the address of the hub
67      * connection is used. */
68     {CONF_VAR_STRING, "publicif", {.str = L""}},
69     /* Diffserv should be supported on IPv4, too, but I don't know the
70      * API to do that. */
71     /** The Diffserv value to use on IPv6 connections when the
72      * minimize cost TOS value is used (see the TOS VALUES
73      * section). */
74     {CONF_VAR_INT, "diffserv-mincost", {.num = 0}},
75     /** The Diffserv value to use on IPv6 connections when the
76      * maximize reliability TOS value is used (see the TOS VALUES
77      * section). */
78     {CONF_VAR_INT, "diffserv-maxrel", {.num = 0}},
79     /** The Diffserv value to use on IPv6 connections when the
80      * maximize throughput TOS value is used (see the TOS VALUES
81      * section). */
82     {CONF_VAR_INT, "diffserv-maxtp", {.num = 0}},
83     /** The Diffserv value to use on IPv6 connections when the
84      * minimize delay TOS value is used (see the TOS VALUES
85      * section). */
86     {CONF_VAR_INT, "diffserv-mindelay", {.num = 0}},
87     {CONF_VAR_END}
88 };
89
90 #define UFD_SOCK 0
91 #define UFD_PIPE 1
92 #define UFD_LISTEN 2
93
94 struct scons {
95     struct scons *n, *p;
96     struct socket *s;
97 };
98
99 struct ufd {
100     struct ufd *next, *prev;
101     int fd;
102     int type;
103     int ignread;
104     struct socket *sk;
105     union {
106         struct {
107             int family;
108             int type;
109             struct sockaddr *remote;
110             socklen_t remotelen;
111             struct {
112                 uid_t uid;
113                 gid_t gid;
114             } ucred;
115         } s;
116         struct {
117             struct lport *lp;
118             int family;
119         } l;
120     } d;
121 };
122
123 static struct ufd *ufds = NULL;
124 static struct scons *rbatch, *wbatch, *cbatch;
125 int numsocks = 0;
126
127 /* XXX: Get autoconf for all this... */
128 int getpublicaddr(int af, struct sockaddr **addr, socklen_t *lenbuf)
129 {
130     struct sockaddr_in *ipv4;
131     struct configvar *var;
132     void *bufend;
133     int sock;
134     struct ifconf conf;
135     struct ifreq *ifr, req;
136     char *pif;
137     
138     if(af == AF_INET)
139     {
140         var = confgetvar("net", "visibleipv4");
141         if(var->val.ipv4.s_addr != 0)
142         {
143             ipv4 = smalloc(sizeof(*ipv4));
144             ipv4->sin_family = AF_INET;
145             ipv4->sin_addr.s_addr = var->val.ipv4.s_addr;
146             *addr = (struct sockaddr *)ipv4;
147             *lenbuf = sizeof(*ipv4);
148             return(0);
149         }
150         if((pif = icswcstombs(confgetstr("net", "publicif"), NULL, NULL)) == NULL)
151         {
152             flog(LOG_ERR, "could not convert net.publicif into local charset: %s", strerror(errno));
153             return(-1);
154         }
155         if(!strcmp(pif, ""))
156             return(1);
157         if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
158             return(-1);
159         conf.ifc_buf = smalloc(conf.ifc_len = 65536);
160         if(ioctl(sock, SIOCGIFCONF, &conf) < 0)
161         {
162             free(conf.ifc_buf);
163             close(sock);
164             return(-1);
165         }
166         bufend = ((char *)conf.ifc_buf) + conf.ifc_len;
167         ipv4 = NULL;
168         for(ifr = conf.ifc_ifcu.ifcu_req; (void *)ifr < bufend; ifr++)
169         {
170             if(strcmp(ifr->ifr_name, pif))
171                 continue;
172             memset(&req, 0, sizeof(req));
173             memcpy(req.ifr_name, ifr->ifr_name, sizeof(ifr->ifr_name));
174             if(ioctl(sock, SIOCGIFFLAGS, &req) < 0)
175                 break;
176             if(!(req.ifr_flags & IFF_UP))
177             {
178                 flog(LOG_WARNING, "public interface is down");
179                 break;
180             }
181             if(ifr->ifr_addr.sa_family != AF_INET)
182             {
183                 flog(LOG_WARNING, "address of the public interface is not AF_INET");
184                 break;
185             }
186             ipv4 = smalloc(sizeof(*ipv4));
187             memcpy(ipv4, &ifr->ifr_addr, sizeof(ifr->ifr_addr));
188             break;
189         }
190         free(conf.ifc_buf);
191         close(sock);
192         if(ipv4 != NULL)
193         {
194             *addr = (struct sockaddr *)ipv4;
195             *lenbuf = sizeof(*ipv4);
196             return(0);
197         }
198         errno = ENETDOWN;
199         return(-1);
200     }
201     return(1);
202 }
203
204 static struct socket *newsock1(int dgram)
205 {
206     struct socket *new;
207     
208     new = memset(smalloc(sizeof(*new)), 0, sizeof(*new));
209     new->refcount = 1;
210     new->state = -1;
211     new->dgram = dgram;
212     numsocks++;
213     return(new);
214 }
215
216 static struct socket *sockpair(int dgram)
217 {
218     struct socket *s1, *s2;
219     
220     s1 = newsock1(dgram);
221     s2 = newsock1(dgram);
222     s1->back = s2;
223     s2->back = s1;
224     putsock(s2);
225     return(s1);
226 }
227
228 static void sksetstate(struct socket *sk, int state)
229 {
230     sk->state = state;
231     sk->back->state = state;
232 }
233
234 static void closeufd(struct ufd *ufd)
235 {
236     if(ufd->fd != -1)
237         close(ufd->fd);
238     ufd->fd = -1;
239 }
240
241 static void freeufd(struct ufd *ufd)
242 {
243     if(ufd->next != NULL)
244         ufd->next->prev = ufd->prev;
245     if(ufd->prev != NULL)
246         ufd->prev->next = ufd->next;
247     if(ufd == ufds)
248         ufds = ufd->next;
249     closeufd(ufd);
250     putsock(ufd->sk);
251     if(ufd->type == UFD_SOCK) {
252         if(ufd->d.s.remote != NULL)
253             free(ufd->d.s.remote);
254     }
255     free(ufd);
256 }
257
258 static struct ufd *mkufd(int fd, int type, struct socket *sk)
259 {
260     struct ufd *ufd;
261     
262     ufd = memset(smalloc(sizeof(*ufd)), 0, sizeof(*ufd));
263     ufd->fd = fd;
264     if(sk != NULL) {
265         getsock(ufd->sk = sk);
266         sk->ufd = ufd;
267     }
268     if(type == UFD_SOCK) {
269         ufd->d.s.ucred.uid = -1;
270         ufd->d.s.ucred.gid = -1;
271     }
272     ufd->next = ufds;
273     if(ufds)
274         ufds->prev = ufd;
275     ufds = ufd;
276     return(ufd);
277 }
278
279 static struct ufd *dupufd(struct ufd *ufd)
280 {
281     struct ufd *nufd;
282     struct socket *nsk;
283     
284     if(ufd->sk != NULL)
285         nsk = sockpair(ufd->sk->dgram);
286     else
287         nsk = NULL;
288     nufd = mkufd(ufd->fd, ufd->type, nsk);
289     if(nsk != NULL)
290         putsock(nsk);
291     if((nufd->fd = dup(ufd->fd)) < 0)
292     {
293         flog(LOG_WARNING, "could not dup() fd: %s", strerror(errno));
294         freeufd(nufd);
295         return(NULL);
296     }
297     if(ufd->type == UFD_SOCK) {
298         nufd->d.s.family = ufd->d.s.family;
299         nufd->d.s.type = ufd->d.s.type;
300         nufd->d.s.ucred.uid = ufd->d.s.ucred.uid;
301         nufd->d.s.ucred.gid = ufd->d.s.ucred.gid;
302         if(ufd->d.s.remote != NULL)
303             nufd->d.s.remote = memcpy(smalloc(ufd->d.s.remotelen), ufd->d.s.remote, nufd->d.s.remotelen = ufd->d.s.remotelen);
304     } else if(ufd->type == UFD_LISTEN) {
305         nufd->d.l.family = ufd->d.l.family;
306     }
307     return(nufd);
308 }
309
310 static struct socket *mksock(int domain, int type)
311 {
312     int fd;
313     struct socket *sk;
314     struct ufd *ufd;
315     
316     if((fd = socket(domain, type, 0)) < 0)
317     {
318         flog(LOG_CRIT, "could not create socket: %s", strerror(errno));
319         return(NULL);
320     }
321     sk = sockpair(type == SOCK_DGRAM);
322     ufd = mkufd(fd, UFD_SOCK, sk);
323     ufd->d.s.family = domain;
324     ufd->d.s.type = type;
325     fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
326     return(sk);
327 }
328
329 struct socket *wrapsock(int fd)
330 {
331     struct socket *sk;
332     struct ufd *ufd;
333     
334     sk = sockpair(0);
335     ufd = mkufd(fd, UFD_PIPE, sk->back);
336     sksetstate(sk, SOCK_EST);
337     fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
338     return(sk);
339 }
340
341 void getsock(struct socket *sk)
342 {
343     sk->refcount++;
344 }
345
346 static void freesock(struct socket *sk)
347 {
348     struct dgrambuf *buf;
349     
350     if(sk->dgram) {
351         while((buf = sk->buf.d.f) != NULL) {
352             sk->buf.d.f = buf->next;
353             freedgbuf(buf);
354         }
355     } else {
356         if(sk->buf.s.buf != NULL)
357             free(sk->buf.s.buf);
358     }
359     free(sk);
360     numsocks--;
361 }
362
363 void putsock(struct socket *sk)
364 {
365     if(--(sk->refcount) < 0) {
366         flog(LOG_CRIT, "BUG: socket refcount < 0");
367         abort();
368     }
369     if((sk->refcount == 0) && (sk->back->refcount == 0)) {
370         freesock(sk);
371         freesock(sk->back);
372     }
373 }
374
375 static void linksock(struct scons **list, struct socket *sk)
376 {
377     struct scons *sc;
378     
379     for(sc = *list; sc != NULL; sc = sc->n) {
380         if(sc->s == sk)
381             return;
382     }
383     sc = smalloc(sizeof(*sc));
384     getsock(sc->s = sk);
385     sc->n = *list;
386     sc->p = NULL;
387     if(*list)
388         (*list)->p = sc;
389     *list = sc;
390 }
391
392 void sockpushdata(struct socket *sk, void *buf, size_t size)
393 {
394     if(size == 0)
395         return;
396     if(sk->dgram) {
397         /* XXX */
398     } else {
399         sizebuf(&sk->buf.s.buf, &sk->buf.s.bufsize, sk->buf.s.datasize + size, 1, 1);
400         memmove(sk->buf.s.buf + size, sk->buf.s.buf, sk->buf.s.datasize);
401         memcpy(sk->buf.s.buf, buf, size);
402         sk->buf.s.datasize += size;
403         linksock(&rbatch, sk);
404     }
405 }
406
407 /* Read as the preterite of `read' */
408 void sockread(struct socket *sk)
409 {
410     linksock(&wbatch, sk->back);
411 }
412
413 void freedgbuf(struct dgrambuf *dg)
414 {
415     if(dg->data != NULL)
416         free(dg->data);
417     if(dg->addr != NULL)
418         free(dg->addr);
419     free(dg);
420 }
421
422 struct dgrambuf *sockgetdgbuf(struct socket *sk)
423 {
424     struct dgrambuf *dbuf;
425     
426     if((dbuf = sk->buf.d.f) == NULL)
427         return(NULL);
428     sk->buf.d.f = dbuf->next;
429     if(dbuf->next == NULL)
430         sk->buf.d.l = NULL;
431     dbuf->next = NULL;
432     sockread(sk);
433     return(dbuf);
434 }
435
436 void *sockgetinbuf(struct socket *sk, size_t *size)
437 {
438     void *buf;
439     struct dgrambuf *dbuf;
440     
441     if(sk->dgram) {
442         dbuf = sockgetdgbuf(sk);
443         buf = dbuf->data;
444         *size = dbuf->size;
445         free(dbuf->addr);
446         free(dbuf);
447     } else {
448         if((sk->buf.s.buf == NULL) || (sk->buf.s.datasize == 0))
449         {
450             *size = 0;
451             return(NULL);
452         }
453         buf = sk->buf.s.buf;
454         *size = sk->buf.s.datasize;
455         sk->buf.s.buf = NULL;
456         sk->buf.s.bufsize = sk->buf.s.datasize = 0;
457         sockread(sk);
458     }
459     return(buf);
460 }
461
462 void sockqueue(struct socket *sk, void *data, size_t size)
463 {
464     struct dgrambuf *new;
465     struct sockaddr *remote;
466     socklen_t remotelen;
467     
468     if(size == 0)
469         return;
470     if(sk->state == SOCK_STL)
471         return;
472     if(sk->dgram) {
473         if(sockpeeraddr(sk, &remote, &remotelen))
474             return;
475         new = smalloc(sizeof(*new));
476         new->next = NULL;
477         memcpy(new->data = smalloc(size), data, new->size = size);
478         new->addr = remote;
479         new->addrlen = remotelen;
480         if(sk->back->buf.d.l == NULL)
481         {
482             sk->back->buf.d.l = sk->back->buf.d.f = new;
483         } else {
484             sk->back->buf.d.l->next = new;
485             sk->back->buf.d.l = new;
486         }
487     } else {
488         sizebuf(&(sk->back->buf.s.buf), &(sk->back->buf.s.bufsize), sk->back->buf.s.datasize + size, 1, 1);
489         memcpy(sk->back->buf.s.buf + sk->back->buf.s.datasize, data, size);
490         sk->back->buf.s.datasize += size;
491     }
492     linksock(&rbatch, sk->back);
493 }
494
495 void sockqueuedg(struct socket *sk, struct dgrambuf *dg)
496 {
497     if(sk->state == SOCK_STL) {
498         freedgbuf(dg);
499         return;
500     }
501     if(!sk->dgram) {
502         flog(LOG_ERR, "BUG: sockqueuedg called on non-dgram socket");
503         freedgbuf(dg);
504         return;
505     }
506     dg->next = NULL;
507     if(sk->back->buf.d.l == NULL)
508     {
509         sk->back->buf.d.l = sk->back->buf.d.f = dg;
510     } else {
511         sk->back->buf.d.l->next = dg;
512         sk->back->buf.d.l = dg;
513     }
514     linksock(&rbatch, sk->back);
515 }
516
517 void sockeos(struct socket *sk)
518 {
519     sksetstate(sk, SOCK_STL);
520     if(sk->back->eos == 0)
521         sk->back->eos = 1;
522     linksock(&rbatch, sk->back);
523 }
524
525 static void sockerror(struct socket *sk, int en)
526 {
527     sksetstate(sk, SOCK_STL);
528     if(sk->back->errcb != NULL)
529         sk->back->errcb(sk->back, en, sk->back->data);
530 }
531
532 static void recvcmsg(struct ufd *ufd, struct msghdr *msg)
533 {
534     struct cmsghdr *cmsg;
535     
536     for(cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg))
537     {
538 #if UNIX_AUTH_STYLE == 1
539         if((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SCM_CREDENTIALS))
540         {
541             struct ucred *cred;
542             if(ufd->d.s.ucred.uid == -1)
543             {
544                 cred = (struct ucred *)CMSG_DATA(cmsg);
545                 ufd->d.s.ucred.uid = cred->uid;
546                 ufd->d.s.ucred.gid = cred->gid;
547             }
548         }
549 #endif
550     }
551 }
552
553 static int ufddgram(struct ufd *ufd)
554 {
555     int dgram;
556
557     if(ufd->type == UFD_SOCK) {
558         dgram = ufd->d.s.type == SOCK_DGRAM;
559     } else if(ufd->type == UFD_PIPE) {
560         dgram = 0;
561     } else {
562         flog(LOG_ERR, "BUG: calling ufddgram on ufd of bad type %i", ufd->type);
563         return(-1);
564     }
565     if(ufd->sk == NULL) {
566         flog(LOG_ERR, "BUG: calling ufddgram on socketless ufd (type %i)", ufd->type);
567         return(-1);
568     }
569     if(dgram != ufd->sk->dgram) {
570         flog(LOG_ERR, "BUG: ufd/socket dgram value mismatch");
571         return(-1);
572     }
573     return(dgram);
574 }
575
576 static void sockrecv(struct ufd *ufd)
577 {
578     int ret, inq;
579     int dgram;
580     struct dgrambuf *dbuf;
581     struct msghdr msg;
582     char cbuf[65536];
583     struct iovec bufvec;
584     void *buf;
585     
586     memset(&msg, 0, sizeof(msg));
587     msg.msg_iov = &bufvec;
588     msg.msg_iovlen = 1;
589     msg.msg_control = cbuf;
590     msg.msg_controllen = sizeof(cbuf);
591     if((dgram = ufddgram(ufd)) < 0)
592         return;
593     if(dgram) {
594 #if defined(HAVE_LINUX_SOCKIOS_H) && defined(SIOCINQ)
595         if(ioctl(ufd->fd, SIOCINQ, &inq))
596         {
597             /* I don't really know what could go wrong here, so let's
598              * assume it's transient. */
599             flog(LOG_WARNING, "SIOCINQ return %s on socket %i", strerror(errno), ufd->fd);
600             return;
601         }
602 #else
603         inq = 65536;
604 #endif
605         dbuf = smalloc(sizeof(*dbuf));
606         dbuf->data = smalloc(inq);
607         dbuf->addr = smalloc(dbuf->addrlen = sizeof(struct sockaddr_storage));
608         msg.msg_name = dbuf->addr;
609         msg.msg_namelen = dbuf->addrlen;
610         bufvec.iov_base = dbuf->data;
611         bufvec.iov_len = inq;
612         ret = recvmsg(ufd->fd, &msg, 0);
613         dbuf->addrlen = msg.msg_namelen;
614         if(ret < 0)
615         {
616             freedgbuf(dbuf);
617             if((errno == EINTR) || (errno == EAGAIN))
618                 return;
619             closeufd(ufd);
620             sockerror(ufd->sk, errno);
621             return;
622         }
623         if(msg.msg_flags & MSG_CTRUNC)
624             flog(LOG_DEBUG, "ancillary data was truncated");
625         else
626             recvcmsg(ufd, &msg);
627         /* On UDP/IPv[46], ret == 0 doesn't mean EOF (since UDP can't
628          * have EOF), but rather an empty packet. I don't know if any
629          * other potential DGRAM protocols might have an EOF
630          * condition, so let's play safe. */
631         if(ret == 0)
632         {
633             freedgbuf(dbuf);
634             if((ufd->type != UFD_SOCK) || !((ufd->d.s.family == AF_INET) || (ufd->d.s.family == AF_INET6)))
635             {
636                 sockeos(ufd->sk);
637                 closeufd(ufd);
638             }
639             return;
640         }
641         dbuf->addr = srealloc(dbuf->addr, dbuf->addrlen);
642         dbuf->data = srealloc(dbuf->data, dbuf->size = ret);
643         dbuf->next = NULL;
644         sockqueuedg(ufd->sk, dbuf);
645     } else {
646 #if defined(HAVE_LINUX_SOCKIOS_H) && defined(SIOCINQ)
647         /* SIOCINQ is Linux-specific AFAIK, but I really have no idea
648          * how to read the inqueue size on other OSs */
649         if(ufd->type == UFD_SOCK) {
650             if(ioctl(ufd->fd, SIOCINQ, &inq))
651             {
652                 /* I don't really know what could go wrong here, so let's
653                  * assume it's transient. */
654                 flog(LOG_WARNING, "SIOCINQ return %s on socket %i, falling back to 2048 bytes", strerror(errno), ufd->fd);
655                 inq = 2048;
656             }
657         } else {
658             /* There are perils when trying to use SIOCINQ on files >2GiB... */
659             inq = 65536;
660         }
661 #else
662         inq = 2048;
663 #endif
664         if(inq > 65536)
665             inq = 65536;
666         /* This part could be optimized by telling the kernel to read
667          * directly into ufd->sk->back->buf, but that would be uglier
668          * by not using the socket function interface. */
669         buf = smalloc(inq);
670         if(ufd->type == UFD_SOCK)
671         {
672             bufvec.iov_base = buf;
673             bufvec.iov_len = inq;
674             ret = recvmsg(ufd->fd, &msg, 0);
675         } else {
676             ret = read(ufd->fd, buf, inq);
677             msg.msg_controllen = 0;
678             msg.msg_flags = 0;
679         }
680         if(ret < 0)
681         {
682             free(buf);
683             if((errno == EINTR) || (errno == EAGAIN))
684                 return;
685             closeufd(ufd);
686             sockerror(ufd->sk, errno);
687             return;
688         }
689         if(msg.msg_flags & MSG_CTRUNC)
690             flog(LOG_DEBUG, "ancillary data was truncated");
691         else
692             recvcmsg(ufd, &msg);
693         if(ret == 0)
694         {
695             free(buf);
696             closeufd(ufd);
697             sockeos(ufd->sk);
698             return;
699         }
700         sockqueue(ufd->sk, buf, ret);
701         free(buf);
702     }
703 }
704
705 static void sockflush(struct ufd *ufd)
706 {
707     int ret;
708     struct dgrambuf *dbuf;
709     int dgram;
710     
711     if((dgram = ufddgram(ufd)) < 0)
712         return;
713     if(dgram) {
714         dbuf = sockgetdgbuf(ufd->sk);
715         sendto(ufd->fd, dbuf->data, dbuf->size, MSG_DONTWAIT | MSG_NOSIGNAL, dbuf->addr, dbuf->addrlen);
716         freedgbuf(dbuf);
717     } else {
718         if(ufd->type == UFD_SOCK)
719             ret = send(ufd->fd, ufd->sk->buf.s.buf, ufd->sk->buf.s.datasize, MSG_DONTWAIT | MSG_NOSIGNAL);
720         else
721             ret = write(ufd->fd, ufd->sk->buf.s.buf, ufd->sk->buf.s.datasize);
722         if(ret < 0) {
723             /* For now, assume transient error, since
724              * the socket is polled for errors */
725             return;
726         }
727         if(ret > 0) {
728             memmove(ufd->sk->buf.s.buf, ((char *)ufd->sk->buf.s.buf) + ret, ufd->sk->buf.s.datasize -= ret);
729             sockread(ufd->sk);
730         }
731     }
732 }
733
734 void closesock(struct socket *sk)
735 {
736 /*
737     struct sockaddr_un *un;
738     
739     if((sk->family == AF_UNIX) && !sockgetlocalname(sk, (struct sockaddr **)(void *)&un, NULL) && (un->sun_family == PF_UNIX))
740     {
741         if((sk->state == SOCK_LST) && strchr(un->sun_path, '/'))
742         {
743             if(unlink(un->sun_path))
744                 flog(LOG_WARNING, "could not unlink Unix socket %s: %s", un->sun_path, strerror(errno));
745         }
746     }
747 */
748     sksetstate(sk, SOCK_STL);
749     sockeos(sk);
750 }
751
752 size_t sockgetdatalen(struct socket *sk)
753 {
754     struct dgrambuf *b;
755     size_t ret;
756     
757     if(sk->dgram) {
758         ret = 0;
759         for(b = sk->buf.d.f; b != NULL; b = b->next)
760             ret += b->size;
761     } else {
762         ret = sk->buf.s.datasize;
763     }
764     return(ret);
765 }
766
767 size_t sockqueuesize(struct socket *sk)
768 {
769     return(sockgetdatalen(sk->back));
770 }
771
772 /*
773  * Seriously, I don't know if it's naughty or not to remove
774  * pre-existing Unix sockets.
775  */
776 static int rebindunix(struct ufd *ufd, struct sockaddr *name, socklen_t namelen)
777 {
778     struct sockaddr_un *un;
779     struct stat sb;
780     
781     if((ufd->d.l.family != AF_UNIX) || (name->sa_family != PF_UNIX))
782         return(-1);
783     un = (struct sockaddr_un *)name;
784     if(stat(un->sun_path, &sb))
785         return(-1);
786     if(!S_ISSOCK(sb.st_mode))
787         return(-1);
788     if(unlink(un->sun_path))
789         return(-1);
790     if(bind(ufd->fd, name, namelen) < 0)
791         return(-1);
792     return(0);
793 }
794
795 /*
796  * The difference between netcslisten() and netcslistenlocal() is that
797  * netcslistenlocal() always listens on the local host, instead of
798  * following proxy/passive mode directions. It is suitable for eg. the
799  * UI channel, while the file sharing networks should, naturally, use
800  * netcslisten() instead.
801 */
802
803 struct lport *netcslistenlocal(int type, struct sockaddr *name, socklen_t namelen, void (*func)(struct lport *, struct socket *, void *), void *data)
804 {
805     struct lport *lp;
806     struct ufd *ufd;
807     int fd;
808     int intbuf;
809     
810     /* I don't know if this is actually correct (it probably isn't),
811      * but since, at on least Linux systems, PF_* are specifically
812      * #define'd to their AF_* counterparts, it allows for a severely
813      * smoother implementation. If it breaks something on your
814      * platform, please tell me so.
815      */
816     if((fd = socket(name->sa_family, type, 0)) < 0)
817         return(NULL);
818     if(confgetint("net", "reuseaddr")) {
819         intbuf = 1;
820         setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &intbuf, sizeof(intbuf));
821     }
822     ufd = mkufd(fd, UFD_LISTEN, NULL);
823     ufd->d.l.lp = lp;
824     ufd->d.l.family = name->sa_family;
825     if((bind(fd, name, namelen) < 0) && ((errno != EADDRINUSE) || (rebindunix(ufd, name, namelen) < 0))) {
826         freeufd(ufd);
827         return(NULL);
828     }
829     if(listen(fd, 16) < 0)
830     {
831         freeufd(ufd);
832         return(NULL);
833     }
834     lp->acceptcb = func;
835     lp->data = data;
836     return(lp);
837 }
838
839 struct lport *netcslisten(int type, struct sockaddr *name, socklen_t namelen, void (*func)(struct lport *, struct socket *, void *), void *data)
840 {
841     if(confgetint("net", "mode") == 1)
842     {
843         errno = EOPNOTSUPP;
844         return(NULL);
845     }
846     if(confgetint("net", "mode") == 0)
847         return(netcslistenlocal(type, name, namelen, func, data));
848     errno = EOPNOTSUPP;
849     return(NULL);
850 }
851
852 struct lport *netcstcplisten(int port, int local, void (*func)(struct lport *, struct socket *, void *), void *data)
853 {
854     struct sockaddr_in addr;
855 #ifdef HAVE_IPV6
856     struct sockaddr_in6 addr6;
857 #endif
858     struct lport *(*csfunc)(int, struct sockaddr *, socklen_t, void (*)(struct lport *, struct socket *, void *), void *);
859     struct lport *ret;
860     
861     if(local)
862         csfunc = netcslistenlocal;
863     else
864         csfunc = netcslisten;
865 #ifdef HAVE_IPV6
866     memset(&addr6, 0, sizeof(addr6));
867     addr6.sin6_family = AF_INET6;
868     addr6.sin6_port = htons(port);
869     addr6.sin6_addr = in6addr_any;
870     if((ret = csfunc(SOCK_STREAM, (struct sockaddr *)&addr6, sizeof(addr6), func, data)) != NULL)
871         return(ret);
872     if((ret == NULL) && (errno != EAFNOSUPPORT))
873         return(NULL);
874 #endif
875     memset(&addr, 0, sizeof(addr));
876     addr.sin_family = AF_INET;
877     addr.sin_port = htons(port);
878     return(csfunc(SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr), func, data));
879 }
880
881 struct socket *netcsdgram(struct sockaddr *name, socklen_t namelen)
882 {
883     struct socket *sk;
884     int mode;
885     
886     mode = confgetint("net", "mode");
887     if((mode == 0) || (mode == 1))
888     {
889         if((sk = mksock(name->sa_family, SOCK_DGRAM)) == NULL)
890             return(NULL);
891         if(bind(sk->ufd->fd, name, namelen) < 0)
892         {
893             putsock(sk);
894             return(NULL);
895         }
896         sksetstate(sk, SOCK_EST);
897         return(sk->back);
898     }
899     errno = EOPNOTSUPP;
900     return(NULL);
901 }
902
903 struct socket *netdgramconn(struct socket *sk, struct sockaddr *addr, socklen_t addrlen)
904 {
905     struct ufd *nufd;
906     
907     nufd = dupufd(sk->back->ufd);
908     sk = nufd->sk->back;
909     memcpy(nufd->d.s.remote = smalloc(addrlen), addr, nufd->d.s.remotelen = addrlen);
910     nufd->ignread = 1;
911     return(sk);
912 }
913
914 struct socket *netcsconn(struct sockaddr *addr, socklen_t addrlen, void (*func)(struct socket *, int, void *), void *data)
915 {
916     struct socket *sk;
917     int mode;
918     
919     mode = confgetint("net", "mode");
920     if((mode == 0) || (mode == 1))
921     {
922         if((sk = mksock(addr->sa_family, SOCK_STREAM)) == NULL)
923             return(NULL);
924         memcpy(sk->ufd->d.s.remote = smalloc(addrlen), addr, sk->ufd->d.s.remotelen = addrlen);
925         sk->back->conncb = func;
926         sk->back->data = data;
927         if(!connect(sk->ufd->fd, addr, addrlen))
928         {
929             sksetstate(sk, SOCK_EST);
930             linksock(&cbatch, sk->back);
931             return(sk->back);
932         }
933         if(errno == EINPROGRESS)
934         {
935             sksetstate(sk, SOCK_SYN);
936             return(sk->back);
937         }
938         putsock(sk);
939         return(NULL);
940     }
941     errno = EOPNOTSUPP;
942     return(NULL);
943 }
944
945 static void acceptunix(struct ufd *ufd)
946 {
947     int buf;
948     
949     buf = 1;
950 #if UNIX_AUTH_STYLE == 1
951     if(setsockopt(ufd->fd, SOL_SOCKET, SO_PASSCRED, &buf, sizeof(buf)) < 0)
952         flog(LOG_WARNING, "could not enable SO_PASSCRED on Unix socket %i: %s", ufd->fd, strerror(errno));
953 #elif UNIX_AUTH_STYLE == 2
954     if(getpeereid(ufd->fd, &ufd->d.s.ucred.uid, &ufd->d.s.ucred.gid) < 0)
955     {
956         flog(LOG_WARNING, "could not get peer creds on Unix socket %i: %s", ufd->fd, strerror(errno));
957         ufd->d.s.ucred.uid = -1;
958         ufd->d.s.ucred.gid = -1;
959     }
960 #endif
961 }
962
963 int pollsocks(int timeout)
964 {
965     int ret;
966     socklen_t retlen;
967     int newfd, maxfd;
968     fd_set rfds, wfds, efds;
969     struct ufd *ufd, *nufd, *next;
970     struct socket *nsk;
971     struct sockaddr_storage ss;
972     socklen_t sslen;
973     struct timeval tv;
974     struct scons *sc, *nsc;
975     
976     FD_ZERO(&rfds);
977     FD_ZERO(&wfds);
978     FD_ZERO(&efds);
979     for(maxfd = 0, ufd = ufds; ufd != NULL; ufd = ufd->next) {
980         if(ufd->fd < 0)
981             continue;
982         if(!ufd->ignread)
983             FD_SET(ufd->fd, &rfds);
984         if(ufd->sk != NULL) {
985             if(sockgetdatalen(ufd->sk) > 0)
986                 FD_SET(ufd->fd, &wfds);
987             else if(ufd->sk->state == SOCK_SYN)
988                 FD_SET(ufd->fd, &wfds);
989         }
990         FD_SET(ufd->fd, &efds);
991         if(ufd->fd > maxfd)
992             maxfd = ufd->fd;
993     }
994     tv.tv_sec = timeout / 1000;
995     tv.tv_usec = (timeout % 1000) * 1000;
996     ret = select(maxfd + 1, &rfds, &wfds, &efds, (timeout < 0)?NULL:&tv);
997     if(ret < 0) {
998         if(errno != EINTR) {
999             flog(LOG_CRIT, "pollsocks: select errored out: %s", strerror(errno));
1000             /* To avoid CPU hogging in case it's bad, which it
1001              * probably is. */
1002             sleep(1);
1003         }
1004         return(1);
1005     }
1006     for(ufd = ufds; ufd != NULL; ufd = ufd->next)
1007     {
1008         if(ufd->sk < 0)
1009             continue;
1010         if(ufd->type == UFD_LISTEN) {
1011             if(FD_ISSET(ufd->fd, &rfds)) {
1012                 sslen = sizeof(ss);
1013                 if((newfd = accept(ufd->fd, (struct sockaddr *)&ss, &sslen)) < 0) {
1014                     if(ufd->d.l.lp->errcb != NULL)
1015                         ufd->d.l.lp->errcb(ufd->d.l.lp, errno, ufd->d.l.lp->data);
1016                 }
1017                 nsk = sockpair(0);
1018                 nufd = mkufd(newfd, UFD_SOCK, nsk);
1019                 nufd->d.s.family = ufd->d.l.family;
1020                 sksetstate(nsk, SOCK_EST);
1021                 memcpy(nufd->d.s.remote = smalloc(sslen), &ss, sslen);
1022                 nufd->d.s.remotelen = sslen;
1023                 if(ss.ss_family == PF_UNIX)
1024                     acceptunix(nufd);
1025                 if(ufd->d.l.lp->acceptcb != NULL)
1026                     ufd->d.l.lp->acceptcb(ufd->d.l.lp, nsk, ufd->d.l.lp->data);
1027                 putsock(nsk);
1028             }
1029             if(FD_ISSET(ufd->fd, &efds)) {
1030                 retlen = sizeof(ret);
1031                 getsockopt(ufd->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
1032                 if(ufd->d.l.lp->errcb != NULL)
1033                     ufd->d.l.lp->errcb(ufd->d.l.lp, ret, ufd->d.l.lp->data);
1034                 continue;
1035             }
1036         } else {
1037             if(ufd->sk->state == SOCK_SYN) {
1038                 if(FD_ISSET(ufd->fd, &efds)) {
1039                     retlen = sizeof(ret);
1040                     getsockopt(ufd->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
1041                     if(ufd->sk->back->conncb != NULL)
1042                         ufd->sk->back->conncb(ufd->sk->back, ret, ufd->sk->back->data);
1043                     closeufd(ufd);
1044                     continue;
1045                 }
1046                 if(FD_ISSET(ufd->fd, &rfds) || FD_ISSET(ufd->fd, &wfds)) {
1047                     sksetstate(ufd->sk, SOCK_EST);
1048                     linksock(&cbatch, ufd->sk->back);
1049                 }
1050             } else if(ufd->sk->state == SOCK_EST) {
1051                 if(FD_ISSET(ufd->fd, &efds)) {
1052                     retlen = sizeof(ret);
1053                     getsockopt(ufd->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
1054                     sockerror(ufd->sk, ret);
1055                     closeufd(ufd);
1056                     continue;
1057                 }
1058                 if(FD_ISSET(ufd->fd, &rfds))
1059                     sockrecv(ufd);
1060                 if(FD_ISSET(ufd->fd, &wfds))
1061                     sockflush(ufd);
1062             }
1063         }
1064     }
1065     for(ufd = ufds; ufd != NULL; ufd = next)
1066     {
1067         next = ufd->next;
1068         if(sockgetdatalen(ufd->sk) == 0) {
1069             if(ufd->sk->eos) {
1070                 closeufd(ufd);
1071                 closesock(ufd->sk);
1072             }
1073             if((ufd->sk->refcount == 1) && (ufd->sk->back->refcount == 0)) {
1074                 freeufd(ufd);
1075                 continue;
1076             }
1077         }
1078     }
1079     return(1);
1080 }
1081
1082 int socksettos(struct socket *sk, int tos)
1083 {
1084     int buf;
1085     
1086     if(sk->family == AF_UNIX)
1087         return(0); /* Unix sockets are always perfect. :) */
1088     if(sk->family == AF_INET)
1089     {
1090         switch(tos)
1091         {
1092         case 0:
1093             buf = 0;
1094             break;
1095         case SOCK_TOS_MINCOST:
1096             buf = 0x02;
1097             break;
1098         case SOCK_TOS_MAXREL:
1099             buf = 0x04;
1100             break;
1101         case SOCK_TOS_MAXTP:
1102             buf = 0x08;
1103             break;
1104         case SOCK_TOS_MINDELAY:
1105             buf = 0x10;
1106             break;
1107         default:
1108             flog(LOG_WARNING, "attempted to set unknown TOS value %i to IPv4 sock", tos);
1109             return(-1);
1110         }
1111         if(setsockopt(sk->fd, IPPROTO_IP, IP_TOS, &buf, sizeof(buf)) < 0)
1112         {
1113             flog(LOG_WARNING, "could not set sock TOS to %i: %s", tos, strerror(errno));
1114             return(-1);
1115         }
1116         return(0);
1117     }
1118     if(sk->family == AF_INET6)
1119     {
1120         switch(tos)
1121         {
1122         case 0:
1123             buf = 0;
1124         case SOCK_TOS_MINCOST:
1125             buf = confgetint("net", "diffserv-mincost");
1126             break;
1127         case SOCK_TOS_MAXREL:
1128             buf = confgetint("net", "diffserv-maxrel");
1129             break;
1130         case SOCK_TOS_MAXTP:
1131             buf = confgetint("net", "diffserv-maxtp");
1132             break;
1133         case SOCK_TOS_MINDELAY:
1134             buf = confgetint("net", "diffserv-mindelay");
1135             break;
1136         default:
1137             flog(LOG_WARNING, "attempted to set unknown TOS value %i to IPv4 sock", tos);
1138             return(-1);
1139         }
1140         /*
1141           On Linux, the API IPv6 flow label management doesn't seem to
1142           be entirely complete, so I guess this will have to wait.
1143           
1144         if(setsockopt(...) < 0)
1145         {
1146             flog(LOG_WARNING, "could not set sock traffic class to %i: %s", tos, strerror(errno));
1147             return(-1);
1148         }
1149         */
1150         return(0);
1151     }
1152     flog(LOG_WARNING, "could not set TOS on sock of family %i", sk->family);
1153     return(1);
1154 }
1155
1156 struct resolvedata
1157 {
1158     int fd;
1159     void (*callback)(struct sockaddr *addr, int addrlen, void *data);
1160     void *data;
1161     struct sockaddr_storage addr;
1162     int addrlen;
1163 };
1164
1165 static void resolvecb(pid_t pid, int status, struct resolvedata *data)
1166 {
1167     static char buf[80];
1168     int ret;
1169     struct sockaddr_in *ipv4;
1170     
1171     if(!status)
1172     {
1173         if((ret = read(data->fd, buf, sizeof(buf))) != 4)
1174         {
1175             errno = ENOENT;
1176             data->callback(NULL, 0, data->data);
1177         } else {
1178             ipv4 = (struct sockaddr_in *)&data->addr;
1179             memcpy(&ipv4->sin_addr, buf, 4);
1180             data->callback((struct sockaddr *)ipv4, sizeof(*ipv4), data->data);
1181         }
1182     } else {
1183         errno = ENOENT;
1184         data->callback(NULL, 0, data->data);
1185     }
1186     close(data->fd);
1187     free(data);
1188 }
1189
1190 int netresolve(char *addr, void (*callback)(struct sockaddr *addr, int addrlen, void *data), void *data)
1191 {
1192     int i;
1193     char *p;
1194     int port;
1195     int pfd[2];
1196     pid_t child;
1197     struct resolvedata *rdata;
1198     struct sockaddr_in ipv4;
1199     struct hostent *he;
1200     sigset_t sigset;
1201     
1202     /* IPv4 */
1203     port = -1;
1204     if((p = strchr(addr, ':')) != NULL)
1205     {
1206         *p = 0;
1207         port = atoi(p + 1);
1208     }
1209     ipv4.sin_family = AF_INET;
1210     ipv4.sin_port = htons(port);
1211     if(inet_aton(addr, &ipv4.sin_addr))
1212     {
1213         callback((struct sockaddr *)&ipv4, sizeof(ipv4), data);
1214     } else {
1215         sigemptyset(&sigset);
1216         sigaddset(&sigset, SIGCHLD);
1217         sigprocmask(SIG_BLOCK, &sigset, NULL);
1218         if((pipe(pfd) < 0) || ((child = fork()) < 0))
1219         {
1220             sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1221             return(-1);
1222         }
1223         if(child == 0)
1224         {
1225             sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1226             for(i = 3; i < FD_SETSIZE; i++)
1227             {
1228                 if(i != pfd[1])
1229                     close(i);
1230             }
1231             signal(SIGALRM, SIG_DFL);
1232             alarm(30);
1233             if((he = gethostbyname(addr)) == NULL)
1234                 exit(1);
1235             write(pfd[1], he->h_addr_list[0], 4);
1236             exit(0);
1237         } else {
1238             close(pfd[1]);
1239             fcntl(pfd[0], F_SETFL, fcntl(pfd[0], F_GETFL) | O_NONBLOCK);
1240             rdata = smalloc(sizeof(*rdata));
1241             rdata->fd = pfd[0];
1242             rdata->callback = callback;
1243             rdata->data = data;
1244             memcpy(&rdata->addr, &ipv4, rdata->addrlen = sizeof(ipv4));
1245             childcallback(child, (void (*)(pid_t, int, void *))resolvecb, rdata);
1246             sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1247             return(1);
1248         }
1249     }
1250     return(0);
1251 }
1252
1253 int sockgetlocalname(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf)
1254 {
1255     socklen_t len;
1256     struct sockaddr_storage name;
1257     
1258     *namebuf = NULL;
1259     if((sk->state == SOCK_STL) || (sk->fd < 0))
1260         return(-1);
1261     len = sizeof(name);
1262     if(getsockname(sk->fd, (struct sockaddr *)&name, &len) < 0)
1263     {
1264         flog(LOG_ERR, "BUG: alive socket with dead fd in sockgetlocalname (%s)", strerror(errno));
1265         return(-1);
1266     }
1267     *namebuf = memcpy(smalloc(len), &name, len);
1268     if(lenbuf != NULL)
1269         *lenbuf = len;
1270     return(0);
1271 }
1272
1273 static void sethostaddr(struct sockaddr *dst, struct sockaddr *src)
1274 {
1275     if(dst->sa_family != src->sa_family)
1276     {
1277         flog(LOG_ERR, "BUG: non-matching socket families in sethostaddr (%i -> %i)", src->sa_family, dst->sa_family);
1278         return;
1279     }
1280     switch(src->sa_family)
1281     {
1282     case AF_INET:
1283         ((struct sockaddr_in *)dst)->sin_addr = ((struct sockaddr_in *)src)->sin_addr;
1284         break;
1285     case AF_INET6:
1286         ((struct sockaddr_in6 *)dst)->sin6_addr = ((struct sockaddr_in6 *)src)->sin6_addr;
1287         break;
1288     default:
1289         flog(LOG_WARNING, "sethostaddr unimplemented for family %i", src->sa_family);
1290         break;
1291     }
1292 }
1293
1294 static int makepublic(struct sockaddr *addr)
1295 {
1296     int ret;
1297     socklen_t plen;
1298     struct sockaddr *pname;
1299     
1300     if((ret = getpublicaddr(addr->sa_family, &pname, &plen)) < 0)
1301     {
1302         flog(LOG_ERR, "could not get public address: %s", strerror(errno));
1303         return(-1);
1304     }
1305     if(ret)
1306         return(0);
1307     sethostaddr(addr, pname);
1308     free(pname);
1309     return(0);
1310 }
1311
1312 int sockgetremotename(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf)
1313 {
1314     socklen_t len;
1315     struct sockaddr *name;
1316     
1317     switch(confgetint("net", "mode"))
1318     {
1319     case 0:
1320         *namebuf = NULL;
1321         if((sk->state == SOCK_STL) || (sk->fd < 0))
1322         {
1323             errno = EBADF;
1324             return(-1);
1325         }
1326         if(!sockgetlocalname(sk, &name, &len))
1327         {
1328             *namebuf = name;
1329             *lenbuf = len;
1330             makepublic(name);
1331             return(0);
1332         }
1333         flog(LOG_ERR, "could not get remotely accessible name by any means");
1334         return(-1);
1335     case 1:
1336         errno = EOPNOTSUPP;
1337         return(-1);
1338     default:
1339         flog(LOG_CRIT, "unknown net mode %i active", confgetint("net", "mode"));
1340         errno = EOPNOTSUPP;
1341         return(-1);
1342     }
1343 }
1344
1345 int sockgetremotename2(struct socket *sk, struct socket *sk2, struct sockaddr **namebuf, socklen_t *lenbuf)
1346 {
1347     struct sockaddr *name1, *name2;
1348     socklen_t len1, len2;
1349     
1350     if(sk->family != sk2->family)
1351     {
1352         flog(LOG_ERR, "using sockgetremotename2 with sockets of differing family: %i %i", sk->family, sk2->family);
1353         return(-1);
1354     }
1355     if(sockgetremotename(sk, &name1, &len1))
1356         return(-1);
1357     if(sockgetremotename(sk2, &name2, &len2)) {
1358         free(name1);
1359         return(-1);
1360     }
1361     sethostaddr(name1, name2);
1362     free(name2);
1363     *namebuf = name1;
1364     *lenbuf = len1;
1365     return(0);
1366 }
1367
1368 void sockblock(struct socket *sk, int block)
1369 {
1370     sk->block = block;
1371 }
1372
1373 int sockpeeraddr(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf)
1374 {
1375     return(-1);
1376 }
1377
1378 char *formatsockpeer(struct socket *sk)
1379 {
1380     struct sockaddr *name;
1381     socklen_t nlen;
1382     char *ret;
1383     
1384     if(sockpeeraddr(sk, &name, &nlen))
1385         return(NULL);
1386     ret = formataddress(name, nlen);
1387     free(name);
1388     return(ret);
1389 }
1390
1391 int addreq(struct sockaddr *x, struct sockaddr *y)
1392 {
1393     struct sockaddr_un *u1, *u2;
1394     struct sockaddr_in *n1, *n2;
1395 #ifdef HAVE_IPV6
1396     struct sockaddr_in6 *s1, *s2;
1397 #endif
1398     
1399     if(x->sa_family != y->sa_family)
1400         return(0);
1401     switch(x->sa_family) {
1402     case AF_UNIX:
1403         u1 = (struct sockaddr_un *)x; u2 = (struct sockaddr_un *)y;
1404         if(strncmp(u1->sun_path, u2->sun_path, sizeof(u1->sun_path)))
1405             return(0);
1406         break;
1407     case AF_INET:
1408         n1 = (struct sockaddr_in *)x; n2 = (struct sockaddr_in *)y;
1409         if(n1->sin_port != n2->sin_port)
1410             return(0);
1411         if(n1->sin_addr.s_addr != n2->sin_addr.s_addr)
1412             return(0);
1413         break;
1414 #ifdef HAVE_IPV6
1415     case AF_INET6:
1416         s1 = (struct sockaddr_in6 *)x; s2 = (struct sockaddr_in6 *)y;
1417         if(s1->sin6_port != s2->sin6_port)
1418             return(0);
1419         if(memcmp(s1->sin6_addr.s6_addr, s2->sin6_addr.s6_addr, sizeof(s1->sin6_addr.s6_addr)))
1420             return(0);
1421         break;
1422 #endif
1423     }
1424     return(1);
1425 }
1426
1427 char *formataddress(struct sockaddr *arg, socklen_t arglen)
1428 {
1429     struct sockaddr_in *ipv4;
1430 #ifdef HAVE_IPV6
1431     struct sockaddr_in6 *ipv6;
1432 #endif
1433     static char *ret = NULL;
1434     char buf[1024];
1435     
1436     if(ret != NULL)
1437         free(ret);
1438     ret = NULL;
1439     switch(arg->sa_family)
1440     {
1441     case AF_UNIX:
1442         ret = sstrdup("Unix socket");
1443         break;
1444     case AF_INET:
1445         ipv4 = (struct sockaddr_in *)arg;
1446         if(inet_ntop(AF_INET, &ipv4->sin_addr, buf, sizeof(buf)) == NULL)
1447             return(NULL);
1448         ret = sprintf2("%s:%i", buf, (int)ntohs(ipv4->sin_port));
1449         break;
1450 #ifdef HAVE_IPV6
1451     case AF_INET6:
1452         ipv6 = (struct sockaddr_in6 *)arg;
1453         if(inet_ntop(AF_INET6, &ipv6->sin6_addr, buf, sizeof(buf)) == NULL)
1454             return(NULL);
1455         ret = sprintf2("[%s]:%i", buf, (int)ntohs(ipv6->sin6_port));
1456         break;
1457 #endif
1458     default:
1459         errno = EPFNOSUPPORT;
1460         break;
1461     }
1462     return(ret);
1463 }
1464
1465 #if 0
1466
1467 /* 
1468  * It was very nice to use this, but it seems
1469  * to mess things up, so I guess it has to go... :-(
1470  */
1471
1472 static int formataddress(FILE *stream, const struct printf_info *info, const void *const *args)
1473 {
1474     struct sockaddr *arg;
1475     socklen_t arglen;
1476     struct sockaddr_un *UNIX; /* Some wise guy has #defined unix with
1477                                * lowercase letters to 1, so I do this
1478                                * instead. */
1479     struct sockaddr_in *ipv4;
1480     int ret;
1481     
1482     arg = *(struct sockaddr **)(args[0]);
1483     arglen = *(socklen_t *)(args[1]);
1484     switch(arg->sa_family)
1485     {
1486     case AF_UNIX:
1487         UNIX = (struct sockaddr_un *)arg;
1488         ret = fprintf(stream, "%s", UNIX->sun_path);
1489         break;
1490     case AF_INET:
1491         ipv4 = (struct sockaddr_in *)arg;
1492         ret = fprintf(stream, "%s:%i", inet_ntoa(ipv4->sin_addr), (int)ntohs(ipv4->sin_port));
1493         break;
1494     default:
1495         ret = -1;
1496         errno = EPFNOSUPPORT;
1497         break;
1498     }
1499     return(ret);
1500 }
1501
1502 static int formataddress_arginfo(const struct printf_info *info, size_t n, int *argtypes)
1503 {
1504     if(n > 0)
1505         argtypes[0] = PA_POINTER;
1506     if(n > 1)
1507         argtypes[1] = PA_INT; /* Sources tell me that socklen_t _must_
1508                                * be an int, so I guess this should be
1509                                * safe. */
1510     return(2);
1511 }
1512 #endif
1513
1514 static int init(int hup)
1515 {
1516     if(!hup)
1517     {
1518         /*
1519         if(register_printf_function('N', formataddress, formataddress_arginfo))
1520         {
1521             flog(LOG_CRIT, "could not register printf handler %%N: %s", strerror(errno));
1522             return(1);
1523         }
1524         */
1525     }
1526     return(0);
1527 }
1528
1529 static void terminate(void)
1530 {
1531     while(sockets != NULL)
1532         unlinksock(sockets);
1533 }
1534
1535 static struct module me =
1536 {
1537     .name = "net",
1538     .conf =
1539     {
1540         .vars = myvars
1541     },
1542     .init = init,
1543     .terminate = terminate
1544 };
1545
1546 MODULE(me)