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