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> 1058153Seric #include <signal.h> 1140962Sbostic #include "sendmail.h" 124535Seric 1333780Sbostic #ifndef lint 1433780Sbostic #ifdef DAEMON 15*63863Seric static char sccsid[] = "@(#)daemon.c 8.4 (Berkeley) 07/18/93 (with daemon mode)"; 1633780Sbostic #else 17*63863Seric static char sccsid[] = "@(#)daemon.c 8.4 (Berkeley) 07/18/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 { 171*63863Seric extern char *CommandLineArgs; 172*63863Seric 173*63863Seric /* write the process id on line 1 */ 17458419Seric fprintf(pidf, "%d\n", getpid()); 175*63863Seric 176*63863Seric /* line 2 contains all command line flags */ 177*63863Seric fprintf(pidf, "%s\n", CommandLineArgs); 178*63863Seric 179*63863Seric /* flush and close */ 18058419Seric fclose(pidf); 18158419Seric } 18258419Seric 18358419Seric 1849610Seric if (tTd(15, 1)) 18510206Seric printf("getrequests: %d\n", DaemonSocket); 1869610Seric 1874631Seric for (;;) 1884631Seric { 18914875Seric register int pid; 19011147Seric auto int lotherend; 19153751Seric extern bool refuseconnections(); 19211147Seric 19314875Seric /* see if we are rejecting connections */ 19453751Seric CurrentLA = getla(); 19553751Seric if (refuseconnections()) 19636584Sbostic { 19753751Seric if (!refusingconnections) 19853751Seric { 19953751Seric /* don't queue so peer will fail quickly */ 20053751Seric (void) listen(DaemonSocket, 0); 20153751Seric refusingconnections = TRUE; 20253751Seric } 20357385Seric setproctitle("rejecting connections: load average: %d", 20457385Seric CurrentLA); 20514875Seric sleep(5); 20653751Seric continue; 20736584Sbostic } 20814875Seric 20953751Seric if (refusingconnections) 21053751Seric { 21153751Seric /* start listening again */ 21259783Seric if (listen(DaemonSocket, ListenQueueSize) < 0) 21353751Seric { 21453751Seric syserr("getrequests: cannot listen"); 21553751Seric (void) close(DaemonSocket); 21653751Seric goto severe; 21753751Seric } 21853751Seric setproctitle("accepting connections"); 21953751Seric refusingconnections = FALSE; 22053751Seric } 22153751Seric 2229610Seric /* wait for a connection */ 2239610Seric do 2249610Seric { 2259610Seric errno = 0; 22636230Skarels lotherend = sizeof RealHostAddr; 22746928Sbostic t = accept(DaemonSocket, 22846928Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 2299610Seric } while (t < 0 && errno == EINTR); 2309610Seric if (t < 0) 2315978Seric { 2329610Seric syserr("getrequests: accept"); 2339610Seric sleep(5); 2349610Seric continue; 2355978Seric } 2364631Seric 2375978Seric /* 2385978Seric ** Create a subprocess to process the mail. 2395978Seric */ 2405978Seric 2417677Seric if (tTd(15, 2)) 2429610Seric printf("getrequests: forking (fd = %d)\n", t); 2435978Seric 2444636Seric pid = fork(); 2454636Seric if (pid < 0) 2464631Seric { 2474636Seric syserr("daemon: cannot fork"); 2484636Seric sleep(10); 2499610Seric (void) close(t); 2504636Seric continue; 2514631Seric } 2524631Seric 2534636Seric if (pid == 0) 2544631Seric { 25558951Seric extern char *hostnamebyanyaddr(); 25611147Seric 2574636Seric /* 2584636Seric ** CHILD -- return to caller. 25911147Seric ** Collect verified idea of sending host. 2604636Seric ** Verify calling user id if possible here. 2614636Seric */ 2624631Seric 26324955Seric (void) signal(SIGCHLD, SIG_DFL); 26459156Seric OpMode = MD_SMTP; 26524950Seric 26611147Seric /* determine host name */ 26758951Seric RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 26858778Seric 26955173Seric #ifdef LOG 27063842Seric if (LogLevel > 11) 27155173Seric { 27255173Seric /* log connection information */ 27355173Seric syslog(LOG_INFO, "connect from %s (%s)", 27458951Seric RealHostName, anynet_ntoa(&RealHostAddr)); 27555173Seric } 27655173Seric #endif 27755173Seric 27859254Seric (void) close(DaemonSocket); 27959254Seric InChannel = fdopen(t, "r"); 28059254Seric OutChannel = fdopen(dup(t), "w"); 28159254Seric 28216884Seric /* should we check for illegal connection here? XXX */ 28359156Seric #ifdef XLA 28459156Seric if (!xla_host_ok(RealHostName)) 28559156Seric { 28659254Seric message("421 Too many SMTP sessions for this host"); 28759156Seric exit(0); 28859156Seric } 28959156Seric #endif 29016884Seric 2917677Seric if (tTd(15, 2)) 2925978Seric printf("getreq: returning\n"); 2934636Seric return; 2944631Seric } 2954631Seric 2967117Seric /* close the port so that others will hang (for a while) */ 2979610Seric (void) close(t); 2984631Seric } 2999886Seric /*NOTREACHED*/ 3004631Seric } 3015978Seric /* 30210206Seric ** CLRDAEMON -- reset the daemon connection 30310206Seric ** 30410206Seric ** Parameters: 30510206Seric ** none. 30610206Seric ** 30710206Seric ** Returns: 30810206Seric ** none. 30910206Seric ** 31010206Seric ** Side Effects: 31110206Seric ** releases any resources used by the passive daemon. 31210206Seric */ 31310206Seric 31410206Seric clrdaemon() 31510206Seric { 31610206Seric if (DaemonSocket >= 0) 31710206Seric (void) close(DaemonSocket); 31810206Seric DaemonSocket = -1; 31910206Seric } 32010206Seric /* 32158849Seric ** SETDAEMONOPTIONS -- set options for running the daemon 32258849Seric ** 32358849Seric ** Parameters: 32458849Seric ** p -- the options line. 32558849Seric ** 32658849Seric ** Returns: 32758849Seric ** none. 32858849Seric */ 32958849Seric 33058849Seric setdaemonoptions(p) 33158849Seric register char *p; 33258849Seric { 33358873Seric if (DaemonAddr.sa.sa_family == AF_UNSPEC) 33458873Seric DaemonAddr.sa.sa_family = AF_INET; 33558873Seric 33658849Seric while (p != NULL) 33758849Seric { 33858849Seric register char *f; 33958849Seric register char *v; 34058849Seric 34158849Seric while (isascii(*p) && isspace(*p)) 34258849Seric p++; 34358849Seric if (*p == '\0') 34458849Seric break; 34558849Seric f = p; 34658849Seric p = strchr(p, ','); 34758849Seric if (p != NULL) 34858849Seric *p++ = '\0'; 34958849Seric v = strchr(f, '='); 35058849Seric if (v == NULL) 35158849Seric continue; 35258849Seric while (isascii(*++v) && isspace(*v)) 35358849Seric continue; 35458849Seric 35558849Seric switch (*f) 35658849Seric { 35758873Seric case 'F': /* address family */ 35858849Seric if (isascii(*v) && isdigit(*v)) 35958873Seric DaemonAddr.sa.sa_family = atoi(v); 36058873Seric #ifdef NETINET 36158873Seric else if (strcasecmp(v, "inet") == 0) 36258873Seric DaemonAddr.sa.sa_family = AF_INET; 36358873Seric #endif 36458873Seric #ifdef NETISO 36558873Seric else if (strcasecmp(v, "iso") == 0) 36658873Seric DaemonAddr.sa.sa_family = AF_ISO; 36758873Seric #endif 36858873Seric #ifdef NETNS 36958873Seric else if (strcasecmp(v, "ns") == 0) 37058873Seric DaemonAddr.sa.sa_family = AF_NS; 37158873Seric #endif 37258873Seric #ifdef NETX25 37358873Seric else if (strcasecmp(v, "x.25") == 0) 37458873Seric DaemonAddr.sa.sa_family = AF_CCITT; 37558873Seric #endif 37658849Seric else 37758873Seric syserr("554 Unknown address family %s in Family=option", v); 37858873Seric break; 37958873Seric 38058873Seric case 'A': /* address */ 38158873Seric switch (DaemonAddr.sa.sa_family) 38258849Seric { 38358873Seric #ifdef NETINET 38458873Seric case AF_INET: 38558873Seric if (isascii(*v) && isdigit(*v)) 38658873Seric DaemonAddr.sin.sin_addr.s_addr = inet_network(v); 38758873Seric else 38858873Seric { 38958873Seric register struct netent *np; 39058849Seric 39158873Seric np = getnetbyname(v); 39258873Seric if (np == NULL) 39358873Seric syserr("554 network \"%s\" unknown", v); 39458873Seric else 39558873Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 39658873Seric } 39758873Seric break; 39858873Seric #endif 39958873Seric 40058873Seric default: 40158873Seric syserr("554 Address= option unsupported for family %d", 40258873Seric DaemonAddr.sa.sa_family); 40358873Seric break; 40458849Seric } 40558849Seric break; 40658849Seric 40758873Seric case 'P': /* port */ 40858873Seric switch (DaemonAddr.sa.sa_family) 40958849Seric { 41058873Seric short port; 41158849Seric 41258873Seric #ifdef NETINET 41358873Seric case AF_INET: 41458873Seric if (isascii(*v) && isdigit(*v)) 41558873Seric DaemonAddr.sin.sin_port = atoi(v); 41658849Seric else 41758873Seric { 41858873Seric register struct servent *sp; 41958873Seric 42058873Seric sp = getservbyname(v, "tcp"); 42158873Seric if (sp == NULL) 42258909Seric syserr("554 service \"%s\" unknown", v); 42358873Seric else 42458873Seric DaemonAddr.sin.sin_port = sp->s_port; 42558873Seric } 42658873Seric break; 42758873Seric #endif 42858873Seric 42958873Seric #ifdef NETISO 43058873Seric case AF_ISO: 43158873Seric /* assume two byte transport selector */ 43258873Seric if (isascii(*v) && isdigit(*v)) 43358873Seric port = atoi(v); 43458873Seric else 43558873Seric { 43658873Seric register struct servent *sp; 43758873Seric 43858873Seric sp = getservbyname(v, "tcp"); 43958873Seric if (sp == NULL) 44058909Seric syserr("554 service \"%s\" unknown", v); 44158873Seric else 44258873Seric port = sp->s_port; 44358873Seric } 44458873Seric bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 44558873Seric break; 44658873Seric #endif 44758873Seric 44858873Seric default: 44958873Seric syserr("554 Port= option unsupported for family %d", 45058873Seric DaemonAddr.sa.sa_family); 45158873Seric break; 45258849Seric } 45358849Seric break; 45459783Seric 45559783Seric case 'L': /* listen queue size */ 45659783Seric ListenQueueSize = atoi(v); 45759783Seric break; 45858849Seric } 45958849Seric } 46058849Seric } 46158849Seric /* 4626039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 4636039Seric ** 4646039Seric ** Parameters: 4656039Seric ** host -- the name of the host. 4666633Seric ** port -- the port number to connect to. 46753739Seric ** mci -- a pointer to the mail connection information 46853739Seric ** structure to be filled in. 46952106Seric ** usesecureport -- if set, use a low numbered (reserved) 47052106Seric ** port to provide some rudimentary authentication. 4716039Seric ** 4726039Seric ** Returns: 4736039Seric ** An exit code telling whether the connection could be 4746039Seric ** made and if not why not. 4756039Seric ** 4766039Seric ** Side Effects: 4776039Seric ** none. 4786039Seric */ 4795978Seric 48058755Seric SOCKADDR CurHostAddr; /* address of current host */ 48158305Seric 48254967Seric int 48353739Seric makeconnection(host, port, mci, usesecureport) 4846039Seric char *host; 4857286Seric u_short port; 48654967Seric register MCI *mci; 48752106Seric bool usesecureport; 4886039Seric { 48929430Sbloom register int i, s; 49029430Sbloom register struct hostent *hp = (struct hostent *)NULL; 49158755Seric SOCKADDR addr; 49252106Seric int sav_errno; 49358755Seric int addrlen; 49435651Seric #ifdef NAMED_BIND 49535651Seric extern int h_errno; 49635651Seric #endif 4976039Seric 4986039Seric /* 4996039Seric ** Set up the address for the mailer. 5009308Seric ** Accept "[a.b.c.d]" syntax for host name. 5016039Seric */ 5026039Seric 50335651Seric #ifdef NAMED_BIND 50425475Smiriam h_errno = 0; 50535651Seric #endif 50625475Smiriam errno = 0; 50758864Seric bzero(&CurHostAddr, sizeof CurHostAddr); 50858906Seric CurHostName = host; 50925475Smiriam 5109308Seric if (host[0] == '[') 5119308Seric { 51211147Seric long hid; 51356795Seric register char *p = strchr(host, ']'); 5149308Seric 51511147Seric if (p != NULL) 5169308Seric { 51711147Seric *p = '\0'; 51859884Seric #ifdef NETINET 51911147Seric hid = inet_addr(&host[1]); 52058360Seric if (hid == -1) 52159884Seric #endif 52258360Seric { 52358360Seric /* try it as a host name (avoid MX lookup) */ 52458360Seric hp = gethostbyname(&host[1]); 52558360Seric *p = ']'; 52658360Seric goto gothostent; 52758360Seric } 52811147Seric *p = ']'; 5299308Seric } 53058360Seric if (p == NULL) 5319308Seric { 53258151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 5339308Seric return (EX_NOHOST); 5349308Seric } 53559884Seric #ifdef NETINET 53659884Seric addr.sin.sin_family = AF_INET; /*XXX*/ 53758778Seric addr.sin.sin_addr.s_addr = hid; 53859884Seric #endif 5399308Seric } 5409610Seric else 5419610Seric { 54229430Sbloom hp = gethostbyname(host); 54358360Seric gothostent: 54425475Smiriam if (hp == NULL) 54524945Seric { 54635651Seric #ifdef NAMED_BIND 54725475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 54825475Smiriam return (EX_TEMPFAIL); 54925657Seric 55035651Seric /* if name server is specified, assume temp fail */ 55135651Seric if (errno == ECONNREFUSED && UseNameServer) 55235651Seric return (EX_TEMPFAIL); 55335651Seric #endif 55425475Smiriam return (EX_NOHOST); 55524945Seric } 55658778Seric addr.sa.sa_family = hp->h_addrtype; 55758778Seric switch (hp->h_addrtype) 55858778Seric { 55958778Seric #ifdef NETINET 56058778Seric case AF_INET: 56158755Seric bcopy(hp->h_addr, 56258778Seric &addr.sin.sin_addr, 56358755Seric hp->h_length); 56458778Seric break; 56558778Seric #endif 56658778Seric 56758778Seric default: 56858755Seric bcopy(hp->h_addr, 56958778Seric addr.sa.sa_data, 57058755Seric hp->h_length); 57158778Seric break; 57258778Seric } 57329430Sbloom i = 1; 5749610Seric } 5759610Seric 5769610Seric /* 5779610Seric ** Determine the port number. 5789610Seric */ 5799610Seric 58010011Seric if (port != 0) 58158755Seric port = htons(port); 58210011Seric else 5839610Seric { 5849610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 5859610Seric 5869610Seric if (sp == NULL) 5879610Seric { 58858909Seric syserr("554 makeconnection: service \"smtp\" unknown"); 58957977Seric return (EX_OSERR); 5909610Seric } 59158755Seric port = sp->s_port; 5929610Seric } 5936039Seric 59458778Seric switch (addr.sa.sa_family) 59558755Seric { 59659884Seric #ifdef NETINET 59758755Seric case AF_INET: 59858778Seric addr.sin.sin_port = port; 59958755Seric addrlen = sizeof (struct sockaddr_in); 60058755Seric break; 60159884Seric #endif 60258755Seric 60358755Seric #ifdef NETISO 60458755Seric case AF_ISO: 60558755Seric /* assume two byte transport selector */ 60658755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 60758755Seric addrlen = sizeof (struct sockaddr_iso); 60858755Seric break; 60958755Seric #endif 61058755Seric 61158755Seric default: 61258778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 61358755Seric return (EX_NOHOST); 61458755Seric } 61558755Seric 6166039Seric /* 6176039Seric ** Try to actually open the connection. 6186039Seric */ 6196039Seric 62059156Seric #ifdef XLA 62159156Seric /* if too many connections, don't bother trying */ 62259156Seric if (!xla_noqueue_ok(host)) 62359156Seric return EX_TEMPFAIL; 62459156Seric #endif 62559156Seric 62657736Seric for (;;) 62752106Seric { 62857736Seric if (tTd(16, 1)) 62958755Seric printf("makeconnection (%s [%s])\n", 63058755Seric host, anynet_ntoa(&addr)); 63152106Seric 63258588Seric /* save for logging */ 63358588Seric CurHostAddr = addr; 63458588Seric 63557736Seric if (usesecureport) 63657736Seric { 63757736Seric int rport = IPPORT_RESERVED - 1; 6386039Seric 63957736Seric s = rresvport(&rport); 64057736Seric } 64157736Seric else 64257736Seric { 64357736Seric s = socket(AF_INET, SOCK_STREAM, 0); 64457736Seric } 64557736Seric if (s < 0) 64657736Seric { 64757736Seric sav_errno = errno; 64857736Seric syserr("makeconnection: no socket"); 64957736Seric goto failure; 65057736Seric } 65110347Seric 65257736Seric if (tTd(16, 1)) 65357736Seric printf("makeconnection: fd=%d\n", s); 65457736Seric 65557736Seric /* turn on network debugging? */ 65657736Seric if (tTd(16, 101)) 65757736Seric { 65857736Seric int on = 1; 65957736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 66057736Seric (char *)&on, sizeof on); 66157736Seric } 66257736Seric if (CurEnv->e_xfp != NULL) 66357736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 66457736Seric errno = 0; /* for debugging */ 66558755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 66657736Seric break; 66757736Seric 66857736Seric /* couldn't connect.... figure out why */ 66927744Sbloom sav_errno = errno; 67027744Sbloom (void) close(s); 67129430Sbloom if (hp && hp->h_addr_list[i]) 67229430Sbloom { 67357736Seric if (tTd(16, 1)) 67458755Seric printf("Connect failed (%s); trying new address....\n", 67558755Seric errstring(sav_errno)); 67658778Seric switch (addr.sa.sa_family) 67758778Seric { 67858778Seric #ifdef NETINET 67958778Seric case AF_INET: 68058755Seric bcopy(hp->h_addr_list[i++], 68158778Seric &addr.sin.sin_addr, 68258755Seric hp->h_length); 68358778Seric break; 68458778Seric #endif 68558778Seric 68658778Seric default: 68758755Seric bcopy(hp->h_addr_list[i++], 68858778Seric addr.sa.sa_data, 68952106Seric hp->h_length); 69058778Seric break; 69158778Seric } 69257736Seric continue; 69329430Sbloom } 69429430Sbloom 6956039Seric /* failure, decide if temporary or not */ 6966039Seric failure: 69759254Seric #ifdef XLA 69859254Seric xla_host_end(host); 69959254Seric #endif 70058542Seric if (transienterror(sav_errno)) 70158542Seric return EX_TEMPFAIL; 70258542Seric else 70358542Seric { 70458542Seric message("%s", errstring(sav_errno)); 70558542Seric return (EX_UNAVAILABLE); 7066039Seric } 7076039Seric } 7086039Seric 7096039Seric /* connection ok, put it into canonical form */ 71053739Seric mci->mci_out = fdopen(s, "w"); 71153739Seric mci->mci_in = fdopen(dup(s), "r"); 7126039Seric 71310098Seric return (EX_OK); 7146039Seric } 71510758Seric /* 71610758Seric ** MYHOSTNAME -- return the name of this host. 71710758Seric ** 71810758Seric ** Parameters: 71910758Seric ** hostbuf -- a place to return the name of this host. 72012313Seric ** size -- the size of hostbuf. 72110758Seric ** 72210758Seric ** Returns: 72310758Seric ** A list of aliases for this host. 72410758Seric ** 72510758Seric ** Side Effects: 72658110Seric ** Sets the MyIpAddrs buffer to a list of my IP addresses. 72710758Seric */ 7286039Seric 72958110Seric struct in_addr MyIpAddrs[MAXIPADDR + 1]; 73058110Seric 73110758Seric char ** 73212313Seric myhostname(hostbuf, size) 73310758Seric char hostbuf[]; 73412313Seric int size; 73510758Seric { 73658110Seric register struct hostent *hp; 73710758Seric extern struct hostent *gethostbyname(); 73810758Seric 73923120Seric if (gethostname(hostbuf, size) < 0) 74023120Seric { 74123120Seric (void) strcpy(hostbuf, "localhost"); 74223120Seric } 74311147Seric hp = gethostbyname(hostbuf); 74411147Seric if (hp != NULL) 74516877Seric { 74658110Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 74758110Seric hostbuf[size - 1] = '\0'; 74858110Seric 74958110Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 75058110Seric { 75158110Seric register int i; 75258110Seric 75358110Seric for (i = 0; i < MAXIPADDR; i++) 75458110Seric { 75558110Seric if (hp->h_addr_list[i] == NULL) 75658110Seric break; 75758110Seric MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i]; 75858110Seric } 75958110Seric MyIpAddrs[i].s_addr = 0; 76058110Seric } 76158110Seric 76211147Seric return (hp->h_aliases); 76316877Seric } 76410758Seric else 76510758Seric return (NULL); 76610758Seric } 76751315Seric /* 76858951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 76958308Seric ** 77058951Seric ** Uses RFC1413 protocol to try to get info from the other end. 77158951Seric ** 77258308Seric ** Parameters: 77358308Seric ** fd -- the descriptor 77458308Seric ** 77558308Seric ** Returns: 77658951Seric ** The user@host information associated with this descriptor. 77758308Seric ** 77858308Seric ** Side Effects: 77958951Seric ** Sets RealHostName to the name of the host at the other end. 78058308Seric */ 78158308Seric 78258951Seric #ifdef IDENTPROTO 78358951Seric 78458951Seric static jmp_buf CtxAuthTimeout; 78558951Seric 78658951Seric static 78758951Seric authtimeout() 78858951Seric { 78958951Seric longjmp(CtxAuthTimeout, 1); 79058951Seric } 79158951Seric 79258951Seric #endif 79358951Seric 79458308Seric char * 79558951Seric getauthinfo(fd) 79658308Seric int fd; 79758308Seric { 79858951Seric SOCKADDR fa; 79958951Seric int falen; 80059104Seric register char *p; 80158951Seric #ifdef IDENTPROTO 80258951Seric SOCKADDR la; 80358951Seric int lalen; 80458951Seric register struct servent *sp; 80558951Seric int s; 80658951Seric int i; 80758951Seric EVENT *ev; 80858951Seric #endif 80958951Seric static char hbuf[MAXNAME * 2 + 2]; 81058951Seric extern char *hostnamebyanyaddr(); 81158951Seric extern char RealUserName[]; /* main.c */ 81258308Seric 81358951Seric falen = sizeof fa; 81458951Seric if (getpeername(fd, &fa.sa, &falen) < 0 || falen <= 0) 81558951Seric { 81658951Seric RealHostName = "localhost"; 81758951Seric (void) sprintf(hbuf, "%s@localhost", RealUserName); 81858957Seric if (tTd(9, 1)) 81958951Seric printf("getauthinfo: %s\n", hbuf); 82058951Seric return hbuf; 82158951Seric } 82258951Seric 82358951Seric RealHostName = newstr(hostnamebyanyaddr(&fa)); 82458951Seric RealHostAddr = fa; 82558951Seric 82658951Seric #ifdef IDENTPROTO 82758951Seric lalen = sizeof la; 82858951Seric if (fa.sa.sa_family != AF_INET || 82958951Seric getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || 83058951Seric la.sa.sa_family != AF_INET) 83158951Seric { 83258951Seric /* no ident info */ 83358951Seric goto noident; 83458951Seric } 83558951Seric 83658951Seric /* create ident query */ 83760489Seric (void) sprintf(hbuf, "%d,%d\r\n", 83860489Seric ntohs(fa.sin.sin_port), ntohs(la.sin.sin_port)); 83958951Seric 84058951Seric /* create local address */ 84158951Seric bzero(&la, sizeof la); 84258951Seric 84358951Seric /* create foreign address */ 84458951Seric sp = getservbyname("auth", "tcp"); 84558951Seric if (sp != NULL) 84658951Seric fa.sin.sin_port = sp->s_port; 84758308Seric else 84859097Seric fa.sin.sin_port = htons(113); 84958951Seric 85058951Seric s = -1; 85158951Seric if (setjmp(CtxAuthTimeout) != 0) 85258951Seric { 85358951Seric if (s >= 0) 85458951Seric (void) close(s); 85558951Seric goto noident; 85658951Seric } 85758951Seric 85858951Seric /* put a timeout around the whole thing */ 85958951Seric ev = setevent((time_t) 30, authtimeout, 0); 86058951Seric 86158951Seric /* connect to foreign IDENT server */ 86258951Seric s = socket(AF_INET, SOCK_STREAM, 0); 86358951Seric if (s < 0) 86458951Seric { 86558951Seric clrevent(ev); 86658951Seric goto noident; 86758951Seric } 86858951Seric if (connect(s, &fa.sa, sizeof fa.sin) < 0) 86958951Seric { 87058951Seric closeident: 87158951Seric (void) close(s); 87258951Seric clrevent(ev); 87358951Seric goto noident; 87458951Seric } 87558951Seric 87658957Seric if (tTd(9, 10)) 87758951Seric printf("getauthinfo: sent %s", hbuf); 87858951Seric 87958951Seric /* send query */ 88058951Seric if (write(s, hbuf, strlen(hbuf)) < 0) 88158951Seric goto closeident; 88258951Seric 88358951Seric /* get result */ 88458951Seric i = read(s, hbuf, sizeof hbuf); 88558951Seric (void) close(s); 88658951Seric clrevent(ev); 88758951Seric if (i <= 0) 88858951Seric goto noident; 88958951Seric if (hbuf[--i] == '\n' && hbuf[--i] == '\r') 89058951Seric i--; 89158951Seric hbuf[++i] = '\0'; 89258951Seric 89358957Seric if (tTd(9, 3)) 89458951Seric printf("getauthinfo: got %s\n", hbuf); 89558951Seric 89658951Seric /* parse result */ 89758951Seric p = strchr(hbuf, ':'); 89858951Seric if (p == NULL) 89958951Seric { 90058951Seric /* malformed response */ 90158951Seric goto noident; 90258951Seric } 90358951Seric while (isascii(*++p) && isspace(*p)) 90458951Seric continue; 90558951Seric if (strncasecmp(p, "userid", 6) != 0) 90658951Seric { 90758951Seric /* presumably an error string */ 90858951Seric goto noident; 90958951Seric } 91058951Seric p += 6; 91158951Seric while (isascii(*p) && isspace(*p)) 91258951Seric p++; 91358951Seric if (*p++ != ':') 91458951Seric { 91558951Seric /* either useridxx or malformed response */ 91658951Seric goto noident; 91758951Seric } 91858951Seric 91958951Seric /* p now points to the OSTYPE field */ 92058951Seric p = strchr(p, ':'); 92158951Seric if (p == NULL) 92258951Seric { 92358951Seric /* malformed response */ 92458951Seric goto noident; 92558951Seric } 92658951Seric 92758957Seric /* 1413 says don't do this -- but it's broken otherwise */ 92858957Seric while (isascii(*++p) && isspace(*p)) 92958957Seric continue; 93058957Seric 93158951Seric /* p now points to the authenticated name */ 93258951Seric (void) sprintf(hbuf, "%s@%s", p, RealHostName); 93358957Seric goto finish; 93458957Seric 93558957Seric #endif /* IDENTPROTO */ 93658957Seric 93758957Seric noident: 93858957Seric (void) strcpy(hbuf, RealHostName); 93958957Seric 94058957Seric finish: 94158951Seric if (RealHostName[0] != '[') 94258951Seric { 94358951Seric p = &hbuf[strlen(hbuf)]; 94458951Seric (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); 94558951Seric } 94658957Seric if (tTd(9, 1)) 94758951Seric printf("getauthinfo: %s\n", hbuf); 94858308Seric return hbuf; 94958308Seric } 95058308Seric /* 95160089Seric ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 95253751Seric ** 95353751Seric ** Parameters: 95456823Seric ** map -- a pointer to this map (unused). 95560089Seric ** name -- the (presumably unqualified) hostname. 95660257Seric ** av -- unused -- for compatibility with other mapping 95755019Seric ** functions. 95859084Seric ** statp -- an exit status (out parameter) -- set to 95959084Seric ** EX_TEMPFAIL if the name server is unavailable. 96053751Seric ** 96153751Seric ** Returns: 96253751Seric ** The mapping, if found. 96353751Seric ** NULL if no mapping found. 96453751Seric ** 96553751Seric ** Side Effects: 96653751Seric ** Looks up the host specified in hbuf. If it is not 96753751Seric ** the canonical name for that host, return the canonical 96853751Seric ** name. 96953751Seric */ 97051315Seric 97153751Seric char * 97260257Seric host_map_lookup(map, name, av, statp) 97356823Seric MAP *map; 97460089Seric char *name; 97560257Seric char **av; 97659084Seric int *statp; 97716911Seric { 97816911Seric register struct hostent *hp; 97933932Sbostic u_long in_addr; 98056823Seric char *cp; 98158110Seric int i; 98259671Seric register STAB *s; 98360257Seric char hbuf[MAXNAME]; 98459671Seric extern struct hostent *gethostbyaddr(); 98559671Seric extern int h_errno; 98616911Seric 98725574Smiriam /* 98859671Seric ** See if we have already looked up this name. If so, just 98959671Seric ** return it. 99059671Seric */ 99153751Seric 99260089Seric s = stab(name, ST_NAMECANON, ST_ENTER); 99359671Seric if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 99459671Seric { 99559986Seric if (tTd(9, 1)) 99660089Seric printf("host_map_lookup(%s) => CACHE %s\n", 99760089Seric name, s->s_namecanon.nc_cname); 99859671Seric errno = s->s_namecanon.nc_errno; 99959671Seric h_errno = s->s_namecanon.nc_herrno; 100059671Seric *statp = s->s_namecanon.nc_stat; 100159671Seric return s->s_namecanon.nc_cname; 100259671Seric } 100359671Seric 100459671Seric /* 100559671Seric ** If first character is a bracket, then it is an address 100659671Seric ** lookup. Address is copied into a temporary buffer to 100760089Seric ** strip the brackets and to preserve name if address is 100859671Seric ** unknown. 100959671Seric */ 101059671Seric 101160089Seric if (*name != '[') 101253751Seric { 101355019Seric extern bool getcanonname(); 101455019Seric 101558798Seric if (tTd(9, 1)) 101660089Seric printf("host_map_lookup(%s) => ", name); 101759671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 101860089Seric (void) strcpy(hbuf, name); 101963842Seric if (getcanonname(hbuf, sizeof hbuf - 1, TRUE)) 102058796Seric { 102158796Seric if (tTd(9, 1)) 102258796Seric printf("%s\n", hbuf); 102360257Seric cp = map_rewrite(map, hbuf, strlen(hbuf), av); 102460257Seric s->s_namecanon.nc_cname = newstr(cp); 102560257Seric return cp; 102658796Seric } 102753751Seric else 102858796Seric { 102959084Seric register struct hostent *hp; 103059084Seric 103158796Seric if (tTd(9, 1)) 103259084Seric printf("FAIL (%d)\n", h_errno); 103359671Seric s->s_namecanon.nc_errno = errno; 103459671Seric s->s_namecanon.nc_herrno = h_errno; 103559084Seric switch (h_errno) 103659084Seric { 103759084Seric case TRY_AGAIN: 103859596Seric if (UseNameServer) 103959734Seric { 104059734Seric char *msg = "Recipient domain nameserver timed out"; 104159734Seric 104259734Seric message(msg); 104359734Seric if (CurEnv->e_message == NULL) 104460009Seric CurEnv->e_message = newstr(msg); 104559734Seric } 104659084Seric *statp = EX_TEMPFAIL; 104759084Seric break; 104859084Seric 104959084Seric case HOST_NOT_FOUND: 105059084Seric *statp = EX_NOHOST; 105159084Seric break; 105259084Seric 105359084Seric case NO_RECOVERY: 105459084Seric *statp = EX_SOFTWARE; 105559084Seric break; 105659084Seric 105759084Seric default: 105859084Seric *statp = EX_UNAVAILABLE; 105959084Seric break; 106059084Seric } 106159671Seric s->s_namecanon.nc_stat = *statp; 106259084Seric if (*statp != EX_TEMPFAIL || UseNameServer) 106359084Seric return NULL; 106459084Seric 106559084Seric /* 106659084Seric ** Try to look it up in /etc/hosts 106759084Seric */ 106859084Seric 106960089Seric hp = gethostbyname(name); 107059084Seric if (hp == NULL) 107159084Seric { 107259084Seric /* no dice there either */ 107359671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 107459084Seric return NULL; 107559084Seric } 107659084Seric 107759671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 107860257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 107960257Seric s->s_namecanon.nc_cname = newstr(cp); 108060257Seric return cp; 108158796Seric } 108253751Seric } 108360089Seric if ((cp = strchr(name, ']')) == NULL) 108453751Seric return (NULL); 108540994Sbostic *cp = '\0'; 108660089Seric in_addr = inet_addr(&name[1]); 108758110Seric 108858110Seric /* check to see if this is one of our addresses */ 108958110Seric for (i = 0; MyIpAddrs[i].s_addr != 0; i++) 109058110Seric { 109158110Seric if (MyIpAddrs[i].s_addr == in_addr) 109258110Seric { 109360257Seric return map_rewrite(map, MyHostName, strlen(MyHostName), av); 109458110Seric } 109558110Seric } 109658110Seric 109758110Seric /* nope -- ask the name server */ 109833932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 109959671Seric s->s_namecanon.nc_errno = errno; 110059671Seric s->s_namecanon.nc_herrno = h_errno; 110159671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 110233932Sbostic if (hp == NULL) 110359671Seric { 110459671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 110553751Seric return (NULL); 110659671Seric } 110753751Seric 110858110Seric /* found a match -- copy out */ 110960257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 111059671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 111160257Seric s->s_namecanon.nc_cname = newstr(cp); 111260257Seric return cp; 111333932Sbostic } 111458755Seric /* 111558755Seric ** ANYNET_NTOA -- convert a network address to printable form. 111658755Seric ** 111758755Seric ** Parameters: 111858755Seric ** sap -- a pointer to a sockaddr structure. 111958755Seric ** 112058755Seric ** Returns: 112158755Seric ** A printable version of that sockaddr. 112258755Seric */ 112316911Seric 112458755Seric char * 112558755Seric anynet_ntoa(sap) 112658755Seric register SOCKADDR *sap; 112758755Seric { 112858755Seric register char *bp; 112958755Seric register char *ap; 113058755Seric int l; 113158755Seric static char buf[80]; 113258755Seric 113358798Seric /* check for null/zero family */ 113458798Seric if (sap == NULL) 113558798Seric return "NULLADDR"; 113658798Seric if (sap->sa.sa_family == 0) 113758798Seric return "0"; 113858798Seric 113958778Seric #ifdef NETINET 114058778Seric if (sap->sa.sa_family == AF_INET) 114158755Seric { 114258755Seric extern char *inet_ntoa(); 114358755Seric 114458755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 114558755Seric } 114658778Seric #endif 114758755Seric 114858755Seric /* unknown family -- just dump bytes */ 114958778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 115058755Seric bp = &buf[strlen(buf)]; 115158778Seric ap = sap->sa.sa_data; 115258778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 115358755Seric { 115458755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 115558755Seric bp += 3; 115658755Seric } 115758755Seric *--bp = '\0'; 115858755Seric return buf; 115958755Seric } 116058951Seric /* 116158951Seric ** HOSTNAMEBYANYADDR -- return name of host based on address 116258951Seric ** 116358951Seric ** Parameters: 116458951Seric ** sap -- SOCKADDR pointer 116558951Seric ** 116658951Seric ** Returns: 116758951Seric ** text representation of host name. 116858951Seric ** 116958951Seric ** Side Effects: 117058951Seric ** none. 117158951Seric */ 117258755Seric 117358951Seric char * 117458951Seric hostnamebyanyaddr(sap) 117558951Seric register SOCKADDR *sap; 117658951Seric { 117758951Seric register struct hostent *hp; 117858951Seric 117959042Seric #ifdef NAMED_BIND 118059042Seric int saveretry; 118159042Seric 118259042Seric /* shorten name server timeout to avoid higher level timeouts */ 118359042Seric saveretry = _res.retry; 118459042Seric _res.retry = 3; 118559042Seric #endif /* NAMED_BIND */ 118659042Seric 118758951Seric switch (sap->sa.sa_family) 118858951Seric { 118958951Seric #ifdef NETINET 119058951Seric case AF_INET: 119158951Seric hp = gethostbyaddr((char *) &sap->sin.sin_addr, 119258951Seric sizeof sap->sin.sin_addr, 119358951Seric AF_INET); 119458951Seric break; 119558951Seric #endif 119658951Seric 119758951Seric #ifdef NETISO 119858951Seric case AF_ISO: 119958951Seric hp = gethostbyaddr((char *) &sap->siso.siso_addr, 120058951Seric sizeof sap->siso.siso_addr, 120158951Seric AF_ISO); 120258951Seric break; 120358951Seric #endif 120458951Seric 120558951Seric default: 120658951Seric hp = gethostbyaddr(sap->sa.sa_data, 120758951Seric sizeof sap->sa.sa_data, 120858951Seric sap->sa.sa_family); 120958951Seric break; 121058951Seric } 121158951Seric 121259042Seric #ifdef NAMED_BIND 121359042Seric _res.retry = saveretry; 121459042Seric #endif /* NAMED_BIND */ 121559042Seric 121658951Seric if (hp != NULL) 121758951Seric return hp->h_name; 121858951Seric else 121958951Seric { 122058951Seric /* produce a dotted quad */ 122158951Seric static char buf[512]; 122258951Seric 122358951Seric (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); 122458951Seric return buf; 122558951Seric } 122658951Seric } 122758951Seric 122856795Seric # else /* DAEMON */ 122916911Seric /* code for systems without sophisticated networking */ 123010758Seric 123110758Seric /* 123210758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 123311297Seric ** 123411297Seric ** Can't convert to upper case here because might be a UUCP name. 123512313Seric ** 123612313Seric ** Mark, you can change this to be anything you want...... 123710758Seric */ 123810758Seric 123910758Seric char ** 124012313Seric myhostname(hostbuf, size) 124110758Seric char hostbuf[]; 124212313Seric int size; 124310758Seric { 124410758Seric register FILE *f; 124510758Seric 124610758Seric hostbuf[0] = '\0'; 124710758Seric f = fopen("/usr/include/whoami", "r"); 124810758Seric if (f != NULL) 124910758Seric { 125012313Seric (void) fgets(hostbuf, size, f); 125110758Seric fixcrlf(hostbuf, TRUE); 125210758Seric (void) fclose(f); 125310758Seric } 125410758Seric return (NULL); 125510758Seric } 125616911Seric /* 125758951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 125858308Seric ** 125958308Seric ** Parameters: 126058308Seric ** fd -- the descriptor 126158308Seric ** 126258308Seric ** Returns: 126358308Seric ** The host name associated with this descriptor, if it can 126458308Seric ** be determined. 126558308Seric ** NULL otherwise. 126658308Seric ** 126758308Seric ** Side Effects: 126858308Seric ** none 126958308Seric */ 127058308Seric 127158308Seric char * 127258951Seric getauthinfo(fd) 127358308Seric int fd; 127458308Seric { 127558308Seric return NULL; 127658308Seric } 127758308Seric /* 127816911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 127916911Seric ** 128016911Seric ** Parameters: 128156823Seric ** map -- a pointer to the database map. 128260089Seric ** name -- a buffer containing a hostname. 128353751Seric ** avp -- a pointer to a (cf file defined) argument vector. 128459084Seric ** statp -- an exit status (out parameter). 128516911Seric ** 128616911Seric ** Returns: 128753751Seric ** mapped host name 128851315Seric ** FALSE otherwise. 128916911Seric ** 129016911Seric ** Side Effects: 129160089Seric ** Looks up the host specified in name. If it is not 129216911Seric ** the canonical name for that host, replace it with 129316911Seric ** the canonical name. If the name is unknown, or it 129416911Seric ** is already the canonical name, leave it unchanged. 129516911Seric */ 129610758Seric 129716911Seric /*ARGSUSED*/ 129853751Seric char * 129960089Seric host_map_lookup(map, name, avp, statp) 130056823Seric MAP *map; 130160089Seric char *name; 130253751Seric char **avp; 130359084Seric char *statp; 130416911Seric { 130559084Seric register struct hostent *hp; 130659084Seric 130760089Seric hp = gethostbyname(name); 130859084Seric if (hp != NULL) 130959084Seric return hp->h_name; 131059084Seric *statp = EX_NOHOST; 131153751Seric return NULL; 131216911Seric } 131316911Seric 131456795Seric #endif /* DAEMON */ 1315