a8059d887e37c5cc48ce3b9f62c7c3e6dc56fe08
[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         free(sc);
979     }
980     for(sc = rbatch, rbatch = NULL; sc; sc = nsc) {
981         nsc = sc->n;
982         if(sc->s->readcb != NULL)
983             sc->s->readcb(sc->s, sc->s->data);
984         if((sockgetdatalen(sc->s) == 0) && (sc->s->eos == 1)) {
985             if(sc->s->errcb != NULL)
986                 sc->s->errcb(sc->s, 0, sc->s->data);
987             sc->s->eos = 2;
988         }
989         free(sc);
990     }
991     for(sc = wbatch, wbatch = NULL; sc; sc = nsc) {
992         nsc = sc->n;
993         if(sc->s->writecb != NULL)
994             sc->s->writecb(sc->s, sc->s->data);
995         free(sc);
996     }
997 }
998
999 static void cleansocks(void)
1000 {
1001     struct ufd *ufd, *next;
1002     
1003     for(ufd = ufds; ufd != NULL; ufd = next) {
1004         next = ufd->next;
1005         if(ufd->sk && (sockgetdatalen(ufd->sk) == 0)) {
1006             if(ufd->sk->eos == 1) {
1007                 ufd->sk->eos = 2;
1008                 closeufd(ufd);
1009                 closesock(ufd->sk);
1010             }
1011             if((ufd->sk->refcount == 1) && (ufd->sk->back->refcount == 0)) {
1012                 freeufd(ufd);
1013                 continue;
1014             }
1015         }
1016     }
1017 }
1018
1019 int pollsocks(int timeout)
1020 {
1021     int ret;
1022     socklen_t retlen;
1023     int newfd, maxfd;
1024     fd_set rfds, wfds, efds;
1025     struct ufd *ufd, *nufd;
1026     struct socket *nsk;
1027     struct sockaddr_storage ss;
1028     socklen_t sslen;
1029     struct timeval tv;
1030     
1031     cleansocks();
1032     FD_ZERO(&rfds);
1033     FD_ZERO(&wfds);
1034     FD_ZERO(&efds);
1035     for(maxfd = 0, ufd = ufds; ufd != NULL; ufd = ufd->next) {
1036         if(ufd->fd < 0)
1037             continue;
1038         if(!ufd->ignread)
1039             FD_SET(ufd->fd, &rfds);
1040         if(ufd->sk != NULL) {
1041             if(sockgetdatalen(ufd->sk) > 0)
1042                 FD_SET(ufd->fd, &wfds);
1043             else if(ufd->sk->state == SOCK_SYN)
1044                 FD_SET(ufd->fd, &wfds);
1045         }
1046         FD_SET(ufd->fd, &efds);
1047         if(ufd->fd > maxfd)
1048             maxfd = ufd->fd;
1049     }
1050     if(rbatch || wbatch || cbatch)
1051         timeout = 0;
1052     tv.tv_sec = timeout / 1000;
1053     tv.tv_usec = (timeout % 1000) * 1000;
1054     ret = select(maxfd + 1, &rfds, &wfds, &efds, (timeout < 0)?NULL:&tv);
1055     if(ret < 0) {
1056         if(errno != EINTR) {
1057             flog(LOG_CRIT, "pollsocks: select errored out: %s", strerror(errno));
1058             /* To avoid CPU hogging in case it's bad, which it
1059              * probably is. */
1060             sleep(1);
1061         }
1062         return(1);
1063     }
1064     for(ufd = ufds; ufd != NULL; ufd = ufd->next) {
1065         if(ufd->sk < 0)
1066             continue;
1067         if(ufd->type == UFD_LISTEN) {
1068             if(FD_ISSET(ufd->fd, &rfds)) {
1069                 sslen = sizeof(ss);
1070                 if((newfd = accept(ufd->fd, (struct sockaddr *)&ss, &sslen)) < 0) {
1071                     if(ufd->d.l.lp->errcb != NULL)
1072                         ufd->d.l.lp->errcb(ufd->d.l.lp, errno, ufd->d.l.lp->data);
1073                 }
1074                 nsk = sockpair(0);
1075                 nufd = mkufd(newfd, UFD_SOCK, nsk);
1076                 nufd->d.s.family = ufd->d.l.family;
1077                 sksetstate(nsk, SOCK_EST);
1078                 memcpy(nufd->d.s.remote = smalloc(sslen), &ss, sslen);
1079                 nufd->d.s.remotelen = sslen;
1080                 if(ss.ss_family == PF_UNIX)
1081                     acceptunix(nufd);
1082                 if(ufd->d.l.lp->acceptcb != NULL)
1083                     ufd->d.l.lp->acceptcb(ufd->d.l.lp, nsk->back, ufd->d.l.lp->data);
1084                 putsock(nsk);
1085             }
1086             if(FD_ISSET(ufd->fd, &efds)) {
1087                 retlen = sizeof(ret);
1088                 getsockopt(ufd->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
1089                 if(ufd->d.l.lp->errcb != NULL)
1090                     ufd->d.l.lp->errcb(ufd->d.l.lp, ret, ufd->d.l.lp->data);
1091                 continue;
1092             }
1093         } else {
1094             if(ufd->sk->state == SOCK_SYN) {
1095                 if(FD_ISSET(ufd->fd, &efds)) {
1096                     retlen = sizeof(ret);
1097                     getsockopt(ufd->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
1098                     if(ufd->sk->back->conncb != NULL)
1099                         ufd->sk->back->conncb(ufd->sk->back, ret, ufd->sk->back->data);
1100                     closeufd(ufd);
1101                     continue;
1102                 }
1103                 if(FD_ISSET(ufd->fd, &rfds) || FD_ISSET(ufd->fd, &wfds)) {
1104                     sksetstate(ufd->sk, SOCK_EST);
1105                     linksock(&cbatch, ufd->sk->back);
1106                 }
1107             } else if(ufd->sk->state == SOCK_EST) {
1108                 if(FD_ISSET(ufd->fd, &efds)) {
1109                     retlen = sizeof(ret);
1110                     getsockopt(ufd->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
1111                     sockerror(ufd->sk, ret);
1112                     closeufd(ufd);
1113                     continue;
1114                 }
1115                 if(FD_ISSET(ufd->fd, &rfds))
1116                     sockrecv(ufd);
1117                 if(ufd->fd == -1)
1118                     continue;
1119                 if(FD_ISSET(ufd->fd, &wfds))
1120                     sockflush(ufd);
1121             }
1122         }
1123     }
1124     runbatches();
1125     cleansocks();
1126     return(1);
1127 }
1128
1129 static struct ufd *getskufd(struct socket *sk)
1130 {
1131     while(1) {
1132         if(sk->back->ufd != NULL)
1133             return(sk->back->ufd);
1134         if((sk = sk->back->pnext) == NULL)
1135             break;
1136     }
1137     return(NULL);
1138 }
1139
1140 int socksettos(struct socket *sk, int tos)
1141 {
1142     int buf;
1143     struct ufd *ufd;
1144     
1145     ufd = getskufd(sk);
1146     if(ufd->type != UFD_SOCK) {
1147         errno = EOPNOTSUPP;
1148         return(-1);
1149     }
1150     if(ufd->d.s.family == AF_UNIX)
1151         return(0); /* Unix sockets are always perfect. :) */
1152     if(ufd->d.s.family == AF_INET)
1153     {
1154         switch(tos)
1155         {
1156         case 0:
1157             buf = 0;
1158             break;
1159         case SOCK_TOS_MINCOST:
1160             buf = 0x02;
1161             break;
1162         case SOCK_TOS_MAXREL:
1163             buf = 0x04;
1164             break;
1165         case SOCK_TOS_MAXTP:
1166             buf = 0x08;
1167             break;
1168         case SOCK_TOS_MINDELAY:
1169             buf = 0x10;
1170             break;
1171         default:
1172             flog(LOG_WARNING, "attempted to set unknown TOS value %i to IPv4 sock", tos);
1173             return(-1);
1174         }
1175         if(setsockopt(ufd->fd, IPPROTO_IP, IP_TOS, &buf, sizeof(buf)) < 0)
1176         {
1177             flog(LOG_WARNING, "could not set sock TOS to %i: %s", tos, strerror(errno));
1178             return(-1);
1179         }
1180         return(0);
1181     }
1182     if(ufd->d.s.family == AF_INET6)
1183     {
1184         switch(tos)
1185         {
1186         case 0:
1187             buf = 0;
1188         case SOCK_TOS_MINCOST:
1189             buf = confgetint("net", "diffserv-mincost");
1190             break;
1191         case SOCK_TOS_MAXREL:
1192             buf = confgetint("net", "diffserv-maxrel");
1193             break;
1194         case SOCK_TOS_MAXTP:
1195             buf = confgetint("net", "diffserv-maxtp");
1196             break;
1197         case SOCK_TOS_MINDELAY:
1198             buf = confgetint("net", "diffserv-mindelay");
1199             break;
1200         default:
1201             flog(LOG_WARNING, "attempted to set unknown TOS value %i to IPv4 sock", tos);
1202             return(-1);
1203         }
1204         /*
1205           On Linux, the API IPv6 flow label management doesn't seem to
1206           be entirely complete, so I guess this will have to wait.
1207           
1208         if(setsockopt(...) < 0)
1209         {
1210             flog(LOG_WARNING, "could not set sock traffic class to %i: %s", tos, strerror(errno));
1211             return(-1);
1212         }
1213         */
1214         return(0);
1215     }
1216     flog(LOG_WARNING, "could not set TOS on sock of family %i", ufd->d.s.family);
1217     return(1);
1218 }
1219
1220 struct resolvedata
1221 {
1222     int fd;
1223     void (*callback)(struct sockaddr *addr, int addrlen, void *data);
1224     void *data;
1225     struct sockaddr_storage addr;
1226     int addrlen;
1227 };
1228
1229 static void resolvecb(pid_t pid, int status, struct resolvedata *data)
1230 {
1231     static char buf[80];
1232     int ret;
1233     struct sockaddr_in *ipv4;
1234     
1235     if(!status)
1236     {
1237         if((ret = read(data->fd, buf, sizeof(buf))) != 4)
1238         {
1239             errno = ENOENT;
1240             data->callback(NULL, 0, data->data);
1241         } else {
1242             ipv4 = (struct sockaddr_in *)&data->addr;
1243             memcpy(&ipv4->sin_addr, buf, 4);
1244             data->callback((struct sockaddr *)ipv4, sizeof(*ipv4), data->data);
1245         }
1246     } else {
1247         errno = ENOENT;
1248         data->callback(NULL, 0, data->data);
1249     }
1250     close(data->fd);
1251     free(data);
1252 }
1253
1254 int netresolve(char *addr, void (*callback)(struct sockaddr *addr, int addrlen, void *data), void *data)
1255 {
1256     int i;
1257     char *p;
1258     int port;
1259     int pfd[2];
1260     pid_t child;
1261     struct resolvedata *rdata;
1262     struct sockaddr_in ipv4;
1263     struct hostent *he;
1264     sigset_t sigset;
1265     
1266     /* IPv4 */
1267     port = -1;
1268     if((p = strchr(addr, ':')) != NULL)
1269     {
1270         *p = 0;
1271         port = atoi(p + 1);
1272     }
1273     ipv4.sin_family = AF_INET;
1274     ipv4.sin_port = htons(port);
1275     if(inet_aton(addr, &ipv4.sin_addr))
1276     {
1277         callback((struct sockaddr *)&ipv4, sizeof(ipv4), data);
1278     } else {
1279         sigemptyset(&sigset);
1280         sigaddset(&sigset, SIGCHLD);
1281         sigprocmask(SIG_BLOCK, &sigset, NULL);
1282         if((pipe(pfd) < 0) || ((child = fork()) < 0))
1283         {
1284             sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1285             return(-1);
1286         }
1287         if(child == 0)
1288         {
1289             sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1290             for(i = 3; i < FD_SETSIZE; i++)
1291             {
1292                 if(i != pfd[1])
1293                     close(i);
1294             }
1295             signal(SIGALRM, SIG_DFL);
1296             alarm(30);
1297             if((he = gethostbyname(addr)) == NULL)
1298                 exit(1);
1299             write(pfd[1], he->h_addr_list[0], 4);
1300             exit(0);
1301         } else {
1302             close(pfd[1]);
1303             fcntl(pfd[0], F_SETFL, fcntl(pfd[0], F_GETFL) | O_NONBLOCK);
1304             rdata = smalloc(sizeof(*rdata));
1305             rdata->fd = pfd[0];
1306             rdata->callback = callback;
1307             rdata->data = data;
1308             memcpy(&rdata->addr, &ipv4, rdata->addrlen = sizeof(ipv4));
1309             childcallback(child, (void (*)(pid_t, int, void *))resolvecb, rdata);
1310             sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1311             return(1);
1312         }
1313     }
1314     return(0);
1315 }
1316
1317 static int getlocalname(int fd, struct sockaddr **namebuf, socklen_t *lenbuf)
1318 {
1319     socklen_t len;
1320     struct sockaddr_storage name;
1321     
1322     *namebuf = NULL;
1323     if(fd < 0)
1324         return(-1);
1325     len = sizeof(name);
1326     if(getsockname(fd, (struct sockaddr *)&name, &len) < 0)
1327     {
1328         flog(LOG_ERR, "BUG: alive socket with dead fd in sockgetlocalname (%s)", strerror(errno));
1329         return(-1);
1330     }
1331     *namebuf = memcpy(smalloc(len), &name, len);
1332     if(lenbuf != NULL)
1333         *lenbuf = len;
1334     return(0);
1335 }
1336
1337 int lstgetlocalname(struct lport *lp, struct sockaddr **namebuf, socklen_t *lenbuf)
1338 {
1339     struct ufd *ufd;
1340
1341     ufd = lp->ufd;
1342     return(getlocalname(ufd->fd, namebuf, lenbuf));
1343 }
1344
1345 int sockgetlocalname(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf)
1346 {
1347     struct ufd *ufd;
1348
1349     ufd = getskufd(sk);
1350     if(ufd->type != UFD_SOCK) {
1351         errno = EOPNOTSUPP;
1352         return(-1);
1353     }
1354     return(getlocalname(ufd->fd, namebuf, lenbuf));
1355 }
1356
1357 static void sethostaddr(struct sockaddr *dst, struct sockaddr *src)
1358 {
1359     if(dst->sa_family != src->sa_family)
1360     {
1361         flog(LOG_ERR, "BUG: non-matching socket families in sethostaddr (%i -> %i)", src->sa_family, dst->sa_family);
1362         return;
1363     }
1364     switch(src->sa_family)
1365     {
1366     case AF_INET:
1367         ((struct sockaddr_in *)dst)->sin_addr = ((struct sockaddr_in *)src)->sin_addr;
1368         break;
1369     case AF_INET6:
1370         ((struct sockaddr_in6 *)dst)->sin6_addr = ((struct sockaddr_in6 *)src)->sin6_addr;
1371         break;
1372     default:
1373         flog(LOG_WARNING, "sethostaddr unimplemented for family %i", src->sa_family);
1374         break;
1375     }
1376 }
1377
1378 static int makepublic(struct sockaddr *addr)
1379 {
1380     int ret;
1381     socklen_t plen;
1382     struct sockaddr *pname;
1383     
1384     if((ret = getpublicaddr(addr->sa_family, &pname, &plen)) < 0)
1385     {
1386         flog(LOG_ERR, "could not get public address: %s", strerror(errno));
1387         return(-1);
1388     }
1389     if(ret)
1390         return(0);
1391     sethostaddr(addr, pname);
1392     free(pname);
1393     return(0);
1394 }
1395
1396 static int getremotename(int fd, struct sockaddr **namebuf, socklen_t *lenbuf)
1397 {
1398     socklen_t len;
1399     struct sockaddr *name;
1400
1401     switch(confgetint("net", "mode")) {
1402     case 0:
1403         *namebuf = NULL;
1404         if(!getlocalname(fd, &name, &len)) {
1405             *namebuf = name;
1406             *lenbuf = len;
1407             makepublic(name);
1408             return(0);
1409         }
1410         flog(LOG_ERR, "could not get remotely accessible name by any means");
1411         return(-1);
1412     case 1:
1413         errno = EOPNOTSUPP;
1414         return(-1);
1415     default:
1416         flog(LOG_CRIT, "unknown net mode %i active", confgetint("net", "mode"));
1417         errno = EOPNOTSUPP;
1418         return(-1);
1419     }
1420 }
1421
1422 int sockgetremotename(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf)
1423 {
1424     struct ufd *ufd;
1425     
1426     ufd = getskufd(sk);
1427     if(ufd->type != UFD_SOCK) {
1428         errno = EOPNOTSUPP;
1429         return(-1);
1430     }
1431     if(ufd->fd < 0) {
1432         errno = EBADF;
1433         return(-1);
1434     }
1435     return(getremotename(ufd->fd, namebuf, lenbuf));
1436 }
1437
1438 int lstgetremotename(struct lport *lp, struct sockaddr **namebuf, socklen_t *lenbuf)
1439 {
1440     struct ufd *ufd;
1441     
1442     ufd = lp->ufd;
1443     return(getremotename(ufd->fd, namebuf, lenbuf));
1444 }
1445
1446 int sockgetremotename2(struct socket *sk, struct socket *sk2, struct sockaddr **namebuf, socklen_t *lenbuf)
1447 {
1448     struct sockaddr *name1, *name2;
1449     socklen_t len1, len2;
1450     struct ufd *ufd1, *ufd2;
1451     
1452     ufd1 = getskufd(sk);
1453     ufd2 = getskufd(sk2);
1454     if((ufd1->type != UFD_SOCK) || (ufd2->type != UFD_SOCK)) {
1455         errno = EOPNOTSUPP;
1456         return(-1);
1457     }
1458     if(ufd1->d.s.family != ufd2->d.s.family)
1459     {
1460         flog(LOG_ERR, "using sockgetremotename2 with sockets of differing family: %i %i", ufd1->d.s.family, ufd2->d.s.family);
1461         return(-1);
1462     }
1463     if(getremotename(ufd1->fd, &name1, &len1))
1464         return(-1);
1465     if(getremotename(ufd2->fd, &name2, &len2)) {
1466         free(name1);
1467         return(-1);
1468     }
1469     sethostaddr(name1, name2);
1470     free(name2);
1471     *namebuf = name1;
1472     *lenbuf = len1;
1473     return(0);
1474 }
1475
1476 int lstgetremotename2(struct lport *lp, struct socket *sk2, struct sockaddr **namebuf, socklen_t *lenbuf)
1477 {
1478     struct sockaddr *name1, *name2;
1479     socklen_t len1, len2;
1480     struct ufd *ufd1, *ufd2;
1481     
1482     ufd1 = lp->ufd;
1483     ufd2 = getskufd(sk2);
1484     if(ufd2->type != UFD_SOCK) {
1485         errno = EOPNOTSUPP;
1486         return(-1);
1487     }
1488     if(ufd1->d.s.family != ufd2->d.s.family)
1489     {
1490         flog(LOG_ERR, "using lstgetremotename2 with sockets of differing family: %i %i", ufd1->d.s.family, ufd2->d.s.family);
1491         return(-1);
1492     }
1493     if(getremotename(ufd1->fd, &name1, &len1))
1494         return(-1);
1495     if(getremotename(ufd2->fd, &name2, &len2)) {
1496         free(name1);
1497         return(-1);
1498     }
1499     sethostaddr(name1, name2);
1500     free(name2);
1501     *namebuf = name1;
1502     *lenbuf = len1;
1503     return(0);
1504 }
1505
1506 int getucred(struct socket *sk, uid_t *uid, gid_t *gid)
1507 {
1508     struct ufd *ufd;
1509     
1510     ufd = getskufd(sk);
1511     if(ufd->type != UFD_SOCK) {
1512         errno = EOPNOTSUPP;
1513         return(-1);
1514     }
1515     if(ufd->d.s.family != AF_UNIX) {
1516         errno = EOPNOTSUPP;
1517         return(-1);
1518     }
1519     *uid = ufd->d.s.ucred.uid;
1520     *gid = ufd->d.s.ucred.gid;
1521     return(0);
1522 }
1523
1524 void sockblock(struct socket *sk, int block)
1525 {
1526     struct ufd *ufd;
1527     
1528     ufd = getskufd(sk);
1529     ufd->ignread = block;
1530 }
1531
1532 int sockfamily(struct socket *sk)
1533 {
1534     struct ufd *ufd;
1535     
1536     ufd = getskufd(sk);
1537     if(ufd->type != UFD_SOCK) {
1538         errno = EOPNOTSUPP;
1539         return(-1);
1540     }
1541     return(ufd->d.s.family);
1542 }
1543
1544 int sockpeeraddr(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf)
1545 {
1546     struct ufd *ufd;
1547     
1548     ufd = getskufd(sk);
1549     if(ufd->type != UFD_SOCK) {
1550         errno = EOPNOTSUPP;
1551         return(-1);
1552     }
1553     if(ufd->d.s.remote == NULL)
1554         return(-1);
1555     *namebuf = memcpy(smalloc(ufd->d.s.remotelen), ufd->d.s.remote, ufd->d.s.remotelen);
1556     if(lenbuf != NULL)
1557         *lenbuf = ufd->d.s.remotelen;
1558     return(0);
1559 }
1560
1561 char *formatsockpeer(struct socket *sk)
1562 {
1563     struct sockaddr *name;
1564     socklen_t nlen;
1565     char *ret;
1566     
1567     if(sockpeeraddr(sk, &name, &nlen))
1568         return(NULL);
1569     ret = formataddress(name, nlen);
1570     free(name);
1571     return(ret);
1572 }
1573
1574 int addreq(struct sockaddr *x, struct sockaddr *y)
1575 {
1576     struct sockaddr_un *u1, *u2;
1577     struct sockaddr_in *n1, *n2;
1578 #ifdef HAVE_IPV6
1579     struct sockaddr_in6 *s1, *s2;
1580 #endif
1581     
1582     if(x->sa_family != y->sa_family)
1583         return(0);
1584     switch(x->sa_family) {
1585     case AF_UNIX:
1586         u1 = (struct sockaddr_un *)x; u2 = (struct sockaddr_un *)y;
1587         if(strncmp(u1->sun_path, u2->sun_path, sizeof(u1->sun_path)))
1588             return(0);
1589         break;
1590     case AF_INET:
1591         n1 = (struct sockaddr_in *)x; n2 = (struct sockaddr_in *)y;
1592         if(n1->sin_port != n2->sin_port)
1593             return(0);
1594         if(n1->sin_addr.s_addr != n2->sin_addr.s_addr)
1595             return(0);
1596         break;
1597 #ifdef HAVE_IPV6
1598     case AF_INET6:
1599         s1 = (struct sockaddr_in6 *)x; s2 = (struct sockaddr_in6 *)y;
1600         if(s1->sin6_port != s2->sin6_port)
1601             return(0);
1602         if(memcmp(s1->sin6_addr.s6_addr, s2->sin6_addr.s6_addr, sizeof(s1->sin6_addr.s6_addr)))
1603             return(0);
1604         break;
1605 #endif
1606     }
1607     return(1);
1608 }
1609
1610 char *formataddress(struct sockaddr *arg, socklen_t arglen)
1611 {
1612     struct sockaddr_in *ipv4;
1613 #ifdef HAVE_IPV6
1614     struct sockaddr_in6 *ipv6;
1615 #endif
1616     static char *ret = NULL;
1617     char buf[1024];
1618     
1619     if(ret != NULL)
1620         free(ret);
1621     ret = NULL;
1622     switch(arg->sa_family)
1623     {
1624     case AF_UNIX:
1625         ret = sstrdup("Unix socket");
1626         break;
1627     case AF_INET:
1628         ipv4 = (struct sockaddr_in *)arg;
1629         if(inet_ntop(AF_INET, &ipv4->sin_addr, buf, sizeof(buf)) == NULL)
1630             return(NULL);
1631         ret = sprintf2("%s:%i", buf, (int)ntohs(ipv4->sin_port));
1632         break;
1633 #ifdef HAVE_IPV6
1634     case AF_INET6:
1635         ipv6 = (struct sockaddr_in6 *)arg;
1636         if(inet_ntop(AF_INET6, &ipv6->sin6_addr, buf, sizeof(buf)) == NULL)
1637             return(NULL);
1638         ret = sprintf2("[%s]:%i", buf, (int)ntohs(ipv6->sin6_port));
1639         break;
1640 #endif
1641     default:
1642         errno = EPFNOSUPPORT;
1643         break;
1644     }
1645     return(ret);
1646 }
1647
1648 #if 0
1649
1650 /* 
1651  * It was very nice to use this, but it seems
1652  * to mess things up, so I guess it has to go... :-(
1653  */
1654
1655 static int formataddress(FILE *stream, const struct printf_info *info, const void *const *args)
1656 {
1657     struct sockaddr *arg;
1658     socklen_t arglen;
1659     struct sockaddr_un *UNIX; /* Some wise guy has #defined unix with
1660                                * lowercase letters to 1, so I do this
1661                                * instead. */
1662     struct sockaddr_in *ipv4;
1663     int ret;
1664     
1665     arg = *(struct sockaddr **)(args[0]);
1666     arglen = *(socklen_t *)(args[1]);
1667     switch(arg->sa_family)
1668     {
1669     case AF_UNIX:
1670         UNIX = (struct sockaddr_un *)arg;
1671         ret = fprintf(stream, "%s", UNIX->sun_path);
1672         break;
1673     case AF_INET:
1674         ipv4 = (struct sockaddr_in *)arg;
1675         ret = fprintf(stream, "%s:%i", inet_ntoa(ipv4->sin_addr), (int)ntohs(ipv4->sin_port));
1676         break;
1677     default:
1678         ret = -1;
1679         errno = EPFNOSUPPORT;
1680         break;
1681     }
1682     return(ret);
1683 }
1684
1685 static int formataddress_arginfo(const struct printf_info *info, size_t n, int *argtypes)
1686 {
1687     if(n > 0)
1688         argtypes[0] = PA_POINTER;
1689     if(n > 1)
1690         argtypes[1] = PA_INT; /* Sources tell me that socklen_t _must_
1691                                * be an int, so I guess this should be
1692                                * safe. */
1693     return(2);
1694 }
1695 #endif
1696
1697 static int init(int hup)
1698 {
1699     if(!hup)
1700     {
1701         /*
1702         if(register_printf_function('N', formataddress, formataddress_arginfo))
1703         {
1704             flog(LOG_CRIT, "could not register printf handler %%N: %s", strerror(errno));
1705             return(1);
1706         }
1707         */
1708     }
1709     return(0);
1710 }
1711
1712 static void terminate(void)
1713 {
1714     /*
1715     while(ufds != NULL)
1716         freeufd(ufds);
1717     */
1718 }
1719
1720 static struct module me =
1721 {
1722     .name = "net",
1723     .conf =
1724     {
1725         .vars = myvars
1726     },
1727     .init = init,
1728     .terminate = terminate
1729 };
1730
1731 MODULE(me)