122700Sdist /* 234920Sbostic * Copyright (c) 1983 Eric P. Allman 3*62522Sbostic * Copyright (c) 1988, 1993 4*62522Sbostic * The Regents of the University of California. All rights reserved. 533780Sbostic * 642825Sbostic * %sccs.include.redist.c% 733780Sbostic */ 822700Sdist 933932Sbostic #include <errno.h> 1058153Seric #include <signal.h> 1140962Sbostic #include "sendmail.h" 124535Seric 1333780Sbostic #ifndef lint 1433780Sbostic #ifdef DAEMON 15*62522Sbostic static char sccsid[] = "@(#)daemon.c 8.1 (Berkeley) 06/07/93 (with daemon mode)"; 1633780Sbostic #else 17*62522Sbostic static char sccsid[] = "@(#)daemon.c 8.1 (Berkeley) 06/07/93 (without daemon mode)"; 1833780Sbostic #endif 1933780Sbostic #endif /* not lint */ 204535Seric 2133780Sbostic #ifdef DAEMON 2233780Sbostic 2323120Seric # include <netdb.h> 2423120Seric # include <sys/wait.h> 2523120Seric # include <sys/time.h> 265978Seric 2759042Seric #ifdef NAMED_BIND 2859042Seric # include <arpa/nameser.h> 2959042Seric # include <resolv.h> 3059042Seric #endif 3159042Seric 324535Seric /* 334535Seric ** DAEMON.C -- routines to use when running as a daemon. 347556Seric ** 357556Seric ** This entire file is highly dependent on the 4.2 BSD 367556Seric ** interprocess communication primitives. No attempt has 377556Seric ** been made to make this file portable to Version 7, 387556Seric ** Version 6, MPX files, etc. If you should try such a 397556Seric ** thing yourself, I recommend chucking the entire file 407556Seric ** and starting from scratch. Basic semantics are: 417556Seric ** 427556Seric ** getrequests() 437556Seric ** Opens a port and initiates a connection. 447556Seric ** Returns in a child. Must set InChannel and 457556Seric ** OutChannel appropriately. 4610206Seric ** clrdaemon() 4710206Seric ** Close any open files associated with getting 4810206Seric ** the connection; this is used when running the queue, 4910206Seric ** etc., to avoid having extra file descriptors during 5010206Seric ** the queue run and to avoid confusing the network 5110206Seric ** code (if it cares). 5252106Seric ** makeconnection(host, port, outfile, infile, usesecureport) 537556Seric ** Make a connection to the named host on the given 547556Seric ** port. Set *outfile and *infile to the files 557556Seric ** appropriate for communication. Returns zero on 567556Seric ** success, else an exit status describing the 577556Seric ** error. 5860089Seric ** host_map_lookup(map, hbuf, avp, pstat) 5956823Seric ** Convert the entry in hbuf into a canonical form. 604535Seric */ 614535Seric /* 624535Seric ** GETREQUESTS -- open mail IPC port and get requests. 634535Seric ** 644535Seric ** Parameters: 654535Seric ** none. 664535Seric ** 674535Seric ** Returns: 684535Seric ** none. 694535Seric ** 704535Seric ** Side Effects: 714535Seric ** Waits until some interesting activity occurs. When 724535Seric ** it does, a child is created to process it, and the 734535Seric ** parent waits for completion. Return from this 749886Seric ** routine is always in the child. The file pointers 759886Seric ** "InChannel" and "OutChannel" should be set to point 769886Seric ** to the communication channel. 774535Seric */ 784535Seric 7958849Seric int DaemonSocket = -1; /* fd describing socket */ 8058849Seric SOCKADDR DaemonAddr; /* socket for incoming */ 8159783Seric int ListenQueueSize = 10; /* size of listen queue */ 8216144Seric 834535Seric getrequests() 844535Seric { 859610Seric int t; 869610Seric register struct servent *sp; 8725027Seric int on = 1; 8853751Seric bool refusingconnections = TRUE; 8958419Seric FILE *pidf; 9046928Sbostic extern void reapchild(); 917117Seric 929610Seric /* 939610Seric ** Set up the address for the mailer. 949610Seric */ 959610Seric 9658849Seric if (DaemonAddr.sin.sin_family == 0) 9758849Seric DaemonAddr.sin.sin_family = AF_INET; 9858849Seric if (DaemonAddr.sin.sin_addr.s_addr == 0) 9958849Seric DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; 10058849Seric if (DaemonAddr.sin.sin_port == 0) 1019610Seric { 10258849Seric sp = getservbyname("smtp", "tcp"); 10358849Seric if (sp == NULL) 10458849Seric { 10558909Seric syserr("554 service \"smtp\" unknown"); 10658849Seric goto severe; 10758849Seric } 10858849Seric DaemonAddr.sin.sin_port = sp->s_port; 1099610Seric } 1109610Seric 1119610Seric /* 1129610Seric ** Try to actually open the connection. 1139610Seric */ 1149610Seric 1159610Seric if (tTd(15, 1)) 11658849Seric printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); 1179610Seric 1189610Seric /* get a socket for the SMTP connection */ 11959041Seric DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0); 12010206Seric if (DaemonSocket < 0) 1219610Seric { 1229610Seric /* probably another daemon already */ 1239610Seric syserr("getrequests: can't create socket"); 1249610Seric severe: 1259610Seric # ifdef LOG 1269610Seric if (LogLevel > 0) 12757663Seric syslog(LOG_ALERT, "problem creating SMTP socket"); 12856795Seric # endif /* LOG */ 1299610Seric finis(); 1309610Seric } 13110347Seric 13210347Seric /* turn on network debugging? */ 13356328Seric if (tTd(15, 101)) 13424945Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 13510347Seric 13625027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 13725027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 13825027Seric 13959041Seric switch (DaemonAddr.sa.sa_family) 1409610Seric { 14159041Seric # ifdef NETINET 14259041Seric case AF_INET: 14359041Seric t = sizeof DaemonAddr.sin; 14459041Seric break; 14559041Seric # endif 14659041Seric 14759041Seric # ifdef NETISO 14859041Seric case AF_ISO: 14959041Seric t = sizeof DaemonAddr.siso; 15059041Seric break; 15159041Seric # endif 15259041Seric 15359041Seric default: 15459041Seric t = sizeof DaemonAddr; 15559041Seric break; 15659041Seric } 15759041Seric 15859041Seric if (bind(DaemonSocket, &DaemonAddr.sa, t) < 0) 15959041Seric { 1609610Seric syserr("getrequests: cannot bind"); 16110206Seric (void) close(DaemonSocket); 1629610Seric goto severe; 1639610Seric } 1649610Seric 16524955Seric (void) signal(SIGCHLD, reapchild); 16624945Seric 16758419Seric /* write the pid to the log file for posterity */ 16858419Seric pidf = fopen(PidFile, "w"); 16958419Seric if (pidf != NULL) 17058419Seric { 17158419Seric fprintf(pidf, "%d\n", getpid()); 17258419Seric fclose(pidf); 17358419Seric } 17458419Seric 17558419Seric 1769610Seric if (tTd(15, 1)) 17710206Seric printf("getrequests: %d\n", DaemonSocket); 1789610Seric 1794631Seric for (;;) 1804631Seric { 18114875Seric register int pid; 18211147Seric auto int lotherend; 18353751Seric extern bool refuseconnections(); 18411147Seric 18514875Seric /* see if we are rejecting connections */ 18653751Seric CurrentLA = getla(); 18753751Seric if (refuseconnections()) 18836584Sbostic { 18953751Seric if (!refusingconnections) 19053751Seric { 19153751Seric /* don't queue so peer will fail quickly */ 19253751Seric (void) listen(DaemonSocket, 0); 19353751Seric refusingconnections = TRUE; 19453751Seric } 19557385Seric setproctitle("rejecting connections: load average: %d", 19657385Seric CurrentLA); 19714875Seric sleep(5); 19853751Seric continue; 19936584Sbostic } 20014875Seric 20153751Seric if (refusingconnections) 20253751Seric { 20353751Seric /* start listening again */ 20459783Seric if (listen(DaemonSocket, ListenQueueSize) < 0) 20553751Seric { 20653751Seric syserr("getrequests: cannot listen"); 20753751Seric (void) close(DaemonSocket); 20853751Seric goto severe; 20953751Seric } 21053751Seric setproctitle("accepting connections"); 21153751Seric refusingconnections = FALSE; 21253751Seric } 21353751Seric 2149610Seric /* wait for a connection */ 2159610Seric do 2169610Seric { 2179610Seric errno = 0; 21836230Skarels lotherend = sizeof RealHostAddr; 21946928Sbostic t = accept(DaemonSocket, 22046928Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 2219610Seric } while (t < 0 && errno == EINTR); 2229610Seric if (t < 0) 2235978Seric { 2249610Seric syserr("getrequests: accept"); 2259610Seric sleep(5); 2269610Seric continue; 2275978Seric } 2284631Seric 2295978Seric /* 2305978Seric ** Create a subprocess to process the mail. 2315978Seric */ 2325978Seric 2337677Seric if (tTd(15, 2)) 2349610Seric printf("getrequests: forking (fd = %d)\n", t); 2355978Seric 2364636Seric pid = fork(); 2374636Seric if (pid < 0) 2384631Seric { 2394636Seric syserr("daemon: cannot fork"); 2404636Seric sleep(10); 2419610Seric (void) close(t); 2424636Seric continue; 2434631Seric } 2444631Seric 2454636Seric if (pid == 0) 2464631Seric { 24758951Seric extern char *hostnamebyanyaddr(); 24811147Seric 2494636Seric /* 2504636Seric ** CHILD -- return to caller. 25111147Seric ** Collect verified idea of sending host. 2524636Seric ** Verify calling user id if possible here. 2534636Seric */ 2544631Seric 25524955Seric (void) signal(SIGCHLD, SIG_DFL); 25659156Seric OpMode = MD_SMTP; 25724950Seric 25811147Seric /* determine host name */ 25958951Seric RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 26058778Seric 26155173Seric #ifdef LOG 26257977Seric if (LogLevel > 10) 26355173Seric { 26455173Seric /* log connection information */ 26555173Seric syslog(LOG_INFO, "connect from %s (%s)", 26658951Seric RealHostName, anynet_ntoa(&RealHostAddr)); 26755173Seric } 26855173Seric #endif 26955173Seric 27059254Seric (void) close(DaemonSocket); 27159254Seric InChannel = fdopen(t, "r"); 27259254Seric OutChannel = fdopen(dup(t), "w"); 27359254Seric 27416884Seric /* should we check for illegal connection here? XXX */ 27559156Seric #ifdef XLA 27659156Seric if (!xla_host_ok(RealHostName)) 27759156Seric { 27859254Seric message("421 Too many SMTP sessions for this host"); 27959156Seric exit(0); 28059156Seric } 28159156Seric #endif 28216884Seric 2837677Seric if (tTd(15, 2)) 2845978Seric printf("getreq: returning\n"); 2854636Seric return; 2864631Seric } 2874631Seric 2887117Seric /* close the port so that others will hang (for a while) */ 2899610Seric (void) close(t); 2904631Seric } 2919886Seric /*NOTREACHED*/ 2924631Seric } 2935978Seric /* 29410206Seric ** CLRDAEMON -- reset the daemon connection 29510206Seric ** 29610206Seric ** Parameters: 29710206Seric ** none. 29810206Seric ** 29910206Seric ** Returns: 30010206Seric ** none. 30110206Seric ** 30210206Seric ** Side Effects: 30310206Seric ** releases any resources used by the passive daemon. 30410206Seric */ 30510206Seric 30610206Seric clrdaemon() 30710206Seric { 30810206Seric if (DaemonSocket >= 0) 30910206Seric (void) close(DaemonSocket); 31010206Seric DaemonSocket = -1; 31110206Seric } 31210206Seric /* 31358849Seric ** SETDAEMONOPTIONS -- set options for running the daemon 31458849Seric ** 31558849Seric ** Parameters: 31658849Seric ** p -- the options line. 31758849Seric ** 31858849Seric ** Returns: 31958849Seric ** none. 32058849Seric */ 32158849Seric 32258849Seric setdaemonoptions(p) 32358849Seric register char *p; 32458849Seric { 32558873Seric if (DaemonAddr.sa.sa_family == AF_UNSPEC) 32658873Seric DaemonAddr.sa.sa_family = AF_INET; 32758873Seric 32858849Seric while (p != NULL) 32958849Seric { 33058849Seric register char *f; 33158849Seric register char *v; 33258849Seric 33358849Seric while (isascii(*p) && isspace(*p)) 33458849Seric p++; 33558849Seric if (*p == '\0') 33658849Seric break; 33758849Seric f = p; 33858849Seric p = strchr(p, ','); 33958849Seric if (p != NULL) 34058849Seric *p++ = '\0'; 34158849Seric v = strchr(f, '='); 34258849Seric if (v == NULL) 34358849Seric continue; 34458849Seric while (isascii(*++v) && isspace(*v)) 34558849Seric continue; 34658849Seric 34758849Seric switch (*f) 34858849Seric { 34958873Seric case 'F': /* address family */ 35058849Seric if (isascii(*v) && isdigit(*v)) 35158873Seric DaemonAddr.sa.sa_family = atoi(v); 35258873Seric #ifdef NETINET 35358873Seric else if (strcasecmp(v, "inet") == 0) 35458873Seric DaemonAddr.sa.sa_family = AF_INET; 35558873Seric #endif 35658873Seric #ifdef NETISO 35758873Seric else if (strcasecmp(v, "iso") == 0) 35858873Seric DaemonAddr.sa.sa_family = AF_ISO; 35958873Seric #endif 36058873Seric #ifdef NETNS 36158873Seric else if (strcasecmp(v, "ns") == 0) 36258873Seric DaemonAddr.sa.sa_family = AF_NS; 36358873Seric #endif 36458873Seric #ifdef NETX25 36558873Seric else if (strcasecmp(v, "x.25") == 0) 36658873Seric DaemonAddr.sa.sa_family = AF_CCITT; 36758873Seric #endif 36858849Seric else 36958873Seric syserr("554 Unknown address family %s in Family=option", v); 37058873Seric break; 37158873Seric 37258873Seric case 'A': /* address */ 37358873Seric switch (DaemonAddr.sa.sa_family) 37458849Seric { 37558873Seric #ifdef NETINET 37658873Seric case AF_INET: 37758873Seric if (isascii(*v) && isdigit(*v)) 37858873Seric DaemonAddr.sin.sin_addr.s_addr = inet_network(v); 37958873Seric else 38058873Seric { 38158873Seric register struct netent *np; 38258849Seric 38358873Seric np = getnetbyname(v); 38458873Seric if (np == NULL) 38558873Seric syserr("554 network \"%s\" unknown", v); 38658873Seric else 38758873Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 38858873Seric } 38958873Seric break; 39058873Seric #endif 39158873Seric 39258873Seric default: 39358873Seric syserr("554 Address= option unsupported for family %d", 39458873Seric DaemonAddr.sa.sa_family); 39558873Seric break; 39658849Seric } 39758849Seric break; 39858849Seric 39958873Seric case 'P': /* port */ 40058873Seric switch (DaemonAddr.sa.sa_family) 40158849Seric { 40258873Seric short port; 40358849Seric 40458873Seric #ifdef NETINET 40558873Seric case AF_INET: 40658873Seric if (isascii(*v) && isdigit(*v)) 40758873Seric DaemonAddr.sin.sin_port = atoi(v); 40858849Seric else 40958873Seric { 41058873Seric register struct servent *sp; 41158873Seric 41258873Seric sp = getservbyname(v, "tcp"); 41358873Seric if (sp == NULL) 41458909Seric syserr("554 service \"%s\" unknown", v); 41558873Seric else 41658873Seric DaemonAddr.sin.sin_port = sp->s_port; 41758873Seric } 41858873Seric break; 41958873Seric #endif 42058873Seric 42158873Seric #ifdef NETISO 42258873Seric case AF_ISO: 42358873Seric /* assume two byte transport selector */ 42458873Seric if (isascii(*v) && isdigit(*v)) 42558873Seric port = atoi(v); 42658873Seric else 42758873Seric { 42858873Seric register struct servent *sp; 42958873Seric 43058873Seric sp = getservbyname(v, "tcp"); 43158873Seric if (sp == NULL) 43258909Seric syserr("554 service \"%s\" unknown", v); 43358873Seric else 43458873Seric port = sp->s_port; 43558873Seric } 43658873Seric bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 43758873Seric break; 43858873Seric #endif 43958873Seric 44058873Seric default: 44158873Seric syserr("554 Port= option unsupported for family %d", 44258873Seric DaemonAddr.sa.sa_family); 44358873Seric break; 44458849Seric } 44558849Seric break; 44659783Seric 44759783Seric case 'L': /* listen queue size */ 44859783Seric ListenQueueSize = atoi(v); 44959783Seric break; 45058849Seric } 45158849Seric } 45258849Seric } 45358849Seric /* 4546039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 4556039Seric ** 4566039Seric ** Parameters: 4576039Seric ** host -- the name of the host. 4586633Seric ** port -- the port number to connect to. 45953739Seric ** mci -- a pointer to the mail connection information 46053739Seric ** structure to be filled in. 46152106Seric ** usesecureport -- if set, use a low numbered (reserved) 46252106Seric ** port to provide some rudimentary authentication. 4636039Seric ** 4646039Seric ** Returns: 4656039Seric ** An exit code telling whether the connection could be 4666039Seric ** made and if not why not. 4676039Seric ** 4686039Seric ** Side Effects: 4696039Seric ** none. 4706039Seric */ 4715978Seric 47258755Seric SOCKADDR CurHostAddr; /* address of current host */ 47358305Seric 47454967Seric int 47553739Seric makeconnection(host, port, mci, usesecureport) 4766039Seric char *host; 4777286Seric u_short port; 47854967Seric register MCI *mci; 47952106Seric bool usesecureport; 4806039Seric { 48129430Sbloom register int i, s; 48229430Sbloom register struct hostent *hp = (struct hostent *)NULL; 48358755Seric SOCKADDR addr; 48452106Seric int sav_errno; 48558755Seric int addrlen; 48635651Seric #ifdef NAMED_BIND 48735651Seric extern int h_errno; 48835651Seric #endif 4896039Seric 4906039Seric /* 4916039Seric ** Set up the address for the mailer. 4929308Seric ** Accept "[a.b.c.d]" syntax for host name. 4936039Seric */ 4946039Seric 49535651Seric #ifdef NAMED_BIND 49625475Smiriam h_errno = 0; 49735651Seric #endif 49825475Smiriam errno = 0; 49958864Seric bzero(&CurHostAddr, sizeof CurHostAddr); 50058906Seric CurHostName = host; 50125475Smiriam 5029308Seric if (host[0] == '[') 5039308Seric { 50411147Seric long hid; 50556795Seric register char *p = strchr(host, ']'); 5069308Seric 50711147Seric if (p != NULL) 5089308Seric { 50911147Seric *p = '\0'; 51059884Seric #ifdef NETINET 51111147Seric hid = inet_addr(&host[1]); 51258360Seric if (hid == -1) 51359884Seric #endif 51458360Seric { 51558360Seric /* try it as a host name (avoid MX lookup) */ 51658360Seric hp = gethostbyname(&host[1]); 51758360Seric *p = ']'; 51858360Seric goto gothostent; 51958360Seric } 52011147Seric *p = ']'; 5219308Seric } 52258360Seric if (p == NULL) 5239308Seric { 52458151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 5259308Seric return (EX_NOHOST); 5269308Seric } 52759884Seric #ifdef NETINET 52859884Seric addr.sin.sin_family = AF_INET; /*XXX*/ 52958778Seric addr.sin.sin_addr.s_addr = hid; 53059884Seric #endif 5319308Seric } 5329610Seric else 5339610Seric { 53429430Sbloom hp = gethostbyname(host); 53558360Seric gothostent: 53625475Smiriam if (hp == NULL) 53724945Seric { 53835651Seric #ifdef NAMED_BIND 53925475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 54025475Smiriam return (EX_TEMPFAIL); 54125657Seric 54235651Seric /* if name server is specified, assume temp fail */ 54335651Seric if (errno == ECONNREFUSED && UseNameServer) 54435651Seric return (EX_TEMPFAIL); 54535651Seric #endif 54625475Smiriam return (EX_NOHOST); 54724945Seric } 54858778Seric addr.sa.sa_family = hp->h_addrtype; 54958778Seric switch (hp->h_addrtype) 55058778Seric { 55158778Seric #ifdef NETINET 55258778Seric case AF_INET: 55358755Seric bcopy(hp->h_addr, 55458778Seric &addr.sin.sin_addr, 55558755Seric hp->h_length); 55658778Seric break; 55758778Seric #endif 55858778Seric 55958778Seric default: 56058755Seric bcopy(hp->h_addr, 56158778Seric addr.sa.sa_data, 56258755Seric hp->h_length); 56358778Seric break; 56458778Seric } 56529430Sbloom i = 1; 5669610Seric } 5679610Seric 5689610Seric /* 5699610Seric ** Determine the port number. 5709610Seric */ 5719610Seric 57210011Seric if (port != 0) 57358755Seric port = htons(port); 57410011Seric else 5759610Seric { 5769610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 5779610Seric 5789610Seric if (sp == NULL) 5799610Seric { 58058909Seric syserr("554 makeconnection: service \"smtp\" unknown"); 58157977Seric return (EX_OSERR); 5829610Seric } 58358755Seric port = sp->s_port; 5849610Seric } 5856039Seric 58658778Seric switch (addr.sa.sa_family) 58758755Seric { 58859884Seric #ifdef NETINET 58958755Seric case AF_INET: 59058778Seric addr.sin.sin_port = port; 59158755Seric addrlen = sizeof (struct sockaddr_in); 59258755Seric break; 59359884Seric #endif 59458755Seric 59558755Seric #ifdef NETISO 59658755Seric case AF_ISO: 59758755Seric /* assume two byte transport selector */ 59858755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 59958755Seric addrlen = sizeof (struct sockaddr_iso); 60058755Seric break; 60158755Seric #endif 60258755Seric 60358755Seric default: 60458778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 60558755Seric return (EX_NOHOST); 60658755Seric } 60758755Seric 6086039Seric /* 6096039Seric ** Try to actually open the connection. 6106039Seric */ 6116039Seric 61259156Seric #ifdef XLA 61359156Seric /* if too many connections, don't bother trying */ 61459156Seric if (!xla_noqueue_ok(host)) 61559156Seric return EX_TEMPFAIL; 61659156Seric #endif 61759156Seric 61857736Seric for (;;) 61952106Seric { 62057736Seric if (tTd(16, 1)) 62158755Seric printf("makeconnection (%s [%s])\n", 62258755Seric host, anynet_ntoa(&addr)); 62352106Seric 62458588Seric /* save for logging */ 62558588Seric CurHostAddr = addr; 62658588Seric 62757736Seric if (usesecureport) 62857736Seric { 62957736Seric int rport = IPPORT_RESERVED - 1; 6306039Seric 63157736Seric s = rresvport(&rport); 63257736Seric } 63357736Seric else 63457736Seric { 63557736Seric s = socket(AF_INET, SOCK_STREAM, 0); 63657736Seric } 63757736Seric if (s < 0) 63857736Seric { 63957736Seric sav_errno = errno; 64057736Seric syserr("makeconnection: no socket"); 64157736Seric goto failure; 64257736Seric } 64310347Seric 64457736Seric if (tTd(16, 1)) 64557736Seric printf("makeconnection: fd=%d\n", s); 64657736Seric 64757736Seric /* turn on network debugging? */ 64857736Seric if (tTd(16, 101)) 64957736Seric { 65057736Seric int on = 1; 65157736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 65257736Seric (char *)&on, sizeof on); 65357736Seric } 65457736Seric if (CurEnv->e_xfp != NULL) 65557736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 65657736Seric errno = 0; /* for debugging */ 65758755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 65857736Seric break; 65957736Seric 66057736Seric /* couldn't connect.... figure out why */ 66127744Sbloom sav_errno = errno; 66227744Sbloom (void) close(s); 66329430Sbloom if (hp && hp->h_addr_list[i]) 66429430Sbloom { 66557736Seric if (tTd(16, 1)) 66658755Seric printf("Connect failed (%s); trying new address....\n", 66758755Seric errstring(sav_errno)); 66858778Seric switch (addr.sa.sa_family) 66958778Seric { 67058778Seric #ifdef NETINET 67158778Seric case AF_INET: 67258755Seric bcopy(hp->h_addr_list[i++], 67358778Seric &addr.sin.sin_addr, 67458755Seric hp->h_length); 67558778Seric break; 67658778Seric #endif 67758778Seric 67858778Seric default: 67958755Seric bcopy(hp->h_addr_list[i++], 68058778Seric addr.sa.sa_data, 68152106Seric hp->h_length); 68258778Seric break; 68358778Seric } 68457736Seric continue; 68529430Sbloom } 68629430Sbloom 6876039Seric /* failure, decide if temporary or not */ 6886039Seric failure: 68959254Seric #ifdef XLA 69059254Seric xla_host_end(host); 69159254Seric #endif 69258542Seric if (transienterror(sav_errno)) 69358542Seric return EX_TEMPFAIL; 69458542Seric else 69558542Seric { 69658542Seric message("%s", errstring(sav_errno)); 69758542Seric return (EX_UNAVAILABLE); 6986039Seric } 6996039Seric } 7006039Seric 7016039Seric /* connection ok, put it into canonical form */ 70253739Seric mci->mci_out = fdopen(s, "w"); 70353739Seric mci->mci_in = fdopen(dup(s), "r"); 7046039Seric 70510098Seric return (EX_OK); 7066039Seric } 70710758Seric /* 70810758Seric ** MYHOSTNAME -- return the name of this host. 70910758Seric ** 71010758Seric ** Parameters: 71110758Seric ** hostbuf -- a place to return the name of this host. 71212313Seric ** size -- the size of hostbuf. 71310758Seric ** 71410758Seric ** Returns: 71510758Seric ** A list of aliases for this host. 71610758Seric ** 71710758Seric ** Side Effects: 71858110Seric ** Sets the MyIpAddrs buffer to a list of my IP addresses. 71910758Seric */ 7206039Seric 72158110Seric struct in_addr MyIpAddrs[MAXIPADDR + 1]; 72258110Seric 72310758Seric char ** 72412313Seric myhostname(hostbuf, size) 72510758Seric char hostbuf[]; 72612313Seric int size; 72710758Seric { 72858110Seric register struct hostent *hp; 72910758Seric extern struct hostent *gethostbyname(); 73010758Seric 73123120Seric if (gethostname(hostbuf, size) < 0) 73223120Seric { 73323120Seric (void) strcpy(hostbuf, "localhost"); 73423120Seric } 73511147Seric hp = gethostbyname(hostbuf); 73611147Seric if (hp != NULL) 73716877Seric { 73858110Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 73958110Seric hostbuf[size - 1] = '\0'; 74058110Seric 74158110Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 74258110Seric { 74358110Seric register int i; 74458110Seric 74558110Seric for (i = 0; i < MAXIPADDR; i++) 74658110Seric { 74758110Seric if (hp->h_addr_list[i] == NULL) 74858110Seric break; 74958110Seric MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i]; 75058110Seric } 75158110Seric MyIpAddrs[i].s_addr = 0; 75258110Seric } 75358110Seric 75411147Seric return (hp->h_aliases); 75516877Seric } 75610758Seric else 75710758Seric return (NULL); 75810758Seric } 75951315Seric /* 76058951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 76158308Seric ** 76258951Seric ** Uses RFC1413 protocol to try to get info from the other end. 76358951Seric ** 76458308Seric ** Parameters: 76558308Seric ** fd -- the descriptor 76658308Seric ** 76758308Seric ** Returns: 76858951Seric ** The user@host information associated with this descriptor. 76958308Seric ** 77058308Seric ** Side Effects: 77158951Seric ** Sets RealHostName to the name of the host at the other end. 77258308Seric */ 77358308Seric 77458951Seric #ifdef IDENTPROTO 77558951Seric 77658951Seric static jmp_buf CtxAuthTimeout; 77758951Seric 77858951Seric static 77958951Seric authtimeout() 78058951Seric { 78158951Seric longjmp(CtxAuthTimeout, 1); 78258951Seric } 78358951Seric 78458951Seric #endif 78558951Seric 78658308Seric char * 78758951Seric getauthinfo(fd) 78858308Seric int fd; 78958308Seric { 79058951Seric SOCKADDR fa; 79158951Seric int falen; 79259104Seric register char *p; 79358951Seric #ifdef IDENTPROTO 79458951Seric SOCKADDR la; 79558951Seric int lalen; 79658951Seric register struct servent *sp; 79758951Seric int s; 79858951Seric int i; 79958951Seric EVENT *ev; 80058951Seric #endif 80158951Seric static char hbuf[MAXNAME * 2 + 2]; 80258951Seric extern char *hostnamebyanyaddr(); 80358951Seric extern char RealUserName[]; /* main.c */ 80458308Seric 80558951Seric falen = sizeof fa; 80658951Seric if (getpeername(fd, &fa.sa, &falen) < 0 || falen <= 0) 80758951Seric { 80858951Seric RealHostName = "localhost"; 80958951Seric (void) sprintf(hbuf, "%s@localhost", RealUserName); 81058957Seric if (tTd(9, 1)) 81158951Seric printf("getauthinfo: %s\n", hbuf); 81258951Seric return hbuf; 81358951Seric } 81458951Seric 81558951Seric RealHostName = newstr(hostnamebyanyaddr(&fa)); 81658951Seric RealHostAddr = fa; 81758951Seric 81858951Seric #ifdef IDENTPROTO 81958951Seric lalen = sizeof la; 82058951Seric if (fa.sa.sa_family != AF_INET || 82158951Seric getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || 82258951Seric la.sa.sa_family != AF_INET) 82358951Seric { 82458951Seric /* no ident info */ 82558951Seric goto noident; 82658951Seric } 82758951Seric 82858951Seric /* create ident query */ 82960489Seric (void) sprintf(hbuf, "%d,%d\r\n", 83060489Seric ntohs(fa.sin.sin_port), ntohs(la.sin.sin_port)); 83158951Seric 83258951Seric /* create local address */ 83358951Seric bzero(&la, sizeof la); 83458951Seric 83558951Seric /* create foreign address */ 83658951Seric sp = getservbyname("auth", "tcp"); 83758951Seric if (sp != NULL) 83858951Seric fa.sin.sin_port = sp->s_port; 83958308Seric else 84059097Seric fa.sin.sin_port = htons(113); 84158951Seric 84258951Seric s = -1; 84358951Seric if (setjmp(CtxAuthTimeout) != 0) 84458951Seric { 84558951Seric if (s >= 0) 84658951Seric (void) close(s); 84758951Seric goto noident; 84858951Seric } 84958951Seric 85058951Seric /* put a timeout around the whole thing */ 85158951Seric ev = setevent((time_t) 30, authtimeout, 0); 85258951Seric 85358951Seric /* connect to foreign IDENT server */ 85458951Seric s = socket(AF_INET, SOCK_STREAM, 0); 85558951Seric if (s < 0) 85658951Seric { 85758951Seric clrevent(ev); 85858951Seric goto noident; 85958951Seric } 86058951Seric if (connect(s, &fa.sa, sizeof fa.sin) < 0) 86158951Seric { 86258951Seric closeident: 86358951Seric (void) close(s); 86458951Seric clrevent(ev); 86558951Seric goto noident; 86658951Seric } 86758951Seric 86858957Seric if (tTd(9, 10)) 86958951Seric printf("getauthinfo: sent %s", hbuf); 87058951Seric 87158951Seric /* send query */ 87258951Seric if (write(s, hbuf, strlen(hbuf)) < 0) 87358951Seric goto closeident; 87458951Seric 87558951Seric /* get result */ 87658951Seric i = read(s, hbuf, sizeof hbuf); 87758951Seric (void) close(s); 87858951Seric clrevent(ev); 87958951Seric if (i <= 0) 88058951Seric goto noident; 88158951Seric if (hbuf[--i] == '\n' && hbuf[--i] == '\r') 88258951Seric i--; 88358951Seric hbuf[++i] = '\0'; 88458951Seric 88558957Seric if (tTd(9, 3)) 88658951Seric printf("getauthinfo: got %s\n", hbuf); 88758951Seric 88858951Seric /* parse result */ 88958951Seric p = strchr(hbuf, ':'); 89058951Seric if (p == NULL) 89158951Seric { 89258951Seric /* malformed response */ 89358951Seric goto noident; 89458951Seric } 89558951Seric while (isascii(*++p) && isspace(*p)) 89658951Seric continue; 89758951Seric if (strncasecmp(p, "userid", 6) != 0) 89858951Seric { 89958951Seric /* presumably an error string */ 90058951Seric goto noident; 90158951Seric } 90258951Seric p += 6; 90358951Seric while (isascii(*p) && isspace(*p)) 90458951Seric p++; 90558951Seric if (*p++ != ':') 90658951Seric { 90758951Seric /* either useridxx or malformed response */ 90858951Seric goto noident; 90958951Seric } 91058951Seric 91158951Seric /* p now points to the OSTYPE field */ 91258951Seric p = strchr(p, ':'); 91358951Seric if (p == NULL) 91458951Seric { 91558951Seric /* malformed response */ 91658951Seric goto noident; 91758951Seric } 91858951Seric 91958957Seric /* 1413 says don't do this -- but it's broken otherwise */ 92058957Seric while (isascii(*++p) && isspace(*p)) 92158957Seric continue; 92258957Seric 92358951Seric /* p now points to the authenticated name */ 92458951Seric (void) sprintf(hbuf, "%s@%s", p, RealHostName); 92558957Seric goto finish; 92658957Seric 92758957Seric #endif /* IDENTPROTO */ 92858957Seric 92958957Seric noident: 93058957Seric (void) strcpy(hbuf, RealHostName); 93158957Seric 93258957Seric finish: 93358951Seric if (RealHostName[0] != '[') 93458951Seric { 93558951Seric p = &hbuf[strlen(hbuf)]; 93658951Seric (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); 93758951Seric } 93858957Seric if (tTd(9, 1)) 93958951Seric printf("getauthinfo: %s\n", hbuf); 94058308Seric return hbuf; 94158308Seric } 94258308Seric /* 94360089Seric ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 94453751Seric ** 94553751Seric ** Parameters: 94656823Seric ** map -- a pointer to this map (unused). 94760089Seric ** name -- the (presumably unqualified) hostname. 94860257Seric ** av -- unused -- for compatibility with other mapping 94955019Seric ** functions. 95059084Seric ** statp -- an exit status (out parameter) -- set to 95159084Seric ** EX_TEMPFAIL if the name server is unavailable. 95253751Seric ** 95353751Seric ** Returns: 95453751Seric ** The mapping, if found. 95553751Seric ** NULL if no mapping found. 95653751Seric ** 95753751Seric ** Side Effects: 95853751Seric ** Looks up the host specified in hbuf. If it is not 95953751Seric ** the canonical name for that host, return the canonical 96053751Seric ** name. 96153751Seric */ 96251315Seric 96353751Seric char * 96460257Seric host_map_lookup(map, name, av, statp) 96556823Seric MAP *map; 96660089Seric char *name; 96760257Seric char **av; 96859084Seric int *statp; 96916911Seric { 97016911Seric register struct hostent *hp; 97133932Sbostic u_long in_addr; 97256823Seric char *cp; 97358110Seric int i; 97459671Seric register STAB *s; 97560257Seric char hbuf[MAXNAME]; 97659671Seric extern struct hostent *gethostbyaddr(); 97759671Seric extern int h_errno; 97816911Seric 97925574Smiriam /* 98059671Seric ** See if we have already looked up this name. If so, just 98159671Seric ** return it. 98259671Seric */ 98353751Seric 98460089Seric s = stab(name, ST_NAMECANON, ST_ENTER); 98559671Seric if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 98659671Seric { 98759986Seric if (tTd(9, 1)) 98860089Seric printf("host_map_lookup(%s) => CACHE %s\n", 98960089Seric name, s->s_namecanon.nc_cname); 99059671Seric errno = s->s_namecanon.nc_errno; 99159671Seric h_errno = s->s_namecanon.nc_herrno; 99259671Seric *statp = s->s_namecanon.nc_stat; 99359671Seric return s->s_namecanon.nc_cname; 99459671Seric } 99559671Seric 99659671Seric /* 99759671Seric ** If first character is a bracket, then it is an address 99859671Seric ** lookup. Address is copied into a temporary buffer to 99960089Seric ** strip the brackets and to preserve name if address is 100059671Seric ** unknown. 100159671Seric */ 100259671Seric 100360089Seric if (*name != '[') 100453751Seric { 100555019Seric extern bool getcanonname(); 100655019Seric 100758798Seric if (tTd(9, 1)) 100860089Seric printf("host_map_lookup(%s) => ", name); 100959671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 101060089Seric (void) strcpy(hbuf, name); 101160089Seric if (getcanonname(hbuf, sizeof hbuf - 1)) 101258796Seric { 101358796Seric if (tTd(9, 1)) 101458796Seric printf("%s\n", hbuf); 101560257Seric cp = map_rewrite(map, hbuf, strlen(hbuf), av); 101660257Seric s->s_namecanon.nc_cname = newstr(cp); 101760257Seric return cp; 101858796Seric } 101953751Seric else 102058796Seric { 102159084Seric register struct hostent *hp; 102259084Seric 102358796Seric if (tTd(9, 1)) 102459084Seric printf("FAIL (%d)\n", h_errno); 102559671Seric s->s_namecanon.nc_errno = errno; 102659671Seric s->s_namecanon.nc_herrno = h_errno; 102759084Seric switch (h_errno) 102859084Seric { 102959084Seric case TRY_AGAIN: 103059596Seric if (UseNameServer) 103159734Seric { 103259734Seric char *msg = "Recipient domain nameserver timed out"; 103359734Seric 103459734Seric message(msg); 103559734Seric if (CurEnv->e_message == NULL) 103660009Seric CurEnv->e_message = newstr(msg); 103759734Seric } 103859084Seric *statp = EX_TEMPFAIL; 103959084Seric break; 104059084Seric 104159084Seric case HOST_NOT_FOUND: 104259084Seric *statp = EX_NOHOST; 104359084Seric break; 104459084Seric 104559084Seric case NO_RECOVERY: 104659084Seric *statp = EX_SOFTWARE; 104759084Seric break; 104859084Seric 104959084Seric default: 105059084Seric *statp = EX_UNAVAILABLE; 105159084Seric break; 105259084Seric } 105359671Seric s->s_namecanon.nc_stat = *statp; 105459084Seric if (*statp != EX_TEMPFAIL || UseNameServer) 105559084Seric return NULL; 105659084Seric 105759084Seric /* 105859084Seric ** Try to look it up in /etc/hosts 105959084Seric */ 106059084Seric 106160089Seric hp = gethostbyname(name); 106259084Seric if (hp == NULL) 106359084Seric { 106459084Seric /* no dice there either */ 106559671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 106659084Seric return NULL; 106759084Seric } 106859084Seric 106959671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 107060257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 107160257Seric s->s_namecanon.nc_cname = newstr(cp); 107260257Seric return cp; 107358796Seric } 107453751Seric } 107560089Seric if ((cp = strchr(name, ']')) == NULL) 107653751Seric return (NULL); 107740994Sbostic *cp = '\0'; 107860089Seric in_addr = inet_addr(&name[1]); 107958110Seric 108058110Seric /* check to see if this is one of our addresses */ 108158110Seric for (i = 0; MyIpAddrs[i].s_addr != 0; i++) 108258110Seric { 108358110Seric if (MyIpAddrs[i].s_addr == in_addr) 108458110Seric { 108560257Seric return map_rewrite(map, MyHostName, strlen(MyHostName), av); 108658110Seric } 108758110Seric } 108858110Seric 108958110Seric /* nope -- ask the name server */ 109033932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 109159671Seric s->s_namecanon.nc_errno = errno; 109259671Seric s->s_namecanon.nc_herrno = h_errno; 109359671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 109433932Sbostic if (hp == NULL) 109559671Seric { 109659671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 109753751Seric return (NULL); 109859671Seric } 109953751Seric 110058110Seric /* found a match -- copy out */ 110160257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 110259671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 110360257Seric s->s_namecanon.nc_cname = newstr(cp); 110460257Seric return cp; 110533932Sbostic } 110658755Seric /* 110758755Seric ** ANYNET_NTOA -- convert a network address to printable form. 110858755Seric ** 110958755Seric ** Parameters: 111058755Seric ** sap -- a pointer to a sockaddr structure. 111158755Seric ** 111258755Seric ** Returns: 111358755Seric ** A printable version of that sockaddr. 111458755Seric */ 111516911Seric 111658755Seric char * 111758755Seric anynet_ntoa(sap) 111858755Seric register SOCKADDR *sap; 111958755Seric { 112058755Seric register char *bp; 112158755Seric register char *ap; 112258755Seric int l; 112358755Seric static char buf[80]; 112458755Seric 112558798Seric /* check for null/zero family */ 112658798Seric if (sap == NULL) 112758798Seric return "NULLADDR"; 112858798Seric if (sap->sa.sa_family == 0) 112958798Seric return "0"; 113058798Seric 113158778Seric #ifdef NETINET 113258778Seric if (sap->sa.sa_family == AF_INET) 113358755Seric { 113458755Seric extern char *inet_ntoa(); 113558755Seric 113658755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 113758755Seric } 113858778Seric #endif 113958755Seric 114058755Seric /* unknown family -- just dump bytes */ 114158778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 114258755Seric bp = &buf[strlen(buf)]; 114358778Seric ap = sap->sa.sa_data; 114458778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 114558755Seric { 114658755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 114758755Seric bp += 3; 114858755Seric } 114958755Seric *--bp = '\0'; 115058755Seric return buf; 115158755Seric } 115258951Seric /* 115358951Seric ** HOSTNAMEBYANYADDR -- return name of host based on address 115458951Seric ** 115558951Seric ** Parameters: 115658951Seric ** sap -- SOCKADDR pointer 115758951Seric ** 115858951Seric ** Returns: 115958951Seric ** text representation of host name. 116058951Seric ** 116158951Seric ** Side Effects: 116258951Seric ** none. 116358951Seric */ 116458755Seric 116558951Seric char * 116658951Seric hostnamebyanyaddr(sap) 116758951Seric register SOCKADDR *sap; 116858951Seric { 116958951Seric register struct hostent *hp; 117058951Seric 117159042Seric #ifdef NAMED_BIND 117259042Seric int saveretry; 117359042Seric 117459042Seric /* shorten name server timeout to avoid higher level timeouts */ 117559042Seric saveretry = _res.retry; 117659042Seric _res.retry = 3; 117759042Seric #endif /* NAMED_BIND */ 117859042Seric 117958951Seric switch (sap->sa.sa_family) 118058951Seric { 118158951Seric #ifdef NETINET 118258951Seric case AF_INET: 118358951Seric hp = gethostbyaddr((char *) &sap->sin.sin_addr, 118458951Seric sizeof sap->sin.sin_addr, 118558951Seric AF_INET); 118658951Seric break; 118758951Seric #endif 118858951Seric 118958951Seric #ifdef NETISO 119058951Seric case AF_ISO: 119158951Seric hp = gethostbyaddr((char *) &sap->siso.siso_addr, 119258951Seric sizeof sap->siso.siso_addr, 119358951Seric AF_ISO); 119458951Seric break; 119558951Seric #endif 119658951Seric 119758951Seric default: 119858951Seric hp = gethostbyaddr(sap->sa.sa_data, 119958951Seric sizeof sap->sa.sa_data, 120058951Seric sap->sa.sa_family); 120158951Seric break; 120258951Seric } 120358951Seric 120459042Seric #ifdef NAMED_BIND 120559042Seric _res.retry = saveretry; 120659042Seric #endif /* NAMED_BIND */ 120759042Seric 120858951Seric if (hp != NULL) 120958951Seric return hp->h_name; 121058951Seric else 121158951Seric { 121258951Seric /* produce a dotted quad */ 121358951Seric static char buf[512]; 121458951Seric 121558951Seric (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); 121658951Seric return buf; 121758951Seric } 121858951Seric } 121958951Seric 122056795Seric # else /* DAEMON */ 122116911Seric /* code for systems without sophisticated networking */ 122210758Seric 122310758Seric /* 122410758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 122511297Seric ** 122611297Seric ** Can't convert to upper case here because might be a UUCP name. 122712313Seric ** 122812313Seric ** Mark, you can change this to be anything you want...... 122910758Seric */ 123010758Seric 123110758Seric char ** 123212313Seric myhostname(hostbuf, size) 123310758Seric char hostbuf[]; 123412313Seric int size; 123510758Seric { 123610758Seric register FILE *f; 123710758Seric 123810758Seric hostbuf[0] = '\0'; 123910758Seric f = fopen("/usr/include/whoami", "r"); 124010758Seric if (f != NULL) 124110758Seric { 124212313Seric (void) fgets(hostbuf, size, f); 124310758Seric fixcrlf(hostbuf, TRUE); 124410758Seric (void) fclose(f); 124510758Seric } 124610758Seric return (NULL); 124710758Seric } 124816911Seric /* 124958951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 125058308Seric ** 125158308Seric ** Parameters: 125258308Seric ** fd -- the descriptor 125358308Seric ** 125458308Seric ** Returns: 125558308Seric ** The host name associated with this descriptor, if it can 125658308Seric ** be determined. 125758308Seric ** NULL otherwise. 125858308Seric ** 125958308Seric ** Side Effects: 126058308Seric ** none 126158308Seric */ 126258308Seric 126358308Seric char * 126458951Seric getauthinfo(fd) 126558308Seric int fd; 126658308Seric { 126758308Seric return NULL; 126858308Seric } 126958308Seric /* 127016911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 127116911Seric ** 127216911Seric ** Parameters: 127356823Seric ** map -- a pointer to the database map. 127460089Seric ** name -- a buffer containing a hostname. 127553751Seric ** avp -- a pointer to a (cf file defined) argument vector. 127659084Seric ** statp -- an exit status (out parameter). 127716911Seric ** 127816911Seric ** Returns: 127953751Seric ** mapped host name 128051315Seric ** FALSE otherwise. 128116911Seric ** 128216911Seric ** Side Effects: 128360089Seric ** Looks up the host specified in name. If it is not 128416911Seric ** the canonical name for that host, replace it with 128516911Seric ** the canonical name. If the name is unknown, or it 128616911Seric ** is already the canonical name, leave it unchanged. 128716911Seric */ 128810758Seric 128916911Seric /*ARGSUSED*/ 129053751Seric char * 129160089Seric host_map_lookup(map, name, avp, statp) 129256823Seric MAP *map; 129360089Seric char *name; 129453751Seric char **avp; 129559084Seric char *statp; 129616911Seric { 129759084Seric register struct hostent *hp; 129859084Seric 129960089Seric hp = gethostbyname(name); 130059084Seric if (hp != NULL) 130159084Seric return hp->h_name; 130259084Seric *statp = EX_NOHOST; 130353751Seric return NULL; 130416911Seric } 130516911Seric 130656795Seric #endif /* DAEMON */ 1307