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