Back to index

courier  0.68.2
tcpd.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2009 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #if    HAVE_CONFIG_H
00007 #include      "config.h"
00008 #endif
00009 
00010 /*
00011 ** OK - the poop is that if we include socks.h after stdio.h, SOCKSfwrite
00012 ** does not get prototyped.
00013 ** If we include socks.h before stdio.h, gcc will complain about getc being
00014 ** redefined.  The easiest solution is to simply undef getc, because we
00015 ** don't use it here.
00016 */
00017 
00018 #include      "soxwrap/soxwrap.h"
00019 #include      <stdio.h>
00020 
00021 
00022 #include      <sys/types.h>
00023 #include      <sys/time.h>
00024 #include      <arpa/inet.h>
00025 #include      <pwd.h>
00026 #include      <grp.h>
00027 #include      <stdlib.h>
00028 #include      <string.h>
00029 #include      <ctype.h>
00030 #include      <stdio.h>
00031 #include      <errno.h>
00032 #include      <signal.h>
00033 #if    HAVE_SYS_STAT_H
00034 #include      <sys/stat.h>
00035 #endif
00036 #if    HAVE_FCNTL_H
00037 #include      <fcntl.h>
00038 #endif
00039 #if    HAVE_SYS_IOCTL_H
00040 #include      <sys/ioctl.h>
00041 #endif
00042 #if HAVE_UNISTD_H
00043 #include      <unistd.h>
00044 #endif
00045 #include      "waitlib/waitlib.h"
00046 #include      "rfc1035/rfc1035.h"
00047 #include      "liblock/config.h"
00048 #include      "liblock/liblock.h"
00049 #include      "tcpremoteinfo.h"
00050 #include      "numlib/numlib.h"
00051 #include      "argparse.h"
00052 
00053 #include      <netdb.h>
00054 
00055 
00056 static const char *accessarg=0;
00057 static const char *accesslocal=0;
00058 static const char *denymsgarg=0;
00059 static const char *listenarg=0;
00060 static const char *ipaddrarg=0;
00061 static const char *userarg=0;
00062 static const char *grouparg=0;
00063 static const char *maxprocsarg=0;
00064 static const char *warnarg=0;
00065 static const char *maxperiparg=0;
00066 static const char *maxpercarg=0;
00067 static const char *droparg=0;
00068 static const char *nodnslookup=0;
00069 static const char *noidentlookup=0;
00070 static const char *stderrarg=0;
00071 static const char *stderrloggerarg=0;
00072 static const char *pidarg=0;
00073 static const char *proxyarg=0;
00074 static const char *restartarg=0;
00075 static const char *stoparg=0;
00076 static const char *stderrloggername=0;
00077 
00078 static char *lockfilename;
00079 
00080 static void setup_block(const char *);
00081 
00082 static struct args arginfo[]={
00083        {"access", &accessarg},
00084        {"accesslocal", &accesslocal},
00085        {"denymsg", &denymsgarg},
00086        {"drop", &droparg},
00087        {"address", &ipaddrarg},
00088        {"block", 0, setup_block},
00089        {"group", &grouparg},
00090        {"listen", &listenarg},
00091        {"maxperc", &maxpercarg},
00092        {"maxperip", &maxperiparg},
00093        {"maxprocs", &maxprocsarg},
00094        {"warn", &warnarg},
00095        {"nodnslookup", &nodnslookup},
00096        {"noidentlookup", &noidentlookup},
00097        {"pid", &pidarg},
00098        {"restart", &restartarg},
00099        {"stderr", &stderrarg},
00100        {"stderrlogger", &stderrloggerarg},
00101        {"stderrloggername", &stderrloggername},
00102        {"stop", &stoparg},
00103        {"user", &userarg},
00104        {"proxy", &proxyarg},
00105        {0}
00106        } ;
00107 
00108 /* Ports we're listening on: */
00109 
00110 static struct portinfo {
00111        struct portinfo *next;
00112        const char *ipaddr;  /* Specific IP addr, or 0 */
00113        const char *servname;       /* Service name/port */
00114 
00115        int fd1, fd2;        /* BSD may need both IPv4 and IPv6 sockets */
00116 } *fdlist=0;
00117 static int maxfd;
00118 
00119 static int nprocs, maxperc, maxperip, nwarn;
00120 static pid_t *pids;
00121 static time_t last_alert=0, last_warn=0;
00122 static RFC1035_ADDR *addrs;
00123 
00124 static int sighup_received=0;
00125 
00126 struct blocklist_s {
00127        struct blocklist_s *next;
00128        char *zone;
00129        char *var;
00130        struct in_addr ia;   /* 0, anything */
00131        char *msg;           /* NULL, query for TXT record */
00132        } *blocklist=0;
00133 
00134 extern int openaccess(const char *);
00135 extern void closeaccess();
00136 extern char *chkaccess(const char *);
00137 
00138 static void setup_block(const char *blockinfo)
00139 {
00140 struct blocklist_s *newbl=(struct blocklist_s *)malloc(sizeof(*blocklist));
00141 char   *p;
00142 struct blocklist_s **blptr;
00143 
00144        for (blptr= &blocklist; *blptr; blptr=&(*blptr)->next)
00145               ;
00146 
00147        if (!newbl || (newbl->zone=malloc(strlen(blockinfo)+1)) == 0)
00148        {
00149               perror("malloc");
00150               exit(1);
00151        }
00152 
00153        *blptr=newbl;
00154        newbl->next=0;
00155        strcpy(newbl->zone, blockinfo);
00156        newbl->var=strchr(newbl->zone, ',');
00157        newbl->msg=0;
00158        newbl->ia.s_addr=INADDR_ANY;
00159 
00160        if (newbl->var)
00161               *newbl->var++=0;
00162        if (newbl->var && *newbl->var)
00163               newbl->msg=strchr(newbl->var, ',');
00164        if (newbl->msg)
00165               *newbl->msg++=0;
00166        if (newbl->var && (p=strchr(newbl->var, '/')) != 0)
00167        {
00168               *p++=0;
00169               rfc1035_aton_ipv4(p, &newbl->ia);
00170        }
00171 }
00172 
00173 static int isid(const char *p)
00174 {
00175        while (*p)
00176        {
00177               if (*p < '0' || *p > '9')   return (0);
00178               ++p;
00179        }
00180        return (1);
00181 }
00182 
00183 static RETSIGTYPE sigexit(int n)
00184 {
00185        kill( -getpid(), SIGTERM);
00186        _exit(0);
00187 
00188 #if RETSIGTYPE != void
00189        return (0)
00190 #endif
00191 }
00192 
00193 static RETSIGTYPE sighup(int n)
00194 {
00195        sighup_received=1;
00196 
00197        signal(SIGHUP, sighup);
00198 
00199 #if RETSIGTYPE != void
00200        return (0)
00201 #endif
00202 }
00203 
00204 /*
00205 ** Initialize a single listening socket
00206 */
00207 
00208 static struct portinfo *createport(const char *a, const char *s)
00209 {
00210        struct portinfo *p=(struct portinfo *)malloc(sizeof(struct portinfo));
00211 
00212        if (!p)
00213        {
00214               perror("malloc");
00215               return (NULL);
00216        }
00217 
00218        p->next=fdlist;
00219        fdlist=p;
00220        p->ipaddr=a;
00221        p->servname=s;
00222        p->fd1=p->fd2= -1;
00223        return (p);
00224 }
00225 
00226 static int parseaddr(const char *p)
00227 {
00228        char *buf=strdup(p);
00229        char *q, *a, *s;
00230 
00231        if (!buf)
00232        {
00233               perror("malloc");
00234               return (-1);
00235        }
00236 
00237        for (q=buf; (q=strtok(q, ",")) != NULL; q=0)
00238        {
00239               if ((s=strrchr(q, '.')) != 0)
00240               {
00241                      *s++=0;
00242                      a=q;
00243               }
00244               else
00245               {
00246                      a=0;
00247                      s=q;
00248               }
00249 
00250               if (createport(a, s) == NULL)
00251                      return (-1);
00252        }
00253 
00254        if (ipaddrarg)
00255        {
00256               struct portinfo *p;
00257 
00258               for (p=fdlist; p; p=p->next)
00259               {
00260                      if (p->ipaddr && strcmp(p->ipaddr, "0"))
00261                             continue;
00262                      p->ipaddr=ipaddrarg;
00263               }
00264        }
00265 
00266        return (0);
00267 }
00268 
00269 /*
00270 ** Create one socket, bound to a specific host/port
00271 */
00272 
00273 static int mksocket(const char *ipaddrarg,       /* Host/IP address */
00274                   const char *servname,   /* Service/port */
00275                   int flags)
00276 
00277 #define MKS_USEAFINET4 1
00278 #define MKS_ERROK 2
00279 
00280 {
00281        struct servent *servptr;
00282        int    port;
00283        int    fd;
00284 
00285        RFC1035_ADDR addr;
00286        RFC1035_NETADDR  netaddr;
00287        const struct sockaddr *sinaddr;
00288        int    sinaddrlen;
00289 
00290 #if    RFC1035_IPV6
00291        struct sockaddr_in6  sin6;
00292 #endif
00293 
00294        struct sockaddr_in   sin4;
00295 
00296        int    af;
00297 
00298        servptr=getservbyname(servname, "tcp");
00299        if (servptr)
00300               port=servptr->s_port;
00301        else
00302        {
00303               port=atoi(servname);
00304               if (port <= 0 || port > 65535)
00305               {
00306                      fprintf(stderr, "Invalid port: %s\n", servname);
00307                      return (-1);
00308               }
00309               port=htons(port);
00310        }
00311 
00312        /* Create an IPv6 or an IPv4 socket */
00313 
00314 #if    RFC1035_IPV6
00315        if (flags & MKS_USEAFINET4)
00316        {
00317               fd=socket(PF_INET, SOCK_STREAM, 0);
00318               af=AF_INET;
00319        }
00320        else
00321 #endif
00322               fd=rfc1035_mksocket(SOCK_STREAM, 0, &af);
00323 
00324        if (fd < 0)
00325        {
00326               perror("socket");
00327               return (-1);
00328        }
00329 
00330        /* Figure out what to bind based on what socket we created */
00331 
00332        if (ipaddrarg && strcmp(ipaddrarg, "0"))
00333        {
00334               if (rfc1035_aton(ipaddrarg, &addr) < 0)
00335               {
00336                      fprintf(stderr,"Invalid IP address: %s\n", ipaddrarg);
00337                      close(fd);
00338                      return (-1);
00339               }
00340 
00341               if (rfc1035_mkaddress(af, &netaddr, &addr, port, &sinaddr,
00342                             &sinaddrlen))
00343               {
00344                      fprintf(stderr,"Unable to bind IP address: %s\n",
00345                             ipaddrarg);
00346                      close(fd);
00347                      return (-1);
00348               }
00349        }
00350        else   /* Bind default address */
00351        {
00352 #if    RFC1035_IPV6
00353               if (af == AF_INET6)
00354               {
00355                      memset(&sin6, 0, sizeof(sin6));
00356                      sin6.sin6_family=AF_INET6;
00357                      sin6.sin6_addr=in6addr_any;
00358                      sin6.sin6_port=port;
00359                      sinaddr=(const struct sockaddr *)&sin6;
00360                      sinaddrlen=sizeof(sin6);
00361               }
00362               else
00363 #endif
00364                      if (af == AF_INET)
00365                      {
00366                             sin4.sin_family=AF_INET;
00367                             sin4.sin_addr.s_addr=INADDR_ANY;
00368                             sin4.sin_port=port;
00369                             sinaddr=(const struct sockaddr *)&sin4;
00370                             sinaddrlen=sizeof(sin4);
00371                      }
00372                      else
00373                      {
00374                             errno=EAFNOSUPPORT;
00375                             perror("socket");
00376                             close(fd);
00377                             return (-1);
00378                      }
00379        }
00380 
00381        {
00382               int dummy=1;
00383 
00384               if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
00385                      (const char *)&dummy, sizeof(dummy)) < 0)
00386               {
00387                      perror("setsockopt");
00388               }
00389        }
00390 
00391        if (fcntl(fd, F_SETFD, FD_CLOEXEC))
00392        {
00393               perror("fcntl");
00394               close(fd);
00395               return (-1);
00396        }
00397 
00398        if (fcntl(fd, F_SETFL, O_NONBLOCK))
00399        {
00400               perror("fcntl");
00401               close(fd);
00402               return (-1);
00403        }
00404 
00405        if (sox_bind(fd, (struct sockaddr *)sinaddr, sinaddrlen) < 0)
00406        {
00407               if (flags & MKS_ERROK)
00408               {
00409                      close(fd);
00410                      return (-2);
00411               }
00412 
00413               perror("bind");
00414               close(fd);
00415               return (-1);
00416        }
00417 
00418        if (sox_listen(fd,
00419 #ifdef SOMAXCONN
00420                      SOMAXCONN
00421 #else
00422                      5
00423 #endif
00424                      ))
00425        {
00426               if (flags && MKS_ERROK)
00427               {
00428                      close(fd);
00429                      return (-2);
00430               }
00431               perror("listen");
00432               close(fd);
00433               return (-1);
00434        }
00435        return (fd);
00436 }
00437 
00438 static int mksockets()
00439 {
00440        struct portinfo *p;
00441 
00442        maxfd= -1;
00443 
00444        for (p=fdlist; p; p=p->next)
00445        {
00446               int fd;
00447               struct in_addr addr;
00448               int fd_flag=0;
00449 
00450               if (p->ipaddr && strcmp(p->ipaddr, "0"))
00451               {
00452                      /* FreeBSD needs AF_INET binds for IPv4 addys */
00453 
00454                      if (rfc1035_aton_ipv4(p->ipaddr, &addr) == 0)
00455                      {
00456                             fd_flag=MKS_USEAFINET4;
00457                      }
00458               }
00459 
00460               fd=mksocket(p->ipaddr, p->servname, fd_flag);
00461 
00462               if (fd < 0)
00463                      break;
00464 
00465               p->fd1=fd;
00466 
00467               if (fd > maxfd)
00468                      maxfd=fd;
00469 
00470               /* BSD requires both an IPv6 and an IPv4 socket */
00471 
00472 #if    RFC1035_IPV6
00473               if (p->ipaddr == 0 || strcmp(p->ipaddr, "0") == 0)
00474               {
00475                      fd=mksocket(p->ipaddr, p->servname,
00476                                 (MKS_USEAFINET4|MKS_ERROK));
00477 
00478                      if (fd == -2)
00479                             continue;     /* Ok if bind failed */
00480                      if (fd < 0)
00481                             break;
00482 
00483                      if (fd > maxfd)
00484                             maxfd=fd;
00485                      p->fd2=fd;
00486               }
00487 #endif
00488 
00489        }
00490 
00491        if (p) /* Clean up after ourselves, after an error */
00492        {
00493               for (p=fdlist; p; p=p->next)
00494               {
00495                      if (p->fd1 >= 0)
00496                             close(p->fd1);
00497                      if (p->fd2 >= 0)
00498                             close(p->fd2);
00499               }
00500               return (-1);
00501        }
00502 
00503        return (0);
00504 }
00505 
00506 static int init(int argc, char **argv)
00507 {
00508 int    argn;
00509 
00510 struct group *gr;
00511 int    i;
00512 gid_t  gid=0;
00513 const  char *servname;
00514 int    forced=0;
00515 int    lockfd=-1;
00516  
00517        argn=argparse(argc, argv, arginfo);
00518 
00519        if ((stoparg || restartarg) && pidarg == 0)
00520        {
00521               fprintf(stderr, "%s: -pid argument is required.\n", argv[0]);
00522               return (-1);
00523        }
00524 
00525        if (pidarg)
00526        {
00527               lockfilename=malloc(strlen(pidarg)+sizeof(".lock"));
00528               if (!lockfilename)
00529               {
00530                      perror("malloc");
00531                      return (-1);
00532               }
00533               strcat(strcpy(lockfilename, pidarg), ".lock");
00534        }
00535 
00536        if (stoparg)
00537        {
00538               ll_daemon_stop(lockfilename, pidarg);
00539               exit(0);
00540        }
00541 
00542        if (restartarg)
00543        {
00544               ll_daemon_restart(lockfilename, pidarg);
00545               exit(0);
00546        }
00547 
00548        if (argc - argn < 2)
00549        {
00550               fprintf(stderr, "Usage: %s [options] port prog arg1 arg2...\n",
00551                      argv[0]);
00552               return (-1);
00553        }
00554 
00555        if (pidarg) { /* -start implied for backwards compatibility */
00556               lockfd=ll_daemon_start(lockfilename);
00557               if (lockfd < 0)
00558               {
00559                      perror("ll_daemon_start");
00560                      return (-1);
00561               }
00562        }
00563 
00564        servname=argv[argn++];
00565 
00566        if (parseaddr(servname))
00567        {
00568               close(lockfd);
00569               return (-1);
00570        }
00571 
00572        if (mksockets())
00573        {
00574               close(lockfd);
00575               return (-1);
00576        }
00577 
00578        signal(SIGINT, sigexit);
00579        signal(SIGHUP, sighup);
00580        signal(SIGTERM, sigexit);
00581 
00582 #if 0
00583        {
00584        int    fd2;
00585        int    dummy;
00586 
00587               perror("bind");
00588               if (!forcebindarg || errno != EADDRINUSE)
00589               {
00590                      sox_close(fd);
00591                      return (-1);
00592               }
00593 
00594               /* Poke around */
00595 
00596               if ((fd2=rfc1035_mksocket(SOCK_STREAM, 0, &dummy)) < 0)
00597                      /* Better get same socket as fd */
00598               {
00599                      perror("socket");
00600                      sox_close(fd);
00601                      return (-1);
00602               }
00603 
00604               if (sox_connect(fd2, (struct sockaddr *)sinaddr,
00605                      sinaddrlen) == 0)
00606               {
00607                      sox_close(fd2);
00608                      sox_close(fd);
00609                      return (-1);
00610               }
00611               sox_close(fd2);
00612               savepid();
00613               sleep(60);
00614               forced=1;
00615        }
00616 #endif
00617 
00618        if (pidarg)
00619               ll_daemon_started(pidarg, lockfd);
00620 
00621        if (grouparg)
00622        {
00623               if (isid(grouparg))
00624                      gid=atoi(grouparg);
00625               else if ((gr=getgrnam(grouparg)) == 0)
00626               {
00627                      fprintf(stderr, "Group not found: %s\n", grouparg);
00628                      close(lockfd);
00629                      return (-1);
00630               }
00631               else   gid=gr->gr_gid;
00632 
00633               libmail_changegroup(gid);
00634        }
00635 
00636        if (userarg)
00637        {
00638        uid_t  uid;
00639 
00640               if (isid(userarg))
00641               {
00642                      uid=atoi(userarg);
00643                      libmail_changeuidgid(uid, getgid());
00644               }
00645               else
00646               {
00647               gid_t  g=getgid(), *gp=0;
00648 
00649                      if (grouparg) gp= &g;
00650                      libmail_changeusername(userarg, gp);
00651               }
00652        }
00653 
00654        if (pidarg && ll_daemon_resetio())
00655        {
00656               perror("ll_daemon_resetio");
00657               close(lockfd);
00658               return (-1);
00659        }
00660 
00661        if (stderrloggerarg)
00662        {
00663        pid_t  p;
00664        int    waitstat;
00665        int    pipefd[2];
00666        const char *progname=argv[argn];
00667 
00668               if (pipe(pipefd) < 0)
00669               {
00670                      perror("pipe");
00671                      return (-1);
00672               }
00673 
00674               signal(SIGCHLD, SIG_DFL);
00675               while ((p=fork()) == -1)
00676               {
00677                      sleep(5);
00678               }
00679 
00680               if (p == 0)
00681               {
00682                      signal(SIGHUP, SIG_IGN);
00683                      sox_close(0);
00684                      sox_dup(pipefd[0]);
00685                      sox_close(pipefd[0]);
00686                      sox_close(pipefd[1]);
00687                      sox_close(1);
00688                      open("/dev/null", O_WRONLY);
00689                      sox_close(2);
00690                      sox_dup(1);
00691                      closeaccess();
00692                      while ((p=fork()) == -1)
00693                      {
00694                             sleep(5);
00695                      }
00696                      if (p == 0)
00697                      {
00698                      const char *p=strrchr(progname, '/');
00699 
00700                             if (p) ++p;
00701                             else p=progname;
00702 
00703                             if (stderrloggername && *stderrloggername)
00704                                    p=stderrloggername;
00705 
00706                             execl(stderrloggerarg, stderrloggerarg,
00707                                           p, (char *)0);
00708                             perror(stderrloggerarg);
00709                             _exit(5);
00710                      }
00711                      _exit(0);
00712               }
00713               sox_close(2);
00714               sox_dup(pipefd[1]);
00715               sox_close(pipefd[0]);
00716               sox_close(pipefd[1]);
00717               while (wait(&waitstat) != p)
00718                      ;
00719        }
00720        else if (stderrarg)
00721        {
00722        int    fd=open(stderrarg, O_WRONLY|O_APPEND|O_CREAT, 0660);
00723 
00724               if (!fd)
00725               {
00726                      perror(stderrarg);
00727                      return (-1);
00728               }
00729               sox_close(2);
00730               sox_dup(fd);
00731               sox_close(fd);
00732        }
00733 
00734        nprocs=40;
00735        if (maxprocsarg)
00736        {
00737               nprocs=atoi(maxprocsarg);
00738               if (nprocs <= 0)
00739               {
00740                      fprintf(stderr, "Invalid -maxprocsarg option.\n");
00741                      return (-1);
00742               }
00743        }
00744 
00745        nwarn= nprocs - (nprocs / 10 + 1);
00746 
00747        if (warnarg)
00748        {
00749               int c=atoi(warnarg);
00750 
00751               if (c >= 0 && c <= nprocs)
00752                      nwarn=c;
00753        }
00754 
00755        if ((pids=malloc(sizeof(*pids)*nprocs)) == 0)
00756        {
00757               perror("malloc");
00758               return (-1);
00759        }
00760        if ((addrs=malloc(sizeof(*addrs)*nprocs)) == 0)
00761        {
00762               free(pids);
00763               perror("malloc");
00764               return (-1);
00765        }
00766 
00767 
00768        for (i=0; i<nprocs; i++)
00769               pids[i]= -1;
00770 
00771        maxperc=nprocs;
00772        maxperip=4;
00773 
00774        if (maxpercarg)
00775        {
00776               maxperc=atoi(maxpercarg);
00777               if (maxperc <= 0)
00778               {
00779                      fprintf(stderr, "Invalid -maxperc option.\n");
00780                      free(pids);
00781                      free(addrs);
00782                      return (-1);
00783               }
00784        }
00785        if (maxperiparg)
00786        {
00787               maxperip=atoi(maxperiparg);
00788               if (maxperip <= 0)
00789               {
00790                      fprintf(stderr, "Invalid -maxperip option.\n");
00791                      free(pids);
00792                      free(addrs);
00793                      return (-1);
00794               }
00795        }
00796        if (forced)
00797        {
00798               fprintf(stderr, "couriertcpd: ready.\n");
00799               fflush(stderr);
00800        }
00801        return (argn);
00802 }
00803 
00804 static void run(int, const RFC1035_ADDR *, int, const char *, char **);
00805 
00806 static void doreap(pid_t p, int wait_stat)
00807 {
00808 int    n;
00809 
00810        for (n=0; n<nprocs; n++)
00811               if (p == pids[n])
00812               {
00813                      pids[n]= -1;
00814                      break;
00815               }
00816 }
00817 
00818 static RETSIGTYPE childsig(int signum)
00819 {
00820        signum=signum;
00821        wait_reap(doreap, childsig);
00822 #if RETSIGTYPE != void
00823        return (0);
00824 #endif
00825 }
00826 
00827 static int doallowaccess(char *, int);
00828 
00829 #if    RFC1035_IPV6
00830 
00831 static int allowaccess(const RFC1035_ADDR *sin, int port)
00832 {
00833 char   buf[RFC1035_MAXNAMESIZE+1+6];
00834 char   *q;
00835 int    i;
00836 
00837        if (IN6_IS_ADDR_V4MAPPED(sin))
00838        {
00839        const char *p=inet_ntop(AF_INET6, sin, buf, sizeof(buf)-6);
00840 
00841               if (p && (q=strrchr(buf, ':')) != 0)
00842                      return (doallowaccess(q+1, port));
00843               return (1);
00844        }
00845        q=buf;
00846        for (i=0; i<sizeof(*sin); i += 2)
00847        {
00848 #define       B(i) ((unsigned long)((unsigned char *)sin)[i])
00849        unsigned long n=(B(i) << 8) | B(i+1);
00850 #undef B
00851               sprintf(q, ":%04lx", n);
00852               q += 5;
00853        }
00854        *q=0;
00855        return (doallowaccess(buf, port));
00856 }
00857 
00858 #else
00859 static int allowaccess(const RFC1035_ADDR *sin, int port)
00860 {
00861 char   buf[RFC1035_NTOABUFSIZE+6];
00862 
00863        rfc1035_ntoa(sin, buf);
00864        return (doallowaccess(buf, port));
00865 }
00866 #endif
00867 
00868 static int doallowaccess(char *buf, int port)
00869 {
00870 char   *accessptr;
00871 char *p, *q, *r;
00872 int    quote=0;
00873 int    l;
00874 
00875        if (accessarg == 0)  return (1);
00876 
00877        if (port) snprintf(buf+strlen(buf), 7, ".%d", ntohs(port));
00878        while ((accessptr= *buf ? chkaccess(buf):0) == 0)
00879        {
00880               if ((accessptr=strrchr(buf, '.')) == 0
00881 #if RFC1035_IPV6
00882                      && (accessptr=strrchr(buf, ':')) == 0
00883 #endif
00884                      )
00885               {
00886                      if (port)
00887                      {
00888                             snprintf(buf, 8, "*.%d", ntohs(port));
00889                             if ((accessptr=chkaccess(buf)) != 0)
00890                                    break;
00891                      }
00892                      if ((accessptr=chkaccess("*")) != 0)
00893                             break;
00894                      return (1);
00895               }
00896               *accessptr=0;
00897        }
00898 
00899        if (strncmp(accessptr, "deny", 4) == 0)
00900        {
00901               free(accessptr);
00902               return (0);
00903        }
00904 
00905        p=accessptr;
00906        if (strncmp(accessptr, "allow", 5) == 0)
00907        {
00908               p += 5;
00909               if (*p == ',')       ++p;
00910        }
00911 
00912        while ( p && *p )
00913        {
00914               q=p;
00915               r=q;
00916               while (*p)
00917               {
00918                      if (*p == ',' && !quote)
00919                      {
00920                             *p++=0;
00921                             break;
00922                      }
00923                      if (!quote && (*p == '"' || *p == '\''))
00924                      {
00925                             quote=*p;
00926                             p++;
00927                             continue;
00928                      }
00929                      if (quote && *p == quote)
00930                      {
00931                             quote=0;
00932                             p++;
00933                             continue;
00934                      }
00935                      *r++=*p++;
00936               }
00937               *r=0;
00938               if (strchr(q, '=') == 0)
00939               {
00940               char   *r=malloc(strlen(q)+2);
00941 
00942                      if (!r)
00943                      {
00944                             perror("malloc");
00945                             return (0);
00946                      }
00947                      q=strcat(strcpy(r, q), "=");
00948               }
00949 
00950               while (*q && isspace((int)(unsigned char)*q))    ++q;
00951               while ((l=strlen(q)) > 0
00952                      && isspace((int)(unsigned char)q[l-1]))
00953                      q[--l]=0;
00954               putenv(q);
00955        }
00956        return (1);
00957 }
00958 
00959 /* Wait until we have at least one available slot left */
00960 
00961 static int getfreeslot(int *pidptr)
00962 {
00963        int n;
00964 
00965        for (;;)
00966        {
00967               wait_block();
00968 
00969               for (n=0; n<nprocs; n++)
00970               {
00971                      if (pids[*pidptr] == (pid_t)-1)    break;
00972                      if (++*pidptr >= nprocs)    *pidptr=0;
00973               }
00974               if (pids[*pidptr] != (pid_t)-1)
00975               {
00976                      wait_forchild(doreap, childsig);
00977                      continue;
00978               }
00979               break;
00980        }
00981        wait_clear(childsig);
00982        return (*pidptr);
00983 }
00984 
00985 static void accepted(int, int, RFC1035_NETADDR *, int, const char *, char **);
00986 
00987 static int doit(int argn, int argc, char **argv)
00988 {
00989        char   **ptrs;
00990        int    pidptr;
00991        struct portinfo *pi;
00992        fd_set fdr, fdrcopy;
00993        int    dummy;
00994 
00995        ptrs=(char **)malloc((argc-argn+1) * sizeof(char *));
00996        if (!ptrs)
00997        {
00998               perror("malloc");
00999               return (-1);
01000        }
01001        for (dummy=0; dummy<argc-argn; dummy++)
01002        {
01003               ptrs[dummy]=argv[argn+dummy];
01004        }
01005        ptrs[dummy]=0;
01006 
01007        if (listenarg)
01008        {
01009               dummy=atoi(listenarg);
01010               if (dummy <= 0)
01011               {
01012                      fprintf(stderr, "Invalid -listen option.\n");
01013                      exit(1);
01014               }
01015        }
01016 
01017        FD_ZERO(&fdrcopy);
01018        for (pi=fdlist; pi; pi=pi->next)
01019        {
01020               if (pi->fd1 >= 0)
01021                      FD_SET(pi->fd1, &fdrcopy);
01022 
01023               if (pi->fd2 >= 0)
01024                      FD_SET(pi->fd2, &fdrcopy);
01025        }
01026 
01027        pidptr=0;
01028 
01029        signal(SIGCHLD, childsig);
01030 
01031 #if    HAVE_SETPGRP
01032 #if    SETPGRP_VOID
01033        setpgrp();
01034 #else
01035        setpgrp(0, 0);
01036 #endif
01037 #else
01038 #if    HAVE_SETPGID
01039        setpgid(0, 0);
01040 #endif
01041 #endif
01042 #ifdef  TIOCNOTTY
01043 
01044        {
01045        int fd=open("/dev/tty", O_RDWR);
01046 
01047               if (fd >= 0)
01048               {
01049                      ioctl(fd, TIOCNOTTY, 0);
01050                      close(fd);
01051               }
01052        }
01053 #endif
01054 
01055        signal(SIGPIPE, SIG_IGN);
01056        for (;;)
01057        {
01058               int n;
01059               int sockfd;
01060               RFC1035_NETADDR      sin;
01061               socklen_t     sinl;
01062 
01063               fdr=fdrcopy;
01064 
01065               if (select(maxfd+1, &fdr, NULL, NULL, NULL) <= 0)
01066               {
01067                      if (errno != EINTR)
01068                             perror("accept");
01069                      continue;
01070               }
01071 
01072               for (pi=fdlist; pi; pi=pi->next)
01073               {
01074                      if (pi->fd1 >= 0 && FD_ISSET(pi->fd1, &fdr) &&
01075                          ((n=getfreeslot(&pidptr)),
01076                           (sinl = sizeof(sin)),
01077                           (sockfd=sox_accept(pi->fd1,
01078                                           (struct sockaddr *)&sin,
01079                                           &sinl))) >= 0)
01080                      {
01081                             accepted(n, sockfd, &sin, sinl,
01082                                     argv[argn], ptrs);
01083                      }
01084 
01085                      if (pi->fd2 >= 0 && FD_ISSET(pi->fd2, &fdr) &&
01086                          ((n=getfreeslot(&pidptr)),
01087                           (sinl = sizeof(sin)), 
01088                           (sockfd=sox_accept(pi->fd2,
01089                                           (struct sockaddr *)&sin,
01090                                           &sinl))) >= 0)
01091                      {
01092                             accepted(n, sockfd, &sin, sinl,
01093                                     argv[argn], ptrs);
01094                      }
01095               }
01096        }
01097 }
01098 
01099 static void denied(int sockfd)
01100 {
01101        if (denymsgarg) {
01102               if (write(sockfd, denymsgarg, strlen(denymsgarg)) < 0 ||
01103                   write(sockfd, "\n", 1) < 0)
01104               {
01105                      sox_close(sockfd);
01106                      _exit(1);
01107               }
01108        }
01109        sox_close(sockfd);
01110        _exit(0);
01111 }
01112 
01113 static void accepted(int n, int sockfd, RFC1035_NETADDR *sin, int sinl,
01114                    const char *prog,
01115                    char **args)
01116 {
01117        RFC1035_ADDR addr;
01118        int    addrport;
01119 #ifdef SO_LINGER
01120        int    dummy;
01121        struct linger l;
01122 #endif
01123        pid_t  p;
01124        int cnt;
01125 
01126        if (rfc1035_sockaddrip(sin, sinl, &addr)
01127            || rfc1035_sockaddrport(sin, sinl, &addrport))
01128        {
01129               sox_close(sockfd);
01130               return;
01131        }
01132 
01133        /* Turn off the CLOEXEC and NONBLOCK bits */
01134 
01135        if (fcntl(sockfd, F_SETFD, 0))
01136        {
01137               perror("fcntl");
01138               sox_close(sockfd);
01139               return;
01140        }
01141 
01142        if (fcntl(sockfd, F_SETFL, 0))
01143        {
01144               perror("fcntl");
01145               sox_close(sockfd);
01146               return;
01147        }
01148 
01149        if (sighup_received)
01150        {
01151               sighup_received=0;
01152               if (accessarg)
01153               {
01154                      closeaccess();
01155                      if (openaccess(accessarg))
01156                             perror(accessarg);
01157               }
01158        }
01159 
01160 #ifdef SO_KEEPALIVE
01161        dummy=1;
01162        if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
01163                      (const char *)&dummy, sizeof(dummy)) < 0)
01164        {
01165               perror("setsockopt");
01166        }
01167 #endif
01168 
01169 #ifdef SO_LINGER
01170        l.l_onoff=0;
01171        l.l_linger=0;
01172 
01173        if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER,
01174                      (const char *)&l, sizeof(l)) < 0)
01175        {
01176               perror("setsockopt");
01177        }
01178 #endif
01179        wait_block();
01180        if ((p=fork()) == -1)
01181        {
01182               perror("fork");
01183               sox_close(sockfd);
01184               return;
01185        }
01186 
01187        if (p == 0)
01188        {
01189               wait_restore(childsig);
01190 
01191               if (accesslocal) /* Lookup local interface address too? */
01192               {
01193               RFC1035_NETADDR lsin;
01194               RFC1035_ADDR laddr;
01195               int    lport;
01196               socklen_t     i=sizeof(lsin);
01197               
01198                      if (sox_getsockname(sockfd, (struct sockaddr *)&lsin, &i) == 0 &&
01199                             rfc1035_sockaddrip(&lsin, i, &laddr) == 0 &&
01200                             rfc1035_sockaddrport(&lsin, i, &lport) == 0 &&
01201                             allowaccess(&laddr,lport) == 0)
01202                      {
01203                             sox_close(sockfd);
01204                             _exit(0);
01205                      }
01206               }
01207 
01208               if (allowaccess(&addr,0) == 0)
01209               {
01210                      denied(sockfd);
01211               }
01212 
01213               run(sockfd, &addr, addrport, prog, args);
01214        }
01215        pids[n]=p;
01216 
01217        memcpy(addrs+n, &addr, sizeof(addr));
01218        sox_close(sockfd);
01219        wait_clear(childsig);
01220 
01221        for (cnt=n=0; n<nprocs; n++)
01222               if (pids[n] != (pid_t)-1)
01223                      ++cnt;
01224 
01225        if (cnt == nprocs)
01226        {
01227               time_t t;
01228 
01229               time(&t);
01230               if (last_alert == 0 || last_alert > t || last_alert < t - 60)
01231               {
01232                      last_alert=t;
01233                      fprintf(stderr,
01234                             "ALERT: %d maximum active connections.\n",
01235                             nprocs);
01236               }
01237        }
01238        else if (cnt >= nwarn)
01239        {
01240               time_t t;
01241 
01242               time(&t);
01243               if (last_warn == 0 || last_warn > t || last_warn < t - 60)
01244               {
01245                      last_warn=t;
01246                      fprintf(stderr, "WARN: %d active connections.\n",
01247                             cnt);
01248               }
01249        }
01250 }
01251 
01252 static void mysetenv(const char *name, const char *val)
01253 {
01254 char   *p=malloc(strlen(name)+strlen(val)+2);
01255 
01256        if (!p)
01257        {
01258               perror("malloc");
01259               _exit(1);
01260        }
01261        putenv(strcat(strcat(strcpy(p, name), "="), val));
01262 }
01263 
01264 /*
01265 ** Convert IP address to host name.  Make sure the IP address resolves
01266 ** backwards and forwards.
01267 */
01268 
01269 static void ip2host(const RFC1035_ADDR *addr, const char *env)
01270 {
01271 const char *remotehost="softdnserr";
01272 char   buf[RFC1035_MAXNAMESIZE+1];
01273 
01274 #if TCPDUSERFC1035
01275 struct rfc1035_res res;
01276 #endif
01277 
01278        if (nodnslookup)     return;
01279 
01280        rfc1035_ntoa(addr, buf);
01281 
01282 #if TCPDUSERFC1035
01283 
01284        rfc1035_init_resolv(&res);
01285 
01286        if (rfc1035_ptr(&res, addr, buf) != 0)
01287        {
01288               if (errno == ENOENT)
01289                      remotehost=0;
01290        }
01291        else
01292        {
01293               RFC1035_ADDR *ias;
01294               unsigned nias, n;
01295 
01296               if (rfc1035_a(&res, buf, &ias, &nias) != 0)
01297               {
01298                      if (errno == ENOENT)
01299                             remotehost=0;
01300               }
01301               else
01302               {
01303                      remotehost=0;
01304                      for (n=0; n<nias; n++)
01305                      {
01306                      char   a[RFC1035_MAXNAMESIZE];
01307                      char   b[RFC1035_MAXNAMESIZE];
01308 
01309                             rfc1035_ntoa(&ias[n], a);
01310                             rfc1035_ntoa(addr, b);
01311 
01312                             if (strcmp(a, b) == 0)
01313                             {
01314                                    remotehost=buf;
01315                             }
01316                      }
01317               }
01318        }
01319        rfc1035_destroy_resolv(&res);
01320 
01321 #else
01322 
01323        {
01324        struct hostent *he;
01325        unsigned n;
01326        struct in_addr in;
01327 
01328 #if    RFC1035_IPV6
01329 
01330               if (IN6_IS_ADDR_V4MAPPED(addr))
01331                      memcpy(&in, (char *)addr + 12, 4);
01332               else   return;
01333 #else
01334               in= *addr;
01335 #endif
01336 
01337               he=gethostbyaddr( (char *)&in, sizeof(in), AF_INET);
01338               if (!he)
01339               {
01340                      switch (h_errno)     {
01341                      case HOST_NOT_FOUND:
01342                      case NO_DATA:
01343                             remotehost=0;
01344                             break;
01345                      }
01346               }
01347               else
01348               {
01349                      strcpy(buf, he->h_name);
01350                      he=gethostbyname(buf);
01351                      if (!he)
01352                      {
01353                             switch (h_errno)     {
01354                             case HOST_NOT_FOUND:
01355                             case NO_DATA:
01356                                    remotehost=0;
01357                                    break;
01358                             }
01359                      }
01360                      else for (n=0, remotehost=0; he->h_addr_list[n]; n++)
01361                      {
01362                      struct in_addr hin;
01363 
01364                             if (he->h_addrtype != AF_INET ||
01365                                    he->h_length < sizeof(hin))
01366                                    break;
01367                             memcpy((char *)&hin, he->h_addr_list[n],
01368                                    sizeof(hin));
01369                             if (hin.s_addr == in.s_addr)
01370                             {
01371                                    remotehost=buf;
01372                                    break;
01373                             }
01374                      }
01375 
01376               }
01377        }
01378 #endif
01379        if (remotehost)
01380               mysetenv(env, remotehost);
01381 }
01382 
01383 static void mkmymsg(const char *varname, const char *msg)
01384 {
01385 const char *p=getenv("TCPREMOTEIP");
01386 char *q=malloc(strlen(msg)+1+strlen(p));
01387 char *r;
01388 
01389        if (!q)
01390        {
01391               perror("malloc");
01392               exit(1);
01393        }
01394 
01395        for (r=q; *msg; msg++)
01396        {
01397               if (*msg == '@')
01398               {
01399                      strcpy(r, p);
01400                      while (*r)    r++;
01401                      ++msg;
01402                      break;
01403               }
01404               *r++=*msg;
01405        }
01406        while (*msg)
01407               *r++=*msg++;
01408        *r=0;
01409        mysetenv(varname, q);
01410        free(q);
01411 }
01412 
01413 /*
01414 ** check_blocklist is called once for each blocklist query to process.
01415 */
01416 
01417 static void docheckblocklist(struct blocklist_s *p, const char *nameptr)
01418 {
01419        const char *q;
01420        const char *varname=p->var;
01421        char   hostname[RFC1035_MAXNAMESIZE+1];
01422        char   buf[RFC1035_MAXNAMESIZE+1];
01423        int    hasnotxt;
01424        struct blocklist_s *pp;
01425        struct rfc1035_reply *replyp;
01426        struct rfc1035_res res;
01427        int i;
01428 
01429        hostname[0]=0;
01430        strncat(hostname, nameptr, RFC1035_MAXNAMESIZE);
01431 
01432        if (!varname) varname="BLOCK";
01433 
01434        if ((q=getenv(varname)) != 0)      return;
01435                                    /* Env var already set */
01436 
01437        rfc1035_init_resolv(&res);
01438 
01439        if (p->ia.s_addr == INADDR_ANY)
01440        {
01441               /* We're not looking for a particular token IP address */
01442 
01443               if (p->msg == 0 || *p->msg == 0)
01444               {
01445                      /*
01446                      ** We don't have a predefined error message, therefore
01447                      ** we expect TXT records.
01448                      */
01449                      if ((i=rfc1035_resolve_cname(&res,
01450                                    hostname,
01451                                    RFC1035_TYPE_TXT,
01452                                    RFC1035_CLASS_IN, &replyp, 0)) >= 0)
01453                      {
01454                             rfc1035_rr_gettxt(replyp->allrrs[i], 0,
01455                                    hostname);
01456                             mysetenv(varname, hostname);
01457                      }
01458               }
01459               else
01460               {
01461                      /*
01462                      ** A predefined error message has been supplied, so
01463                      ** just look for the IP address.  Perhaps the
01464                      ** blacklist does not provide TXT records, so query
01465                      ** for A records only.
01466                      */
01467 
01468                      if ((i=rfc1035_resolve_cname(&res,
01469                                    hostname,
01470                                    RFC1035_TYPE_A,
01471                                    RFC1035_CLASS_IN, &replyp, 0)) >= 0)
01472                      {
01473                             mkmymsg(varname, p->msg);
01474                      }
01475               }
01476 
01477               if (replyp)   rfc1035_replyfree(replyp);
01478               rfc1035_destroy_resolv(&res);
01479               return;
01480        }
01481 
01482        /*
01483        ** Looking for a specific A record in the blacklist.  Possibly due
01484        ** to different messages for different A records.
01485        ** See if all -block options for the same zone have predefined
01486        ** error messages, so we can be satisfied with an A query only.
01487        */
01488 
01489        hasnotxt=0;
01490 
01491        for (pp=p; pp; pp=pp->next)
01492        {
01493               if (strcmp(pp->zone, p->zone))     continue;
01494               if (pp->msg == 0 || *pp->msg == 0) hasnotxt=1;
01495        }
01496 
01497        /*
01498        ** If no text were provided, we need both A and TXT records, so
01499        ** issue an ANY query, and parse the results.
01500        */
01501 
01502        (void)rfc1035_resolve_cname(&res,
01503                      hostname,
01504                      hasnotxt ? RFC1035_TYPE_ANY:RFC1035_TYPE_A,
01505                      RFC1035_CLASS_IN, &replyp, 0);
01506 
01507        if (!replyp)
01508        {
01509               rfc1035_destroy_resolv(&res);
01510               return;
01511        }
01512 
01513        for (i=0; i<replyp->ancount+replyp->nscount+replyp->arcount; i++)
01514        {
01515        int    j;
01516 
01517               /*
01518               ** Go through the DNS response, and check every A record
01519               ** in there.
01520               */
01521               rfc1035_replyhostname(replyp, replyp->allrrs[i]->rrname, buf);
01522               if (rfc1035_hostnamecmp(buf, hostname))   continue;
01523               if (replyp->allrrs[i]->rrtype != RFC1035_TYPE_A)
01524                      continue;
01525 
01526               /*
01527               ** Go through the remaining blocklist, and set the environment
01528               ** variable for each block entry for this zone and IP address.
01529               */
01530               for (pp=p; pp; pp=pp->next)
01531               {
01532               const char *vvarname=pp->var;
01533 
01534                      if (strcmp(pp->zone, p->zone))     continue;
01535 
01536                      if (pp->ia.s_addr != replyp->allrrs[i]->rr.inaddr.s_addr)
01537                             continue;
01538 
01539                      if (!vvarname)       vvarname="BLOCK";
01540 
01541                      /*
01542                      ** The -block option was kind enough to supply the
01543                      ** error message.
01544                      */
01545 
01546                      if (pp->msg && *pp->msg)
01547                      {
01548                             mkmymsg(vvarname, pp->msg);
01549                             continue;
01550                      }
01551 
01552                      /* No predefined message, look for a TXT record. */
01553 
01554                      if ((j=rfc1035_replysearch_all(&res,
01555                                                  replyp, hostname,
01556                                                  RFC1035_TYPE_TXT,
01557                                                  RFC1035_CLASS_IN, 0)) >= 0)
01558                      {
01559                             rfc1035_rr_gettxt(replyp->allrrs[j], 0, buf);
01560                             mysetenv(vvarname, buf);
01561                      }
01562                      else   mysetenv(vvarname, "Access denied.");
01563               }
01564        }
01565        rfc1035_replyfree(replyp);
01566        rfc1035_destroy_resolv(&res);
01567 }
01568 
01569 static void check_blocklist_ipv4(struct blocklist_s *p,
01570        const struct in_addr *ia)
01571 {
01572 unsigned a,b,c,d;
01573 char   hostname[RFC1035_MAXNAMESIZE+1];
01574 const unsigned char *q=(const unsigned char *)ia;
01575 
01576        /* Calculate DNS query hostname */
01577 
01578        a=q[0];
01579        b=q[1];
01580        c=q[2];
01581        d=q[3];
01582 
01583        sprintf(hostname, "%u.%u.%u.%u.%s", d, c, b, a, p->zone);
01584        docheckblocklist(p, hostname);
01585 }
01586 
01587 #if    RFC1035_IPV6
01588 
01589 static void check_blocklist(struct blocklist_s *p, const RFC1035_ADDR *ia)
01590 {
01591        if (IN6_IS_ADDR_V4MAPPED(ia))
01592        {
01593        struct in_addr ia4;
01594 
01595               memcpy(&ia4, (const char *)ia + 12, 4);
01596               check_blocklist_ipv4(p, &ia4);
01597        }
01598 }
01599 
01600 #else
01601 static void check_blocklist(struct blocklist_s *p, const RFC1035_ADDR *ia)
01602 {
01603        check_blocklist_ipv4(p, ia);
01604 }
01605 #endif
01606 
01607 static void check_drop(int sockfd)
01608 {
01609        const char *p, *q;
01610        char *r;
01611 
01612        p=droparg;
01613 
01614        if (p && !*p)
01615               p="BLOCK";
01616 
01617        for (; p && *p; q=p)
01618        {
01619               if (*p == ',')
01620               {
01621                      q= ++p;
01622                      continue;
01623               }
01624 
01625               for (q=p; *q; ++q)
01626                      if (*q == ',')
01627                             break;
01628 
01629               r=malloc(q-p+1);
01630 
01631               if (!r)
01632               {
01633                      perror("malloc");
01634                      _exit(1);
01635               }
01636 
01637               memcpy(r, p, q-p);
01638               r[q-p]=0;
01639 
01640               p=getenv(r);
01641               free(r);
01642 
01643               if (p && *p)
01644               {
01645                      fprintf(stderr,
01646                             "WARN: dropped blocked connection from %s\n",
01647                             getenv("TCPREMOTEIP"));
01648                      denied(sockfd);
01649               }
01650        }
01651 }
01652 
01653 static void proxy();
01654 
01655 static void run(int fd, const RFC1035_ADDR *addr, int addrport,
01656        const char *prog, char **argv)
01657 {
01658 RFC1035_NETADDR lsin;
01659 RFC1035_ADDR laddr;
01660 int    lport;
01661 
01662 socklen_t     i;
01663 int    ipcnt, ccnt;
01664 char   buf[RFC1035_MAXNAMESIZE+128];
01665 struct blocklist_s *bl;
01666 const char *remoteinfo;
01667 const char *p;
01668 
01669        i=sizeof(lsin);
01670        if (sox_getsockname(fd, (struct sockaddr *)&lsin, &i) ||
01671               rfc1035_sockaddrip(&lsin, i, &laddr) ||
01672               rfc1035_sockaddrport(&lsin, i, &lport))
01673        {
01674               fprintf(stderr, "getsockname failed.\n");
01675               exit(1);
01676        }
01677 
01678        if (!noidentlookup && (remoteinfo=tcpremoteinfo(
01679               &laddr, lport,
01680               addr, addrport, 0)) != 0)
01681        {
01682        char   *q=malloc(sizeof("TCPREMOTEINFO=")+strlen(remoteinfo));
01683 
01684               if (!q)
01685               {
01686                      perror("malloc");
01687                      _exit(1);
01688               }
01689 
01690               strcat(strcpy(q, "TCPREMOTEINFO="), remoteinfo);
01691               putenv(q);
01692        }
01693 
01694 /* check if it's an exception to the global ip limit */
01695        if( (p=getenv("MAXCPERIP")) != NULL )
01696        {
01697               int j = atoi(p);
01698 
01699               if( j > 0 )
01700                      maxperip = j;
01701        }
01702 
01703        for (i=0, ipcnt=ccnt=0; i<nprocs; i++)
01704        {
01705        RFC1035_ADDR *psin;
01706        int    j;
01707 
01708               if (pids[i] == (pid_t)-1)   continue;
01709 
01710               psin=addrs+i;
01711 
01712               for (j=0; j<sizeof(*addr); j++)
01713                      if ( ((char *)addr)[j] != ((char *)psin)[j])
01714                             break;
01715 
01716               if (j >= sizeof(*addr) &&
01717                      ++ipcnt >= maxperip)
01718               {
01719                      rfc1035_ntoa(addr, buf);
01720                      fprintf(stderr,"ALERT: Maximum connection limit reached for %s\n",buf);
01721                      _exit(0);     /* Too many from same IP address */
01722               }
01723 
01724               if ( j >= sizeof(*addr)-1 &&
01725                      ++ccnt >= maxperc)
01726                      _exit(0);     /* Too many from same netblock */
01727 
01728        }
01729 
01730        rfc1035_ntoa(addr, buf);
01731        mysetenv("TCPREMOTEIP", buf);
01732        sprintf(buf, "%d", ntohs(addrport));
01733        mysetenv("TCPREMOTEPORT", buf);
01734        ip2host(addr, "TCPREMOTEHOST");
01735 
01736        rfc1035_ntoa(&laddr, buf);
01737        mysetenv("TCPLOCALIP", buf);
01738        sprintf(buf, "%d", ntohs(lport));
01739        mysetenv("TCPLOCALPORT", buf);
01740        ip2host(&laddr, "TCPLOCALHOST");
01741 
01742        for (bl=blocklist; bl; bl=bl->next)
01743               check_blocklist(bl, addr);
01744 
01745        check_drop(fd);
01746        sox_close(0);
01747        sox_close(1);
01748        sox_dup(fd);
01749        sox_dup(fd);
01750        sox_close(fd);
01751        if (stderrarg && strcmp(stderrarg, "socket") == 0)
01752        {
01753               sox_close(2);
01754               sox_dup(1);
01755        }
01756        proxy();
01757        signal(SIGPIPE, SIG_DFL);
01758 
01759        execv(prog, argv);
01760        perror(prog);
01761        exit(1);
01762 }
01763 
01764 int main(int argc, char **argv)
01765 {
01766 int argn=init(argc, argv);
01767 int rc;
01768 
01769        if (argn < 0)
01770        {
01771               exit(1);
01772        }
01773        if (accessarg && openaccess(accessarg))
01774               perror(accessarg);
01775        if (accesslocal && !accessarg)
01776               fprintf(stderr,"-accesslocal requires -access\n");
01777        rc=doit(argn, argc, argv);
01778        kill( -getpid(), SIGTERM);
01779        exit(rc);
01780        return (0);
01781 }
01782 
01783 #if 1
01784 
01785 static void proxy()
01786 {
01787 }
01788 
01789 #else
01790 
01791 /*
01792 ** SOCKSv5 does not support wildcards binds, for now, so there's no
01793 ** reason to manually proxy anything, yet.
01794 */
01795 
01796 
01797 /***************************************************************************
01798 
01799 Manual proxy, to support SOCKS encryption.  Because encrypted connection to
01800 the SOCKS server is supported transparently in libsocks5, we can't just
01801 run the app, because we'll lose libsocks5's intercept of read/write, et al
01802 
01803 ***************************************************************************/
01804 
01805 struct proxybuf {
01806        char buffer[BUFSIZ];
01807        char   *p;
01808        int buffered;
01809        int rfd, wfd;
01810        } ;
01811 
01812 static void proxy_init(struct proxybuf *b, int r, int w)
01813 {
01814        b->buffered=0;
01815        b->rfd=r;
01816        b->wfd=w;
01817 }
01818 
01819 static int proxy_setfd(struct proxybuf *b, fd_set *r, fd_set *w, int *max)
01820 {
01821        /* If we have something buffered, write it out */
01822 
01823        if (b->buffered)
01824        {
01825               FD_SET(b->wfd, w);
01826               if (b->wfd > *max)   *max=b->wfd;
01827               return (1);
01828        }
01829 
01830        if (b->rfd < 0)
01831        {
01832               if (b->wfd >= 0)
01833               {
01834                      sox_close(b->wfd);
01835                      b->wfd= -1;
01836               }
01837               return (0);   /* Nothing else to do */
01838        }
01839 
01840        if (b->rfd > *max)   *max=b->rfd;
01841        FD_SET(b->rfd, r);
01842        return (1);
01843 }
01844 
01845 static void proxy_dofd(struct proxybuf *b, fd_set *r, fd_set *w)
01846 {
01847        if (b->buffered)
01848        {
01849               if (FD_ISSET(b->wfd, w))
01850               {
01851               int    n=sox_write(b->wfd, b->p, b->buffered);
01852 
01853                      if (n <= 0)
01854                      {
01855                             sox_close(b->rfd);
01856                             sox_close(b->wfd);
01857                             b->rfd=b->wfd= -1;
01858                             b->buffered=0;
01859                             return;
01860                      }
01861                      b->p += n;
01862                      b->buffered -= n;
01863               }
01864               return;
01865        }
01866 
01867        if (b->rfd >= 0 && FD_ISSET(b->rfd, r))
01868        {
01869        int    n=sox_read(b->rfd, b->buffer, sizeof(b->buffer));
01870 
01871               if (n <= 0)
01872               {
01873                      sox_close(b->rfd);
01874                      sox_close(b->wfd);
01875                      b->rfd=b->wfd= -1;
01876                      b->buffered=0;
01877                      return;
01878               }
01879               b->p = b->buffer;
01880               b->buffered=n;
01881        }
01882 }
01883 
01884 static void proxy_do(struct proxybuf *);
01885 
01886 static void proxy()
01887 {
01888 int    pipefd0[2], pipefd1[2], pipefd2[2];
01889 pid_t  p, p2;
01890 int    waitstat;
01891 struct proxybuf proxy_[3];
01892 
01893        if (!proxyarg)       return;
01894 
01895        if (pipe(pipefd0) || pipe(pipefd1) || pipe(pipefd2))
01896        {
01897               perror("pipe");
01898               exit(1);
01899        }
01900 
01901        p=fork();
01902        if (p == -1)
01903        {
01904               perror("fork");
01905               exit(1);
01906        }
01907 
01908        /*
01909        ** The parent goes on its merry way, but first makes sure that the
01910        ** child process is OK.
01911        */
01912 
01913        if (p)
01914        {
01915               while ((p2=wait(&waitstat)) != p)
01916               {
01917                      if (p2 == -1 && errno != EINTR)
01918                      {
01919                             perror("wait");
01920                             exit(1);
01921                      }
01922               }
01923               if (waitstat)
01924                      exit(0);
01925               sox_close(0);
01926               sox_close(1);
01927               sox_close(2);
01928               errno=EINVAL;
01929               if (sox_dup(pipefd0[0]) != 0 ||
01930                      sox_dup(pipefd1[1]) != 1 ||
01931                      sox_dup(pipefd2[1]) != 2)
01932               {
01933                      perror("dup(app)");
01934                      exit(1);
01935               }
01936               sox_close(pipefd0[0]);
01937               sox_close(pipefd0[1]);
01938               sox_close(pipefd1[0]);
01939               sox_close(pipefd1[1]);
01940               sox_close(pipefd2[0]);
01941               sox_close(pipefd2[1]);
01942               return;
01943        }
01944 
01945        p=fork();
01946        if (p == -1)  exit(1);
01947        if (p) exit(0);
01948 
01949        sox_close(pipefd0[0]);
01950        sox_close(pipefd1[1]);
01951        sox_close(pipefd2[1]);
01952 
01953        proxy_init(&proxy_[0], 0, pipefd0[1]);
01954        proxy_init(&proxy_[1], pipefd1[0], 1);
01955        proxy_init(&proxy_[2], pipefd2[0], 2);
01956        proxy_do(proxy_);
01957        exit(0);
01958 }
01959 
01960 static void proxy_do(struct proxybuf *p)
01961 {
01962 fd_set r, w;
01963 
01964        for (;;)
01965        {
01966        int    m=0;
01967        int    rc0, rc1, rc2;
01968 
01969               FD_ZERO(&r);
01970               FD_ZERO(&w);
01971 
01972               rc0=proxy_setfd(p, &r, &w, &m);
01973               rc1=proxy_setfd(p+1, &r, &w, &m);
01974               rc2=proxy_setfd(p+2, &r, &w, &m);
01975 
01976               if (rc0 == 0 && rc1 == 0 && rc2 == 0)
01977                      break;
01978 
01979               if (rc0 == 0 || rc1 == 0 || rc2 == 0)
01980                      alarm(10);
01981 
01982               if (select(m+1, &r, &w, 0, 0) < 0)
01983               {
01984                      perror("select");
01985                      break;
01986               }
01987 
01988               proxy_dofd(p, &r, &w);
01989               proxy_dofd(p+1, &r, &w);
01990               proxy_dofd(p+2, &r, &w);
01991        }
01992 }
01993 #endif