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