# 2.11BSD#431 - /usr/src/usr.sbin/sendmail/src/daemon.c

##### Functions

    clrdaemon         X
    getrequests       X
    makeconnection    X
    maphostname       X
    myhostname        X

##### Variables

    DaemonSocket      X
    NetName           X
    SendmailAddress   X
    h_errno           X

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

#### Defined functions

clrdaemon defined in line 270; used 1 times

- in /usr/src/usr.sbin/sendmail/src/queue.c line 321

getrequests defined in line 83; used 1 times

- in /usr/src/usr.sbin/sendmail/src/main.c line 643

makeconnection defined in line 296; used 2 times

- in /usr/src/usr.sbin/sendmail/src/deliver.c line 727, 734

maphostname defined in line 585; used 1 times

- in /usr/src/usr.sbin/sendmail/src/parseaddr.c line 767

myhostname defined in line 546; used 2 times

- in /usr/src/usr.sbin/sendmail/src/main.c line 115, 242

#### Defined variables

DaemonSocket defined in line 80; used 16 times

- in line 114-115(2), 130-145(7), 153, 172, 238, 272-274(3), 393

NetName defined in line 81; used 4 times

- in line 218-222(3)
- in /usr/src/usr.sbin/sendmail/src/readcf.c line 824

SccsId defined in line 27; never used
SendmailAddress defined in line 78; used 15 times

- in line 100-102(3), 110, 136(2), 329, 347, 355, 365, 398-399(3), 426(2)

h_errno defined in line 294; used 2 times

- in line 310, 337

Last modified: 1997-10-03 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2252 |