Annotation of 43BSDTahoe/usr.lib/sendmail/src/daemon.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1983 Eric P. Allman
        !             3:  * Copyright (c) 1988 Regents of the University of California.
        !             4:  * All rights reserved.
        !             5:  *
        !             6:  * Redistribution and use in source and binary forms are permitted
        !             7:  * provided that the above copyright notice and this paragraph are
        !             8:  * duplicated in all such forms and that any documentation,
        !             9:  * advertising materials, and other materials related to such
        !            10:  * distribution and use acknowledge that the software was developed
        !            11:  * by the University of California, Berkeley.  The name of the
        !            12:  * University may not be used to endorse or promote products derived
        !            13:  * from this software without specific prior written permission.
        !            14:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !            15:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !            16:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            17:  */
        !            18: 
        !            19: #include <errno.h>
        !            20: #include <sendmail.h>
        !            21: 
        !            22: #ifndef lint
        !            23: #ifdef DAEMON
        !            24: static char sccsid[] = "@(#)daemon.c   5.26 (Berkeley) 6/30/88 (with daemon mode)";
        !            25: #else
        !            26: static char sccsid[] = "@(#)daemon.c   5.26 (Berkeley) 6/30/88 (without daemon mode)";
        !            27: #endif
        !            28: #endif /* not lint */
        !            29: 
        !            30: #ifdef DAEMON
        !            31: 
        !            32: # include <netdb.h>
        !            33: # include <sys/signal.h>
        !            34: # include <sys/wait.h>
        !            35: # include <sys/time.h>
        !            36: # include <sys/resource.h>
        !            37: 
        !            38: /*
        !            39: **  DAEMON.C -- routines to use when running as a daemon.
        !            40: **
        !            41: **     This entire file is highly dependent on the 4.2 BSD
        !            42: **     interprocess communication primitives.  No attempt has
        !            43: **     been made to make this file portable to Version 7,
        !            44: **     Version 6, MPX files, etc.  If you should try such a
        !            45: **     thing yourself, I recommend chucking the entire file
        !            46: **     and starting from scratch.  Basic semantics are:
        !            47: **
        !            48: **     getrequests()
        !            49: **             Opens a port and initiates a connection.
        !            50: **             Returns in a child.  Must set InChannel and
        !            51: **             OutChannel appropriately.
        !            52: **     clrdaemon()
        !            53: **             Close any open files associated with getting
        !            54: **             the connection; this is used when running the queue,
        !            55: **             etc., to avoid having extra file descriptors during
        !            56: **             the queue run and to avoid confusing the network
        !            57: **             code (if it cares).
        !            58: **     makeconnection(host, port, outfile, infile)
        !            59: **             Make a connection to the named host on the given
        !            60: **             port.  Set *outfile and *infile to the files
        !            61: **             appropriate for communication.  Returns zero on
        !            62: **             success, else an exit status describing the
        !            63: **             error.
        !            64: **     maphostname(hbuf, hbufsize)
        !            65: **             Convert the entry in hbuf into a canonical form.  It
        !            66: **             may not be larger than hbufsize.
        !            67: */
        !            68: /*
        !            69: **  GETREQUESTS -- open mail IPC port and get requests.
        !            70: **
        !            71: **     Parameters:
        !            72: **             none.
        !            73: **
        !            74: **     Returns:
        !            75: **             none.
        !            76: **
        !            77: **     Side Effects:
        !            78: **             Waits until some interesting activity occurs.  When
        !            79: **             it does, a child is created to process it, and the
        !            80: **             parent waits for completion.  Return from this
        !            81: **             routine is always in the child.  The file pointers
        !            82: **             "InChannel" and "OutChannel" should be set to point
        !            83: **             to the communication channel.
        !            84: */
        !            85: 
        !            86: struct sockaddr_in     SendmailAddress;/* internet address of sendmail */
        !            87: 
        !            88: int    DaemonSocket    = -1;           /* fd describing socket */
        !            89: char   *NetName;                       /* name of home (local?) network */
        !            90: 
        !            91: getrequests()
        !            92: {
        !            93:        int t;
        !            94:        register struct servent *sp;
        !            95:        int on = 1;
        !            96:        extern reapchild();
        !            97: 
        !            98:        /*
        !            99:        **  Set up the address for the mailer.
        !           100:        */
        !           101: 
        !           102:        sp = getservbyname("smtp", "tcp");
        !           103:        if (sp == NULL)
        !           104:        {
        !           105:                syserr("server \"smtp\" unknown");
        !           106:                goto severe;
        !           107:        }
        !           108:        SendmailAddress.sin_family = AF_INET;
        !           109:        SendmailAddress.sin_addr.s_addr = INADDR_ANY;
        !           110:        SendmailAddress.sin_port = sp->s_port;
        !           111: 
        !           112:        /*
        !           113:        **  Try to actually open the connection.
        !           114:        */
        !           115: 
        !           116: # ifdef DEBUG
        !           117:        if (tTd(15, 1))
        !           118:                printf("getrequests: port 0x%x\n", SendmailAddress.sin_port);
        !           119: # endif DEBUG
        !           120: 
        !           121:        /* get a socket for the SMTP connection */
        !           122:        DaemonSocket = socket(AF_INET, SOCK_STREAM, 0);
        !           123:        if (DaemonSocket < 0)
        !           124:        {
        !           125:                /* probably another daemon already */
        !           126:                syserr("getrequests: can't create socket");
        !           127:          severe:
        !           128: # ifdef LOG
        !           129:                if (LogLevel > 0)
        !           130:                        syslog(LOG_ALERT, "cannot get connection");
        !           131: # endif LOG
        !           132:                finis();
        !           133:        }
        !           134: 
        !           135: #ifdef DEBUG
        !           136:        /* turn on network debugging? */
        !           137:        if (tTd(15, 15))
        !           138:                (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on);
        !           139: #endif DEBUG
        !           140: 
        !           141:        (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on);
        !           142:        (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on);
        !           143: 
        !           144:        if (bind(DaemonSocket, &SendmailAddress, sizeof SendmailAddress) < 0)
        !           145:        {
        !           146:                syserr("getrequests: cannot bind");
        !           147:                (void) close(DaemonSocket);
        !           148:                goto severe;
        !           149:        }
        !           150:        if (listen(DaemonSocket, 10) < 0)
        !           151:        {
        !           152:                syserr("getrequests: cannot listen");
        !           153:                (void) close(DaemonSocket);
        !           154:                goto severe;
        !           155:        }
        !           156: 
        !           157:        (void) signal(SIGCHLD, reapchild);
        !           158: 
        !           159: # ifdef DEBUG
        !           160:        if (tTd(15, 1))
        !           161:                printf("getrequests: %d\n", DaemonSocket);
        !           162: # endif DEBUG
        !           163: 
        !           164:        for (;;)
        !           165:        {
        !           166:                register int pid;
        !           167:                auto int lotherend;
        !           168:                struct sockaddr_in otherend;
        !           169:                extern int RefuseLA;
        !           170: 
        !           171:                /* see if we are rejecting connections */
        !           172:                while (getla() > RefuseLA)
        !           173:                        sleep(5);
        !           174: 
        !           175:                /* wait for a connection */
        !           176:                do
        !           177:                {
        !           178:                        errno = 0;
        !           179:                        lotherend = sizeof otherend;
        !           180:                        t = accept(DaemonSocket, &otherend, &lotherend);
        !           181:                } while (t < 0 && errno == EINTR);
        !           182:                if (t < 0)
        !           183:                {
        !           184:                        syserr("getrequests: accept");
        !           185:                        sleep(5);
        !           186:                        continue;
        !           187:                }
        !           188: 
        !           189:                /*
        !           190:                **  Create a subprocess to process the mail.
        !           191:                */
        !           192: 
        !           193: # ifdef DEBUG
        !           194:                if (tTd(15, 2))
        !           195:                        printf("getrequests: forking (fd = %d)\n", t);
        !           196: # endif DEBUG
        !           197: 
        !           198:                pid = fork();
        !           199:                if (pid < 0)
        !           200:                {
        !           201:                        syserr("daemon: cannot fork");
        !           202:                        sleep(10);
        !           203:                        (void) close(t);
        !           204:                        continue;
        !           205:                }
        !           206: 
        !           207:                if (pid == 0)
        !           208:                {
        !           209:                        extern struct hostent *gethostbyaddr();
        !           210:                        register struct hostent *hp;
        !           211:                        char buf[MAXNAME];
        !           212: 
        !           213:                        /*
        !           214:                        **  CHILD -- return to caller.
        !           215:                        **      Collect verified idea of sending host.
        !           216:                        **      Verify calling user id if possible here.
        !           217:                        */
        !           218: 
        !           219:                        (void) signal(SIGCHLD, SIG_DFL);
        !           220: 
        !           221:                        /* determine host name */
        !           222:                        hp = gethostbyaddr((char *) &otherend.sin_addr, sizeof otherend.sin_addr, AF_INET);
        !           223:                        if (hp != NULL)
        !           224:                        {
        !           225:                                (void) strcpy(buf, hp->h_name);
        !           226:                                if (NetName != NULL && NetName[0] != '\0' &&
        !           227:                                    index(hp->h_name, '.') == NULL)
        !           228:                                {
        !           229:                                        (void) strcat(buf, ".");
        !           230:                                        (void) strcat(buf, NetName);
        !           231:                                }
        !           232:                        }
        !           233:                        else
        !           234:                        {
        !           235:                                extern char *inet_ntoa();
        !           236: 
        !           237:                                /* produce a dotted quad */
        !           238:                                (void) sprintf(buf, "[%s]",
        !           239:                                        inet_ntoa(otherend.sin_addr));
        !           240:                        }
        !           241: 
        !           242:                        /* should we check for illegal connection here? XXX */
        !           243: 
        !           244:                        RealHostName = newstr(buf);
        !           245: 
        !           246:                        (void) close(DaemonSocket);
        !           247:                        InChannel = fdopen(t, "r");
        !           248:                        OutChannel = fdopen(dup(t), "w");
        !           249: # ifdef DEBUG
        !           250:                        if (tTd(15, 2))
        !           251:                                printf("getreq: returning\n");
        !           252: # endif DEBUG
        !           253: # ifdef LOG
        !           254:                        if (LogLevel > 11)
        !           255:                                syslog(LOG_DEBUG, "connected, pid=%d", getpid());
        !           256: # endif LOG
        !           257:                        return;
        !           258:                }
        !           259: 
        !           260:                /* close the port so that others will hang (for a while) */
        !           261:                (void) close(t);
        !           262:        }
        !           263:        /*NOTREACHED*/
        !           264: }
        !           265: /*
        !           266: **  CLRDAEMON -- reset the daemon connection
        !           267: **
        !           268: **     Parameters:
        !           269: **             none.
        !           270: **
        !           271: **     Returns:
        !           272: **             none.
        !           273: **
        !           274: **     Side Effects:
        !           275: **             releases any resources used by the passive daemon.
        !           276: */
        !           277: 
        !           278: clrdaemon()
        !           279: {
        !           280:        if (DaemonSocket >= 0)
        !           281:                (void) close(DaemonSocket);
        !           282:        DaemonSocket = -1;
        !           283: }
        !           284: /*
        !           285: **  MAKECONNECTION -- make a connection to an SMTP socket on another machine.
        !           286: **
        !           287: **     Parameters:
        !           288: **             host -- the name of the host.
        !           289: **             port -- the port number to connect to.
        !           290: **             outfile -- a pointer to a place to put the outfile
        !           291: **                     descriptor.
        !           292: **             infile -- ditto for infile.
        !           293: **
        !           294: **     Returns:
        !           295: **             An exit code telling whether the connection could be
        !           296: **                     made and if not why not.
        !           297: **
        !           298: **     Side Effects:
        !           299: **             none.
        !           300: */
        !           301: 
        !           302: int    h_errno;        /*this will go away when code implemented*/
        !           303: 
        !           304: makeconnection(host, port, outfile, infile)
        !           305:        char *host;
        !           306:        u_short port;
        !           307:        FILE **outfile;
        !           308:        FILE **infile;
        !           309: {
        !           310:        register int i, s;
        !           311:        register struct hostent *hp = (struct hostent *)NULL;
        !           312:        extern char *inet_ntoa();
        !           313:        int sav_errno;
        !           314: 
        !           315:        /*
        !           316:        **  Set up the address for the mailer.
        !           317:        **      Accept "[a.b.c.d]" syntax for host name.
        !           318:        */
        !           319: 
        !           320:        h_errno = 0;
        !           321:        errno = 0;
        !           322: 
        !           323:        if (host[0] == '[')
        !           324:        {
        !           325:                long hid;
        !           326:                register char *p = index(host, ']');
        !           327: 
        !           328:                if (p != NULL)
        !           329:                {
        !           330:                        *p = '\0';
        !           331:                        hid = inet_addr(&host[1]);
        !           332:                        *p = ']';
        !           333:                }
        !           334:                if (p == NULL || hid == -1)
        !           335:                {
        !           336:                        usrerr("Invalid numeric domain spec \"%s\"", host);
        !           337:                        return (EX_NOHOST);
        !           338:                }
        !           339:                SendmailAddress.sin_addr.s_addr = hid;
        !           340:        }
        !           341:        else
        !           342:        {
        !           343:                hp = gethostbyname(host);
        !           344:                if (hp == NULL)
        !           345:                {
        !           346:                        if (errno == ETIMEDOUT || h_errno == TRY_AGAIN)
        !           347:                                return (EX_TEMPFAIL);
        !           348: 
        !           349:                        /*
        !           350:                        **  XXX Should look for mail forwarder record here
        !           351:                        **  XXX if (h_errno == NO_ADDRESS).
        !           352:                        */
        !           353: 
        !           354:                        return (EX_NOHOST);
        !           355:                }
        !           356:                bcopy(hp->h_addr, (char *) &SendmailAddress.sin_addr, hp->h_length);
        !           357:                i = 1;
        !           358:        }
        !           359: 
        !           360:        /*
        !           361:        **  Determine the port number.
        !           362:        */
        !           363: 
        !           364:        if (port != 0)
        !           365:                SendmailAddress.sin_port = htons(port);
        !           366:        else
        !           367:        {
        !           368:                register struct servent *sp = getservbyname("smtp", "tcp");
        !           369: 
        !           370:                if (sp == NULL)
        !           371:                {
        !           372:                        syserr("makeconnection: server \"smtp\" unknown");
        !           373:                        return (EX_OSFILE);
        !           374:                }
        !           375:                SendmailAddress.sin_port = sp->s_port;
        !           376:        }
        !           377: 
        !           378:        /*
        !           379:        **  Try to actually open the connection.
        !           380:        */
        !           381: 
        !           382: again:
        !           383: # ifdef DEBUG
        !           384:        if (tTd(16, 1))
        !           385:                printf("makeconnection (%s [%s])\n", host,
        !           386:                    inet_ntoa(SendmailAddress.sin_addr.s_addr));
        !           387: # endif DEBUG
        !           388: 
        !           389:        s = socket(AF_INET, SOCK_STREAM, 0);
        !           390:        if (s < 0)
        !           391:        {
        !           392:                syserr("makeconnection: no socket");
        !           393:                sav_errno = errno;
        !           394:                goto failure;
        !           395:        }
        !           396: 
        !           397: # ifdef DEBUG
        !           398:        if (tTd(16, 1))
        !           399:                printf("makeconnection: %d\n", s);
        !           400: 
        !           401:        /* turn on network debugging? */
        !           402:        if (tTd(16, 14))
        !           403:        {
        !           404:                int on = 1;
        !           405:                (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on);
        !           406:        }
        !           407: # endif DEBUG
        !           408:        (void) fflush(CurEnv->e_xfp);                   /* for debugging */
        !           409:        errno = 0;                                      /* for debugging */
        !           410:        SendmailAddress.sin_family = AF_INET;
        !           411:        if (connect(s, &SendmailAddress, sizeof SendmailAddress) < 0)
        !           412:        {
        !           413:                sav_errno = errno;
        !           414:                (void) close(s);
        !           415:                if (hp && hp->h_addr_list[i])
        !           416:                {
        !           417:                        bcopy(hp->h_addr_list[i++],
        !           418:                            (char *)&SendmailAddress.sin_addr, hp->h_length);
        !           419:                        goto again;
        !           420:                }
        !           421: 
        !           422:                /* failure, decide if temporary or not */
        !           423:        failure:
        !           424:                switch (sav_errno)
        !           425:                {
        !           426:                  case EISCONN:
        !           427:                  case ETIMEDOUT:
        !           428:                  case EINPROGRESS:
        !           429:                  case EALREADY:
        !           430:                  case EADDRINUSE:
        !           431:                  case EHOSTDOWN:
        !           432:                  case ENETDOWN:
        !           433:                  case ENETRESET:
        !           434:                  case ENOBUFS:
        !           435:                  case ECONNREFUSED:
        !           436:                  case ECONNRESET:
        !           437:                  case EHOSTUNREACH:
        !           438:                  case ENETUNREACH:
        !           439:                        /* there are others, I'm sure..... */
        !           440:                        return (EX_TEMPFAIL);
        !           441: 
        !           442:                  case EPERM:
        !           443:                        /* why is this happening? */
        !           444:                        syserr("makeconnection: funny failure, addr=%lx, port=%x",
        !           445:                                SendmailAddress.sin_addr.s_addr, SendmailAddress.sin_port);
        !           446:                        return (EX_TEMPFAIL);
        !           447: 
        !           448:                  default:
        !           449:                        message(Arpa_Info, "%s", errstring(sav_errno));
        !           450:                        return (EX_UNAVAILABLE);
        !           451:                }
        !           452:        }
        !           453: 
        !           454:        /* connection ok, put it into canonical form */
        !           455:        *outfile = fdopen(s, "w");
        !           456:        *infile = fdopen(s, "r");
        !           457: 
        !           458:        return (EX_OK);
        !           459: }
        !           460: /*
        !           461: **  MYHOSTNAME -- return the name of this host.
        !           462: **
        !           463: **     Parameters:
        !           464: **             hostbuf -- a place to return the name of this host.
        !           465: **             size -- the size of hostbuf.
        !           466: **
        !           467: **     Returns:
        !           468: **             A list of aliases for this host.
        !           469: **
        !           470: **     Side Effects:
        !           471: **             none.
        !           472: */
        !           473: 
        !           474: char **
        !           475: myhostname(hostbuf, size)
        !           476:        char hostbuf[];
        !           477:        int size;
        !           478: {
        !           479:        extern struct hostent *gethostbyname();
        !           480:        struct hostent *hp;
        !           481: 
        !           482:        if (gethostname(hostbuf, size) < 0)
        !           483:        {
        !           484:                (void) strcpy(hostbuf, "localhost");
        !           485:        }
        !           486:        hp = gethostbyname(hostbuf);
        !           487:        if (hp != NULL)
        !           488:        {
        !           489:                (void) strcpy(hostbuf, hp->h_name);
        !           490:                return (hp->h_aliases);
        !           491:        }
        !           492:        else
        !           493:                return (NULL);
        !           494: }
        !           495: 
        !           496: /*
        !           497:  *  MAPHOSTNAME -- turn a hostname into canonical form
        !           498:  *
        !           499:  *     Parameters:
        !           500:  *             hbuf -- a buffer containing a hostname.
        !           501:  *             hbsize -- the size of hbuf.
        !           502:  *
        !           503:  *     Returns:
        !           504:  *             none.
        !           505:  *
        !           506:  *     Side Effects:
        !           507:  *             Looks up the host specified in hbuf.  If it is not
        !           508:  *             the canonical name for that host, replace it with
        !           509:  *             the canonical name.  If the name is unknown, or it
        !           510:  *             is already the canonical name, leave it unchanged.
        !           511:  */
        !           512: maphostname(hbuf, hbsize)
        !           513:        char *hbuf;
        !           514:        int hbsize;
        !           515: {
        !           516:        register struct hostent *hp;
        !           517:        u_long in_addr;
        !           518:        char ptr[256];
        !           519:        struct hostent *gethostbyaddr();
        !           520: 
        !           521:        /*
        !           522:         * If first character is a bracket, then it is an address
        !           523:         * lookup.  Address is copied into a temporary buffer to
        !           524:         * strip the brackets and to preserve hbuf if address is
        !           525:         * unknown.
        !           526:         */
        !           527:        if (*hbuf != '[') {
        !           528:                getcanonname(hbuf, hbsize);
        !           529:                return;
        !           530:        }
        !           531:        *index(strcpy(ptr, hbuf), ']') = '\0';
        !           532:        in_addr = inet_addr(&ptr[1]);
        !           533:        hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET);
        !           534:        if (hp == NULL)
        !           535:                return;
        !           536:        if (strlen(hp->h_name) >= hbsize)
        !           537:                hp->h_name[hbsize - 1] = '\0';
        !           538:        (void)strcpy(hbuf, hp->h_name);
        !           539: }
        !           540: 
        !           541: # else DAEMON
        !           542: /* code for systems without sophisticated networking */
        !           543: 
        !           544: /*
        !           545: **  MYHOSTNAME -- stub version for case of no daemon code.
        !           546: **
        !           547: **     Can't convert to upper case here because might be a UUCP name.
        !           548: **
        !           549: **     Mark, you can change this to be anything you want......
        !           550: */
        !           551: 
        !           552: char **
        !           553: myhostname(hostbuf, size)
        !           554:        char hostbuf[];
        !           555:        int size;
        !           556: {
        !           557:        register FILE *f;
        !           558: 
        !           559:        hostbuf[0] = '\0';
        !           560:        f = fopen("/usr/include/whoami", "r");
        !           561:        if (f != NULL)
        !           562:        {
        !           563:                (void) fgets(hostbuf, size, f);
        !           564:                fixcrlf(hostbuf, TRUE);
        !           565:                (void) fclose(f);
        !           566:        }
        !           567:        return (NULL);
        !           568: }
        !           569: /*
        !           570: **  MAPHOSTNAME -- turn a hostname into canonical form
        !           571: **
        !           572: **     Parameters:
        !           573: **             hbuf -- a buffer containing a hostname.
        !           574: **             hbsize -- the size of hbuf.
        !           575: **
        !           576: **     Returns:
        !           577: **             none.
        !           578: **
        !           579: **     Side Effects:
        !           580: **             Looks up the host specified in hbuf.  If it is not
        !           581: **             the canonical name for that host, replace it with
        !           582: **             the canonical name.  If the name is unknown, or it
        !           583: **             is already the canonical name, leave it unchanged.
        !           584: */
        !           585: 
        !           586: /*ARGSUSED*/
        !           587: maphostname(hbuf, hbsize)
        !           588:        char *hbuf;
        !           589:        int hbsize;
        !           590: {
        !           591:        return;
        !           592: }
        !           593: 
        !           594: #endif DAEMON

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.