122700Sdist /* 234920Sbostic * Copyright (c) 1983 Eric P. Allman 362522Sbostic * Copyright (c) 1988, 1993 462522Sbostic * The Regents of the University of California. All rights reserved. 533780Sbostic * 642825Sbostic * %sccs.include.redist.c% 733780Sbostic */ 822700Sdist 933932Sbostic #include <errno.h> 1040962Sbostic #include "sendmail.h" 114535Seric 1233780Sbostic #ifndef lint 1333780Sbostic #ifdef DAEMON 14*66812Seric static char sccsid[] = "@(#)daemon.c 8.43 (Berkeley) 04/16/94 (with daemon mode)"; 1533780Sbostic #else 16*66812Seric static char sccsid[] = "@(#)daemon.c 8.43 (Berkeley) 04/16/94 (without daemon mode)"; 1733780Sbostic #endif 1833780Sbostic #endif /* not lint */ 194535Seric 2033780Sbostic #ifdef DAEMON 2133780Sbostic 2223120Seric # include <netdb.h> 2364338Seric # include <arpa/inet.h> 245978Seric 2566334Seric #if NAMED_BIND 2659042Seric # include <arpa/nameser.h> 2759042Seric # include <resolv.h> 2859042Seric #endif 2959042Seric 304535Seric /* 314535Seric ** DAEMON.C -- routines to use when running as a daemon. 327556Seric ** 337556Seric ** This entire file is highly dependent on the 4.2 BSD 347556Seric ** interprocess communication primitives. No attempt has 357556Seric ** been made to make this file portable to Version 7, 367556Seric ** Version 6, MPX files, etc. If you should try such a 377556Seric ** thing yourself, I recommend chucking the entire file 387556Seric ** and starting from scratch. Basic semantics are: 397556Seric ** 407556Seric ** getrequests() 417556Seric ** Opens a port and initiates a connection. 427556Seric ** Returns in a child. Must set InChannel and 437556Seric ** OutChannel appropriately. 4410206Seric ** clrdaemon() 4510206Seric ** Close any open files associated with getting 4610206Seric ** the connection; this is used when running the queue, 4710206Seric ** etc., to avoid having extra file descriptors during 4810206Seric ** the queue run and to avoid confusing the network 4910206Seric ** code (if it cares). 5052106Seric ** makeconnection(host, port, outfile, infile, usesecureport) 517556Seric ** Make a connection to the named host on the given 527556Seric ** port. Set *outfile and *infile to the files 537556Seric ** appropriate for communication. Returns zero on 547556Seric ** success, else an exit status describing the 557556Seric ** error. 5660089Seric ** host_map_lookup(map, hbuf, avp, pstat) 5756823Seric ** Convert the entry in hbuf into a canonical form. 584535Seric */ 594535Seric /* 604535Seric ** GETREQUESTS -- open mail IPC port and get requests. 614535Seric ** 624535Seric ** Parameters: 634535Seric ** none. 644535Seric ** 654535Seric ** Returns: 664535Seric ** none. 674535Seric ** 684535Seric ** Side Effects: 694535Seric ** Waits until some interesting activity occurs. When 704535Seric ** it does, a child is created to process it, and the 714535Seric ** parent waits for completion. Return from this 729886Seric ** routine is always in the child. The file pointers 739886Seric ** "InChannel" and "OutChannel" should be set to point 749886Seric ** to the communication channel. 754535Seric */ 764535Seric 7758849Seric int DaemonSocket = -1; /* fd describing socket */ 7858849Seric SOCKADDR DaemonAddr; /* socket for incoming */ 7959783Seric int ListenQueueSize = 10; /* size of listen queue */ 8064381Seric int TcpRcvBufferSize = 0; /* size of TCP receive buffer */ 8164381Seric int TcpSndBufferSize = 0; /* size of TCP send buffer */ 8216144Seric 834535Seric getrequests() 844535Seric { 859610Seric int t; 8625027Seric int on = 1; 8753751Seric bool refusingconnections = TRUE; 8858419Seric FILE *pidf; 8964828Seric int socksize; 9066793Seric #ifdef XDEBUG 9166793Seric bool j_has_dot; 9266793Seric #endif 9346928Sbostic extern void reapchild(); 947117Seric 959610Seric /* 969610Seric ** Set up the address for the mailer. 979610Seric */ 989610Seric 9958849Seric if (DaemonAddr.sin.sin_family == 0) 10058849Seric DaemonAddr.sin.sin_family = AF_INET; 10158849Seric if (DaemonAddr.sin.sin_addr.s_addr == 0) 10258849Seric DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; 10358849Seric if (DaemonAddr.sin.sin_port == 0) 1049610Seric { 10565169Seric register struct servent *sp; 10665169Seric 10758849Seric sp = getservbyname("smtp", "tcp"); 10858849Seric if (sp == NULL) 10958849Seric { 11058909Seric syserr("554 service \"smtp\" unknown"); 11165169Seric DaemonAddr.sin.sin_port = htons(25); 11258849Seric } 11365169Seric else 11465169Seric DaemonAddr.sin.sin_port = sp->s_port; 1159610Seric } 1169610Seric 1179610Seric /* 1189610Seric ** Try to actually open the connection. 1199610Seric */ 1209610Seric 1219610Seric if (tTd(15, 1)) 12258849Seric printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); 1239610Seric 1249610Seric /* get a socket for the SMTP connection */ 12559041Seric DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0); 12610206Seric if (DaemonSocket < 0) 1279610Seric { 1289610Seric /* probably another daemon already */ 1299610Seric syserr("getrequests: can't create socket"); 1309610Seric severe: 1319610Seric # ifdef LOG 1329610Seric if (LogLevel > 0) 13357663Seric syslog(LOG_ALERT, "problem creating SMTP socket"); 13456795Seric # endif /* LOG */ 1359610Seric finis(); 1369610Seric } 13710347Seric 13810347Seric /* turn on network debugging? */ 13956328Seric if (tTd(15, 101)) 14024945Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 14110347Seric 14225027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 14325027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 14425027Seric 14564391Seric #ifdef SO_RCVBUF 14664391Seric if (TcpRcvBufferSize > 0) 14764391Seric { 14864391Seric if (setsockopt(DaemonSocket, SOL_SOCKET, SO_RCVBUF, 14964561Seric (char *) &TcpRcvBufferSize, 15064391Seric sizeof(TcpRcvBufferSize)) < 0) 15164391Seric syserr("getrequests: setsockopt(SO_RCVBUF)"); 15264391Seric } 15364391Seric #endif 15464391Seric 15559041Seric switch (DaemonAddr.sa.sa_family) 1569610Seric { 15759041Seric # ifdef NETINET 15859041Seric case AF_INET: 15964828Seric socksize = sizeof DaemonAddr.sin; 16059041Seric break; 16159041Seric # endif 16259041Seric 16359041Seric # ifdef NETISO 16459041Seric case AF_ISO: 16564828Seric socksize = sizeof DaemonAddr.siso; 16659041Seric break; 16759041Seric # endif 16859041Seric 16959041Seric default: 17064828Seric socksize = sizeof DaemonAddr; 17159041Seric break; 17259041Seric } 17359041Seric 17464828Seric if (bind(DaemonSocket, &DaemonAddr.sa, socksize) < 0) 17559041Seric { 1769610Seric syserr("getrequests: cannot bind"); 17710206Seric (void) close(DaemonSocket); 1789610Seric goto severe; 1799610Seric } 1809610Seric 18164035Seric (void) setsignal(SIGCHLD, reapchild); 18224945Seric 18358419Seric /* write the pid to the log file for posterity */ 18458419Seric pidf = fopen(PidFile, "w"); 18558419Seric if (pidf != NULL) 18658419Seric { 18763863Seric extern char *CommandLineArgs; 18863863Seric 18963863Seric /* write the process id on line 1 */ 19058419Seric fprintf(pidf, "%d\n", getpid()); 19163863Seric 19263863Seric /* line 2 contains all command line flags */ 19363863Seric fprintf(pidf, "%s\n", CommandLineArgs); 19463863Seric 19563863Seric /* flush and close */ 19658419Seric fclose(pidf); 19758419Seric } 19858419Seric 19966793Seric #ifdef XDEBUG 20066793Seric { 201*66812Seric char jbuf[MAXHOSTNAMELEN]; 20258419Seric 203*66812Seric expand("\201j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv); 204*66812Seric j_has_dot = strchr(jbuf, '.') != NULL; 20566793Seric } 20666793Seric #endif 20766793Seric 2089610Seric if (tTd(15, 1)) 20910206Seric printf("getrequests: %d\n", DaemonSocket); 2109610Seric 2114631Seric for (;;) 2124631Seric { 21314875Seric register int pid; 21411147Seric auto int lotherend; 21553751Seric extern bool refuseconnections(); 21611147Seric 21714875Seric /* see if we are rejecting connections */ 21853751Seric CurrentLA = getla(); 21953751Seric if (refuseconnections()) 22036584Sbostic { 22153751Seric if (!refusingconnections) 22253751Seric { 22353751Seric /* don't queue so peer will fail quickly */ 22453751Seric (void) listen(DaemonSocket, 0); 22553751Seric refusingconnections = TRUE; 22653751Seric } 22757385Seric setproctitle("rejecting connections: load average: %d", 22857385Seric CurrentLA); 22914875Seric sleep(5); 23053751Seric continue; 23136584Sbostic } 23214875Seric 23353751Seric if (refusingconnections) 23453751Seric { 23553751Seric /* start listening again */ 23659783Seric if (listen(DaemonSocket, ListenQueueSize) < 0) 23753751Seric { 23853751Seric syserr("getrequests: cannot listen"); 23953751Seric (void) close(DaemonSocket); 24053751Seric goto severe; 24153751Seric } 24253751Seric setproctitle("accepting connections"); 24353751Seric refusingconnections = FALSE; 24453751Seric } 24553751Seric 24666793Seric #ifdef XDEBUG 24766793Seric /* check for disaster */ 24866793Seric { 24966793Seric register STAB *s; 250*66812Seric char jbuf[MAXHOSTNAMELEN]; 25166793Seric 252*66812Seric expand("\201j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv); 253*66812Seric if ((s = stab(jbuf, ST_CLASS, ST_FIND)) == NULL || 25466793Seric !bitnset('w', s->s_class)) 25566793Seric { 25666793Seric dumpstate("daemon lost $j"); 25766793Seric syslog(LOG_ALERT, "daemon process doesn't have $j in $=w; see syslog"); 25866793Seric abort(); 25966793Seric } 260*66812Seric else if (j_has_dot && strchr(jbuf, '.') == NULL) 26166793Seric { 26266793Seric dumpstate("daemon $j lost dot"); 26366793Seric syslog(LOG_ALERT, "daemon process $j lost dot; see syslog"); 26466793Seric abort(); 26566793Seric } 26666793Seric } 26766793Seric #endif 26866793Seric 2699610Seric /* wait for a connection */ 2709610Seric do 2719610Seric { 2729610Seric errno = 0; 27364828Seric lotherend = socksize; 27446928Sbostic t = accept(DaemonSocket, 27546928Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 2769610Seric } while (t < 0 && errno == EINTR); 2779610Seric if (t < 0) 2785978Seric { 2799610Seric syserr("getrequests: accept"); 2809610Seric sleep(5); 2819610Seric continue; 2825978Seric } 2834631Seric 2845978Seric /* 2855978Seric ** Create a subprocess to process the mail. 2865978Seric */ 2875978Seric 2887677Seric if (tTd(15, 2)) 2899610Seric printf("getrequests: forking (fd = %d)\n", t); 2905978Seric 2914636Seric pid = fork(); 2924636Seric if (pid < 0) 2934631Seric { 2944636Seric syserr("daemon: cannot fork"); 2954636Seric sleep(10); 2969610Seric (void) close(t); 2974636Seric continue; 2984631Seric } 2994631Seric 3004636Seric if (pid == 0) 3014631Seric { 30264086Seric char *p; 30358951Seric extern char *hostnamebyanyaddr(); 30411147Seric 3054636Seric /* 3064636Seric ** CHILD -- return to caller. 30711147Seric ** Collect verified idea of sending host. 3084636Seric ** Verify calling user id if possible here. 3094636Seric */ 3104631Seric 31164035Seric (void) setsignal(SIGCHLD, SIG_DFL); 31266017Seric DisConnected = FALSE; 31324950Seric 31466032Seric setproctitle("startup with %s", 31566032Seric anynet_ntoa(&RealHostAddr)); 31666032Seric 31711147Seric /* determine host name */ 31864086Seric p = hostnamebyanyaddr(&RealHostAddr); 31964086Seric RealHostName = newstr(p); 32066032Seric setproctitle("startup with %s", p); 32158778Seric 32255173Seric #ifdef LOG 32363842Seric if (LogLevel > 11) 32455173Seric { 32555173Seric /* log connection information */ 32655173Seric syslog(LOG_INFO, "connect from %s (%s)", 32758951Seric RealHostName, anynet_ntoa(&RealHostAddr)); 32855173Seric } 32955173Seric #endif 33055173Seric 33159254Seric (void) close(DaemonSocket); 33264724Seric if ((InChannel = fdopen(t, "r")) == NULL || 33364724Seric (t = dup(t)) < 0 || 33464724Seric (OutChannel = fdopen(t, "w")) == NULL) 33564724Seric { 33664724Seric syserr("cannot open SMTP server channel, fd=%d", t); 33764724Seric exit(0); 33864724Seric } 33959254Seric 34016884Seric /* should we check for illegal connection here? XXX */ 34159156Seric #ifdef XLA 34259156Seric if (!xla_host_ok(RealHostName)) 34359156Seric { 34459254Seric message("421 Too many SMTP sessions for this host"); 34559156Seric exit(0); 34659156Seric } 34759156Seric #endif 34816884Seric 3497677Seric if (tTd(15, 2)) 3505978Seric printf("getreq: returning\n"); 3514636Seric return; 3524631Seric } 3534631Seric 3547117Seric /* close the port so that others will hang (for a while) */ 3559610Seric (void) close(t); 3564631Seric } 3579886Seric /*NOTREACHED*/ 3584631Seric } 3595978Seric /* 36010206Seric ** CLRDAEMON -- reset the daemon connection 36110206Seric ** 36210206Seric ** Parameters: 36310206Seric ** none. 36410206Seric ** 36510206Seric ** Returns: 36610206Seric ** none. 36710206Seric ** 36810206Seric ** Side Effects: 36910206Seric ** releases any resources used by the passive daemon. 37010206Seric */ 37110206Seric 37210206Seric clrdaemon() 37310206Seric { 37410206Seric if (DaemonSocket >= 0) 37510206Seric (void) close(DaemonSocket); 37610206Seric DaemonSocket = -1; 37710206Seric } 37810206Seric /* 37958849Seric ** SETDAEMONOPTIONS -- set options for running the daemon 38058849Seric ** 38158849Seric ** Parameters: 38258849Seric ** p -- the options line. 38358849Seric ** 38458849Seric ** Returns: 38558849Seric ** none. 38658849Seric */ 38758849Seric 38858849Seric setdaemonoptions(p) 38958849Seric register char *p; 39058849Seric { 39158873Seric if (DaemonAddr.sa.sa_family == AF_UNSPEC) 39258873Seric DaemonAddr.sa.sa_family = AF_INET; 39358873Seric 39458849Seric while (p != NULL) 39558849Seric { 39658849Seric register char *f; 39758849Seric register char *v; 39858849Seric 39958849Seric while (isascii(*p) && isspace(*p)) 40058849Seric p++; 40158849Seric if (*p == '\0') 40258849Seric break; 40358849Seric f = p; 40458849Seric p = strchr(p, ','); 40558849Seric if (p != NULL) 40658849Seric *p++ = '\0'; 40758849Seric v = strchr(f, '='); 40858849Seric if (v == NULL) 40958849Seric continue; 41058849Seric while (isascii(*++v) && isspace(*v)) 41158849Seric continue; 41258849Seric 41358849Seric switch (*f) 41458849Seric { 41558873Seric case 'F': /* address family */ 41658849Seric if (isascii(*v) && isdigit(*v)) 41758873Seric DaemonAddr.sa.sa_family = atoi(v); 41858873Seric #ifdef NETINET 41958873Seric else if (strcasecmp(v, "inet") == 0) 42058873Seric DaemonAddr.sa.sa_family = AF_INET; 42158873Seric #endif 42258873Seric #ifdef NETISO 42358873Seric else if (strcasecmp(v, "iso") == 0) 42458873Seric DaemonAddr.sa.sa_family = AF_ISO; 42558873Seric #endif 42658873Seric #ifdef NETNS 42758873Seric else if (strcasecmp(v, "ns") == 0) 42858873Seric DaemonAddr.sa.sa_family = AF_NS; 42958873Seric #endif 43058873Seric #ifdef NETX25 43158873Seric else if (strcasecmp(v, "x.25") == 0) 43258873Seric DaemonAddr.sa.sa_family = AF_CCITT; 43358873Seric #endif 43458849Seric else 43558873Seric syserr("554 Unknown address family %s in Family=option", v); 43658873Seric break; 43758873Seric 43858873Seric case 'A': /* address */ 43958873Seric switch (DaemonAddr.sa.sa_family) 44058849Seric { 44158873Seric #ifdef NETINET 44258873Seric case AF_INET: 44358873Seric if (isascii(*v) && isdigit(*v)) 44458873Seric DaemonAddr.sin.sin_addr.s_addr = inet_network(v); 44558873Seric else 44658873Seric { 44758873Seric register struct netent *np; 44858849Seric 44958873Seric np = getnetbyname(v); 45058873Seric if (np == NULL) 45158873Seric syserr("554 network \"%s\" unknown", v); 45258873Seric else 45358873Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 45458873Seric } 45558873Seric break; 45658873Seric #endif 45758873Seric 45858873Seric default: 45958873Seric syserr("554 Address= option unsupported for family %d", 46058873Seric DaemonAddr.sa.sa_family); 46158873Seric break; 46258849Seric } 46358849Seric break; 46458849Seric 46558873Seric case 'P': /* port */ 46658873Seric switch (DaemonAddr.sa.sa_family) 46758849Seric { 46858873Seric short port; 46958849Seric 47058873Seric #ifdef NETINET 47158873Seric case AF_INET: 47258873Seric if (isascii(*v) && isdigit(*v)) 47364366Seric DaemonAddr.sin.sin_port = htons(atoi(v)); 47458849Seric else 47558873Seric { 47658873Seric register struct servent *sp; 47758873Seric 47858873Seric sp = getservbyname(v, "tcp"); 47958873Seric if (sp == NULL) 48058909Seric syserr("554 service \"%s\" unknown", v); 48158873Seric else 48258873Seric DaemonAddr.sin.sin_port = sp->s_port; 48358873Seric } 48458873Seric break; 48558873Seric #endif 48658873Seric 48758873Seric #ifdef NETISO 48858873Seric case AF_ISO: 48958873Seric /* assume two byte transport selector */ 49058873Seric if (isascii(*v) && isdigit(*v)) 49164366Seric port = htons(atoi(v)); 49258873Seric else 49358873Seric { 49458873Seric register struct servent *sp; 49558873Seric 49658873Seric sp = getservbyname(v, "tcp"); 49758873Seric if (sp == NULL) 49858909Seric syserr("554 service \"%s\" unknown", v); 49958873Seric else 50058873Seric port = sp->s_port; 50158873Seric } 50258873Seric bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 50358873Seric break; 50458873Seric #endif 50558873Seric 50658873Seric default: 50758873Seric syserr("554 Port= option unsupported for family %d", 50858873Seric DaemonAddr.sa.sa_family); 50958873Seric break; 51058849Seric } 51158849Seric break; 51259783Seric 51359783Seric case 'L': /* listen queue size */ 51459783Seric ListenQueueSize = atoi(v); 51559783Seric break; 51664381Seric 51764381Seric case 'S': /* send buffer size */ 51864381Seric TcpSndBufferSize = atoi(v); 51964381Seric break; 52064381Seric 52164381Seric case 'R': /* receive buffer size */ 52264381Seric TcpRcvBufferSize = atoi(v); 52364381Seric break; 52458849Seric } 52558849Seric } 52658849Seric } 52758849Seric /* 5286039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 5296039Seric ** 5306039Seric ** Parameters: 5316039Seric ** host -- the name of the host. 5326633Seric ** port -- the port number to connect to. 53353739Seric ** mci -- a pointer to the mail connection information 53453739Seric ** structure to be filled in. 53552106Seric ** usesecureport -- if set, use a low numbered (reserved) 53652106Seric ** port to provide some rudimentary authentication. 5376039Seric ** 5386039Seric ** Returns: 5396039Seric ** An exit code telling whether the connection could be 5406039Seric ** made and if not why not. 5416039Seric ** 5426039Seric ** Side Effects: 5436039Seric ** none. 5446039Seric */ 5455978Seric 54658755Seric SOCKADDR CurHostAddr; /* address of current host */ 54758305Seric 54854967Seric int 54953739Seric makeconnection(host, port, mci, usesecureport) 5506039Seric char *host; 5517286Seric u_short port; 55254967Seric register MCI *mci; 55352106Seric bool usesecureport; 5546039Seric { 55529430Sbloom register int i, s; 55629430Sbloom register struct hostent *hp = (struct hostent *)NULL; 55758755Seric SOCKADDR addr; 55852106Seric int sav_errno; 55958755Seric int addrlen; 56066334Seric #if NAMED_BIND 56135651Seric extern int h_errno; 56235651Seric #endif 5636039Seric 5646039Seric /* 5656039Seric ** Set up the address for the mailer. 5669308Seric ** Accept "[a.b.c.d]" syntax for host name. 5676039Seric */ 5686039Seric 56966334Seric #if NAMED_BIND 57025475Smiriam h_errno = 0; 57135651Seric #endif 57225475Smiriam errno = 0; 57358864Seric bzero(&CurHostAddr, sizeof CurHostAddr); 57464334Seric SmtpPhase = mci->mci_phase = "initial connection"; 57558906Seric CurHostName = host; 57625475Smiriam 5779308Seric if (host[0] == '[') 5789308Seric { 57911147Seric long hid; 58056795Seric register char *p = strchr(host, ']'); 5819308Seric 58211147Seric if (p != NULL) 5839308Seric { 58411147Seric *p = '\0'; 58559884Seric #ifdef NETINET 58611147Seric hid = inet_addr(&host[1]); 58758360Seric if (hid == -1) 58859884Seric #endif 58958360Seric { 59058360Seric /* try it as a host name (avoid MX lookup) */ 59158360Seric hp = gethostbyname(&host[1]); 59266349Seric if (hp == NULL && p[-1] == '.') 59366349Seric { 59466349Seric p[-1] = '\0'; 59566349Seric hp = gethostbyname(&host[1]); 59666349Seric p[-1] = '.'; 59766349Seric } 59858360Seric *p = ']'; 59958360Seric goto gothostent; 60058360Seric } 60111147Seric *p = ']'; 6029308Seric } 60358360Seric if (p == NULL) 6049308Seric { 60558151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 6069308Seric return (EX_NOHOST); 6079308Seric } 60859884Seric #ifdef NETINET 60959884Seric addr.sin.sin_family = AF_INET; /*XXX*/ 61058778Seric addr.sin.sin_addr.s_addr = hid; 61159884Seric #endif 6129308Seric } 6139610Seric else 6149610Seric { 61566349Seric register char *p = &host[strlen(host) - 1]; 61666349Seric 61729430Sbloom hp = gethostbyname(host); 61866349Seric if (hp == NULL && *p == '.') 61966349Seric { 62066349Seric *p = '\0'; 62166349Seric hp = gethostbyname(host); 62266349Seric *p = '.'; 62366349Seric } 62458360Seric gothostent: 62525475Smiriam if (hp == NULL) 62624945Seric { 62766334Seric #if NAMED_BIND 62825475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 62925475Smiriam return (EX_TEMPFAIL); 63025657Seric 63135651Seric /* if name server is specified, assume temp fail */ 63235651Seric if (errno == ECONNREFUSED && UseNameServer) 63335651Seric return (EX_TEMPFAIL); 63435651Seric #endif 63525475Smiriam return (EX_NOHOST); 63624945Seric } 63758778Seric addr.sa.sa_family = hp->h_addrtype; 63858778Seric switch (hp->h_addrtype) 63958778Seric { 64058778Seric #ifdef NETINET 64158778Seric case AF_INET: 64258755Seric bcopy(hp->h_addr, 64358778Seric &addr.sin.sin_addr, 64464943Seric sizeof addr.sin.sin_addr); 64558778Seric break; 64658778Seric #endif 64758778Seric 64858778Seric default: 64958755Seric bcopy(hp->h_addr, 65058778Seric addr.sa.sa_data, 65158755Seric hp->h_length); 65258778Seric break; 65358778Seric } 65429430Sbloom i = 1; 6559610Seric } 6569610Seric 6579610Seric /* 6589610Seric ** Determine the port number. 6599610Seric */ 6609610Seric 66110011Seric if (port != 0) 66258755Seric port = htons(port); 66310011Seric else 6649610Seric { 6659610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 6669610Seric 6679610Seric if (sp == NULL) 6689610Seric { 66958909Seric syserr("554 makeconnection: service \"smtp\" unknown"); 67065169Seric port = htons(25); 6719610Seric } 67265169Seric else 67365169Seric port = sp->s_port; 6749610Seric } 6756039Seric 67658778Seric switch (addr.sa.sa_family) 67758755Seric { 67859884Seric #ifdef NETINET 67958755Seric case AF_INET: 68058778Seric addr.sin.sin_port = port; 68158755Seric addrlen = sizeof (struct sockaddr_in); 68258755Seric break; 68359884Seric #endif 68458755Seric 68558755Seric #ifdef NETISO 68658755Seric case AF_ISO: 68758755Seric /* assume two byte transport selector */ 68858755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 68958755Seric addrlen = sizeof (struct sockaddr_iso); 69058755Seric break; 69158755Seric #endif 69258755Seric 69358755Seric default: 69458778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 69558755Seric return (EX_NOHOST); 69658755Seric } 69758755Seric 6986039Seric /* 6996039Seric ** Try to actually open the connection. 7006039Seric */ 7016039Seric 70259156Seric #ifdef XLA 70359156Seric /* if too many connections, don't bother trying */ 70459156Seric if (!xla_noqueue_ok(host)) 70559156Seric return EX_TEMPFAIL; 70659156Seric #endif 70759156Seric 70857736Seric for (;;) 70952106Seric { 71057736Seric if (tTd(16, 1)) 71158755Seric printf("makeconnection (%s [%s])\n", 71258755Seric host, anynet_ntoa(&addr)); 71352106Seric 71458588Seric /* save for logging */ 71558588Seric CurHostAddr = addr; 71658588Seric 71757736Seric if (usesecureport) 71857736Seric { 71957736Seric int rport = IPPORT_RESERVED - 1; 7206039Seric 72157736Seric s = rresvport(&rport); 72257736Seric } 72357736Seric else 72457736Seric { 72557736Seric s = socket(AF_INET, SOCK_STREAM, 0); 72657736Seric } 72757736Seric if (s < 0) 72857736Seric { 72957736Seric sav_errno = errno; 73057736Seric syserr("makeconnection: no socket"); 73157736Seric goto failure; 73257736Seric } 73310347Seric 73464381Seric #ifdef SO_SNDBUF 73564381Seric if (TcpSndBufferSize > 0) 73664381Seric { 73764381Seric if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 73864561Seric (char *) &TcpSndBufferSize, 73964381Seric sizeof(TcpSndBufferSize)) < 0) 74064381Seric syserr("makeconnection: setsockopt(SO_SNDBUF)"); 74164381Seric } 74264381Seric #endif 74364381Seric 74457736Seric if (tTd(16, 1)) 74557736Seric printf("makeconnection: fd=%d\n", s); 74657736Seric 74757736Seric /* turn on network debugging? */ 74857736Seric if (tTd(16, 101)) 74957736Seric { 75057736Seric int on = 1; 75157736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 75257736Seric (char *)&on, sizeof on); 75357736Seric } 75457736Seric if (CurEnv->e_xfp != NULL) 75557736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 75657736Seric errno = 0; /* for debugging */ 75758755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 75857736Seric break; 75957736Seric 76057736Seric /* couldn't connect.... figure out why */ 76127744Sbloom sav_errno = errno; 76227744Sbloom (void) close(s); 76329430Sbloom if (hp && hp->h_addr_list[i]) 76429430Sbloom { 76557736Seric if (tTd(16, 1)) 76658755Seric printf("Connect failed (%s); trying new address....\n", 76758755Seric errstring(sav_errno)); 76858778Seric switch (addr.sa.sa_family) 76958778Seric { 77058778Seric #ifdef NETINET 77158778Seric case AF_INET: 77258755Seric bcopy(hp->h_addr_list[i++], 77358778Seric &addr.sin.sin_addr, 77464943Seric sizeof addr.sin.sin_addr); 77558778Seric break; 77658778Seric #endif 77758778Seric 77858778Seric default: 77958755Seric bcopy(hp->h_addr_list[i++], 78058778Seric addr.sa.sa_data, 78152106Seric hp->h_length); 78258778Seric break; 78358778Seric } 78457736Seric continue; 78529430Sbloom } 78629430Sbloom 7876039Seric /* failure, decide if temporary or not */ 7886039Seric failure: 78959254Seric #ifdef XLA 79059254Seric xla_host_end(host); 79159254Seric #endif 79258542Seric if (transienterror(sav_errno)) 79358542Seric return EX_TEMPFAIL; 79458542Seric else 79558542Seric { 79658542Seric message("%s", errstring(sav_errno)); 79758542Seric return (EX_UNAVAILABLE); 7986039Seric } 7996039Seric } 8006039Seric 8016039Seric /* connection ok, put it into canonical form */ 80264724Seric if ((mci->mci_out = fdopen(s, "w")) == NULL || 80364724Seric (s = dup(s)) < 0 || 80464725Seric (mci->mci_in = fdopen(s, "r")) == NULL) 80564724Seric { 80664724Seric syserr("cannot open SMTP client channel, fd=%d", s); 80764724Seric return EX_TEMPFAIL; 80864724Seric } 8096039Seric 81010098Seric return (EX_OK); 8116039Seric } 81210758Seric /* 81310758Seric ** MYHOSTNAME -- return the name of this host. 81410758Seric ** 81510758Seric ** Parameters: 81610758Seric ** hostbuf -- a place to return the name of this host. 81712313Seric ** size -- the size of hostbuf. 81810758Seric ** 81910758Seric ** Returns: 82010758Seric ** A list of aliases for this host. 82110758Seric ** 82210758Seric ** Side Effects: 82364338Seric ** Adds numeric codes to $=w. 82410758Seric */ 8256039Seric 82610758Seric char ** 82712313Seric myhostname(hostbuf, size) 82810758Seric char hostbuf[]; 82912313Seric int size; 83010758Seric { 83158110Seric register struct hostent *hp; 83210758Seric extern struct hostent *gethostbyname(); 83310758Seric 83423120Seric if (gethostname(hostbuf, size) < 0) 83523120Seric { 83623120Seric (void) strcpy(hostbuf, "localhost"); 83723120Seric } 83811147Seric hp = gethostbyname(hostbuf); 83911147Seric if (hp != NULL) 84016877Seric { 841*66812Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 842*66812Seric hostbuf[size - 1] = '\0'; 84366777Seric #ifdef NAMED_BIND 844*66812Seric /* if still no dot, try DNS directly (i.e., avoid NIS) */ 845*66812Seric if (strchr(hostbuf, '.') == NULL) 84666777Seric { 84766777Seric extern bool getcanonname(); 84858110Seric 84966777Seric (void) getcanonname(hostbuf, size, TRUE); 85066777Seric } 85166777Seric #endif 85266777Seric 85358110Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 85458110Seric { 85558110Seric register int i; 85658110Seric 85764338Seric for (i = 0; hp->h_addr_list[i] != NULL; i++) 85858110Seric { 85964338Seric char ipbuf[100]; 86064338Seric 86164338Seric sprintf(ipbuf, "[%s]", 86264338Seric inet_ntoa(*((struct in_addr *) hp->h_addr_list[i]))); 86364338Seric setclass('w', ipbuf); 86458110Seric } 86558110Seric } 86658110Seric 86711147Seric return (hp->h_aliases); 86816877Seric } 86910758Seric else 87010758Seric return (NULL); 87110758Seric } 87251315Seric /* 87358951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 87458308Seric ** 87558951Seric ** Uses RFC1413 protocol to try to get info from the other end. 87658951Seric ** 87758308Seric ** Parameters: 87858308Seric ** fd -- the descriptor 87958308Seric ** 88058308Seric ** Returns: 88158951Seric ** The user@host information associated with this descriptor. 88258308Seric */ 88358308Seric 88464927Seric #if IDENTPROTO 88558951Seric 88658951Seric static jmp_buf CtxAuthTimeout; 88758951Seric 88858951Seric static 88958951Seric authtimeout() 89058951Seric { 89158951Seric longjmp(CtxAuthTimeout, 1); 89258951Seric } 89358951Seric 89458951Seric #endif 89558951Seric 89658308Seric char * 89758951Seric getauthinfo(fd) 89858308Seric int fd; 89958308Seric { 90058951Seric int falen; 90159104Seric register char *p; 90264927Seric #if IDENTPROTO 90358951Seric SOCKADDR la; 90458951Seric int lalen; 90558951Seric register struct servent *sp; 90658951Seric int s; 90758951Seric int i; 90858951Seric EVENT *ev; 90958951Seric #endif 91058951Seric static char hbuf[MAXNAME * 2 + 2]; 91158951Seric extern char *hostnamebyanyaddr(); 91258951Seric extern char RealUserName[]; /* main.c */ 91358308Seric 91466761Seric falen = sizeof RealHostAddr; 91566761Seric if (getpeername(fd, &RealHostAddr.sa, &falen) < 0 || falen <= 0 || 91666761Seric RealHostAddr.sa.sa_family == 0) 91758951Seric { 91858951Seric (void) sprintf(hbuf, "%s@localhost", RealUserName); 91958957Seric if (tTd(9, 1)) 92058951Seric printf("getauthinfo: %s\n", hbuf); 92158951Seric return hbuf; 92258951Seric } 92358951Seric 92466761Seric if (RealHostName == NULL) 92566761Seric { 92666761Seric /* translate that to a host name */ 92766761Seric RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 92866761Seric } 92966761Seric 93064927Seric #if IDENTPROTO 93165831Seric if (TimeOuts.to_ident == 0) 93265831Seric goto noident; 93365831Seric 93458951Seric lalen = sizeof la; 93566761Seric if (RealHostAddr.sa.sa_family != AF_INET || 93658951Seric getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || 93758951Seric la.sa.sa_family != AF_INET) 93858951Seric { 93958951Seric /* no ident info */ 94058951Seric goto noident; 94158951Seric } 94258951Seric 94358951Seric /* create ident query */ 94460489Seric (void) sprintf(hbuf, "%d,%d\r\n", 94566761Seric ntohs(RealHostAddr.sin.sin_port), ntohs(la.sin.sin_port)); 94658951Seric 94758951Seric /* create local address */ 94864747Seric la.sin.sin_port = 0; 94958951Seric 95058951Seric /* create foreign address */ 95158951Seric sp = getservbyname("auth", "tcp"); 95258951Seric if (sp != NULL) 95366761Seric RealHostAddr.sin.sin_port = sp->s_port; 95458308Seric else 95566761Seric RealHostAddr.sin.sin_port = htons(113); 95658951Seric 95758951Seric s = -1; 95858951Seric if (setjmp(CtxAuthTimeout) != 0) 95958951Seric { 96058951Seric if (s >= 0) 96158951Seric (void) close(s); 96258951Seric goto noident; 96358951Seric } 96458951Seric 96558951Seric /* put a timeout around the whole thing */ 96664255Seric ev = setevent(TimeOuts.to_ident, authtimeout, 0); 96758951Seric 96864747Seric /* connect to foreign IDENT server using same address as SMTP socket */ 96958951Seric s = socket(AF_INET, SOCK_STREAM, 0); 97058951Seric if (s < 0) 97158951Seric { 97258951Seric clrevent(ev); 97358951Seric goto noident; 97458951Seric } 97564747Seric if (bind(s, &la.sa, sizeof la.sin) < 0 || 97666761Seric connect(s, &RealHostAddr.sa, sizeof RealHostAddr.sin) < 0) 97758951Seric { 97866011Seric goto closeident; 97958951Seric } 98058951Seric 98158957Seric if (tTd(9, 10)) 98258951Seric printf("getauthinfo: sent %s", hbuf); 98358951Seric 98458951Seric /* send query */ 98558951Seric if (write(s, hbuf, strlen(hbuf)) < 0) 98658951Seric goto closeident; 98758951Seric 98858951Seric /* get result */ 98958951Seric i = read(s, hbuf, sizeof hbuf); 99058951Seric (void) close(s); 99158951Seric clrevent(ev); 99258951Seric if (i <= 0) 99358951Seric goto noident; 99458951Seric if (hbuf[--i] == '\n' && hbuf[--i] == '\r') 99558951Seric i--; 99658951Seric hbuf[++i] = '\0'; 99758951Seric 99858957Seric if (tTd(9, 3)) 99958951Seric printf("getauthinfo: got %s\n", hbuf); 100058951Seric 100158951Seric /* parse result */ 100258951Seric p = strchr(hbuf, ':'); 100358951Seric if (p == NULL) 100458951Seric { 100558951Seric /* malformed response */ 100658951Seric goto noident; 100758951Seric } 100858951Seric while (isascii(*++p) && isspace(*p)) 100958951Seric continue; 101058951Seric if (strncasecmp(p, "userid", 6) != 0) 101158951Seric { 101258951Seric /* presumably an error string */ 101358951Seric goto noident; 101458951Seric } 101558951Seric p += 6; 101658951Seric while (isascii(*p) && isspace(*p)) 101758951Seric p++; 101858951Seric if (*p++ != ':') 101958951Seric { 102058951Seric /* either useridxx or malformed response */ 102158951Seric goto noident; 102258951Seric } 102358951Seric 102458951Seric /* p now points to the OSTYPE field */ 102558951Seric p = strchr(p, ':'); 102658951Seric if (p == NULL) 102758951Seric { 102858951Seric /* malformed response */ 102958951Seric goto noident; 103058951Seric } 103158951Seric 103258957Seric /* 1413 says don't do this -- but it's broken otherwise */ 103358957Seric while (isascii(*++p) && isspace(*p)) 103458957Seric continue; 103558957Seric 103658951Seric /* p now points to the authenticated name */ 103766003Seric (void) sprintf(hbuf, "%s@%s", 103866003Seric p, RealHostName == NULL ? "localhost" : RealHostName); 103958957Seric goto finish; 104058957Seric 104166011Seric closeident: 104266011Seric (void) close(s); 104366011Seric clrevent(ev); 104466011Seric 104558957Seric #endif /* IDENTPROTO */ 104658957Seric 104758957Seric noident: 104866003Seric if (RealHostName == NULL) 104966003Seric { 105066003Seric if (tTd(9, 1)) 105166003Seric printf("getauthinfo: NULL\n"); 105266003Seric return NULL; 105366003Seric } 105458957Seric (void) strcpy(hbuf, RealHostName); 105558957Seric 105658957Seric finish: 105766003Seric if (RealHostName != NULL && RealHostName[0] != '[') 105858951Seric { 105958951Seric p = &hbuf[strlen(hbuf)]; 106058951Seric (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); 106158951Seric } 106258957Seric if (tTd(9, 1)) 106358951Seric printf("getauthinfo: %s\n", hbuf); 106458308Seric return hbuf; 106558308Seric } 106658308Seric /* 106760089Seric ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 106853751Seric ** 106953751Seric ** Parameters: 107056823Seric ** map -- a pointer to this map (unused). 107160089Seric ** name -- the (presumably unqualified) hostname. 107260257Seric ** av -- unused -- for compatibility with other mapping 107355019Seric ** functions. 107459084Seric ** statp -- an exit status (out parameter) -- set to 107559084Seric ** EX_TEMPFAIL if the name server is unavailable. 107653751Seric ** 107753751Seric ** Returns: 107853751Seric ** The mapping, if found. 107953751Seric ** NULL if no mapping found. 108053751Seric ** 108153751Seric ** Side Effects: 108253751Seric ** Looks up the host specified in hbuf. If it is not 108353751Seric ** the canonical name for that host, return the canonical 108453751Seric ** name. 108553751Seric */ 108651315Seric 108753751Seric char * 108860257Seric host_map_lookup(map, name, av, statp) 108956823Seric MAP *map; 109060089Seric char *name; 109160257Seric char **av; 109259084Seric int *statp; 109316911Seric { 109416911Seric register struct hostent *hp; 109533932Sbostic u_long in_addr; 109656823Seric char *cp; 109758110Seric int i; 109859671Seric register STAB *s; 109960257Seric char hbuf[MAXNAME]; 110059671Seric extern struct hostent *gethostbyaddr(); 110166334Seric #if NAMED_BIND 110259671Seric extern int h_errno; 110366029Seric #endif 110416911Seric 110525574Smiriam /* 110659671Seric ** See if we have already looked up this name. If so, just 110759671Seric ** return it. 110859671Seric */ 110953751Seric 111060089Seric s = stab(name, ST_NAMECANON, ST_ENTER); 111159671Seric if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 111259671Seric { 111359986Seric if (tTd(9, 1)) 111460089Seric printf("host_map_lookup(%s) => CACHE %s\n", 111560089Seric name, s->s_namecanon.nc_cname); 111659671Seric errno = s->s_namecanon.nc_errno; 111766334Seric #if NAMED_BIND 111859671Seric h_errno = s->s_namecanon.nc_herrno; 111966029Seric #endif 112059671Seric *statp = s->s_namecanon.nc_stat; 112164797Seric if (CurEnv->e_message == NULL && *statp == EX_TEMPFAIL) 112265199Seric { 112365199Seric sprintf(hbuf, "%s: Name server timeout", 112465199Seric shortenstring(name, 33)); 112565199Seric CurEnv->e_message = newstr(hbuf); 112665199Seric } 112759671Seric return s->s_namecanon.nc_cname; 112859671Seric } 112959671Seric 113059671Seric /* 113159671Seric ** If first character is a bracket, then it is an address 113259671Seric ** lookup. Address is copied into a temporary buffer to 113360089Seric ** strip the brackets and to preserve name if address is 113459671Seric ** unknown. 113559671Seric */ 113659671Seric 113760089Seric if (*name != '[') 113853751Seric { 113955019Seric extern bool getcanonname(); 114055019Seric 114158798Seric if (tTd(9, 1)) 114260089Seric printf("host_map_lookup(%s) => ", name); 114359671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 114460089Seric (void) strcpy(hbuf, name); 114563842Seric if (getcanonname(hbuf, sizeof hbuf - 1, TRUE)) 114658796Seric { 114758796Seric if (tTd(9, 1)) 114858796Seric printf("%s\n", hbuf); 114960257Seric cp = map_rewrite(map, hbuf, strlen(hbuf), av); 115060257Seric s->s_namecanon.nc_cname = newstr(cp); 115160257Seric return cp; 115258796Seric } 115353751Seric else 115458796Seric { 115559084Seric register struct hostent *hp; 115659084Seric 115766029Seric s->s_namecanon.nc_errno = errno; 115866334Seric #if NAMED_BIND 115966029Seric s->s_namecanon.nc_herrno = h_errno; 116058796Seric if (tTd(9, 1)) 116159084Seric printf("FAIL (%d)\n", h_errno); 116259084Seric switch (h_errno) 116359084Seric { 116459084Seric case TRY_AGAIN: 116559596Seric if (UseNameServer) 116659734Seric { 116765202Seric sprintf(hbuf, "%s: Name server timeout", 116865199Seric shortenstring(name, 33)); 116965202Seric message("%s", hbuf); 117059734Seric if (CurEnv->e_message == NULL) 117165202Seric CurEnv->e_message = newstr(hbuf); 117259734Seric } 117359084Seric *statp = EX_TEMPFAIL; 117459084Seric break; 117559084Seric 117659084Seric case HOST_NOT_FOUND: 117759084Seric *statp = EX_NOHOST; 117859084Seric break; 117959084Seric 118059084Seric case NO_RECOVERY: 118159084Seric *statp = EX_SOFTWARE; 118259084Seric break; 118359084Seric 118459084Seric default: 118559084Seric *statp = EX_UNAVAILABLE; 118659084Seric break; 118759084Seric } 118866029Seric #else 118966029Seric if (tTd(9, 1)) 119066029Seric printf("FAIL\n"); 119166029Seric *statp = EX_NOHOST; 119266029Seric #endif 119359671Seric s->s_namecanon.nc_stat = *statp; 119459084Seric if (*statp != EX_TEMPFAIL || UseNameServer) 119559084Seric return NULL; 119659084Seric 119759084Seric /* 119859084Seric ** Try to look it up in /etc/hosts 119959084Seric */ 120059084Seric 120160089Seric hp = gethostbyname(name); 120259084Seric if (hp == NULL) 120359084Seric { 120459084Seric /* no dice there either */ 120559671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 120659084Seric return NULL; 120759084Seric } 120859084Seric 120959671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 121060257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 121160257Seric s->s_namecanon.nc_cname = newstr(cp); 121260257Seric return cp; 121358796Seric } 121453751Seric } 121560089Seric if ((cp = strchr(name, ']')) == NULL) 121653751Seric return (NULL); 121740994Sbostic *cp = '\0'; 121860089Seric in_addr = inet_addr(&name[1]); 121958110Seric 122058110Seric /* nope -- ask the name server */ 122133932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 122259671Seric s->s_namecanon.nc_errno = errno; 122366334Seric #if NAMED_BIND 122459671Seric s->s_namecanon.nc_herrno = h_errno; 122566029Seric #endif 122659671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 122733932Sbostic if (hp == NULL) 122859671Seric { 122959671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 123053751Seric return (NULL); 123159671Seric } 123253751Seric 123358110Seric /* found a match -- copy out */ 123460257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 123559671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 123660257Seric s->s_namecanon.nc_cname = newstr(cp); 123760257Seric return cp; 123833932Sbostic } 123958755Seric /* 124058755Seric ** ANYNET_NTOA -- convert a network address to printable form. 124158755Seric ** 124258755Seric ** Parameters: 124358755Seric ** sap -- a pointer to a sockaddr structure. 124458755Seric ** 124558755Seric ** Returns: 124658755Seric ** A printable version of that sockaddr. 124758755Seric */ 124816911Seric 124958755Seric char * 125058755Seric anynet_ntoa(sap) 125158755Seric register SOCKADDR *sap; 125258755Seric { 125358755Seric register char *bp; 125458755Seric register char *ap; 125558755Seric int l; 125664734Seric static char buf[100]; 125758755Seric 125858798Seric /* check for null/zero family */ 125958798Seric if (sap == NULL) 126058798Seric return "NULLADDR"; 126158798Seric if (sap->sa.sa_family == 0) 126258798Seric return "0"; 126358798Seric 126464734Seric switch (sap->sa.sa_family) 126564734Seric { 126664734Seric #ifdef MAYBENEXTRELEASE /*** UNTESTED *** UNTESTED *** UNTESTED ***/ 126764821Seric #ifdef NETUNIX 126864734Seric case AF_UNIX: 126964758Seric if (sap->sunix.sun_path[0] != '\0') 127064758Seric sprintf(buf, "[UNIX: %.64s]", sap->sunix.sun_path); 127164734Seric else 127264734Seric sprintf(buf, "[UNIX: localhost]"); 127364734Seric return buf; 127464734Seric #endif 127564821Seric #endif 127664734Seric 127758778Seric #ifdef NETINET 127864734Seric case AF_INET: 127958755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 128058778Seric #endif 128158755Seric 128264734Seric default: 128364734Seric /* this case is only to ensure syntactic correctness */ 128464734Seric break; 128564734Seric } 128664734Seric 128758755Seric /* unknown family -- just dump bytes */ 128858778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 128958755Seric bp = &buf[strlen(buf)]; 129058778Seric ap = sap->sa.sa_data; 129158778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 129258755Seric { 129358755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 129458755Seric bp += 3; 129558755Seric } 129658755Seric *--bp = '\0'; 129758755Seric return buf; 129858755Seric } 129958951Seric /* 130058951Seric ** HOSTNAMEBYANYADDR -- return name of host based on address 130158951Seric ** 130258951Seric ** Parameters: 130358951Seric ** sap -- SOCKADDR pointer 130458951Seric ** 130558951Seric ** Returns: 130658951Seric ** text representation of host name. 130758951Seric ** 130858951Seric ** Side Effects: 130958951Seric ** none. 131058951Seric */ 131158755Seric 131258951Seric char * 131358951Seric hostnamebyanyaddr(sap) 131458951Seric register SOCKADDR *sap; 131558951Seric { 131658951Seric register struct hostent *hp; 131764734Seric int saveretry; 131858951Seric 131966334Seric #if NAMED_BIND 132059042Seric /* shorten name server timeout to avoid higher level timeouts */ 132159042Seric saveretry = _res.retry; 132259042Seric _res.retry = 3; 132359042Seric #endif /* NAMED_BIND */ 132459042Seric 132558951Seric switch (sap->sa.sa_family) 132658951Seric { 132758951Seric #ifdef NETINET 132858951Seric case AF_INET: 132958951Seric hp = gethostbyaddr((char *) &sap->sin.sin_addr, 133058951Seric sizeof sap->sin.sin_addr, 133158951Seric AF_INET); 133258951Seric break; 133358951Seric #endif 133458951Seric 133558951Seric #ifdef NETISO 133658951Seric case AF_ISO: 133758951Seric hp = gethostbyaddr((char *) &sap->siso.siso_addr, 133858951Seric sizeof sap->siso.siso_addr, 133958951Seric AF_ISO); 134058951Seric break; 134158951Seric #endif 134258951Seric 134364734Seric #ifdef MAYBENEXTRELEASE /*** UNTESTED *** UNTESTED *** UNTESTED ***/ 134464734Seric case AF_UNIX: 134564734Seric hp = NULL; 134664734Seric break; 134764734Seric #endif 134864734Seric 134958951Seric default: 135058951Seric hp = gethostbyaddr(sap->sa.sa_data, 135158951Seric sizeof sap->sa.sa_data, 135258951Seric sap->sa.sa_family); 135358951Seric break; 135458951Seric } 135558951Seric 135666334Seric #if NAMED_BIND 135759042Seric _res.retry = saveretry; 135859042Seric #endif /* NAMED_BIND */ 135959042Seric 136058951Seric if (hp != NULL) 136158951Seric return hp->h_name; 136258951Seric else 136358951Seric { 136458951Seric /* produce a dotted quad */ 136558951Seric static char buf[512]; 136658951Seric 136758951Seric (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); 136858951Seric return buf; 136958951Seric } 137058951Seric } 137158951Seric 137256795Seric # else /* DAEMON */ 137316911Seric /* code for systems without sophisticated networking */ 137410758Seric 137510758Seric /* 137610758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 137711297Seric ** 137811297Seric ** Can't convert to upper case here because might be a UUCP name. 137912313Seric ** 138012313Seric ** Mark, you can change this to be anything you want...... 138110758Seric */ 138210758Seric 138310758Seric char ** 138412313Seric myhostname(hostbuf, size) 138510758Seric char hostbuf[]; 138612313Seric int size; 138710758Seric { 138810758Seric register FILE *f; 138910758Seric 139010758Seric hostbuf[0] = '\0'; 139110758Seric f = fopen("/usr/include/whoami", "r"); 139210758Seric if (f != NULL) 139310758Seric { 139412313Seric (void) fgets(hostbuf, size, f); 139510758Seric fixcrlf(hostbuf, TRUE); 139610758Seric (void) fclose(f); 139710758Seric } 139810758Seric return (NULL); 139910758Seric } 140016911Seric /* 140158951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 140258308Seric ** 140358308Seric ** Parameters: 140458308Seric ** fd -- the descriptor 140558308Seric ** 140658308Seric ** Returns: 140758308Seric ** The host name associated with this descriptor, if it can 140858308Seric ** be determined. 140958308Seric ** NULL otherwise. 141058308Seric ** 141158308Seric ** Side Effects: 141258308Seric ** none 141358308Seric */ 141458308Seric 141558308Seric char * 141658951Seric getauthinfo(fd) 141758308Seric int fd; 141858308Seric { 141958308Seric return NULL; 142058308Seric } 142158308Seric /* 142216911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 142316911Seric ** 142416911Seric ** Parameters: 142556823Seric ** map -- a pointer to the database map. 142660089Seric ** name -- a buffer containing a hostname. 142753751Seric ** avp -- a pointer to a (cf file defined) argument vector. 142859084Seric ** statp -- an exit status (out parameter). 142916911Seric ** 143016911Seric ** Returns: 143153751Seric ** mapped host name 143251315Seric ** FALSE otherwise. 143316911Seric ** 143416911Seric ** Side Effects: 143560089Seric ** Looks up the host specified in name. If it is not 143616911Seric ** the canonical name for that host, replace it with 143716911Seric ** the canonical name. If the name is unknown, or it 143816911Seric ** is already the canonical name, leave it unchanged. 143916911Seric */ 144010758Seric 144116911Seric /*ARGSUSED*/ 144253751Seric char * 144360089Seric host_map_lookup(map, name, avp, statp) 144456823Seric MAP *map; 144560089Seric char *name; 144653751Seric char **avp; 144759084Seric char *statp; 144816911Seric { 144959084Seric register struct hostent *hp; 145059084Seric 145160089Seric hp = gethostbyname(name); 145259084Seric if (hp != NULL) 145359084Seric return hp->h_name; 145459084Seric *statp = EX_NOHOST; 145553751Seric return NULL; 145616911Seric } 145716911Seric 145856795Seric #endif /* DAEMON */ 1459