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*64035Seric static char sccsid[] = "@(#)daemon.c 8.5 (Berkeley) 07/26/93 (with daemon mode)"; 1533780Sbostic #else 16*64035Seric static char sccsid[] = "@(#)daemon.c 8.5 (Berkeley) 07/26/93 (without daemon mode)"; 1733780Sbostic #endif 1833780Sbostic #endif /* not lint */ 194535Seric 2033780Sbostic #ifdef DAEMON 2133780Sbostic 2223120Seric # include <netdb.h> 2323120Seric # include <sys/wait.h> 2423120Seric # include <sys/time.h> 255978Seric 2659042Seric #ifdef NAMED_BIND 2759042Seric # include <arpa/nameser.h> 2859042Seric # include <resolv.h> 2959042Seric #endif 3059042Seric 314535Seric /* 324535Seric ** DAEMON.C -- routines to use when running as a daemon. 337556Seric ** 347556Seric ** This entire file is highly dependent on the 4.2 BSD 357556Seric ** interprocess communication primitives. No attempt has 367556Seric ** been made to make this file portable to Version 7, 377556Seric ** Version 6, MPX files, etc. If you should try such a 387556Seric ** thing yourself, I recommend chucking the entire file 397556Seric ** and starting from scratch. Basic semantics are: 407556Seric ** 417556Seric ** getrequests() 427556Seric ** Opens a port and initiates a connection. 437556Seric ** Returns in a child. Must set InChannel and 447556Seric ** OutChannel appropriately. 4510206Seric ** clrdaemon() 4610206Seric ** Close any open files associated with getting 4710206Seric ** the connection; this is used when running the queue, 4810206Seric ** etc., to avoid having extra file descriptors during 4910206Seric ** the queue run and to avoid confusing the network 5010206Seric ** code (if it cares). 5152106Seric ** makeconnection(host, port, outfile, infile, usesecureport) 527556Seric ** Make a connection to the named host on the given 537556Seric ** port. Set *outfile and *infile to the files 547556Seric ** appropriate for communication. Returns zero on 557556Seric ** success, else an exit status describing the 567556Seric ** error. 5760089Seric ** host_map_lookup(map, hbuf, avp, pstat) 5856823Seric ** Convert the entry in hbuf into a canonical form. 594535Seric */ 604535Seric /* 614535Seric ** GETREQUESTS -- open mail IPC port and get requests. 624535Seric ** 634535Seric ** Parameters: 644535Seric ** none. 654535Seric ** 664535Seric ** Returns: 674535Seric ** none. 684535Seric ** 694535Seric ** Side Effects: 704535Seric ** Waits until some interesting activity occurs. When 714535Seric ** it does, a child is created to process it, and the 724535Seric ** parent waits for completion. Return from this 739886Seric ** routine is always in the child. The file pointers 749886Seric ** "InChannel" and "OutChannel" should be set to point 759886Seric ** to the communication channel. 764535Seric */ 774535Seric 7858849Seric int DaemonSocket = -1; /* fd describing socket */ 7958849Seric SOCKADDR DaemonAddr; /* socket for incoming */ 8059783Seric int ListenQueueSize = 10; /* size of listen queue */ 8116144Seric 824535Seric getrequests() 834535Seric { 849610Seric int t; 859610Seric register struct servent *sp; 8625027Seric int on = 1; 8753751Seric bool refusingconnections = TRUE; 8858419Seric FILE *pidf; 8946928Sbostic extern void reapchild(); 907117Seric 919610Seric /* 929610Seric ** Set up the address for the mailer. 939610Seric */ 949610Seric 9558849Seric if (DaemonAddr.sin.sin_family == 0) 9658849Seric DaemonAddr.sin.sin_family = AF_INET; 9758849Seric if (DaemonAddr.sin.sin_addr.s_addr == 0) 9858849Seric DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; 9958849Seric if (DaemonAddr.sin.sin_port == 0) 1009610Seric { 10158849Seric sp = getservbyname("smtp", "tcp"); 10258849Seric if (sp == NULL) 10358849Seric { 10458909Seric syserr("554 service \"smtp\" unknown"); 10558849Seric goto severe; 10658849Seric } 10758849Seric DaemonAddr.sin.sin_port = sp->s_port; 1089610Seric } 1099610Seric 1109610Seric /* 1119610Seric ** Try to actually open the connection. 1129610Seric */ 1139610Seric 1149610Seric if (tTd(15, 1)) 11558849Seric printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); 1169610Seric 1179610Seric /* get a socket for the SMTP connection */ 11859041Seric DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0); 11910206Seric if (DaemonSocket < 0) 1209610Seric { 1219610Seric /* probably another daemon already */ 1229610Seric syserr("getrequests: can't create socket"); 1239610Seric severe: 1249610Seric # ifdef LOG 1259610Seric if (LogLevel > 0) 12657663Seric syslog(LOG_ALERT, "problem creating SMTP socket"); 12756795Seric # endif /* LOG */ 1289610Seric finis(); 1299610Seric } 13010347Seric 13110347Seric /* turn on network debugging? */ 13256328Seric if (tTd(15, 101)) 13324945Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 13410347Seric 13525027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 13625027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 13725027Seric 13859041Seric switch (DaemonAddr.sa.sa_family) 1399610Seric { 14059041Seric # ifdef NETINET 14159041Seric case AF_INET: 14259041Seric t = sizeof DaemonAddr.sin; 14359041Seric break; 14459041Seric # endif 14559041Seric 14659041Seric # ifdef NETISO 14759041Seric case AF_ISO: 14859041Seric t = sizeof DaemonAddr.siso; 14959041Seric break; 15059041Seric # endif 15159041Seric 15259041Seric default: 15359041Seric t = sizeof DaemonAddr; 15459041Seric break; 15559041Seric } 15659041Seric 15759041Seric if (bind(DaemonSocket, &DaemonAddr.sa, t) < 0) 15859041Seric { 1599610Seric syserr("getrequests: cannot bind"); 16010206Seric (void) close(DaemonSocket); 1619610Seric goto severe; 1629610Seric } 1639610Seric 164*64035Seric (void) setsignal(SIGCHLD, reapchild); 16524945Seric 16658419Seric /* write the pid to the log file for posterity */ 16758419Seric pidf = fopen(PidFile, "w"); 16858419Seric if (pidf != NULL) 16958419Seric { 17063863Seric extern char *CommandLineArgs; 17163863Seric 17263863Seric /* write the process id on line 1 */ 17358419Seric fprintf(pidf, "%d\n", getpid()); 17463863Seric 17563863Seric /* line 2 contains all command line flags */ 17663863Seric fprintf(pidf, "%s\n", CommandLineArgs); 17763863Seric 17863863Seric /* flush and close */ 17958419Seric fclose(pidf); 18058419Seric } 18158419Seric 18258419Seric 1839610Seric if (tTd(15, 1)) 18410206Seric printf("getrequests: %d\n", DaemonSocket); 1859610Seric 1864631Seric for (;;) 1874631Seric { 18814875Seric register int pid; 18911147Seric auto int lotherend; 19053751Seric extern bool refuseconnections(); 19111147Seric 19214875Seric /* see if we are rejecting connections */ 19353751Seric CurrentLA = getla(); 19453751Seric if (refuseconnections()) 19536584Sbostic { 19653751Seric if (!refusingconnections) 19753751Seric { 19853751Seric /* don't queue so peer will fail quickly */ 19953751Seric (void) listen(DaemonSocket, 0); 20053751Seric refusingconnections = TRUE; 20153751Seric } 20257385Seric setproctitle("rejecting connections: load average: %d", 20357385Seric CurrentLA); 20414875Seric sleep(5); 20553751Seric continue; 20636584Sbostic } 20714875Seric 20853751Seric if (refusingconnections) 20953751Seric { 21053751Seric /* start listening again */ 21159783Seric if (listen(DaemonSocket, ListenQueueSize) < 0) 21253751Seric { 21353751Seric syserr("getrequests: cannot listen"); 21453751Seric (void) close(DaemonSocket); 21553751Seric goto severe; 21653751Seric } 21753751Seric setproctitle("accepting connections"); 21853751Seric refusingconnections = FALSE; 21953751Seric } 22053751Seric 2219610Seric /* wait for a connection */ 2229610Seric do 2239610Seric { 2249610Seric errno = 0; 22536230Skarels lotherend = sizeof RealHostAddr; 22646928Sbostic t = accept(DaemonSocket, 22746928Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 2289610Seric } while (t < 0 && errno == EINTR); 2299610Seric if (t < 0) 2305978Seric { 2319610Seric syserr("getrequests: accept"); 2329610Seric sleep(5); 2339610Seric continue; 2345978Seric } 2354631Seric 2365978Seric /* 2375978Seric ** Create a subprocess to process the mail. 2385978Seric */ 2395978Seric 2407677Seric if (tTd(15, 2)) 2419610Seric printf("getrequests: forking (fd = %d)\n", t); 2425978Seric 2434636Seric pid = fork(); 2444636Seric if (pid < 0) 2454631Seric { 2464636Seric syserr("daemon: cannot fork"); 2474636Seric sleep(10); 2489610Seric (void) close(t); 2494636Seric continue; 2504631Seric } 2514631Seric 2524636Seric if (pid == 0) 2534631Seric { 25458951Seric extern char *hostnamebyanyaddr(); 25511147Seric 2564636Seric /* 2574636Seric ** CHILD -- return to caller. 25811147Seric ** Collect verified idea of sending host. 2594636Seric ** Verify calling user id if possible here. 2604636Seric */ 2614631Seric 262*64035Seric (void) setsignal(SIGCHLD, SIG_DFL); 26359156Seric OpMode = MD_SMTP; 26424950Seric 26511147Seric /* determine host name */ 26658951Seric RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 26758778Seric 26855173Seric #ifdef LOG 26963842Seric if (LogLevel > 11) 27055173Seric { 27155173Seric /* log connection information */ 27255173Seric syslog(LOG_INFO, "connect from %s (%s)", 27358951Seric RealHostName, anynet_ntoa(&RealHostAddr)); 27455173Seric } 27555173Seric #endif 27655173Seric 27759254Seric (void) close(DaemonSocket); 27859254Seric InChannel = fdopen(t, "r"); 27959254Seric OutChannel = fdopen(dup(t), "w"); 28059254Seric 28116884Seric /* should we check for illegal connection here? XXX */ 28259156Seric #ifdef XLA 28359156Seric if (!xla_host_ok(RealHostName)) 28459156Seric { 28559254Seric message("421 Too many SMTP sessions for this host"); 28659156Seric exit(0); 28759156Seric } 28859156Seric #endif 28916884Seric 2907677Seric if (tTd(15, 2)) 2915978Seric printf("getreq: returning\n"); 2924636Seric return; 2934631Seric } 2944631Seric 2957117Seric /* close the port so that others will hang (for a while) */ 2969610Seric (void) close(t); 2974631Seric } 2989886Seric /*NOTREACHED*/ 2994631Seric } 3005978Seric /* 30110206Seric ** CLRDAEMON -- reset the daemon connection 30210206Seric ** 30310206Seric ** Parameters: 30410206Seric ** none. 30510206Seric ** 30610206Seric ** Returns: 30710206Seric ** none. 30810206Seric ** 30910206Seric ** Side Effects: 31010206Seric ** releases any resources used by the passive daemon. 31110206Seric */ 31210206Seric 31310206Seric clrdaemon() 31410206Seric { 31510206Seric if (DaemonSocket >= 0) 31610206Seric (void) close(DaemonSocket); 31710206Seric DaemonSocket = -1; 31810206Seric } 31910206Seric /* 32058849Seric ** SETDAEMONOPTIONS -- set options for running the daemon 32158849Seric ** 32258849Seric ** Parameters: 32358849Seric ** p -- the options line. 32458849Seric ** 32558849Seric ** Returns: 32658849Seric ** none. 32758849Seric */ 32858849Seric 32958849Seric setdaemonoptions(p) 33058849Seric register char *p; 33158849Seric { 33258873Seric if (DaemonAddr.sa.sa_family == AF_UNSPEC) 33358873Seric DaemonAddr.sa.sa_family = AF_INET; 33458873Seric 33558849Seric while (p != NULL) 33658849Seric { 33758849Seric register char *f; 33858849Seric register char *v; 33958849Seric 34058849Seric while (isascii(*p) && isspace(*p)) 34158849Seric p++; 34258849Seric if (*p == '\0') 34358849Seric break; 34458849Seric f = p; 34558849Seric p = strchr(p, ','); 34658849Seric if (p != NULL) 34758849Seric *p++ = '\0'; 34858849Seric v = strchr(f, '='); 34958849Seric if (v == NULL) 35058849Seric continue; 35158849Seric while (isascii(*++v) && isspace(*v)) 35258849Seric continue; 35358849Seric 35458849Seric switch (*f) 35558849Seric { 35658873Seric case 'F': /* address family */ 35758849Seric if (isascii(*v) && isdigit(*v)) 35858873Seric DaemonAddr.sa.sa_family = atoi(v); 35958873Seric #ifdef NETINET 36058873Seric else if (strcasecmp(v, "inet") == 0) 36158873Seric DaemonAddr.sa.sa_family = AF_INET; 36258873Seric #endif 36358873Seric #ifdef NETISO 36458873Seric else if (strcasecmp(v, "iso") == 0) 36558873Seric DaemonAddr.sa.sa_family = AF_ISO; 36658873Seric #endif 36758873Seric #ifdef NETNS 36858873Seric else if (strcasecmp(v, "ns") == 0) 36958873Seric DaemonAddr.sa.sa_family = AF_NS; 37058873Seric #endif 37158873Seric #ifdef NETX25 37258873Seric else if (strcasecmp(v, "x.25") == 0) 37358873Seric DaemonAddr.sa.sa_family = AF_CCITT; 37458873Seric #endif 37558849Seric else 37658873Seric syserr("554 Unknown address family %s in Family=option", v); 37758873Seric break; 37858873Seric 37958873Seric case 'A': /* address */ 38058873Seric switch (DaemonAddr.sa.sa_family) 38158849Seric { 38258873Seric #ifdef NETINET 38358873Seric case AF_INET: 38458873Seric if (isascii(*v) && isdigit(*v)) 38558873Seric DaemonAddr.sin.sin_addr.s_addr = inet_network(v); 38658873Seric else 38758873Seric { 38858873Seric register struct netent *np; 38958849Seric 39058873Seric np = getnetbyname(v); 39158873Seric if (np == NULL) 39258873Seric syserr("554 network \"%s\" unknown", v); 39358873Seric else 39458873Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 39558873Seric } 39658873Seric break; 39758873Seric #endif 39858873Seric 39958873Seric default: 40058873Seric syserr("554 Address= option unsupported for family %d", 40158873Seric DaemonAddr.sa.sa_family); 40258873Seric break; 40358849Seric } 40458849Seric break; 40558849Seric 40658873Seric case 'P': /* port */ 40758873Seric switch (DaemonAddr.sa.sa_family) 40858849Seric { 40958873Seric short port; 41058849Seric 41158873Seric #ifdef NETINET 41258873Seric case AF_INET: 41358873Seric if (isascii(*v) && isdigit(*v)) 41458873Seric DaemonAddr.sin.sin_port = atoi(v); 41558849Seric else 41658873Seric { 41758873Seric register struct servent *sp; 41858873Seric 41958873Seric sp = getservbyname(v, "tcp"); 42058873Seric if (sp == NULL) 42158909Seric syserr("554 service \"%s\" unknown", v); 42258873Seric else 42358873Seric DaemonAddr.sin.sin_port = sp->s_port; 42458873Seric } 42558873Seric break; 42658873Seric #endif 42758873Seric 42858873Seric #ifdef NETISO 42958873Seric case AF_ISO: 43058873Seric /* assume two byte transport selector */ 43158873Seric if (isascii(*v) && isdigit(*v)) 43258873Seric port = atoi(v); 43358873Seric else 43458873Seric { 43558873Seric register struct servent *sp; 43658873Seric 43758873Seric sp = getservbyname(v, "tcp"); 43858873Seric if (sp == NULL) 43958909Seric syserr("554 service \"%s\" unknown", v); 44058873Seric else 44158873Seric port = sp->s_port; 44258873Seric } 44358873Seric bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 44458873Seric break; 44558873Seric #endif 44658873Seric 44758873Seric default: 44858873Seric syserr("554 Port= option unsupported for family %d", 44958873Seric DaemonAddr.sa.sa_family); 45058873Seric break; 45158849Seric } 45258849Seric break; 45359783Seric 45459783Seric case 'L': /* listen queue size */ 45559783Seric ListenQueueSize = atoi(v); 45659783Seric break; 45758849Seric } 45858849Seric } 45958849Seric } 46058849Seric /* 4616039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 4626039Seric ** 4636039Seric ** Parameters: 4646039Seric ** host -- the name of the host. 4656633Seric ** port -- the port number to connect to. 46653739Seric ** mci -- a pointer to the mail connection information 46753739Seric ** structure to be filled in. 46852106Seric ** usesecureport -- if set, use a low numbered (reserved) 46952106Seric ** port to provide some rudimentary authentication. 4706039Seric ** 4716039Seric ** Returns: 4726039Seric ** An exit code telling whether the connection could be 4736039Seric ** made and if not why not. 4746039Seric ** 4756039Seric ** Side Effects: 4766039Seric ** none. 4776039Seric */ 4785978Seric 47958755Seric SOCKADDR CurHostAddr; /* address of current host */ 48058305Seric 48154967Seric int 48253739Seric makeconnection(host, port, mci, usesecureport) 4836039Seric char *host; 4847286Seric u_short port; 48554967Seric register MCI *mci; 48652106Seric bool usesecureport; 4876039Seric { 48829430Sbloom register int i, s; 48929430Sbloom register struct hostent *hp = (struct hostent *)NULL; 49058755Seric SOCKADDR addr; 49152106Seric int sav_errno; 49258755Seric int addrlen; 49335651Seric #ifdef NAMED_BIND 49435651Seric extern int h_errno; 49535651Seric #endif 4966039Seric 4976039Seric /* 4986039Seric ** Set up the address for the mailer. 4999308Seric ** Accept "[a.b.c.d]" syntax for host name. 5006039Seric */ 5016039Seric 50235651Seric #ifdef NAMED_BIND 50325475Smiriam h_errno = 0; 50435651Seric #endif 50525475Smiriam errno = 0; 50658864Seric bzero(&CurHostAddr, sizeof CurHostAddr); 50758906Seric CurHostName = host; 50825475Smiriam 5099308Seric if (host[0] == '[') 5109308Seric { 51111147Seric long hid; 51256795Seric register char *p = strchr(host, ']'); 5139308Seric 51411147Seric if (p != NULL) 5159308Seric { 51611147Seric *p = '\0'; 51759884Seric #ifdef NETINET 51811147Seric hid = inet_addr(&host[1]); 51958360Seric if (hid == -1) 52059884Seric #endif 52158360Seric { 52258360Seric /* try it as a host name (avoid MX lookup) */ 52358360Seric hp = gethostbyname(&host[1]); 52458360Seric *p = ']'; 52558360Seric goto gothostent; 52658360Seric } 52711147Seric *p = ']'; 5289308Seric } 52958360Seric if (p == NULL) 5309308Seric { 53158151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 5329308Seric return (EX_NOHOST); 5339308Seric } 53459884Seric #ifdef NETINET 53559884Seric addr.sin.sin_family = AF_INET; /*XXX*/ 53658778Seric addr.sin.sin_addr.s_addr = hid; 53759884Seric #endif 5389308Seric } 5399610Seric else 5409610Seric { 54129430Sbloom hp = gethostbyname(host); 54258360Seric gothostent: 54325475Smiriam if (hp == NULL) 54424945Seric { 54535651Seric #ifdef NAMED_BIND 54625475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 54725475Smiriam return (EX_TEMPFAIL); 54825657Seric 54935651Seric /* if name server is specified, assume temp fail */ 55035651Seric if (errno == ECONNREFUSED && UseNameServer) 55135651Seric return (EX_TEMPFAIL); 55235651Seric #endif 55325475Smiriam return (EX_NOHOST); 55424945Seric } 55558778Seric addr.sa.sa_family = hp->h_addrtype; 55658778Seric switch (hp->h_addrtype) 55758778Seric { 55858778Seric #ifdef NETINET 55958778Seric case AF_INET: 56058755Seric bcopy(hp->h_addr, 56158778Seric &addr.sin.sin_addr, 56258755Seric hp->h_length); 56358778Seric break; 56458778Seric #endif 56558778Seric 56658778Seric default: 56758755Seric bcopy(hp->h_addr, 56858778Seric addr.sa.sa_data, 56958755Seric hp->h_length); 57058778Seric break; 57158778Seric } 57229430Sbloom i = 1; 5739610Seric } 5749610Seric 5759610Seric /* 5769610Seric ** Determine the port number. 5779610Seric */ 5789610Seric 57910011Seric if (port != 0) 58058755Seric port = htons(port); 58110011Seric else 5829610Seric { 5839610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 5849610Seric 5859610Seric if (sp == NULL) 5869610Seric { 58758909Seric syserr("554 makeconnection: service \"smtp\" unknown"); 58857977Seric return (EX_OSERR); 5899610Seric } 59058755Seric port = sp->s_port; 5919610Seric } 5926039Seric 59358778Seric switch (addr.sa.sa_family) 59458755Seric { 59559884Seric #ifdef NETINET 59658755Seric case AF_INET: 59758778Seric addr.sin.sin_port = port; 59858755Seric addrlen = sizeof (struct sockaddr_in); 59958755Seric break; 60059884Seric #endif 60158755Seric 60258755Seric #ifdef NETISO 60358755Seric case AF_ISO: 60458755Seric /* assume two byte transport selector */ 60558755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 60658755Seric addrlen = sizeof (struct sockaddr_iso); 60758755Seric break; 60858755Seric #endif 60958755Seric 61058755Seric default: 61158778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 61258755Seric return (EX_NOHOST); 61358755Seric } 61458755Seric 6156039Seric /* 6166039Seric ** Try to actually open the connection. 6176039Seric */ 6186039Seric 61959156Seric #ifdef XLA 62059156Seric /* if too many connections, don't bother trying */ 62159156Seric if (!xla_noqueue_ok(host)) 62259156Seric return EX_TEMPFAIL; 62359156Seric #endif 62459156Seric 62557736Seric for (;;) 62652106Seric { 62757736Seric if (tTd(16, 1)) 62858755Seric printf("makeconnection (%s [%s])\n", 62958755Seric host, anynet_ntoa(&addr)); 63052106Seric 63158588Seric /* save for logging */ 63258588Seric CurHostAddr = addr; 63358588Seric 63457736Seric if (usesecureport) 63557736Seric { 63657736Seric int rport = IPPORT_RESERVED - 1; 6376039Seric 63857736Seric s = rresvport(&rport); 63957736Seric } 64057736Seric else 64157736Seric { 64257736Seric s = socket(AF_INET, SOCK_STREAM, 0); 64357736Seric } 64457736Seric if (s < 0) 64557736Seric { 64657736Seric sav_errno = errno; 64757736Seric syserr("makeconnection: no socket"); 64857736Seric goto failure; 64957736Seric } 65010347Seric 65157736Seric if (tTd(16, 1)) 65257736Seric printf("makeconnection: fd=%d\n", s); 65357736Seric 65457736Seric /* turn on network debugging? */ 65557736Seric if (tTd(16, 101)) 65657736Seric { 65757736Seric int on = 1; 65857736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 65957736Seric (char *)&on, sizeof on); 66057736Seric } 66157736Seric if (CurEnv->e_xfp != NULL) 66257736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 66357736Seric errno = 0; /* for debugging */ 66458755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 66557736Seric break; 66657736Seric 66757736Seric /* couldn't connect.... figure out why */ 66827744Sbloom sav_errno = errno; 66927744Sbloom (void) close(s); 67029430Sbloom if (hp && hp->h_addr_list[i]) 67129430Sbloom { 67257736Seric if (tTd(16, 1)) 67358755Seric printf("Connect failed (%s); trying new address....\n", 67458755Seric errstring(sav_errno)); 67558778Seric switch (addr.sa.sa_family) 67658778Seric { 67758778Seric #ifdef NETINET 67858778Seric case AF_INET: 67958755Seric bcopy(hp->h_addr_list[i++], 68058778Seric &addr.sin.sin_addr, 68158755Seric hp->h_length); 68258778Seric break; 68358778Seric #endif 68458778Seric 68558778Seric default: 68658755Seric bcopy(hp->h_addr_list[i++], 68758778Seric addr.sa.sa_data, 68852106Seric hp->h_length); 68958778Seric break; 69058778Seric } 69157736Seric continue; 69229430Sbloom } 69329430Sbloom 6946039Seric /* failure, decide if temporary or not */ 6956039Seric failure: 69659254Seric #ifdef XLA 69759254Seric xla_host_end(host); 69859254Seric #endif 69958542Seric if (transienterror(sav_errno)) 70058542Seric return EX_TEMPFAIL; 70158542Seric else 70258542Seric { 70358542Seric message("%s", errstring(sav_errno)); 70458542Seric return (EX_UNAVAILABLE); 7056039Seric } 7066039Seric } 7076039Seric 7086039Seric /* connection ok, put it into canonical form */ 70953739Seric mci->mci_out = fdopen(s, "w"); 71053739Seric mci->mci_in = fdopen(dup(s), "r"); 7116039Seric 71210098Seric return (EX_OK); 7136039Seric } 71410758Seric /* 71510758Seric ** MYHOSTNAME -- return the name of this host. 71610758Seric ** 71710758Seric ** Parameters: 71810758Seric ** hostbuf -- a place to return the name of this host. 71912313Seric ** size -- the size of hostbuf. 72010758Seric ** 72110758Seric ** Returns: 72210758Seric ** A list of aliases for this host. 72310758Seric ** 72410758Seric ** Side Effects: 72558110Seric ** Sets the MyIpAddrs buffer to a list of my IP addresses. 72610758Seric */ 7276039Seric 72858110Seric struct in_addr MyIpAddrs[MAXIPADDR + 1]; 72958110Seric 73010758Seric char ** 73112313Seric myhostname(hostbuf, size) 73210758Seric char hostbuf[]; 73312313Seric int size; 73410758Seric { 73558110Seric register struct hostent *hp; 73610758Seric extern struct hostent *gethostbyname(); 73710758Seric 73823120Seric if (gethostname(hostbuf, size) < 0) 73923120Seric { 74023120Seric (void) strcpy(hostbuf, "localhost"); 74123120Seric } 74211147Seric hp = gethostbyname(hostbuf); 74311147Seric if (hp != NULL) 74416877Seric { 74558110Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 74658110Seric hostbuf[size - 1] = '\0'; 74758110Seric 74858110Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 74958110Seric { 75058110Seric register int i; 75158110Seric 75258110Seric for (i = 0; i < MAXIPADDR; i++) 75358110Seric { 75458110Seric if (hp->h_addr_list[i] == NULL) 75558110Seric break; 75658110Seric MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i]; 75758110Seric } 75858110Seric MyIpAddrs[i].s_addr = 0; 75958110Seric } 76058110Seric 76111147Seric return (hp->h_aliases); 76216877Seric } 76310758Seric else 76410758Seric return (NULL); 76510758Seric } 76651315Seric /* 76758951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 76858308Seric ** 76958951Seric ** Uses RFC1413 protocol to try to get info from the other end. 77058951Seric ** 77158308Seric ** Parameters: 77258308Seric ** fd -- the descriptor 77358308Seric ** 77458308Seric ** Returns: 77558951Seric ** The user@host information associated with this descriptor. 77658308Seric ** 77758308Seric ** Side Effects: 77858951Seric ** Sets RealHostName to the name of the host at the other end. 77958308Seric */ 78058308Seric 78158951Seric #ifdef IDENTPROTO 78258951Seric 78358951Seric static jmp_buf CtxAuthTimeout; 78458951Seric 78558951Seric static 78658951Seric authtimeout() 78758951Seric { 78858951Seric longjmp(CtxAuthTimeout, 1); 78958951Seric } 79058951Seric 79158951Seric #endif 79258951Seric 79358308Seric char * 79458951Seric getauthinfo(fd) 79558308Seric int fd; 79658308Seric { 79758951Seric SOCKADDR fa; 79858951Seric int falen; 79959104Seric register char *p; 80058951Seric #ifdef IDENTPROTO 80158951Seric SOCKADDR la; 80258951Seric int lalen; 80358951Seric register struct servent *sp; 80458951Seric int s; 80558951Seric int i; 80658951Seric EVENT *ev; 80758951Seric #endif 80858951Seric static char hbuf[MAXNAME * 2 + 2]; 80958951Seric extern char *hostnamebyanyaddr(); 81058951Seric extern char RealUserName[]; /* main.c */ 81158308Seric 81258951Seric falen = sizeof fa; 81358951Seric if (getpeername(fd, &fa.sa, &falen) < 0 || falen <= 0) 81458951Seric { 81558951Seric RealHostName = "localhost"; 81658951Seric (void) sprintf(hbuf, "%s@localhost", RealUserName); 81758957Seric if (tTd(9, 1)) 81858951Seric printf("getauthinfo: %s\n", hbuf); 81958951Seric return hbuf; 82058951Seric } 82158951Seric 82258951Seric RealHostName = newstr(hostnamebyanyaddr(&fa)); 82358951Seric RealHostAddr = fa; 82458951Seric 82558951Seric #ifdef IDENTPROTO 82658951Seric lalen = sizeof la; 82758951Seric if (fa.sa.sa_family != AF_INET || 82858951Seric getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || 82958951Seric la.sa.sa_family != AF_INET) 83058951Seric { 83158951Seric /* no ident info */ 83258951Seric goto noident; 83358951Seric } 83458951Seric 83558951Seric /* create ident query */ 83660489Seric (void) sprintf(hbuf, "%d,%d\r\n", 83760489Seric ntohs(fa.sin.sin_port), ntohs(la.sin.sin_port)); 83858951Seric 83958951Seric /* create local address */ 84058951Seric bzero(&la, sizeof la); 84158951Seric 84258951Seric /* create foreign address */ 84358951Seric sp = getservbyname("auth", "tcp"); 84458951Seric if (sp != NULL) 84558951Seric fa.sin.sin_port = sp->s_port; 84658308Seric else 84759097Seric fa.sin.sin_port = htons(113); 84858951Seric 84958951Seric s = -1; 85058951Seric if (setjmp(CtxAuthTimeout) != 0) 85158951Seric { 85258951Seric if (s >= 0) 85358951Seric (void) close(s); 85458951Seric goto noident; 85558951Seric } 85658951Seric 85758951Seric /* put a timeout around the whole thing */ 85858951Seric ev = setevent((time_t) 30, authtimeout, 0); 85958951Seric 86058951Seric /* connect to foreign IDENT server */ 86158951Seric s = socket(AF_INET, SOCK_STREAM, 0); 86258951Seric if (s < 0) 86358951Seric { 86458951Seric clrevent(ev); 86558951Seric goto noident; 86658951Seric } 86758951Seric if (connect(s, &fa.sa, sizeof fa.sin) < 0) 86858951Seric { 86958951Seric closeident: 87058951Seric (void) close(s); 87158951Seric clrevent(ev); 87258951Seric goto noident; 87358951Seric } 87458951Seric 87558957Seric if (tTd(9, 10)) 87658951Seric printf("getauthinfo: sent %s", hbuf); 87758951Seric 87858951Seric /* send query */ 87958951Seric if (write(s, hbuf, strlen(hbuf)) < 0) 88058951Seric goto closeident; 88158951Seric 88258951Seric /* get result */ 88358951Seric i = read(s, hbuf, sizeof hbuf); 88458951Seric (void) close(s); 88558951Seric clrevent(ev); 88658951Seric if (i <= 0) 88758951Seric goto noident; 88858951Seric if (hbuf[--i] == '\n' && hbuf[--i] == '\r') 88958951Seric i--; 89058951Seric hbuf[++i] = '\0'; 89158951Seric 89258957Seric if (tTd(9, 3)) 89358951Seric printf("getauthinfo: got %s\n", hbuf); 89458951Seric 89558951Seric /* parse result */ 89658951Seric p = strchr(hbuf, ':'); 89758951Seric if (p == NULL) 89858951Seric { 89958951Seric /* malformed response */ 90058951Seric goto noident; 90158951Seric } 90258951Seric while (isascii(*++p) && isspace(*p)) 90358951Seric continue; 90458951Seric if (strncasecmp(p, "userid", 6) != 0) 90558951Seric { 90658951Seric /* presumably an error string */ 90758951Seric goto noident; 90858951Seric } 90958951Seric p += 6; 91058951Seric while (isascii(*p) && isspace(*p)) 91158951Seric p++; 91258951Seric if (*p++ != ':') 91358951Seric { 91458951Seric /* either useridxx or malformed response */ 91558951Seric goto noident; 91658951Seric } 91758951Seric 91858951Seric /* p now points to the OSTYPE field */ 91958951Seric p = strchr(p, ':'); 92058951Seric if (p == NULL) 92158951Seric { 92258951Seric /* malformed response */ 92358951Seric goto noident; 92458951Seric } 92558951Seric 92658957Seric /* 1413 says don't do this -- but it's broken otherwise */ 92758957Seric while (isascii(*++p) && isspace(*p)) 92858957Seric continue; 92958957Seric 93058951Seric /* p now points to the authenticated name */ 93158951Seric (void) sprintf(hbuf, "%s@%s", p, RealHostName); 93258957Seric goto finish; 93358957Seric 93458957Seric #endif /* IDENTPROTO */ 93558957Seric 93658957Seric noident: 93758957Seric (void) strcpy(hbuf, RealHostName); 93858957Seric 93958957Seric finish: 94058951Seric if (RealHostName[0] != '[') 94158951Seric { 94258951Seric p = &hbuf[strlen(hbuf)]; 94358951Seric (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); 94458951Seric } 94558957Seric if (tTd(9, 1)) 94658951Seric printf("getauthinfo: %s\n", hbuf); 94758308Seric return hbuf; 94858308Seric } 94958308Seric /* 95060089Seric ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 95153751Seric ** 95253751Seric ** Parameters: 95356823Seric ** map -- a pointer to this map (unused). 95460089Seric ** name -- the (presumably unqualified) hostname. 95560257Seric ** av -- unused -- for compatibility with other mapping 95655019Seric ** functions. 95759084Seric ** statp -- an exit status (out parameter) -- set to 95859084Seric ** EX_TEMPFAIL if the name server is unavailable. 95953751Seric ** 96053751Seric ** Returns: 96153751Seric ** The mapping, if found. 96253751Seric ** NULL if no mapping found. 96353751Seric ** 96453751Seric ** Side Effects: 96553751Seric ** Looks up the host specified in hbuf. If it is not 96653751Seric ** the canonical name for that host, return the canonical 96753751Seric ** name. 96853751Seric */ 96951315Seric 97053751Seric char * 97160257Seric host_map_lookup(map, name, av, statp) 97256823Seric MAP *map; 97360089Seric char *name; 97460257Seric char **av; 97559084Seric int *statp; 97616911Seric { 97716911Seric register struct hostent *hp; 97833932Sbostic u_long in_addr; 97956823Seric char *cp; 98058110Seric int i; 98159671Seric register STAB *s; 98260257Seric char hbuf[MAXNAME]; 98359671Seric extern struct hostent *gethostbyaddr(); 98459671Seric extern int h_errno; 98516911Seric 98625574Smiriam /* 98759671Seric ** See if we have already looked up this name. If so, just 98859671Seric ** return it. 98959671Seric */ 99053751Seric 99160089Seric s = stab(name, ST_NAMECANON, ST_ENTER); 99259671Seric if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 99359671Seric { 99459986Seric if (tTd(9, 1)) 99560089Seric printf("host_map_lookup(%s) => CACHE %s\n", 99660089Seric name, s->s_namecanon.nc_cname); 99759671Seric errno = s->s_namecanon.nc_errno; 99859671Seric h_errno = s->s_namecanon.nc_herrno; 99959671Seric *statp = s->s_namecanon.nc_stat; 100059671Seric return s->s_namecanon.nc_cname; 100159671Seric } 100259671Seric 100359671Seric /* 100459671Seric ** If first character is a bracket, then it is an address 100559671Seric ** lookup. Address is copied into a temporary buffer to 100660089Seric ** strip the brackets and to preserve name if address is 100759671Seric ** unknown. 100859671Seric */ 100959671Seric 101060089Seric if (*name != '[') 101153751Seric { 101255019Seric extern bool getcanonname(); 101355019Seric 101458798Seric if (tTd(9, 1)) 101560089Seric printf("host_map_lookup(%s) => ", name); 101659671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 101760089Seric (void) strcpy(hbuf, name); 101863842Seric if (getcanonname(hbuf, sizeof hbuf - 1, TRUE)) 101958796Seric { 102058796Seric if (tTd(9, 1)) 102158796Seric printf("%s\n", hbuf); 102260257Seric cp = map_rewrite(map, hbuf, strlen(hbuf), av); 102360257Seric s->s_namecanon.nc_cname = newstr(cp); 102460257Seric return cp; 102558796Seric } 102653751Seric else 102758796Seric { 102859084Seric register struct hostent *hp; 102959084Seric 103058796Seric if (tTd(9, 1)) 103159084Seric printf("FAIL (%d)\n", h_errno); 103259671Seric s->s_namecanon.nc_errno = errno; 103359671Seric s->s_namecanon.nc_herrno = h_errno; 103459084Seric switch (h_errno) 103559084Seric { 103659084Seric case TRY_AGAIN: 103759596Seric if (UseNameServer) 103859734Seric { 103959734Seric char *msg = "Recipient domain nameserver timed out"; 104059734Seric 104159734Seric message(msg); 104259734Seric if (CurEnv->e_message == NULL) 104360009Seric CurEnv->e_message = newstr(msg); 104459734Seric } 104559084Seric *statp = EX_TEMPFAIL; 104659084Seric break; 104759084Seric 104859084Seric case HOST_NOT_FOUND: 104959084Seric *statp = EX_NOHOST; 105059084Seric break; 105159084Seric 105259084Seric case NO_RECOVERY: 105359084Seric *statp = EX_SOFTWARE; 105459084Seric break; 105559084Seric 105659084Seric default: 105759084Seric *statp = EX_UNAVAILABLE; 105859084Seric break; 105959084Seric } 106059671Seric s->s_namecanon.nc_stat = *statp; 106159084Seric if (*statp != EX_TEMPFAIL || UseNameServer) 106259084Seric return NULL; 106359084Seric 106459084Seric /* 106559084Seric ** Try to look it up in /etc/hosts 106659084Seric */ 106759084Seric 106860089Seric hp = gethostbyname(name); 106959084Seric if (hp == NULL) 107059084Seric { 107159084Seric /* no dice there either */ 107259671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 107359084Seric return NULL; 107459084Seric } 107559084Seric 107659671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 107760257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 107860257Seric s->s_namecanon.nc_cname = newstr(cp); 107960257Seric return cp; 108058796Seric } 108153751Seric } 108260089Seric if ((cp = strchr(name, ']')) == NULL) 108353751Seric return (NULL); 108440994Sbostic *cp = '\0'; 108560089Seric in_addr = inet_addr(&name[1]); 108658110Seric 108758110Seric /* check to see if this is one of our addresses */ 108858110Seric for (i = 0; MyIpAddrs[i].s_addr != 0; i++) 108958110Seric { 109058110Seric if (MyIpAddrs[i].s_addr == in_addr) 109158110Seric { 109260257Seric return map_rewrite(map, MyHostName, strlen(MyHostName), av); 109358110Seric } 109458110Seric } 109558110Seric 109658110Seric /* nope -- ask the name server */ 109733932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 109859671Seric s->s_namecanon.nc_errno = errno; 109959671Seric s->s_namecanon.nc_herrno = h_errno; 110059671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 110133932Sbostic if (hp == NULL) 110259671Seric { 110359671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 110453751Seric return (NULL); 110559671Seric } 110653751Seric 110758110Seric /* found a match -- copy out */ 110860257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 110959671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 111060257Seric s->s_namecanon.nc_cname = newstr(cp); 111160257Seric return cp; 111233932Sbostic } 111358755Seric /* 111458755Seric ** ANYNET_NTOA -- convert a network address to printable form. 111558755Seric ** 111658755Seric ** Parameters: 111758755Seric ** sap -- a pointer to a sockaddr structure. 111858755Seric ** 111958755Seric ** Returns: 112058755Seric ** A printable version of that sockaddr. 112158755Seric */ 112216911Seric 112358755Seric char * 112458755Seric anynet_ntoa(sap) 112558755Seric register SOCKADDR *sap; 112658755Seric { 112758755Seric register char *bp; 112858755Seric register char *ap; 112958755Seric int l; 113058755Seric static char buf[80]; 113158755Seric 113258798Seric /* check for null/zero family */ 113358798Seric if (sap == NULL) 113458798Seric return "NULLADDR"; 113558798Seric if (sap->sa.sa_family == 0) 113658798Seric return "0"; 113758798Seric 113858778Seric #ifdef NETINET 113958778Seric if (sap->sa.sa_family == AF_INET) 114058755Seric { 114158755Seric extern char *inet_ntoa(); 114258755Seric 114358755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 114458755Seric } 114558778Seric #endif 114658755Seric 114758755Seric /* unknown family -- just dump bytes */ 114858778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 114958755Seric bp = &buf[strlen(buf)]; 115058778Seric ap = sap->sa.sa_data; 115158778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 115258755Seric { 115358755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 115458755Seric bp += 3; 115558755Seric } 115658755Seric *--bp = '\0'; 115758755Seric return buf; 115858755Seric } 115958951Seric /* 116058951Seric ** HOSTNAMEBYANYADDR -- return name of host based on address 116158951Seric ** 116258951Seric ** Parameters: 116358951Seric ** sap -- SOCKADDR pointer 116458951Seric ** 116558951Seric ** Returns: 116658951Seric ** text representation of host name. 116758951Seric ** 116858951Seric ** Side Effects: 116958951Seric ** none. 117058951Seric */ 117158755Seric 117258951Seric char * 117358951Seric hostnamebyanyaddr(sap) 117458951Seric register SOCKADDR *sap; 117558951Seric { 117658951Seric register struct hostent *hp; 117758951Seric 117859042Seric #ifdef NAMED_BIND 117959042Seric int saveretry; 118059042Seric 118159042Seric /* shorten name server timeout to avoid higher level timeouts */ 118259042Seric saveretry = _res.retry; 118359042Seric _res.retry = 3; 118459042Seric #endif /* NAMED_BIND */ 118559042Seric 118658951Seric switch (sap->sa.sa_family) 118758951Seric { 118858951Seric #ifdef NETINET 118958951Seric case AF_INET: 119058951Seric hp = gethostbyaddr((char *) &sap->sin.sin_addr, 119158951Seric sizeof sap->sin.sin_addr, 119258951Seric AF_INET); 119358951Seric break; 119458951Seric #endif 119558951Seric 119658951Seric #ifdef NETISO 119758951Seric case AF_ISO: 119858951Seric hp = gethostbyaddr((char *) &sap->siso.siso_addr, 119958951Seric sizeof sap->siso.siso_addr, 120058951Seric AF_ISO); 120158951Seric break; 120258951Seric #endif 120358951Seric 120458951Seric default: 120558951Seric hp = gethostbyaddr(sap->sa.sa_data, 120658951Seric sizeof sap->sa.sa_data, 120758951Seric sap->sa.sa_family); 120858951Seric break; 120958951Seric } 121058951Seric 121159042Seric #ifdef NAMED_BIND 121259042Seric _res.retry = saveretry; 121359042Seric #endif /* NAMED_BIND */ 121459042Seric 121558951Seric if (hp != NULL) 121658951Seric return hp->h_name; 121758951Seric else 121858951Seric { 121958951Seric /* produce a dotted quad */ 122058951Seric static char buf[512]; 122158951Seric 122258951Seric (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); 122358951Seric return buf; 122458951Seric } 122558951Seric } 122658951Seric 122756795Seric # else /* DAEMON */ 122816911Seric /* code for systems without sophisticated networking */ 122910758Seric 123010758Seric /* 123110758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 123211297Seric ** 123311297Seric ** Can't convert to upper case here because might be a UUCP name. 123412313Seric ** 123512313Seric ** Mark, you can change this to be anything you want...... 123610758Seric */ 123710758Seric 123810758Seric char ** 123912313Seric myhostname(hostbuf, size) 124010758Seric char hostbuf[]; 124112313Seric int size; 124210758Seric { 124310758Seric register FILE *f; 124410758Seric 124510758Seric hostbuf[0] = '\0'; 124610758Seric f = fopen("/usr/include/whoami", "r"); 124710758Seric if (f != NULL) 124810758Seric { 124912313Seric (void) fgets(hostbuf, size, f); 125010758Seric fixcrlf(hostbuf, TRUE); 125110758Seric (void) fclose(f); 125210758Seric } 125310758Seric return (NULL); 125410758Seric } 125516911Seric /* 125658951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 125758308Seric ** 125858308Seric ** Parameters: 125958308Seric ** fd -- the descriptor 126058308Seric ** 126158308Seric ** Returns: 126258308Seric ** The host name associated with this descriptor, if it can 126358308Seric ** be determined. 126458308Seric ** NULL otherwise. 126558308Seric ** 126658308Seric ** Side Effects: 126758308Seric ** none 126858308Seric */ 126958308Seric 127058308Seric char * 127158951Seric getauthinfo(fd) 127258308Seric int fd; 127358308Seric { 127458308Seric return NULL; 127558308Seric } 127658308Seric /* 127716911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 127816911Seric ** 127916911Seric ** Parameters: 128056823Seric ** map -- a pointer to the database map. 128160089Seric ** name -- a buffer containing a hostname. 128253751Seric ** avp -- a pointer to a (cf file defined) argument vector. 128359084Seric ** statp -- an exit status (out parameter). 128416911Seric ** 128516911Seric ** Returns: 128653751Seric ** mapped host name 128751315Seric ** FALSE otherwise. 128816911Seric ** 128916911Seric ** Side Effects: 129060089Seric ** Looks up the host specified in name. If it is not 129116911Seric ** the canonical name for that host, replace it with 129216911Seric ** the canonical name. If the name is unknown, or it 129316911Seric ** is already the canonical name, leave it unchanged. 129416911Seric */ 129510758Seric 129616911Seric /*ARGSUSED*/ 129753751Seric char * 129860089Seric host_map_lookup(map, name, avp, statp) 129956823Seric MAP *map; 130060089Seric char *name; 130153751Seric char **avp; 130259084Seric char *statp; 130316911Seric { 130459084Seric register struct hostent *hp; 130559084Seric 130660089Seric hp = gethostbyname(name); 130759084Seric if (hp != NULL) 130859084Seric return hp->h_name; 130959084Seric *statp = EX_NOHOST; 131053751Seric return NULL; 131116911Seric } 131216911Seric 131356795Seric #endif /* DAEMON */ 1314