Fixed the immediately obvious socket bugs.
[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     if(ufd->sk != NULL)
251         putsock(ufd->sk);
252     if(ufd->type == UFD_SOCK) {
253         if(ufd->d.s.remote != NULL)
254             free(ufd->d.s.remote);
255     }
256     free(ufd);
257 }
258
259 static struct ufd *mkufd(int fd, int type, struct socket *sk)
260 {
261     struct ufd *ufd;
262     
263     ufd = memset(smalloc(sizeof(*ufd)), 0, sizeof(*ufd));
264     ufd->fd = fd;
265     ufd->type = type;
266     if(sk != NULL) {
267         getsock(ufd->sk = sk);
268         sk->ufd = ufd;
269     }
270     if(type == UFD_SOCK) {
271         ufd->d.s.ucred.uid = -1;
272         ufd->d.s.ucred.gid = -1;
273     }
274     ufd->next = ufds;
275     if(ufds)
276         ufds->prev = ufd;
277     ufds = ufd;
278     return(ufd);
279 }
280
281 static struct ufd *dupufd(struct ufd *ufd)
282 {
283     struct ufd *nufd;
284     struct socket *nsk;
285     
286     if(ufd->sk != NULL)
287         nsk = sockpair(ufd->sk->dgram);
288     else
289         nsk = NULL;
290     nufd = mkufd(ufd->fd, ufd->type, nsk);
291     if(nsk != NULL)
292         putsock(nsk);
293     if((nufd->fd = dup(ufd->fd)) < 0)
294     {
295         flog(LOG_WARNING, "could not dup() fd: %s", strerror(errno));
296         freeufd(nufd);
297         return(NULL);
298     }
299     sksetstate(nsk, SOCK_EST);
300     if(ufd->type == UFD_SOCK) {
301         nufd->d.s.family = ufd->d.s.family;
302         nufd->d.s.type = ufd->d.s.type;
303         nufd->d.s.ucred.uid = ufd->d.s.ucred.uid;
304         nufd->d.s.ucred.gid = ufd->d.s.ucred.gid;
305         if(ufd->d.s.remote != NULL)
306             nufd->d.s.remote = memcpy(smalloc(ufd->d.s.remotelen), ufd->d.s.remote, nufd->d.s.remotelen = ufd->d.s.remotelen);
307     } else if(ufd->type == UFD_LISTEN) {
308         nufd->d.l.family = ufd->d.l.family;
309     }
310     return(nufd);
311 }
312
313 static struct socket *mksock(int domain, int type)
314 {
315     int fd;
316     struct socket *sk;
317     struct ufd *ufd;
318     
319     if((fd = socket(domain, type, 0)) < 0)
320     {
321         flog(LOG_CRIT, "could not create socket: %s", strerror(errno));
322         return(NULL);
323     }
324     sk = sockpair(type == SOCK_DGRAM);
325     ufd = mkufd(fd, UFD_SOCK, sk);
326     ufd->d.s.family = domain;
327     ufd->d.s.type = type;
328     fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
329     return(sk);
330 }
331
332 struct socket *wrapsock(int fd)
333 {
334     struct socket *sk;
335     struct ufd *ufd;
336     
337     sk = sockpair(0);
338     ufd = mkufd(fd, UFD_PIPE, sk->back);
339     sksetstate(sk, SOCK_EST);
340     fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
341     return(sk);
342 }
343
344 void getsock(struct socket *sk)
345 {
346     sk->refcount++;
347 }
348
349 static void freesock(struct socket *sk)
350 {
351     struct dgrambuf *buf;
352     
353     if(sk->dgram) {
354         while((buf = sk->buf.d.f) != NULL) {
355             sk->buf.d.f = buf->next;
356             freedgbuf(buf);
357         }
358     } else {
359         if(sk->buf.s.buf != NULL)
360             free(sk->buf.s.buf);
361     }
362     free(sk);
363     numsocks--;
364 }
365
366 void putsock(struct socket *sk)
367 {
368     if(--(sk->refcount) < 0) {
369         flog(LOG_CRIT, "BUG: socket refcount < 0");
370         abort();
371     }
372     if((sk->refcount == 0) && (sk->back->refcount == 0)) {
373         freesock(sk);
374         freesock(sk->back);
375     }
376 }
377
378 static void linksock(struct scons **list, struct socket *sk)
379 {
380     struct scons *sc;
381     
382     for(sc = *list; sc != NULL; sc = sc->n) {
383         if(sc->s == sk)
384             return;
385     }
386     sc = smalloc(sizeof(*sc));
387     getsock(sc->s = sk);
388     sc->n = *list;
389     sc->p = NULL;
390     if(*list)
391         (*list)->p = sc;
392     *list = sc;
393 }
394
395 void sockpushdata(struct socket *sk, void *buf, size_t size)
396 {
397     if(size == 0)
398         return;
399     if(sk->dgram) {
400         /* XXX */
401     } else {
402         sizebuf(&sk->buf.s.buf, &sk->buf.s.bufsize, sk->buf.s.datasize + size, 1, 1);
403         memmove(sk->buf.s.buf + size, sk->buf.s.buf, sk->buf.s.datasize);
404         memcpy(sk->buf.s.buf, buf, size);
405         sk->buf.s.datasize += size;
406         linksock(&rbatch, sk);
407     }
408 }
409
410 /* Read as the preterite of `read' */
411 void sockread(struct socket *sk)
412 {
413     if((sockgetdatalen(sk) == 0) && (sk->eos == 1))
414         linksock(&rbatch, sk);
415     linksock(&wbatch, sk->back);
416 }
417
418 void freedgbuf(struct dgrambuf *dg)
419 {
420     if(dg->data != NULL)
421         free(dg->data);
422     if(dg->addr != NULL)
423         free(dg->addr);
424     free(dg);
425 }
426
427 struct dgrambuf *sockgetdgbuf(struct socket *sk)
428 {
429     struct dgrambuf *dbuf;
430     
431     if((dbuf = sk->buf.d.f) == NULL)
432         return(NULL);
433     sk->buf.d.f = dbuf->next;
434     if(dbuf->next == NULL)
435         sk->buf.d.l = NULL;
436     dbuf->next = NULL;
437     sockread(sk);
438     return(dbuf);
439 }
440
441 void *sockgetinbuf(struct socket *sk, size_t *size)
442 {
443     void *buf;
444     struct dgrambuf *dbuf;
445     
446     if(sk->dgram) {
447         dbuf = sockgetdgbuf(sk);
448         buf = dbuf->data;
449         *size = dbuf->size;
450         free(dbuf->addr);
451         free(dbuf);
452     } else {
453         if((sk->buf.s.buf == NULL) || (sk->buf.s.datasize == 0))
454         {
455             *size = 0;
456             return(NULL);
457         }
458         buf = sk->buf.s.buf;
459         *size = sk->buf.s.datasize;
460         sk->buf.s.buf = NULL;
461         sk->buf.s.bufsize = sk->buf.s.datasize = 0;
462         sockread(sk);
463     }
464     return(buf);
465 }
466
467 void sockqueue(struct socket *sk, void *data, size_t size)
468 {
469     struct dgrambuf *new;
470     struct sockaddr *remote;
471     socklen_t remotelen;
472     
473     if(size == 0)
474         return;
475     if(sk->state == SOCK_STL)
476         return;
477     if(sk->dgram) {
478         if(sockpeeraddr(sk, &remote, &remotelen))
479             return;
480         new = smalloc(sizeof(*new));
481         new->next = NULL;
482         memcpy(new->data = smalloc(size), data, new->size = size);
483         new->addr = remote;
484         new->addrlen = remotelen;
485         if(sk->back->buf.d.l == NULL)
486         {
487             sk->back->buf.d.l = sk->back->buf.d.f = new;
488         } else {
489             sk->back->buf.d.l->next = new;
490             sk->back->buf.d.l = new;
491         }
492     } else {
493         sizebuf(&(sk->back->buf.s.buf), &(sk->back->buf.s.bufsize), sk->back->buf.s.datasize + size, 1, 1);
494         memcpy(sk->back->buf.s.buf + sk->back->buf.s.datasize, data, size);
495         sk->back->buf.s.datasize += size;
496     }
497     linksock(&rbatch, sk->back);
498 }
499
500 void sockqueuedg(struct socket *sk, struct dgrambuf *dg)
501 {
502     if(sk->state == SOCK_STL) {
503         freedgbuf(dg);
504         return;
505     }
506     if(!sk->dgram) {
507         flog(LOG_ERR, "BUG: sockqueuedg called on non-dgram socket");
508         freedgbuf(dg);
509         return;
510     }
511     dg->next = NULL;
512     if(sk->back->buf.d.l == NULL)
513     {
514         sk->back->buf.d.l = sk->back->buf.d.f = dg;
515     } else {
516         sk->back->buf.d.l->next = dg;
517         sk->back->buf.d.l = dg;
518     }
519     linksock(&rbatch, sk->back);
520 }
521
522 void sockeos(struct socket *sk)
523 {
524     sksetstate(sk, SOCK_STL);
525     if(sk->back->eos == 0)
526         sk->back->eos = 1;
527     linksock(&rbatch, sk->back);
528 }
529
530 static void sockerror(struct socket *sk, int en)
531 {
532     sksetstate(sk, SOCK_STL);
533     if(sk->back->errcb != NULL)
534         sk->back->errcb(sk->back, en, sk->back->data);
535 }
536
537 static void recvcmsg(struct ufd *ufd, struct msghdr *msg)
538 {
539     struct cmsghdr *cmsg;
540     
541     for(cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg))
542     {
543 #if UNIX_AUTH_STYLE == 1
544         if((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SCM_CREDENTIALS))
545         {
546             struct ucred *cred;
547             if(ufd->d.s.ucred.uid == -1)
548             {
549                 cred = (struct ucred *)CMSG_DATA(cmsg);
550                 ufd->d.s.ucred.uid = cred->uid;
551                 ufd->d.s.ucred.gid = cred->gid;
552             }
553         }
554 #endif
555     }
556 }
557
558 static int ufddgram(struct ufd *ufd)
559 {
560     int dgram;
561
562     if(ufd->type == UFD_SOCK) {
563         dgram = ufd->d.s.type == SOCK_DGRAM;
564     } else if(ufd->type == UFD_PIPE) {
565         dgram = 0;
566     } else {
567         flog(LOG_ERR, "BUG: calling ufddgram on ufd of bad type %i", ufd->type);
568         return(-1);
569     }
570     if(ufd->sk == NULL) {
571         flog(LOG_ERR, "BUG: calling ufddgram on socketless ufd (type %i)", ufd->type);
572         return(-1);
573     }
574     if(dgram != ufd->sk->dgram) {
575         flog(LOG_ERR, "BUG: ufd/socket dgram value mismatch");
576         return(-1);
577     }
578     return(dgram);
579 }
580
581 static void sockrecv(struct ufd *ufd)
582 {
583     int ret, inq;
584     int dgram;
585     struct dgrambuf *dbuf;
586     struct msghdr msg;
587     char cbuf[65536];
588     struct iovec bufvec;
589     void *buf;
590     
591     memset(&msg, 0, sizeof(msg));
592     msg.msg_iov = &bufvec;
593     msg.msg_iovlen = 1;
594     msg.msg_control = cbuf;
595     msg.msg_controllen = sizeof(cbuf);
596     if((dgram = ufddgram(ufd)) < 0)
597         return;
598     if(dgram) {
599 #if defined(HAVE_LINUX_SOCKIOS_H) && defined(SIOCINQ)
600         if(ioctl(ufd->fd, SIOCINQ, &inq))
601         {
602             /* I don't really know what could go wrong here, so let's
603              * assume it's transient. */
604             flog(LOG_WARNING, "SIOCINQ return %s on socket %i", strerror(errno), ufd->fd);
605             return;
606         }
607 #else
608         inq = 65536;
609 #endif
610         dbuf = smalloc(sizeof(*dbuf));
611         dbuf->data = smalloc(inq);
612         dbuf->addr = smalloc(dbuf->addrlen = sizeof(struct sockaddr_storage));
613         msg.msg_name = dbuf->addr;
614         msg.msg_namelen = dbuf->addrlen;
615         bufvec.iov_base = dbuf->data;
616         bufvec.iov_len = inq;
617         ret = recvmsg(ufd->fd, &msg, 0);
618         dbuf->addrlen = msg.msg_namelen;
619         if(ret < 0)
620         {
621             freedgbuf(dbuf);
622             if((errno == EINTR) || (errno == EAGAIN))
623                 return;
624             closeufd(ufd);
625             sockerror(ufd->sk, errno);
626             return;
627         }
628         if(msg.msg_flags & MSG_CTRUNC)
629             flog(LOG_DEBUG, "ancillary data was truncated");
630         else
631             recvcmsg(ufd, &msg);
632         /* On UDP/IPv[46], ret == 0 doesn't mean EOF (since UDP can't
633          * have EOF), but rather an empty packet. I don't know if any
634          * other potential DGRAM protocols might have an EOF
635          * condition, so let's play safe. */
636         if(ret == 0)
637         {
638             freedgbuf(dbuf);
639             if((ufd->type != UFD_SOCK) || !((ufd->d.s.family == AF_INET) || (ufd->d.s.family == AF_INET6)))
640             {
641                 sockeos(ufd->sk);
642                 closeufd(ufd);
643             }
644             return;
645         }
646         dbuf->addr = srealloc(dbuf->addr, dbuf->addrlen);
647         dbuf->data = srealloc(dbuf->data, dbuf->size = ret);
648         dbuf->next = NULL;
649         sockqueuedg(ufd->sk, dbuf);
650     } else {
651 #if defined(HAVE_LINUX_SOCKIOS_H) && defined(SIOCINQ)
652         /* SIOCINQ is Linux-specific AFAIK, but I really have no idea
653          * how to read the inqueue size on other OSs */
654         if(ufd->type == UFD_SOCK) {
655             if(ioctl(ufd->fd, SIOCINQ, &inq))
656             {
657                 /* I don't really know what could go wrong here, so let's
658                  * assume it's transient. */
659                 flog(LOG_WARNING, "SIOCINQ return %s on socket %i, falling back to 2048 bytes", strerror(errno), ufd->fd);
660                 inq = 2048;
661             }
662         } else {
663             /* There are perils when trying to use SIOCINQ on files >2GiB... */
664             inq = 65536;
665         }
666 #else
667         inq = 2048;
668 #endif
669         if(inq > 65536)
670             inq = 65536;
671         /* This part could be optimized by telling the kernel to read
672          * directly into ufd->sk->back->buf, but that would be uglier
673          * by not using the socket function interface. */
674         buf = smalloc(inq);
675         if(ufd->type == UFD_SOCK)
676         {
677             bufvec.iov_base = buf;
678             bufvec.iov_len = inq;
679             ret = recvmsg(ufd->fd, &msg, 0);
680         } else {
681             ret = read(ufd->fd, buf, inq);
682             msg.msg_controllen = 0;
683             msg.msg_flags = 0;
684         }
685         if(ret < 0)
686         {
687             free(buf);
688             if((errno == EINTR) || (errno == EAGAIN))
689                 return;
690             closeufd(ufd);
691             sockerror(ufd->sk, errno);
692             return;
693         }
694         if(msg.msg_flags & MSG_CTRUNC)
695             flog(LOG_DEBUG, "ancillary data was truncated");
696         else
697             recvcmsg(ufd, &msg);
698         if(ret == 0)
699         {
700             free(buf);
701             closeufd(ufd);
702             sockeos(ufd->sk);
703             return;
704         }
705         sockqueue(ufd->sk, buf, ret);
706         free(buf);
707     }
708 }
709
710 static void sockflush(struct ufd *ufd)
711 {
712     int ret;
713     struct dgrambuf *dbuf;
714     int dgram;
715     
716     if((dgram = ufddgram(ufd)) < 0)
717         return;
718     if(dgram) {
719         dbuf = sockgetdgbuf(ufd->sk);
720         sendto(ufd->fd, dbuf->data, dbuf->size, MSG_DONTWAIT | MSG_NOSIGNAL, dbuf->addr, dbuf->addrlen);
721         freedgbuf(dbuf);
722     } else {
723         if(ufd->type == UFD_SOCK)
724             ret = send(ufd->fd, ufd->sk->buf.s.buf, ufd->sk->buf.s.datasize, MSG_DONTWAIT | MSG_NOSIGNAL);
725         else
726             ret = write(ufd->fd, ufd->sk->buf.s.buf, ufd->sk->buf.s.datasize);
727         if(ret < 0) {
728             /* For now, assume transient error, since
729              * the socket is polled for errors */
730             return;
731         }
732         if(ret > 0) {
733             memmove(ufd->sk->buf.s.buf, ((char *)ufd->sk->buf.s.buf) + ret, ufd->sk->buf.s.datasize -= ret);
734             sockread(ufd->sk);
735         }
736     }
737 }
738
739 void closesock(struct socket *sk)
740 {
741 /*
742     struct sockaddr_un *un;
743     
744     if((sk->family == AF_UNIX) && !sockgetlocalname(sk, (struct sockaddr **)(void *)&un, NULL) && (un->sun_family == PF_UNIX))
745     {
746         if((sk->state == SOCK_LST) && strchr(un->sun_path, '/'))
747         {
748             if(unlink(un->sun_path))
749                 flog(LOG_WARNING, "could not unlink Unix socket %s: %s", un->sun_path, strerror(errno));
750         }
751     }
752 */
753     sksetstate(sk, SOCK_STL);
754     sockeos(sk);
755 }
756
757 size_t sockgetdatalen(struct socket *sk)
758 {
759     struct dgrambuf *b;
760     size_t ret;
761     
762     if(sk->dgram) {
763         ret = 0;
764         for(b = sk->buf.d.f; b != NULL; b = b->next)
765             ret += b->size;
766     } else {
767         ret = sk->buf.s.datasize;
768     }
769     return(ret);
770 }
771
772 size_t sockqueuesize(struct socket *sk)
773 {
774     return(sockgetdatalen(sk->back));
775 }
776
777 /*
778  * Seriously, I don't know if it's naughty or not to remove
779  * pre-existing Unix sockets.
780  */
781 static int rebindunix(struct ufd *ufd, struct sockaddr *name, socklen_t namelen)
782 {
783     struct sockaddr_un *un;
784     struct stat sb;
785     
786     if((ufd->d.l.family != AF_UNIX) || (name->sa_family != PF_UNIX))
787         return(-1);
788     un = (struct sockaddr_un *)name;
789     if(stat(un->sun_path, &sb))
790         return(-1);
791     if(!S_ISSOCK(sb.st_mode))
792         return(-1);
793     if(unlink(un->sun_path))
794         return(-1);
795     if(bind(ufd->fd, name, namelen) < 0)
796         return(-1);
797     return(0);
798 }
799
800 void closelport(struct lport *lp)
801 {
802     freeufd(lp->ufd);
803 }
804
805 /*
806  * The difference between netcslisten() and netcslistenlocal() is that
807  * netcslistenlocal() always listens on the local host, instead of
808  * following proxy/passive mode directions. It is suitable for eg. the
809  * UI channel, while the file sharing networks should, naturally, use
810  * netcslisten() instead.
811 */
812
813 struct lport *netcslistenlocal(int type, struct sockaddr *name, socklen_t namelen, void (*func)(struct lport *, struct socket *, void *), void *data)
814 {
815     struct lport *lp;
816     struct ufd *ufd;
817     int fd;
818     int intbuf;
819     
820     /* I don't know if this is actually correct (it probably isn't),
821      * but since, at on least Linux systems, PF_* are specifically
822      * #define'd to their AF_* counterparts, it allows for a severely
823      * smoother implementation. If it breaks something on your
824      * platform, please tell me so.
825      */
826     if((fd = socket(name->sa_family, type, 0)) < 0)
827         return(NULL);
828     if(confgetint("net", "reuseaddr")) {
829         intbuf = 1;
830         setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &intbuf, sizeof(intbuf));
831     }
832     ufd = mkufd(fd, UFD_LISTEN, NULL);
833     ufd->d.l.family = name->sa_family;
834     lp = memset(smalloc(sizeof(*lp)), 0, sizeof(*lp));
835     lp->ufd = ufd;
836     ufd->d.l.lp = lp;
837     if((bind(fd, name, namelen) < 0) && ((errno != EADDRINUSE) || (rebindunix(ufd, name, namelen) < 0))) {
838         freeufd(ufd);
839         return(NULL);
840     }
841     if(listen(fd, 16) < 0)
842     {
843         freeufd(ufd);
844         return(NULL);
845     }
846     lp->acceptcb = func;
847     lp->data = data;
848     return(lp);
849 }
850
851 struct lport *netcslisten(int type, struct sockaddr *name, socklen_t namelen, void (*func)(struct lport *, struct socket *, void *), void *data)
852 {
853     if(confgetint("net", "mode") == 1)
854     {
855         errno = EOPNOTSUPP;
856         return(NULL);
857     }
858     if(confgetint("net", "mode") == 0)
859         return(netcslistenlocal(type, name, namelen, func, data));
860     errno = EOPNOTSUPP;
861     return(NULL);
862 }
863
864 struct lport *netcstcplisten(int port, int local, void (*func)(struct lport *, struct socket *, void *), void *data)
865 {
866     struct sockaddr_in addr;
867 #ifdef HAVE_IPV6
868     struct sockaddr_in6 addr6;
869 #endif
870     struct lport *(*csfunc)(int, struct sockaddr *, socklen_t, void (*)(struct lport *, struct socket *, void *), void *);
871     struct lport *ret;
872     
873     if(local)
874         csfunc = netcslistenlocal;
875     else
876         csfunc = netcslisten;
877 #ifdef HAVE_IPV6
878     memset(&addr6, 0, sizeof(addr6));
879     addr6.sin6_family = AF_INET6;
880     addr6.sin6_port = htons(port);
881     addr6.sin6_addr = in6addr_any;
882     if((ret = csfunc(SOCK_STREAM, (struct sockaddr *)&addr6, sizeof(addr6), func, data)) != NULL)
883         return(ret);
884     if((ret == NULL) && (errno != EAFNOSUPPORT))
885         return(NULL);
886 #endif
887     memset(&addr, 0, sizeof(addr));
888     addr.sin_family = AF_INET;
889     addr.sin_port = htons(port);
890     return(csfunc(SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr), func, data));
891 }
892
893 struct socket *netcsdgram(struct sockaddr *name, socklen_t namelen)
894 {
895     struct socket *sk;
896     int mode;
897     
898     mode = confgetint("net", "mode");
899     if((mode == 0) || (mode == 1))
900     {
901         if((sk = mksock(name->sa_family, SOCK_DGRAM)) == NULL)
902             return(NULL);
903         if(bind(sk->ufd->fd, name, namelen) < 0)
904         {
905             putsock(sk);
906             return(NULL);
907         }
908         sksetstate(sk, SOCK_EST);
909         return(sk->back);
910     }
911     errno = EOPNOTSUPP;
912     return(NULL);
913 }
914
915 struct socket *netdgramconn(struct socket *sk, struct sockaddr *addr, socklen_t addrlen)
916 {
917     struct ufd *nufd;
918     
919     nufd = dupufd(sk->back->ufd);
920     getsock(sk = nufd->sk->back);
921     memcpy(nufd->d.s.remote = smalloc(addrlen), addr, nufd->d.s.remotelen = addrlen);
922     nufd->ignread = 1;
923     return(sk);
924 }
925
926 struct socket *netcsconn(struct sockaddr *addr, socklen_t addrlen, void (*func)(struct socket *, int, void *), void *data)
927 {
928     struct socket *sk;
929     int mode;
930     
931     mode = confgetint("net", "mode");
932     if((mode == 0) || (mode == 1))
933     {
934         if((sk = mksock(addr->sa_family, SOCK_STREAM)) == NULL)
935             return(NULL);
936         memcpy(sk->ufd->d.s.remote = smalloc(addrlen), addr, sk->ufd->d.s.remotelen = addrlen);
937         sk->back->conncb = func;
938         sk->back->data = data;
939         if(!connect(sk->ufd->fd, addr, addrlen))
940         {
941             sksetstate(sk, SOCK_EST);
942             linksock(&cbatch, sk->back);
943             return(sk->back);
944         }
945         if(errno == EINPROGRESS)
946         {
947             sksetstate(sk, SOCK_SYN);
948             return(sk->back);
949         }
950         putsock(sk);
951         return(NULL);
952     }
953     errno = EOPNOTSUPP;
954     return(NULL);
955 }
956
957 static void acceptunix(struct ufd *ufd)
958 {
959     int buf;
960     
961     buf = 1;
962 #if UNIX_AUTH_STYLE == 1
963     if(setsockopt(ufd->fd, SOL_SOCKET, SO_PASSCRED, &buf, sizeof(buf)) < 0)
964         flog(LOG_WARNING, "could not enable SO_PASSCRED on Unix socket %i: %s", ufd->fd, strerror(errno));
965 #elif UNIX_AUTH_STYLE == 2
966     if(getpeereid(ufd->fd, &ufd->d.s.ucred.uid, &ufd->d.s.ucred.gid) < 0)
967     {
968         flog(LOG_WARNING, "could not get peer creds on Unix socket %i: %s", ufd->fd, strerror(errno));
969         ufd->d.s.ucred.uid = -1;
970         ufd->d.s.ucred.gid = -1;
971     }
972 #endif
973 }
974
975 static void runbatches(void)
976 {
977     struct scons *sc, *nsc;
978
979     for(sc = cbatch, cbatch = NULL; sc; sc = nsc) {
980         nsc = sc->n;
981         if(sc->s->conncb != NULL)
982             sc->s->conncb(sc->s, 0, sc->s->data);
983         free(sc);
984     }
985     for(sc = rbatch, rbatch = NULL; sc; sc = nsc) {
986         nsc = sc->n;
987         if(sc->s->readcb != NULL)
988             sc->s->readcb(sc->s, sc->s->data);
989         if((sockgetdatalen(sc->s) == 0) && (sc->s->eos == 1)) {
990             if(sc->s->errcb != NULL)
991                 sc->s->errcb(sc->s, 0, sc->s->data);
992             sc->s->eos = 2;
993         }
994         free(sc);
995     }
996     for(sc = wbatch, wbatch = NULL; sc; sc = nsc) {
997         nsc = sc->n;
998         if(sc->s->writecb != NULL)
999             sc->s->writecb(sc->s, sc->s->data);
1000         free(sc);
1001     }
1002 }
1003
1004 static void cleansocks(void)
1005 {
1006     struct ufd *ufd, *next;
1007     
1008     for(ufd = ufds; ufd != NULL; ufd = next) {
1009         next = ufd->next;
1010         if(ufd->sk && (sockgetdatalen(ufd->sk) == 0)) {
1011             if(ufd->sk->eos == 1) {
1012                 ufd->sk->eos = 2;
1013                 closeufd(ufd);
1014                 closesock(ufd->sk);
1015             }
1016             if((ufd->sk->refcount == 1) && (ufd->sk->back->refcount == 0)) {
1017                 freeufd(ufd);
1018                 continue;
1019             }
1020         }
1021     }
1022 }
1023
1024 int pollsocks(int timeout)
1025 {
1026     int ret;
1027     socklen_t retlen;
1028     int newfd, maxfd;
1029     fd_set rfds, wfds, efds;
1030     struct ufd *ufd, *nufd;
1031     struct socket *nsk;
1032     struct sockaddr_storage ss;
1033     socklen_t sslen;
1034     struct timeval tv;
1035     
1036     cleansocks();
1037     FD_ZERO(&rfds);
1038     FD_ZERO(&wfds);
1039     FD_ZERO(&efds);
1040     for(maxfd = 0, ufd = ufds; ufd != NULL; ufd = ufd->next) {
1041         if(ufd->fd < 0)
1042             continue;
1043         if(!ufd->ignread)
1044             FD_SET(ufd->fd, &rfds);
1045         if(ufd->sk != NULL) {
1046             if(sockgetdatalen(ufd->sk) > 0)
1047                 FD_SET(ufd->fd, &wfds);
1048             else if(ufd->sk->state == SOCK_SYN)
1049                 FD_SET(ufd->fd, &wfds);
1050         }
1051         FD_SET(ufd->fd, &efds);
1052         if(ufd->fd > maxfd)
1053             maxfd = ufd->fd;
1054     }
1055     if(rbatch || wbatch || cbatch)
1056         timeout = 0;
1057     tv.tv_sec = timeout / 1000;
1058     tv.tv_usec = (timeout % 1000) * 1000;
1059     ret = select(maxfd + 1, &rfds, &wfds, &efds, (timeout < 0)?NULL:&tv);
1060     if(ret < 0) {
1061         if(errno != EINTR) {
1062             flog(LOG_CRIT, "pollsocks: select errored out: %s", strerror(errno));
1063             /* To avoid CPU hogging in case it's bad, which it
1064              * probably is. */
1065             sleep(1);
1066         }
1067         return(1);
1068     }
1069     for(ufd = ufds; ufd != NULL; ufd = ufd->next) {
1070         if(ufd->sk < 0)
1071             continue;
1072         if(ufd->type == UFD_LISTEN) {
1073             if(FD_ISSET(ufd->fd, &rfds)) {
1074                 sslen = sizeof(ss);
1075                 if((newfd = accept(ufd->fd, (struct sockaddr *)&ss, &sslen)) < 0) {
1076                     if(ufd->d.l.lp->errcb != NULL)
1077                         ufd->d.l.lp->errcb(ufd->d.l.lp, errno, ufd->d.l.lp->data);
1078                 }
1079                 nsk = sockpair(0);
1080                 nufd = mkufd(newfd, UFD_SOCK, nsk);
1081                 nufd->d.s.family = ufd->d.l.family;
1082                 sksetstate(nsk, SOCK_EST);
1083                 memcpy(nufd->d.s.remote = smalloc(sslen), &ss, sslen);
1084                 nufd->d.s.remotelen = sslen;
1085                 if(ss.ss_family == PF_UNIX)
1086                     acceptunix(nufd);
1087                 if(ufd->d.l.lp->acceptcb != NULL)
1088                     ufd->d.l.lp->acceptcb(ufd->d.l.lp, nsk->back, ufd->d.l.lp->data);
1089                 putsock(nsk);
1090             }
1091             if(FD_ISSET(ufd->fd, &efds)) {
1092                 retlen = sizeof(ret);
1093                 getsockopt(ufd->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
1094                 if(ufd->d.l.lp->errcb != NULL)
1095                     ufd->d.l.lp->errcb(ufd->d.l.lp, ret, ufd->d.l.lp->data);
1096                 continue;
1097             }
1098         } else {
1099             if(ufd->sk->state == SOCK_SYN) {
1100                 if(FD_ISSET(ufd->fd, &efds)) {
1101                     retlen = sizeof(ret);
1102                     getsockopt(ufd->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
1103                     if(ufd->sk->back->conncb != NULL)
1104                         ufd->sk->back->conncb(ufd->sk->back, ret, ufd->sk->back->data);
1105                     closeufd(ufd);
1106                     continue;
1107                 }
1108                 if(FD_ISSET(ufd->fd, &rfds) || FD_ISSET(ufd->fd, &wfds)) {
1109                     sksetstate(ufd->sk, SOCK_EST);
1110                     linksock(&cbatch, ufd->sk->back);
1111                 }
1112             } else if(ufd->sk->state == SOCK_EST) {
1113                 if(FD_ISSET(ufd->fd, &efds)) {
1114                     retlen = sizeof(ret);
1115                     getsockopt(ufd->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
1116                     sockerror(ufd->sk, ret);
1117                     closeufd(ufd);
1118                     continue;
1119                 }
1120                 if(FD_ISSET(ufd->fd, &rfds))
1121                     sockrecv(ufd);
1122                 if(ufd->fd == -1)
1123                     continue;
1124                 if(FD_ISSET(ufd->fd, &wfds))
1125                     sockflush(ufd);
1126             }
1127         }
1128     }
1129     runbatches();
1130     cleansocks();
1131     return(1);
1132 }
1133
1134 static struct ufd *getskufd(struct socket *sk)
1135 {
1136     while(1) {
1137         if(sk->back->ufd != NULL)
1138             return(sk->back->ufd);
1139         if((sk = sk->back->pnext) == NULL)
1140             break;
1141     }
1142     return(NULL);
1143 }
1144
1145 int socksettos(struct socket *sk, int tos)
1146 {
1147     int buf;
1148     struct ufd *ufd;
1149     
1150     ufd = getskufd(sk);
1151     if(ufd->type != UFD_SOCK) {
1152         errno = EOPNOTSUPP;
1153         return(-1);
1154     }
1155     if(ufd->d.s.family == AF_UNIX)
1156         return(0); /* Unix sockets are always perfect. :) */
1157     if(ufd->d.s.family == AF_INET)
1158     {
1159         switch(tos)
1160         {
1161         case 0:
1162             buf = 0;
1163             break;
1164         case SOCK_TOS_MINCOST:
1165             buf = 0x02;
1166             break;
1167         case SOCK_TOS_MAXREL:
1168             buf = 0x04;
1169             break;
1170         case SOCK_TOS_MAXTP:
1171             buf = 0x08;
1172             break;
1173         case SOCK_TOS_MINDELAY:
1174             buf = 0x10;
1175             break;
1176         default:
1177             flog(LOG_WARNING, "attempted to set unknown TOS value %i to IPv4 sock", tos);
1178             return(-1);
1179         }
1180         if(setsockopt(ufd->fd, IPPROTO_IP, IP_TOS, &buf, sizeof(buf)) < 0)
1181         {
1182             flog(LOG_WARNING, "could not set sock TOS to %i: %s", tos, strerror(errno));
1183             return(-1);
1184         }
1185         return(0);
1186     }
1187     if(ufd->d.s.family == AF_INET6)
1188     {
1189         switch(tos)
1190         {
1191         case 0:
1192             buf = 0;
1193         case SOCK_TOS_MINCOST:
1194             buf = confgetint("net", "diffserv-mincost");
1195             break;
1196         case SOCK_TOS_MAXREL:
1197             buf = confgetint("net", "diffserv-maxrel");
1198             break;
1199         case SOCK_TOS_MAXTP:
1200             buf = confgetint("net", "diffserv-maxtp");
1201             break;
1202         case SOCK_TOS_MINDELAY:
1203             buf = confgetint("net", "diffserv-mindelay");
1204             break;
1205         default:
1206             flog(LOG_WARNING, "attempted to set unknown TOS value %i to IPv4 sock", tos);
1207             return(-1);
1208         }
1209         /*
1210           On Linux, the API IPv6 flow label management doesn't seem to
1211           be entirely complete, so I guess this will have to wait.
1212           
1213         if(setsockopt(...) < 0)
1214         {
1215             flog(LOG_WARNING, "could not set sock traffic class to %i: %s", tos, strerror(errno));
1216             return(-1);
1217         }
1218         */
1219         return(0);
1220     }
1221     flog(LOG_WARNING, "could not set TOS on sock of family %i", ufd->d.s.family);
1222     return(1);
1223 }
1224
1225 struct resolvedata
1226 {
1227     int fd;
1228     void (*callback)(struct sockaddr *addr, int addrlen, void *data);
1229     void *data;
1230     struct sockaddr_storage addr;
1231     int addrlen;
1232 };
1233
1234 static void resolvecb(pid_t pid, int status, struct resolvedata *data)
1235 {
1236     static char buf[80];
1237     int ret;
1238     struct sockaddr_in *ipv4;
1239     
1240     if(!status)
1241     {
1242         if((ret = read(data->fd, buf, sizeof(buf))) != 4)
1243         {
1244             errno = ENOENT;
1245             data->callback(NULL, 0, data->data);
1246         } else {
1247             ipv4 = (struct sockaddr_in *)&data->addr;
1248             memcpy(&ipv4->sin_addr, buf, 4);
1249             data->callback((struct sockaddr *)ipv4, sizeof(*ipv4), data->data);
1250         }
1251     } else {
1252         errno = ENOENT;
1253         data->callback(NULL, 0, data->data);
1254     }
1255     close(data->fd);
1256     free(data);
1257 }
1258
1259 int netresolve(char *addr, void (*callback)(struct sockaddr *addr, int addrlen, void *data), void *data)
1260 {
1261     int i;
1262     char *p;
1263     int port;
1264     int pfd[2];
1265     pid_t child;
1266     struct resolvedata *rdata;
1267     struct sockaddr_in ipv4;
1268     struct hostent *he;
1269     sigset_t sigset;
1270     
1271     /* IPv4 */
1272     port = -1;
1273     if((p = strchr(addr, ':')) != NULL)
1274     {
1275         *p = 0;
1276         port = atoi(p + 1);
1277     }
1278     ipv4.sin_family = AF_INET;
1279     ipv4.sin_port = htons(port);
1280     if(inet_aton(addr, &ipv4.sin_addr))
1281     {
1282         callback((struct sockaddr *)&ipv4, sizeof(ipv4), data);
1283     } else {
1284         sigemptyset(&sigset);
1285         sigaddset(&sigset, SIGCHLD);
1286         sigprocmask(SIG_BLOCK, &sigset, NULL);
1287         if((pipe(pfd) < 0) || ((child = fork()) < 0))
1288         {
1289             sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1290             return(-1);
1291         }
1292         if(child == 0)
1293         {
1294             sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1295             for(i = 3; i < FD_SETSIZE; i++)
1296             {
1297                 if(i != pfd[1])
1298                     close(i);
1299             }
1300             signal(SIGALRM, SIG_DFL);
1301             alarm(30);
1302             if((he = gethostbyname(addr)) == NULL)
1303                 exit(1);
1304             write(pfd[1], he->h_addr_list[0], 4);
1305             exit(0);
1306         } else {
1307             close(pfd[1]);
1308             fcntl(pfd[0], F_SETFL, fcntl(pfd[0], F_GETFL) | O_NONBLOCK);
1309             rdata = smalloc(sizeof(*rdata));
1310             rdata->fd = pfd[0];
1311             rdata->callback = callback;
1312             rdata->data = data;
1313             memcpy(&rdata->addr, &ipv4, rdata->addrlen = sizeof(ipv4));
1314             childcallback(child, (void (*)(pid_t, int, void *))resolvecb, rdata);
1315             sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1316             return(1);
1317         }
1318     }
1319     return(0);
1320 }
1321
1322 static int getlocalname(int fd, struct sockaddr **namebuf, socklen_t *lenbuf)
1323 {
1324     socklen_t len;
1325     struct sockaddr_storage name;
1326     
1327     *namebuf = NULL;
1328     if(fd < 0)
1329         return(-1);
1330     len = sizeof(name);
1331     if(getsockname(fd, (struct sockaddr *)&name, &len) < 0)
1332     {
1333         flog(LOG_ERR, "BUG: alive socket with dead fd in sockgetlocalname (%s)", strerror(errno));
1334         return(-1);
1335     }
1336     *namebuf = memcpy(smalloc(len), &name, len);
1337     if(lenbuf != NULL)
1338         *lenbuf = len;
1339     return(0);
1340 }
1341
1342 int lstgetlocalname(struct lport *lp, struct sockaddr **namebuf, socklen_t *lenbuf)
1343 {
1344     struct ufd *ufd;
1345
1346     ufd = lp->ufd;
1347     return(getlocalname(ufd->fd, namebuf, lenbuf));
1348 }
1349
1350 int sockgetlocalname(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf)
1351 {
1352     struct ufd *ufd;
1353
1354     ufd = getskufd(sk);
1355     if(ufd->type != UFD_SOCK) {
1356         errno = EOPNOTSUPP;
1357         return(-1);
1358     }
1359     return(getlocalname(ufd->fd, namebuf, lenbuf));
1360 }
1361
1362 static void sethostaddr(struct sockaddr *dst, struct sockaddr *src)
1363 {
1364     if(dst->sa_family != src->sa_family)
1365     {
1366         flog(LOG_ERR, "BUG: non-matching socket families in sethostaddr (%i -> %i)", src->sa_family, dst->sa_family);
1367         return;
1368     }
1369     switch(src->sa_family)
1370     {
1371     case AF_INET:
1372         ((struct sockaddr_in *)dst)->sin_addr = ((struct sockaddr_in *)src)->sin_addr;
1373         break;
1374     case AF_INET6:
1375         ((struct sockaddr_in6 *)dst)->sin6_addr = ((struct sockaddr_in6 *)src)->sin6_addr;
1376         break;
1377     default:
1378         flog(LOG_WARNING, "sethostaddr unimplemented for family %i", src->sa_family);
1379         break;
1380     }
1381 }
1382
1383 static int makepublic(struct sockaddr *addr)
1384 {
1385     int ret;
1386     socklen_t plen;
1387     struct sockaddr *pname;
1388     
1389     if((ret = getpublicaddr(addr->sa_family, &pname, &plen)) < 0)
1390     {
1391         flog(LOG_ERR, "could not get public address: %s", strerror(errno));
1392         return(-1);
1393     }
1394     if(ret)
1395         return(0);
1396     sethostaddr(addr, pname);
1397     free(pname);
1398     return(0);
1399 }
1400
1401 static int getremotename(int fd, struct sockaddr **namebuf, socklen_t *lenbuf)
1402 {
1403     socklen_t len;
1404     struct sockaddr *name;
1405
1406     switch(confgetint("net", "mode")) {
1407     case 0:
1408         *namebuf = NULL;
1409         if(!getlocalname(fd, &name, &len)) {
1410             *namebuf = name;
1411             *lenbuf = len;
1412             makepublic(name);
1413             return(0);
1414         }
1415         flog(LOG_ERR, "could not get remotely accessible name by any means");
1416         return(-1);
1417     case 1:
1418         errno = EOPNOTSUPP;
1419         return(-1);
1420     default:
1421         flog(LOG_CRIT, "unknown net mode %i active", confgetint("net", "mode"));
1422         errno = EOPNOTSUPP;
1423         return(-1);
1424     }
1425 }
1426
1427 int sockgetremotename(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf)
1428 {
1429     struct ufd *ufd;
1430     
1431     ufd = getskufd(sk);
1432     if(ufd->type != UFD_SOCK) {
1433         errno = EOPNOTSUPP;
1434         return(-1);
1435     }
1436     if(ufd->fd < 0) {
1437         errno = EBADF;
1438         return(-1);
1439     }
1440     return(getremotename(ufd->fd, namebuf, lenbuf));
1441 }
1442
1443 int lstgetremotename(struct lport *lp, struct sockaddr **namebuf, socklen_t *lenbuf)
1444 {
1445     struct ufd *ufd;
1446     
1447     ufd = lp->ufd;
1448     return(getremotename(ufd->fd, namebuf, lenbuf));
1449 }
1450
1451 int sockgetremotename2(struct socket *sk, struct socket *sk2, struct sockaddr **namebuf, socklen_t *lenbuf)
1452 {
1453     struct sockaddr *name1, *name2;
1454     socklen_t len1, len2;
1455     struct ufd *ufd1, *ufd2;
1456     
1457     ufd1 = getskufd(sk);
1458     ufd2 = getskufd(sk2);
1459     if((ufd1->type != UFD_SOCK) || (ufd2->type != UFD_SOCK)) {
1460         errno = EOPNOTSUPP;
1461         return(-1);
1462     }
1463     if(ufd1->d.s.family != ufd2->d.s.family)
1464     {
1465         flog(LOG_ERR, "using sockgetremotename2 with sockets of differing family: %i %i", ufd1->d.s.family, ufd2->d.s.family);
1466         return(-1);
1467     }
1468     if(getremotename(ufd1->fd, &name1, &len1))
1469         return(-1);
1470     if(getremotename(ufd2->fd, &name2, &len2)) {
1471         free(name1);
1472         return(-1);
1473     }
1474     sethostaddr(name1, name2);
1475     free(name2);
1476     *namebuf = name1;
1477     *lenbuf = len1;
1478     return(0);
1479 }
1480
1481 int lstgetremotename2(struct lport *lp, struct socket *sk2, struct sockaddr **namebuf, socklen_t *lenbuf)
1482 {
1483     struct sockaddr *name1, *name2;
1484     socklen_t len1, len2;
1485     struct ufd *ufd1, *ufd2;
1486     
1487     ufd1 = lp->ufd;
1488     ufd2 = getskufd(sk2);
1489     if(ufd2->type != UFD_SOCK) {
1490         errno = EOPNOTSUPP;
1491         return(-1);
1492     }
1493     if(ufd1->d.s.family != ufd2->d.s.family)
1494     {
1495         flog(LOG_ERR, "using lstgetremotename2 with sockets of differing family: %i %i", ufd1->d.s.family, ufd2->d.s.family);
1496         return(-1);
1497     }
1498     if(getremotename(ufd1->fd, &name1, &len1))
1499         return(-1);
1500     if(getremotename(ufd2->fd, &name2, &len2)) {
1501         free(name1);
1502         return(-1);
1503     }
1504     sethostaddr(name1, name2);
1505     free(name2);
1506     *namebuf = name1;
1507     *lenbuf = len1;
1508     return(0);
1509 }
1510
1511 int getucred(struct socket *sk, uid_t *uid, gid_t *gid)
1512 {
1513     struct ufd *ufd;
1514     
1515     ufd = getskufd(sk);
1516     if(ufd->type != UFD_SOCK) {
1517         errno = EOPNOTSUPP;
1518         return(-1);
1519     }
1520     if(ufd->d.s.family != AF_UNIX) {
1521         errno = EOPNOTSUPP;
1522         return(-1);
1523     }
1524     *uid = ufd->d.s.ucred.uid;
1525     *gid = ufd->d.s.ucred.gid;
1526     return(0);
1527 }
1528
1529 void sockblock(struct socket *sk, int block)
1530 {
1531     struct ufd *ufd;
1532     
1533     ufd = getskufd(sk);
1534     ufd->ignread = block;
1535 }
1536
1537 int sockfamily(struct socket *sk)
1538 {
1539     struct ufd *ufd;
1540     
1541     ufd = getskufd(sk);
1542     if(ufd->type != UFD_SOCK) {
1543         errno = EOPNOTSUPP;
1544         return(-1);
1545     }
1546     return(ufd->d.s.family);
1547 }
1548
1549 int sockpeeraddr(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf)
1550 {
1551     struct ufd *ufd;
1552     
1553     ufd = getskufd(sk);
1554     if(ufd->type != UFD_SOCK) {
1555         errno = EOPNOTSUPP;
1556         return(-1);
1557     }
1558     if(ufd->d.s.remote == NULL)
1559         return(-1);
1560     *namebuf = memcpy(smalloc(ufd->d.s.remotelen), ufd->d.s.remote, ufd->d.s.remotelen);
1561     if(lenbuf != NULL)
1562         *lenbuf = ufd->d.s.remotelen;
1563     return(0);
1564 }
1565
1566 char *formatsockpeer(struct socket *sk)
1567 {
1568     struct sockaddr *name;
1569     socklen_t nlen;
1570     char *ret;
1571     
1572     if(sockpeeraddr(sk, &name, &nlen))
1573         return(NULL);
1574     ret = formataddress(name, nlen);
1575     free(name);
1576     return(ret);
1577 }
1578
1579 int addreq(struct sockaddr *x, struct sockaddr *y)
1580 {
1581     struct sockaddr_un *u1, *u2;
1582     struct sockaddr_in *n1, *n2;
1583 #ifdef HAVE_IPV6
1584     struct sockaddr_in6 *s1, *s2;
1585 #endif
1586     
1587     if(x->sa_family != y->sa_family)
1588         return(0);
1589     switch(x->sa_family) {
1590     case AF_UNIX:
1591         u1 = (struct sockaddr_un *)x; u2 = (struct sockaddr_un *)y;
1592         if(strncmp(u1->sun_path, u2->sun_path, sizeof(u1->sun_path)))
1593             return(0);
1594         break;
1595     case AF_INET:
1596         n1 = (struct sockaddr_in *)x; n2 = (struct sockaddr_in *)y;
1597         if(n1->sin_port != n2->sin_port)
1598             return(0);
1599         if(n1->sin_addr.s_addr != n2->sin_addr.s_addr)
1600             return(0);
1601         break;
1602 #ifdef HAVE_IPV6
1603     case AF_INET6:
1604         s1 = (struct sockaddr_in6 *)x; s2 = (struct sockaddr_in6 *)y;
1605         if(s1->sin6_port != s2->sin6_port)
1606             return(0);
1607         if(memcmp(s1->sin6_addr.s6_addr, s2->sin6_addr.s6_addr, sizeof(s1->sin6_addr.s6_addr)))
1608             return(0);
1609         break;
1610 #endif
1611     }
1612     return(1);
1613 }
1614
1615 char *formataddress(struct sockaddr *arg, socklen_t arglen)
1616 {
1617     struct sockaddr_in *ipv4;
1618 #ifdef HAVE_IPV6
1619     struct sockaddr_in6 *ipv6;
1620 #endif
1621     static char *ret = NULL;
1622     char buf[1024];
1623     
1624     if(ret != NULL)
1625         free(ret);
1626     ret = NULL;
1627     switch(arg->sa_family)
1628     {
1629     case AF_UNIX:
1630         ret = sstrdup("Unix socket");
1631         break;
1632     case AF_INET:
1633         ipv4 = (struct sockaddr_in *)arg;
1634         if(inet_ntop(AF_INET, &ipv4->sin_addr, buf, sizeof(buf)) == NULL)
1635             return(NULL);
1636         ret = sprintf2("%s:%i", buf, (int)ntohs(ipv4->sin_port));
1637         break;
1638 #ifdef HAVE_IPV6
1639     case AF_INET6:
1640         ipv6 = (struct sockaddr_in6 *)arg;
1641         if(inet_ntop(AF_INET6, &ipv6->sin6_addr, buf, sizeof(buf)) == NULL)
1642             return(NULL);
1643         ret = sprintf2("[%s]:%i", buf, (int)ntohs(ipv6->sin6_port));
1644         break;
1645 #endif
1646     default:
1647         errno = EPFNOSUPPORT;
1648         break;
1649     }
1650     return(ret);
1651 }
1652
1653 #if 0
1654
1655 /* 
1656  * It was very nice to use this, but it seems
1657  * to mess things up, so I guess it has to go... :-(
1658  */
1659
1660 static int formataddress(FILE *stream, const struct printf_info *info, const void *const *args)
1661 {
1662     struct sockaddr *arg;
1663     socklen_t arglen;
1664     struct sockaddr_un *UNIX; /* Some wise guy has #defined unix with
1665                                * lowercase letters to 1, so I do this
1666                                * instead. */
1667     struct sockaddr_in *ipv4;
1668     int ret;
1669     
1670     arg = *(struct sockaddr **)(args[0]);
1671     arglen = *(socklen_t *)(args[1]);
1672     switch(arg->sa_family)
1673     {
1674     case AF_UNIX:
1675         UNIX = (struct sockaddr_un *)arg;
1676         ret = fprintf(stream, "%s", UNIX->sun_path);
1677         break;
1678     case AF_INET:
1679         ipv4 = (struct sockaddr_in *)arg;
1680         ret = fprintf(stream, "%s:%i", inet_ntoa(ipv4->sin_addr), (int)ntohs(ipv4->sin_port));
1681         break;
1682     default:
1683         ret = -1;
1684         errno = EPFNOSUPPORT;
1685         break;
1686     }
1687     return(ret);
1688 }
1689
1690 static int formataddress_arginfo(const struct printf_info *info, size_t n, int *argtypes)
1691 {
1692     if(n > 0)
1693         argtypes[0] = PA_POINTER;
1694     if(n > 1)
1695         argtypes[1] = PA_INT; /* Sources tell me that socklen_t _must_
1696                                * be an int, so I guess this should be
1697                                * safe. */
1698     return(2);
1699 }
1700 #endif
1701
1702 static int init(int hup)
1703 {
1704     if(!hup)
1705     {
1706         /*
1707         if(register_printf_function('N', formataddress, formataddress_arginfo))
1708         {
1709             flog(LOG_CRIT, "could not register printf handler %%N: %s", strerror(errno));
1710             return(1);
1711         }
1712         */
1713     }
1714     return(0);
1715 }
1716
1717 static void terminate(void)
1718 {
1719     /*
1720     while(ufds != NULL)
1721         freeufd(ufds);
1722     */
1723 }
1724
1725 static struct module me =
1726 {
1727     .name = "net",
1728     .conf =
1729     {
1730         .vars = myvars
1731     },
1732     .init = init,
1733     .terminate = terminate
1734 };
1735
1736 MODULE(me)