Converted pollsocks to use select instead of poll.
[doldaconnect.git] / daemon / net.c
1 /*
2  *  Dolda Connect - Modular multiuser Direct Connect-style client
3  *  Copyright (C) 2004 Fredrik Tolf <fredrik@dolda2000.com>
4  *  
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *  
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *  
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19 /* XXX: Implement SOCKS proxyability */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <string.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <sys/ioctl.h>
29 #include <sys/socket.h>
30 #include <sys/un.h>
31 #include <sys/select.h>
32 #include <arpa/inet.h>
33 #include <netinet/in.h>
34 #include <netdb.h>
35 #include <sys/signal.h>
36 #include <sys/stat.h>       /* For rebindunix() */
37 #ifdef HAVE_LINUX_SOCKIOS_H
38 #include <linux/sockios.h>
39 #endif
40 #include <errno.h>
41 #include <net/if.h>
42
43 #include "conf.h"
44 #include "net.h"
45 #include "module.h"
46 #include "log.h"
47 #include "utils.h"
48 #include "sysevents.h"
49
50 static struct configvar myvars[] =
51 {
52     /** The network mode to use. Currently supported values are 0 for
53      * active mode and 1 for passive mode. In the future, SOCKS5 proxy
54      * support may be added. */
55     {CONF_VAR_INT, "mode", {.num = 0}},
56     /** Set the SO_REUSEADDR socket option on listening sockets, so
57      * that dead TCP connections waiting for timeout are ignored. */
58     {CONF_VAR_BOOL, "reuseaddr", {.num = 0}},
59     /** Overrides the IPv4 address reported to other clients in active
60      * mode. Useful for servers behind NAT routers. If both this and
61      * net.publicif are unspecified the address of the hub connection
62      * is used. */
63     {CONF_VAR_IPV4, "visibleipv4", {.ipv4 = {0}}},
64     /** Specifies an interface name from which to fetch the IPv4
65      * address reported to other clients in active mode. If both this
66      * and net.visibleipv4 are unspecified the address of the hub
67      * connection is used. */
68     {CONF_VAR_STRING, "publicif", {.str = L""}},
69     /* Diffserv should be supported on IPv4, too, but I don't know the
70      * API to do that. */
71     /** The Diffserv value to use on IPv6 connections when the
72      * minimize cost TOS value is used (see the TOS VALUES
73      * section). */
74     {CONF_VAR_INT, "diffserv-mincost", {.num = 0}},
75     /** The Diffserv value to use on IPv6 connections when the
76      * maximize reliability TOS value is used (see the TOS VALUES
77      * section). */
78     {CONF_VAR_INT, "diffserv-maxrel", {.num = 0}},
79     /** The Diffserv value to use on IPv6 connections when the
80      * maximize throughput TOS value is used (see the TOS VALUES
81      * section). */
82     {CONF_VAR_INT, "diffserv-maxtp", {.num = 0}},
83     /** The Diffserv value to use on IPv6 connections when the
84      * minimize delay TOS value is used (see the TOS VALUES
85      * section). */
86     {CONF_VAR_INT, "diffserv-mindelay", {.num = 0}},
87     {CONF_VAR_END}
88 };
89
90 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 ret, fd;
847     socklen_t retlen;
848     int newfd, maxfd;
849     fd_set rfds, wfds, efds;
850     struct socket *sk, *next, *newsk;
851     struct sockaddr_storage ss;
852     socklen_t sslen;
853     struct timeval tv;
854     
855     FD_ZERO(&rfds);
856     FD_ZERO(&wfds);
857     FD_ZERO(&efds);
858     for(maxfd = 0, sk = sockets; sk != NULL; sk = sk->next)
859     {
860         if((sk->state == SOCK_STL) || (sk->fd < 0))
861             continue;
862         if(!sk->ignread)
863             FD_SET(sk->fd, &rfds);
864         if((sk->state == SOCK_SYN) || (sockqueuesize(sk) > 0))
865             FD_SET(sk->fd, &wfds);
866         FD_SET(sk->fd, &efds);
867         if(sk->fd > maxfd)
868             maxfd = sk->fd;
869     }
870     tv.tv_sec = timeout / 1000;
871     tv.tv_usec = (timeout % 1000) * 1000;
872     ret = select(maxfd + 1, &rfds, &wfds, &efds, (timeout < 0)?NULL:&tv);
873     if(ret < 0)
874     {
875         if(errno != EINTR)
876         {
877             flog(LOG_CRIT, "pollsocks: select errored out: %s", strerror(errno));
878             /* To avoid CPU hogging in case it's bad, which it
879              * probably is. */
880             sleep(1);
881         }
882         return(1);
883     }
884     for(sk = sockets; sk != NULL; sk = next)
885     {
886         next = sk->next;
887         fd = sk->fd;
888         switch(sk->state)
889         {
890         case SOCK_LST:
891             if(FD_ISSET(fd, &rfds))
892             {
893                 sslen = sizeof(ss);
894                 if((newfd = accept(fd, (struct sockaddr *)&ss, &sslen)) < 0)
895                 {
896                     if(sk->errcb != NULL)
897                         sk->errcb(sk, errno, sk->data);
898                 }
899                 newsk = newsock(sk->type);
900                 newsk->fd = newfd;
901                 newsk->family = sk->family;
902                 newsk->state = SOCK_EST;
903                 memcpy(newsk->remote = smalloc(sslen), &ss, sslen);
904                 newsk->remotelen = sslen;
905                 if(ss.ss_family == PF_UNIX)
906                     acceptunix(newsk);
907                 if(sk->acceptcb != NULL)
908                     sk->acceptcb(sk, newsk, sk->data);
909                 putsock(newsk);
910             }
911             if(FD_ISSET(fd, &efds))
912             {
913                 retlen = sizeof(ret);
914                 getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
915                 if(sk->errcb != NULL)
916                     sk->errcb(sk, ret, sk->data);
917                 continue;
918             }
919             break;
920         case SOCK_SYN:
921             if(FD_ISSET(fd, &efds))
922             {
923                 retlen = sizeof(ret);
924                 getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
925                 if(sk->conncb != NULL)
926                     sk->conncb(sk, ret, sk->data);
927                 closesock(sk);
928                 continue;
929             }
930             if(FD_ISSET(fd, &rfds) || FD_ISSET(fd, &wfds))
931             {
932                 sk->state = SOCK_EST;
933                 if(sk->conncb != NULL)
934                     sk->conncb(sk, 0, sk->data);
935             }
936             break;
937         case SOCK_EST:
938             if(FD_ISSET(fd, &efds))
939             {
940                 retlen = sizeof(ret);
941                 getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, &retlen);
942                 if(sk->errcb != NULL)
943                     sk->errcb(sk, ret, sk->data);
944                 closesock(sk);
945                 continue;
946             }
947             if(FD_ISSET(fd, &rfds))
948                 sockrecv(sk);
949             if(FD_ISSET(fd, &wfds))
950             {
951                 if(sockqueuesize(sk) > 0)
952                     sockflush(sk);
953             }
954             break;
955         }
956     }
957     for(sk = sockets; sk != NULL; sk = next)
958     {
959         next = sk->next;
960         if(sk->refcount == 1 && (sockqueuesize(sk) == 0))
961         {
962             unlinksock(sk);
963             continue;
964         }
965         if(sk->close && (sockqueuesize(sk) == 0))
966             closesock(sk);
967         if(sk->state == SOCK_STL)
968         {
969             unlinksock(sk);
970             continue;
971         }
972     }
973     return(1);
974 }
975
976 int socksettos(struct socket *sk, int tos)
977 {
978     int buf;
979     
980     if(sk->family == AF_UNIX)
981         return(0); /* Unix sockets are always perfect. :) */
982     if(sk->family == AF_INET)
983     {
984         switch(tos)
985         {
986         case 0:
987             buf = 0;
988             break;
989         case SOCK_TOS_MINCOST:
990             buf = 0x02;
991             break;
992         case SOCK_TOS_MAXREL:
993             buf = 0x04;
994             break;
995         case SOCK_TOS_MAXTP:
996             buf = 0x08;
997             break;
998         case SOCK_TOS_MINDELAY:
999             buf = 0x10;
1000             break;
1001         default:
1002             flog(LOG_WARNING, "attempted to set unknown TOS value %i to IPv4 sock", tos);
1003             return(-1);
1004         }
1005         if(setsockopt(sk->fd, IPPROTO_IP, IP_TOS, &buf, sizeof(buf)) < 0)
1006         {
1007             flog(LOG_WARNING, "could not set sock TOS to %i: %s", tos, strerror(errno));
1008             return(-1);
1009         }
1010         return(0);
1011     }
1012     if(sk->family == AF_INET6)
1013     {
1014         switch(tos)
1015         {
1016         case 0:
1017             buf = 0;
1018         case SOCK_TOS_MINCOST:
1019             buf = confgetint("net", "diffserv-mincost");
1020             break;
1021         case SOCK_TOS_MAXREL:
1022             buf = confgetint("net", "diffserv-maxrel");
1023             break;
1024         case SOCK_TOS_MAXTP:
1025             buf = confgetint("net", "diffserv-maxtp");
1026             break;
1027         case SOCK_TOS_MINDELAY:
1028             buf = confgetint("net", "diffserv-mindelay");
1029             break;
1030         default:
1031             flog(LOG_WARNING, "attempted to set unknown TOS value %i to IPv4 sock", tos);
1032             return(-1);
1033         }
1034         /*
1035           On Linux, the API IPv6 flow label management doesn't seem to
1036           be entirely complete, so I guess this will have to wait.
1037           
1038         if(setsockopt(...) < 0)
1039         {
1040             flog(LOG_WARNING, "could not set sock traffic class to %i: %s", tos, strerror(errno));
1041             return(-1);
1042         }
1043         */
1044         return(0);
1045     }
1046     flog(LOG_WARNING, "could not set TOS on sock of family %i", sk->family);
1047     return(1);
1048 }
1049
1050 struct resolvedata
1051 {
1052     int fd;
1053     void (*callback)(struct sockaddr *addr, int addrlen, void *data);
1054     void *data;
1055     struct sockaddr_storage addr;
1056     int addrlen;
1057 };
1058
1059 static void resolvecb(pid_t pid, int status, struct resolvedata *data)
1060 {
1061     static char buf[80];
1062     int ret;
1063     struct sockaddr_in *ipv4;
1064     
1065     if(!status)
1066     {
1067         if((ret = read(data->fd, buf, sizeof(buf))) != 4)
1068         {
1069             errno = ENOENT;
1070             data->callback(NULL, 0, data->data);
1071         } else {
1072             ipv4 = (struct sockaddr_in *)&data->addr;
1073             memcpy(&ipv4->sin_addr, buf, 4);
1074             data->callback((struct sockaddr *)ipv4, sizeof(*ipv4), data->data);
1075         }
1076     } else {
1077         errno = ENOENT;
1078         data->callback(NULL, 0, data->data);
1079     }
1080     close(data->fd);
1081     free(data);
1082 }
1083
1084 int netresolve(char *addr, void (*callback)(struct sockaddr *addr, int addrlen, void *data), void *data)
1085 {
1086     int i;
1087     char *p;
1088     int port;
1089     int pfd[2];
1090     pid_t child;
1091     struct resolvedata *rdata;
1092     struct sockaddr_in ipv4;
1093     struct hostent *he;
1094     sigset_t sigset;
1095     
1096     /* IPv4 */
1097     port = -1;
1098     if((p = strchr(addr, ':')) != NULL)
1099     {
1100         *p = 0;
1101         port = atoi(p + 1);
1102     }
1103     ipv4.sin_family = AF_INET;
1104     ipv4.sin_port = htons(port);
1105     if(inet_aton(addr, &ipv4.sin_addr))
1106     {
1107         callback((struct sockaddr *)&ipv4, sizeof(ipv4), data);
1108     } else {
1109         sigemptyset(&sigset);
1110         sigaddset(&sigset, SIGCHLD);
1111         sigprocmask(SIG_BLOCK, &sigset, NULL);
1112         if((pipe(pfd) < 0) || ((child = fork()) < 0))
1113         {
1114             sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1115             return(-1);
1116         }
1117         if(child == 0)
1118         {
1119             sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1120             for(i = 3; i < FD_SETSIZE; i++)
1121             {
1122                 if(i != pfd[1])
1123                     close(i);
1124             }
1125             signal(SIGALRM, SIG_DFL);
1126             alarm(30);
1127             if((he = gethostbyname(addr)) == NULL)
1128                 exit(1);
1129             write(pfd[1], he->h_addr_list[0], 4);
1130             exit(0);
1131         } else {
1132             close(pfd[1]);
1133             fcntl(pfd[0], F_SETFL, fcntl(pfd[0], F_GETFL) | O_NONBLOCK);
1134             rdata = smalloc(sizeof(*rdata));
1135             rdata->fd = pfd[0];
1136             rdata->callback = callback;
1137             rdata->data = data;
1138             memcpy(&rdata->addr, &ipv4, rdata->addrlen = sizeof(ipv4));
1139             childcallback(child, (void (*)(pid_t, int, void *))resolvecb, rdata);
1140             sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1141             return(1);
1142         }
1143     }
1144     return(0);
1145 }
1146
1147 int sockgetlocalname(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf)
1148 {
1149     socklen_t len;
1150     struct sockaddr_storage name;
1151     
1152     *namebuf = NULL;
1153     if((sk->state == SOCK_STL) || (sk->fd < 0))
1154         return(-1);
1155     len = sizeof(name);
1156     if(getsockname(sk->fd, (struct sockaddr *)&name, &len) < 0)
1157     {
1158         flog(LOG_ERR, "BUG: alive socket with dead fd in sockgetlocalname (%s)", strerror(errno));
1159         return(-1);
1160     }
1161     *namebuf = memcpy(smalloc(len), &name, len);
1162     if(lenbuf != NULL)
1163         *lenbuf = len;
1164     return(0);
1165 }
1166
1167 static void sethostaddr(struct sockaddr *dst, struct sockaddr *src)
1168 {
1169     if(dst->sa_family != src->sa_family)
1170     {
1171         flog(LOG_ERR, "BUG: non-matching socket families in sethostaddr (%i -> %i)", src->sa_family, dst->sa_family);
1172         return;
1173     }
1174     switch(src->sa_family)
1175     {
1176     case AF_INET:
1177         ((struct sockaddr_in *)dst)->sin_addr = ((struct sockaddr_in *)src)->sin_addr;
1178         break;
1179     case AF_INET6:
1180         ((struct sockaddr_in6 *)dst)->sin6_addr = ((struct sockaddr_in6 *)src)->sin6_addr;
1181         break;
1182     default:
1183         flog(LOG_WARNING, "sethostaddr unimplemented for family %i", src->sa_family);
1184         break;
1185     }
1186 }
1187
1188 static int makepublic(struct sockaddr *addr)
1189 {
1190     int ret;
1191     socklen_t plen;
1192     struct sockaddr *pname;
1193     
1194     if((ret = getpublicaddr(addr->sa_family, &pname, &plen)) < 0)
1195     {
1196         flog(LOG_ERR, "could not get public address: %s", strerror(errno));
1197         return(-1);
1198     }
1199     if(ret)
1200         return(0);
1201     sethostaddr(addr, pname);
1202     free(pname);
1203     return(0);
1204 }
1205
1206 int sockgetremotename(struct socket *sk, struct sockaddr **namebuf, socklen_t *lenbuf)
1207 {
1208     socklen_t len;
1209     struct sockaddr *name;
1210     
1211     switch(confgetint("net", "mode"))
1212     {
1213     case 0:
1214         *namebuf = NULL;
1215         if((sk->state == SOCK_STL) || (sk->fd < 0))
1216         {
1217             errno = EBADF;
1218             return(-1);
1219         }
1220         if(!sockgetlocalname(sk, &name, &len))
1221         {
1222             *namebuf = name;
1223             *lenbuf = len;
1224             makepublic(name);
1225             return(0);
1226         }
1227         flog(LOG_ERR, "could not get remotely accessible name by any means");
1228         return(-1);
1229     case 1:
1230         errno = EOPNOTSUPP;
1231         return(-1);
1232     default:
1233         flog(LOG_CRIT, "unknown net mode %i active", confgetint("net", "mode"));
1234         errno = EOPNOTSUPP;
1235         return(-1);
1236     }
1237 }
1238
1239 int sockgetremotename2(struct socket *sk, struct socket *sk2, struct sockaddr **namebuf, socklen_t *lenbuf)
1240 {
1241     struct sockaddr *name1, *name2;
1242     socklen_t len1, len2;
1243     
1244     if(sk->family != sk2->family)
1245     {
1246         flog(LOG_ERR, "using sockgetremotename2 with sockets of differing family: %i %i", sk->family, sk2->family);
1247         return(-1);
1248     }
1249     if(sockgetremotename(sk, &name1, &len1))
1250         return(-1);
1251     if(sockgetremotename(sk2, &name2, &len2)) {
1252         free(name1);
1253         return(-1);
1254     }
1255     sethostaddr(name1, name2);
1256     free(name2);
1257     *namebuf = name1;
1258     *lenbuf = len1;
1259     return(0);
1260 }
1261
1262 int addreq(struct sockaddr *x, struct sockaddr *y)
1263 {
1264     struct sockaddr_un *u1, *u2;
1265     struct sockaddr_in *n1, *n2;
1266 #ifdef HAVE_IPV6
1267     struct sockaddr_in6 *s1, *s2;
1268 #endif
1269     
1270     if(x->sa_family != y->sa_family)
1271         return(0);
1272     switch(x->sa_family) {
1273     case AF_UNIX:
1274         u1 = (struct sockaddr_un *)x; u2 = (struct sockaddr_un *)y;
1275         if(strncmp(u1->sun_path, u2->sun_path, sizeof(u1->sun_path)))
1276             return(0);
1277         break;
1278     case AF_INET:
1279         n1 = (struct sockaddr_in *)x; n2 = (struct sockaddr_in *)y;
1280         if(n1->sin_port != n2->sin_port)
1281             return(0);
1282         if(n1->sin_addr.s_addr != n2->sin_addr.s_addr)
1283             return(0);
1284         break;
1285 #ifdef HAVE_IPV6
1286     case AF_INET6:
1287         s1 = (struct sockaddr_in6 *)x; s2 = (struct sockaddr_in6 *)y;
1288         if(s1->sin6_port != s2->sin6_port)
1289             return(0);
1290         if(memcmp(s1->sin6_addr.s6_addr, s2->sin6_addr.s6_addr, sizeof(s1->sin6_addr.s6_addr)))
1291             return(0);
1292         break;
1293 #endif
1294     }
1295     return(1);
1296 }
1297
1298 char *formataddress(struct sockaddr *arg, socklen_t arglen)
1299 {
1300     struct sockaddr_in *ipv4;
1301 #ifdef HAVE_IPV6
1302     struct sockaddr_in6 *ipv6;
1303 #endif
1304     static char *ret = NULL;
1305     char buf[1024];
1306     
1307     if(ret != NULL)
1308         free(ret);
1309     ret = NULL;
1310     switch(arg->sa_family)
1311     {
1312     case AF_UNIX:
1313         ret = sstrdup("Unix socket");
1314         break;
1315     case AF_INET:
1316         ipv4 = (struct sockaddr_in *)arg;
1317         if(inet_ntop(AF_INET, &ipv4->sin_addr, buf, sizeof(buf)) == NULL)
1318             return(NULL);
1319         ret = sprintf2("%s:%i", buf, (int)ntohs(ipv4->sin_port));
1320         break;
1321 #ifdef HAVE_IPV6
1322     case AF_INET6:
1323         ipv6 = (struct sockaddr_in6 *)arg;
1324         if(inet_ntop(AF_INET6, &ipv6->sin6_addr, buf, sizeof(buf)) == NULL)
1325             return(NULL);
1326         ret = sprintf2("[%s]:%i", buf, (int)ntohs(ipv6->sin6_port));
1327         break;
1328 #endif
1329     default:
1330         errno = EPFNOSUPPORT;
1331         break;
1332     }
1333     return(ret);
1334 }
1335
1336 #if 0
1337
1338 /* 
1339  * It was very nice to use this, but it seems
1340  * to mess things up, so I guess it has to go... :-(
1341  */
1342
1343 static int formataddress(FILE *stream, const struct printf_info *info, const void *const *args)
1344 {
1345     struct sockaddr *arg;
1346     socklen_t arglen;
1347     struct sockaddr_un *UNIX; /* Some wise guy has #defined unix with
1348                                * lowercase letters to 1, so I do this
1349                                * instead. */
1350     struct sockaddr_in *ipv4;
1351     int ret;
1352     
1353     arg = *(struct sockaddr **)(args[0]);
1354     arglen = *(socklen_t *)(args[1]);
1355     switch(arg->sa_family)
1356     {
1357     case AF_UNIX:
1358         UNIX = (struct sockaddr_un *)arg;
1359         ret = fprintf(stream, "%s", UNIX->sun_path);
1360         break;
1361     case AF_INET:
1362         ipv4 = (struct sockaddr_in *)arg;
1363         ret = fprintf(stream, "%s:%i", inet_ntoa(ipv4->sin_addr), (int)ntohs(ipv4->sin_port));
1364         break;
1365     default:
1366         ret = -1;
1367         errno = EPFNOSUPPORT;
1368         break;
1369     }
1370     return(ret);
1371 }
1372
1373 static int formataddress_arginfo(const struct printf_info *info, size_t n, int *argtypes)
1374 {
1375     if(n > 0)
1376         argtypes[0] = PA_POINTER;
1377     if(n > 1)
1378         argtypes[1] = PA_INT; /* Sources tell me that socklen_t _must_
1379                                * be an int, so I guess this should be
1380                                * safe. */
1381     return(2);
1382 }
1383 #endif
1384
1385 static int init(int hup)
1386 {
1387     if(!hup)
1388     {
1389         /*
1390         if(register_printf_function('N', formataddress, formataddress_arginfo))
1391         {
1392             flog(LOG_CRIT, "could not register printf handler %%N: %s", strerror(errno));
1393             return(1);
1394         }
1395         */
1396     }
1397     return(0);
1398 }
1399
1400 static void terminate(void)
1401 {
1402     while(sockets != NULL)
1403         unlinksock(sockets);
1404 }
1405
1406 static struct module me =
1407 {
1408     .name = "net",
1409     .conf =
1410     {
1411         .vars = myvars
1412     },
1413     .init = init,
1414     .terminate = terminate
1415 };
1416
1417 MODULE(me)