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*64828Seric static char sccsid[] = "@(#)daemon.c 8.23 (Berkeley) 11/11/93 (with daemon mode)"; 1533780Sbostic #else 16*64828Seric static char sccsid[] = "@(#)daemon.c 8.23 (Berkeley) 11/11/93 (without daemon mode)"; 1733780Sbostic #endif 1833780Sbostic #endif /* not lint */ 194535Seric 2033780Sbostic #ifdef DAEMON 2133780Sbostic 2223120Seric # include <netdb.h> 2323120Seric # include <sys/time.h> 2464338Seric # include <arpa/inet.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 */ 8164381Seric int TcpRcvBufferSize = 0; /* size of TCP receive buffer */ 8264381Seric int TcpSndBufferSize = 0; /* size of TCP send buffer */ 8316144Seric 844535Seric getrequests() 854535Seric { 869610Seric int t; 879610Seric register struct servent *sp; 8825027Seric int on = 1; 8953751Seric bool refusingconnections = TRUE; 9058419Seric FILE *pidf; 91*64828Seric int socksize; 9246928Sbostic extern void reapchild(); 937117Seric 949610Seric /* 959610Seric ** Set up the address for the mailer. 969610Seric */ 979610Seric 9858849Seric if (DaemonAddr.sin.sin_family == 0) 9958849Seric DaemonAddr.sin.sin_family = AF_INET; 10058849Seric if (DaemonAddr.sin.sin_addr.s_addr == 0) 10158849Seric DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; 10258849Seric if (DaemonAddr.sin.sin_port == 0) 1039610Seric { 10458849Seric sp = getservbyname("smtp", "tcp"); 10558849Seric if (sp == NULL) 10658849Seric { 10758909Seric syserr("554 service \"smtp\" unknown"); 10858849Seric goto severe; 10958849Seric } 11058849Seric DaemonAddr.sin.sin_port = sp->s_port; 1119610Seric } 1129610Seric 1139610Seric /* 1149610Seric ** Try to actually open the connection. 1159610Seric */ 1169610Seric 1179610Seric if (tTd(15, 1)) 11858849Seric printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); 1199610Seric 1209610Seric /* get a socket for the SMTP connection */ 12159041Seric DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0); 12210206Seric if (DaemonSocket < 0) 1239610Seric { 1249610Seric /* probably another daemon already */ 1259610Seric syserr("getrequests: can't create socket"); 1269610Seric severe: 1279610Seric # ifdef LOG 1289610Seric if (LogLevel > 0) 12957663Seric syslog(LOG_ALERT, "problem creating SMTP socket"); 13056795Seric # endif /* LOG */ 1319610Seric finis(); 1329610Seric } 13310347Seric 13410347Seric /* turn on network debugging? */ 13556328Seric if (tTd(15, 101)) 13624945Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 13710347Seric 13825027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 13925027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 14025027Seric 14164391Seric #ifdef SO_RCVBUF 14264391Seric if (TcpRcvBufferSize > 0) 14364391Seric { 14464391Seric if (setsockopt(DaemonSocket, SOL_SOCKET, SO_RCVBUF, 14564561Seric (char *) &TcpRcvBufferSize, 14664391Seric sizeof(TcpRcvBufferSize)) < 0) 14764391Seric syserr("getrequests: setsockopt(SO_RCVBUF)"); 14864391Seric } 14964391Seric #endif 15064391Seric 15159041Seric switch (DaemonAddr.sa.sa_family) 1529610Seric { 15359041Seric # ifdef NETINET 15459041Seric case AF_INET: 155*64828Seric socksize = sizeof DaemonAddr.sin; 15659041Seric break; 15759041Seric # endif 15859041Seric 15959041Seric # ifdef NETISO 16059041Seric case AF_ISO: 161*64828Seric socksize = sizeof DaemonAddr.siso; 16259041Seric break; 16359041Seric # endif 16459041Seric 16559041Seric default: 166*64828Seric socksize = sizeof DaemonAddr; 16759041Seric break; 16859041Seric } 16959041Seric 170*64828Seric if (bind(DaemonSocket, &DaemonAddr.sa, socksize) < 0) 17159041Seric { 1729610Seric syserr("getrequests: cannot bind"); 17310206Seric (void) close(DaemonSocket); 1749610Seric goto severe; 1759610Seric } 1769610Seric 17764035Seric (void) setsignal(SIGCHLD, reapchild); 17824945Seric 17958419Seric /* write the pid to the log file for posterity */ 18058419Seric pidf = fopen(PidFile, "w"); 18158419Seric if (pidf != NULL) 18258419Seric { 18363863Seric extern char *CommandLineArgs; 18463863Seric 18563863Seric /* write the process id on line 1 */ 18658419Seric fprintf(pidf, "%d\n", getpid()); 18763863Seric 18863863Seric /* line 2 contains all command line flags */ 18963863Seric fprintf(pidf, "%s\n", CommandLineArgs); 19063863Seric 19163863Seric /* flush and close */ 19258419Seric fclose(pidf); 19358419Seric } 19458419Seric 19558419Seric 1969610Seric if (tTd(15, 1)) 19710206Seric printf("getrequests: %d\n", DaemonSocket); 1989610Seric 1994631Seric for (;;) 2004631Seric { 20114875Seric register int pid; 20211147Seric auto int lotherend; 20353751Seric extern bool refuseconnections(); 20411147Seric 20514875Seric /* see if we are rejecting connections */ 20653751Seric CurrentLA = getla(); 20753751Seric if (refuseconnections()) 20836584Sbostic { 20953751Seric if (!refusingconnections) 21053751Seric { 21153751Seric /* don't queue so peer will fail quickly */ 21253751Seric (void) listen(DaemonSocket, 0); 21353751Seric refusingconnections = TRUE; 21453751Seric } 21557385Seric setproctitle("rejecting connections: load average: %d", 21657385Seric CurrentLA); 21714875Seric sleep(5); 21853751Seric continue; 21936584Sbostic } 22014875Seric 22153751Seric if (refusingconnections) 22253751Seric { 22353751Seric /* start listening again */ 22459783Seric if (listen(DaemonSocket, ListenQueueSize) < 0) 22553751Seric { 22653751Seric syserr("getrequests: cannot listen"); 22753751Seric (void) close(DaemonSocket); 22853751Seric goto severe; 22953751Seric } 23053751Seric setproctitle("accepting connections"); 23153751Seric refusingconnections = FALSE; 23253751Seric } 23353751Seric 2349610Seric /* wait for a connection */ 2359610Seric do 2369610Seric { 2379610Seric errno = 0; 238*64828Seric lotherend = socksize; 23946928Sbostic t = accept(DaemonSocket, 24046928Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 2419610Seric } while (t < 0 && errno == EINTR); 2429610Seric if (t < 0) 2435978Seric { 2449610Seric syserr("getrequests: accept"); 2459610Seric sleep(5); 2469610Seric continue; 2475978Seric } 2484631Seric 2495978Seric /* 2505978Seric ** Create a subprocess to process the mail. 2515978Seric */ 2525978Seric 2537677Seric if (tTd(15, 2)) 2549610Seric printf("getrequests: forking (fd = %d)\n", t); 2555978Seric 2564636Seric pid = fork(); 2574636Seric if (pid < 0) 2584631Seric { 2594636Seric syserr("daemon: cannot fork"); 2604636Seric sleep(10); 2619610Seric (void) close(t); 2624636Seric continue; 2634631Seric } 2644631Seric 2654636Seric if (pid == 0) 2664631Seric { 26764086Seric char *p; 26858951Seric extern char *hostnamebyanyaddr(); 26911147Seric 2704636Seric /* 2714636Seric ** CHILD -- return to caller. 27211147Seric ** Collect verified idea of sending host. 2734636Seric ** Verify calling user id if possible here. 2744636Seric */ 2754631Seric 27664035Seric (void) setsignal(SIGCHLD, SIG_DFL); 27759156Seric OpMode = MD_SMTP; 27824950Seric 27911147Seric /* determine host name */ 28064086Seric p = hostnamebyanyaddr(&RealHostAddr); 28164086Seric RealHostName = newstr(p); 28258778Seric 28355173Seric #ifdef LOG 28463842Seric if (LogLevel > 11) 28555173Seric { 28655173Seric /* log connection information */ 28755173Seric syslog(LOG_INFO, "connect from %s (%s)", 28858951Seric RealHostName, anynet_ntoa(&RealHostAddr)); 28955173Seric } 29055173Seric #endif 29155173Seric 29259254Seric (void) close(DaemonSocket); 29364724Seric if ((InChannel = fdopen(t, "r")) == NULL || 29464724Seric (t = dup(t)) < 0 || 29564724Seric (OutChannel = fdopen(t, "w")) == NULL) 29664724Seric { 29764724Seric syserr("cannot open SMTP server channel, fd=%d", t); 29864724Seric exit(0); 29964724Seric } 30059254Seric 30116884Seric /* should we check for illegal connection here? XXX */ 30259156Seric #ifdef XLA 30359156Seric if (!xla_host_ok(RealHostName)) 30459156Seric { 30559254Seric message("421 Too many SMTP sessions for this host"); 30659156Seric exit(0); 30759156Seric } 30859156Seric #endif 30916884Seric 3107677Seric if (tTd(15, 2)) 3115978Seric printf("getreq: returning\n"); 3124636Seric return; 3134631Seric } 3144631Seric 3157117Seric /* close the port so that others will hang (for a while) */ 3169610Seric (void) close(t); 3174631Seric } 3189886Seric /*NOTREACHED*/ 3194631Seric } 3205978Seric /* 32110206Seric ** CLRDAEMON -- reset the daemon connection 32210206Seric ** 32310206Seric ** Parameters: 32410206Seric ** none. 32510206Seric ** 32610206Seric ** Returns: 32710206Seric ** none. 32810206Seric ** 32910206Seric ** Side Effects: 33010206Seric ** releases any resources used by the passive daemon. 33110206Seric */ 33210206Seric 33310206Seric clrdaemon() 33410206Seric { 33510206Seric if (DaemonSocket >= 0) 33610206Seric (void) close(DaemonSocket); 33710206Seric DaemonSocket = -1; 33810206Seric } 33910206Seric /* 34058849Seric ** SETDAEMONOPTIONS -- set options for running the daemon 34158849Seric ** 34258849Seric ** Parameters: 34358849Seric ** p -- the options line. 34458849Seric ** 34558849Seric ** Returns: 34658849Seric ** none. 34758849Seric */ 34858849Seric 34958849Seric setdaemonoptions(p) 35058849Seric register char *p; 35158849Seric { 35258873Seric if (DaemonAddr.sa.sa_family == AF_UNSPEC) 35358873Seric DaemonAddr.sa.sa_family = AF_INET; 35458873Seric 35558849Seric while (p != NULL) 35658849Seric { 35758849Seric register char *f; 35858849Seric register char *v; 35958849Seric 36058849Seric while (isascii(*p) && isspace(*p)) 36158849Seric p++; 36258849Seric if (*p == '\0') 36358849Seric break; 36458849Seric f = p; 36558849Seric p = strchr(p, ','); 36658849Seric if (p != NULL) 36758849Seric *p++ = '\0'; 36858849Seric v = strchr(f, '='); 36958849Seric if (v == NULL) 37058849Seric continue; 37158849Seric while (isascii(*++v) && isspace(*v)) 37258849Seric continue; 37358849Seric 37458849Seric switch (*f) 37558849Seric { 37658873Seric case 'F': /* address family */ 37758849Seric if (isascii(*v) && isdigit(*v)) 37858873Seric DaemonAddr.sa.sa_family = atoi(v); 37958873Seric #ifdef NETINET 38058873Seric else if (strcasecmp(v, "inet") == 0) 38158873Seric DaemonAddr.sa.sa_family = AF_INET; 38258873Seric #endif 38358873Seric #ifdef NETISO 38458873Seric else if (strcasecmp(v, "iso") == 0) 38558873Seric DaemonAddr.sa.sa_family = AF_ISO; 38658873Seric #endif 38758873Seric #ifdef NETNS 38858873Seric else if (strcasecmp(v, "ns") == 0) 38958873Seric DaemonAddr.sa.sa_family = AF_NS; 39058873Seric #endif 39158873Seric #ifdef NETX25 39258873Seric else if (strcasecmp(v, "x.25") == 0) 39358873Seric DaemonAddr.sa.sa_family = AF_CCITT; 39458873Seric #endif 39558849Seric else 39658873Seric syserr("554 Unknown address family %s in Family=option", v); 39758873Seric break; 39858873Seric 39958873Seric case 'A': /* address */ 40058873Seric switch (DaemonAddr.sa.sa_family) 40158849Seric { 40258873Seric #ifdef NETINET 40358873Seric case AF_INET: 40458873Seric if (isascii(*v) && isdigit(*v)) 40558873Seric DaemonAddr.sin.sin_addr.s_addr = inet_network(v); 40658873Seric else 40758873Seric { 40858873Seric register struct netent *np; 40958849Seric 41058873Seric np = getnetbyname(v); 41158873Seric if (np == NULL) 41258873Seric syserr("554 network \"%s\" unknown", v); 41358873Seric else 41458873Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 41558873Seric } 41658873Seric break; 41758873Seric #endif 41858873Seric 41958873Seric default: 42058873Seric syserr("554 Address= option unsupported for family %d", 42158873Seric DaemonAddr.sa.sa_family); 42258873Seric break; 42358849Seric } 42458849Seric break; 42558849Seric 42658873Seric case 'P': /* port */ 42758873Seric switch (DaemonAddr.sa.sa_family) 42858849Seric { 42958873Seric short port; 43058849Seric 43158873Seric #ifdef NETINET 43258873Seric case AF_INET: 43358873Seric if (isascii(*v) && isdigit(*v)) 43464366Seric DaemonAddr.sin.sin_port = htons(atoi(v)); 43558849Seric else 43658873Seric { 43758873Seric register struct servent *sp; 43858873Seric 43958873Seric sp = getservbyname(v, "tcp"); 44058873Seric if (sp == NULL) 44158909Seric syserr("554 service \"%s\" unknown", v); 44258873Seric else 44358873Seric DaemonAddr.sin.sin_port = sp->s_port; 44458873Seric } 44558873Seric break; 44658873Seric #endif 44758873Seric 44858873Seric #ifdef NETISO 44958873Seric case AF_ISO: 45058873Seric /* assume two byte transport selector */ 45158873Seric if (isascii(*v) && isdigit(*v)) 45264366Seric port = htons(atoi(v)); 45358873Seric else 45458873Seric { 45558873Seric register struct servent *sp; 45658873Seric 45758873Seric sp = getservbyname(v, "tcp"); 45858873Seric if (sp == NULL) 45958909Seric syserr("554 service \"%s\" unknown", v); 46058873Seric else 46158873Seric port = sp->s_port; 46258873Seric } 46358873Seric bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 46458873Seric break; 46558873Seric #endif 46658873Seric 46758873Seric default: 46858873Seric syserr("554 Port= option unsupported for family %d", 46958873Seric DaemonAddr.sa.sa_family); 47058873Seric break; 47158849Seric } 47258849Seric break; 47359783Seric 47459783Seric case 'L': /* listen queue size */ 47559783Seric ListenQueueSize = atoi(v); 47659783Seric break; 47764381Seric 47864381Seric case 'S': /* send buffer size */ 47964381Seric TcpSndBufferSize = atoi(v); 48064381Seric break; 48164381Seric 48264381Seric case 'R': /* receive buffer size */ 48364381Seric TcpRcvBufferSize = atoi(v); 48464381Seric break; 48558849Seric } 48658849Seric } 48758849Seric } 48858849Seric /* 4896039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 4906039Seric ** 4916039Seric ** Parameters: 4926039Seric ** host -- the name of the host. 4936633Seric ** port -- the port number to connect to. 49453739Seric ** mci -- a pointer to the mail connection information 49553739Seric ** structure to be filled in. 49652106Seric ** usesecureport -- if set, use a low numbered (reserved) 49752106Seric ** port to provide some rudimentary authentication. 4986039Seric ** 4996039Seric ** Returns: 5006039Seric ** An exit code telling whether the connection could be 5016039Seric ** made and if not why not. 5026039Seric ** 5036039Seric ** Side Effects: 5046039Seric ** none. 5056039Seric */ 5065978Seric 50758755Seric SOCKADDR CurHostAddr; /* address of current host */ 50858305Seric 50954967Seric int 51053739Seric makeconnection(host, port, mci, usesecureport) 5116039Seric char *host; 5127286Seric u_short port; 51354967Seric register MCI *mci; 51452106Seric bool usesecureport; 5156039Seric { 51629430Sbloom register int i, s; 51729430Sbloom register struct hostent *hp = (struct hostent *)NULL; 51858755Seric SOCKADDR addr; 51952106Seric int sav_errno; 52058755Seric int addrlen; 52135651Seric #ifdef NAMED_BIND 52235651Seric extern int h_errno; 52335651Seric #endif 5246039Seric 5256039Seric /* 5266039Seric ** Set up the address for the mailer. 5279308Seric ** Accept "[a.b.c.d]" syntax for host name. 5286039Seric */ 5296039Seric 53035651Seric #ifdef NAMED_BIND 53125475Smiriam h_errno = 0; 53235651Seric #endif 53325475Smiriam errno = 0; 53458864Seric bzero(&CurHostAddr, sizeof CurHostAddr); 53564334Seric SmtpPhase = mci->mci_phase = "initial connection"; 53658906Seric CurHostName = host; 53725475Smiriam 5389308Seric if (host[0] == '[') 5399308Seric { 54011147Seric long hid; 54156795Seric register char *p = strchr(host, ']'); 5429308Seric 54311147Seric if (p != NULL) 5449308Seric { 54511147Seric *p = '\0'; 54659884Seric #ifdef NETINET 54711147Seric hid = inet_addr(&host[1]); 54858360Seric if (hid == -1) 54959884Seric #endif 55058360Seric { 55158360Seric /* try it as a host name (avoid MX lookup) */ 55258360Seric hp = gethostbyname(&host[1]); 55358360Seric *p = ']'; 55458360Seric goto gothostent; 55558360Seric } 55611147Seric *p = ']'; 5579308Seric } 55858360Seric if (p == NULL) 5599308Seric { 56058151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 5619308Seric return (EX_NOHOST); 5629308Seric } 56359884Seric #ifdef NETINET 56459884Seric addr.sin.sin_family = AF_INET; /*XXX*/ 56558778Seric addr.sin.sin_addr.s_addr = hid; 56659884Seric #endif 5679308Seric } 5689610Seric else 5699610Seric { 57029430Sbloom hp = gethostbyname(host); 57158360Seric gothostent: 57225475Smiriam if (hp == NULL) 57324945Seric { 57435651Seric #ifdef NAMED_BIND 57525475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 57625475Smiriam return (EX_TEMPFAIL); 57725657Seric 57835651Seric /* if name server is specified, assume temp fail */ 57935651Seric if (errno == ECONNREFUSED && UseNameServer) 58035651Seric return (EX_TEMPFAIL); 58135651Seric #endif 58225475Smiriam return (EX_NOHOST); 58324945Seric } 58458778Seric addr.sa.sa_family = hp->h_addrtype; 58558778Seric switch (hp->h_addrtype) 58658778Seric { 58758778Seric #ifdef NETINET 58858778Seric case AF_INET: 58958755Seric bcopy(hp->h_addr, 59058778Seric &addr.sin.sin_addr, 59158755Seric hp->h_length); 59258778Seric break; 59358778Seric #endif 59458778Seric 59558778Seric default: 59658755Seric bcopy(hp->h_addr, 59758778Seric addr.sa.sa_data, 59858755Seric hp->h_length); 59958778Seric break; 60058778Seric } 60129430Sbloom i = 1; 6029610Seric } 6039610Seric 6049610Seric /* 6059610Seric ** Determine the port number. 6069610Seric */ 6079610Seric 60810011Seric if (port != 0) 60958755Seric port = htons(port); 61010011Seric else 6119610Seric { 6129610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 6139610Seric 6149610Seric if (sp == NULL) 6159610Seric { 61658909Seric syserr("554 makeconnection: service \"smtp\" unknown"); 61757977Seric return (EX_OSERR); 6189610Seric } 61958755Seric port = sp->s_port; 6209610Seric } 6216039Seric 62258778Seric switch (addr.sa.sa_family) 62358755Seric { 62459884Seric #ifdef NETINET 62558755Seric case AF_INET: 62658778Seric addr.sin.sin_port = port; 62758755Seric addrlen = sizeof (struct sockaddr_in); 62858755Seric break; 62959884Seric #endif 63058755Seric 63158755Seric #ifdef NETISO 63258755Seric case AF_ISO: 63358755Seric /* assume two byte transport selector */ 63458755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 63558755Seric addrlen = sizeof (struct sockaddr_iso); 63658755Seric break; 63758755Seric #endif 63858755Seric 63958755Seric default: 64058778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 64158755Seric return (EX_NOHOST); 64258755Seric } 64358755Seric 6446039Seric /* 6456039Seric ** Try to actually open the connection. 6466039Seric */ 6476039Seric 64859156Seric #ifdef XLA 64959156Seric /* if too many connections, don't bother trying */ 65059156Seric if (!xla_noqueue_ok(host)) 65159156Seric return EX_TEMPFAIL; 65259156Seric #endif 65359156Seric 65457736Seric for (;;) 65552106Seric { 65657736Seric if (tTd(16, 1)) 65758755Seric printf("makeconnection (%s [%s])\n", 65858755Seric host, anynet_ntoa(&addr)); 65952106Seric 66058588Seric /* save for logging */ 66158588Seric CurHostAddr = addr; 66258588Seric 66357736Seric if (usesecureport) 66457736Seric { 66557736Seric int rport = IPPORT_RESERVED - 1; 6666039Seric 66757736Seric s = rresvport(&rport); 66857736Seric } 66957736Seric else 67057736Seric { 67157736Seric s = socket(AF_INET, SOCK_STREAM, 0); 67257736Seric } 67357736Seric if (s < 0) 67457736Seric { 67557736Seric sav_errno = errno; 67657736Seric syserr("makeconnection: no socket"); 67757736Seric goto failure; 67857736Seric } 67910347Seric 68064381Seric #ifdef SO_SNDBUF 68164381Seric if (TcpSndBufferSize > 0) 68264381Seric { 68364381Seric if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 68464561Seric (char *) &TcpSndBufferSize, 68564381Seric sizeof(TcpSndBufferSize)) < 0) 68664381Seric syserr("makeconnection: setsockopt(SO_SNDBUF)"); 68764381Seric } 68864381Seric #endif 68964381Seric 69057736Seric if (tTd(16, 1)) 69157736Seric printf("makeconnection: fd=%d\n", s); 69257736Seric 69357736Seric /* turn on network debugging? */ 69457736Seric if (tTd(16, 101)) 69557736Seric { 69657736Seric int on = 1; 69757736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 69857736Seric (char *)&on, sizeof on); 69957736Seric } 70057736Seric if (CurEnv->e_xfp != NULL) 70157736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 70257736Seric errno = 0; /* for debugging */ 70358755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 70457736Seric break; 70557736Seric 70657736Seric /* couldn't connect.... figure out why */ 70727744Sbloom sav_errno = errno; 70827744Sbloom (void) close(s); 70929430Sbloom if (hp && hp->h_addr_list[i]) 71029430Sbloom { 71157736Seric if (tTd(16, 1)) 71258755Seric printf("Connect failed (%s); trying new address....\n", 71358755Seric errstring(sav_errno)); 71458778Seric switch (addr.sa.sa_family) 71558778Seric { 71658778Seric #ifdef NETINET 71758778Seric case AF_INET: 71858755Seric bcopy(hp->h_addr_list[i++], 71958778Seric &addr.sin.sin_addr, 72058755Seric hp->h_length); 72158778Seric break; 72258778Seric #endif 72358778Seric 72458778Seric default: 72558755Seric bcopy(hp->h_addr_list[i++], 72658778Seric addr.sa.sa_data, 72752106Seric hp->h_length); 72858778Seric break; 72958778Seric } 73057736Seric continue; 73129430Sbloom } 73229430Sbloom 7336039Seric /* failure, decide if temporary or not */ 7346039Seric failure: 73559254Seric #ifdef XLA 73659254Seric xla_host_end(host); 73759254Seric #endif 73858542Seric if (transienterror(sav_errno)) 73958542Seric return EX_TEMPFAIL; 74058542Seric else 74158542Seric { 74258542Seric message("%s", errstring(sav_errno)); 74358542Seric return (EX_UNAVAILABLE); 7446039Seric } 7456039Seric } 7466039Seric 7476039Seric /* connection ok, put it into canonical form */ 74864724Seric if ((mci->mci_out = fdopen(s, "w")) == NULL || 74964724Seric (s = dup(s)) < 0 || 75064725Seric (mci->mci_in = fdopen(s, "r")) == NULL) 75164724Seric { 75264724Seric syserr("cannot open SMTP client channel, fd=%d", s); 75364724Seric return EX_TEMPFAIL; 75464724Seric } 7556039Seric 75610098Seric return (EX_OK); 7576039Seric } 75810758Seric /* 75910758Seric ** MYHOSTNAME -- return the name of this host. 76010758Seric ** 76110758Seric ** Parameters: 76210758Seric ** hostbuf -- a place to return the name of this host. 76312313Seric ** size -- the size of hostbuf. 76410758Seric ** 76510758Seric ** Returns: 76610758Seric ** A list of aliases for this host. 76710758Seric ** 76810758Seric ** Side Effects: 76964338Seric ** Adds numeric codes to $=w. 77010758Seric */ 7716039Seric 77210758Seric char ** 77312313Seric myhostname(hostbuf, size) 77410758Seric char hostbuf[]; 77512313Seric int size; 77610758Seric { 77758110Seric register struct hostent *hp; 77810758Seric extern struct hostent *gethostbyname(); 77910758Seric 78023120Seric if (gethostname(hostbuf, size) < 0) 78123120Seric { 78223120Seric (void) strcpy(hostbuf, "localhost"); 78323120Seric } 78411147Seric hp = gethostbyname(hostbuf); 78511147Seric if (hp != NULL) 78616877Seric { 78758110Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 78858110Seric hostbuf[size - 1] = '\0'; 78958110Seric 79058110Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 79158110Seric { 79258110Seric register int i; 79358110Seric 79464338Seric for (i = 0; hp->h_addr_list[i] != NULL; i++) 79558110Seric { 79664338Seric char ipbuf[100]; 79764338Seric 79864338Seric sprintf(ipbuf, "[%s]", 79964338Seric inet_ntoa(*((struct in_addr *) hp->h_addr_list[i]))); 80064338Seric setclass('w', ipbuf); 80158110Seric } 80258110Seric } 80358110Seric 80411147Seric return (hp->h_aliases); 80516877Seric } 80610758Seric else 80710758Seric return (NULL); 80810758Seric } 80951315Seric /* 81058951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 81158308Seric ** 81258951Seric ** Uses RFC1413 protocol to try to get info from the other end. 81358951Seric ** 81458308Seric ** Parameters: 81558308Seric ** fd -- the descriptor 81658308Seric ** 81758308Seric ** Returns: 81858951Seric ** The user@host information associated with this descriptor. 81958308Seric ** 82058308Seric ** Side Effects: 82158951Seric ** Sets RealHostName to the name of the host at the other end. 82258308Seric */ 82358308Seric 82458951Seric #ifdef IDENTPROTO 82558951Seric 82658951Seric static jmp_buf CtxAuthTimeout; 82758951Seric 82858951Seric static 82958951Seric authtimeout() 83058951Seric { 83158951Seric longjmp(CtxAuthTimeout, 1); 83258951Seric } 83358951Seric 83458951Seric #endif 83558951Seric 83658308Seric char * 83758951Seric getauthinfo(fd) 83858308Seric int fd; 83958308Seric { 84058951Seric SOCKADDR fa; 84158951Seric int falen; 84259104Seric register char *p; 84358951Seric #ifdef IDENTPROTO 84458951Seric SOCKADDR la; 84558951Seric int lalen; 84658951Seric register struct servent *sp; 84758951Seric int s; 84858951Seric int i; 84958951Seric EVENT *ev; 85058951Seric #endif 85158951Seric static char hbuf[MAXNAME * 2 + 2]; 85258951Seric extern char *hostnamebyanyaddr(); 85358951Seric extern char RealUserName[]; /* main.c */ 85458308Seric 85558951Seric falen = sizeof fa; 85658951Seric if (getpeername(fd, &fa.sa, &falen) < 0 || falen <= 0) 85758951Seric { 85858951Seric RealHostName = "localhost"; 85958951Seric (void) sprintf(hbuf, "%s@localhost", RealUserName); 86058957Seric if (tTd(9, 1)) 86158951Seric printf("getauthinfo: %s\n", hbuf); 86258951Seric return hbuf; 86358951Seric } 86458951Seric 86564086Seric p = hostnamebyanyaddr(&fa); 86664086Seric RealHostName = newstr(p); 86758951Seric RealHostAddr = fa; 86858951Seric 86958951Seric #ifdef IDENTPROTO 87058951Seric lalen = sizeof la; 87158951Seric if (fa.sa.sa_family != AF_INET || 87258951Seric getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || 87358951Seric la.sa.sa_family != AF_INET) 87458951Seric { 87558951Seric /* no ident info */ 87658951Seric goto noident; 87758951Seric } 87858951Seric 87958951Seric /* create ident query */ 88060489Seric (void) sprintf(hbuf, "%d,%d\r\n", 88160489Seric ntohs(fa.sin.sin_port), ntohs(la.sin.sin_port)); 88258951Seric 88358951Seric /* create local address */ 88464747Seric la.sin.sin_port = 0; 88558951Seric 88658951Seric /* create foreign address */ 88758951Seric sp = getservbyname("auth", "tcp"); 88858951Seric if (sp != NULL) 88958951Seric fa.sin.sin_port = sp->s_port; 89058308Seric else 89159097Seric fa.sin.sin_port = htons(113); 89258951Seric 89358951Seric s = -1; 89458951Seric if (setjmp(CtxAuthTimeout) != 0) 89558951Seric { 89658951Seric if (s >= 0) 89758951Seric (void) close(s); 89858951Seric goto noident; 89958951Seric } 90058951Seric 90158951Seric /* put a timeout around the whole thing */ 90264255Seric ev = setevent(TimeOuts.to_ident, authtimeout, 0); 90358951Seric 90464747Seric /* connect to foreign IDENT server using same address as SMTP socket */ 90558951Seric s = socket(AF_INET, SOCK_STREAM, 0); 90658951Seric if (s < 0) 90758951Seric { 90858951Seric clrevent(ev); 90958951Seric goto noident; 91058951Seric } 91164747Seric if (bind(s, &la.sa, sizeof la.sin) < 0 || 91264747Seric connect(s, &fa.sa, sizeof fa.sin) < 0) 91358951Seric { 91458951Seric closeident: 91558951Seric (void) close(s); 91658951Seric clrevent(ev); 91758951Seric goto noident; 91858951Seric } 91958951Seric 92058957Seric if (tTd(9, 10)) 92158951Seric printf("getauthinfo: sent %s", hbuf); 92258951Seric 92358951Seric /* send query */ 92458951Seric if (write(s, hbuf, strlen(hbuf)) < 0) 92558951Seric goto closeident; 92658951Seric 92758951Seric /* get result */ 92858951Seric i = read(s, hbuf, sizeof hbuf); 92958951Seric (void) close(s); 93058951Seric clrevent(ev); 93158951Seric if (i <= 0) 93258951Seric goto noident; 93358951Seric if (hbuf[--i] == '\n' && hbuf[--i] == '\r') 93458951Seric i--; 93558951Seric hbuf[++i] = '\0'; 93658951Seric 93758957Seric if (tTd(9, 3)) 93858951Seric printf("getauthinfo: got %s\n", hbuf); 93958951Seric 94058951Seric /* parse result */ 94158951Seric p = strchr(hbuf, ':'); 94258951Seric if (p == NULL) 94358951Seric { 94458951Seric /* malformed response */ 94558951Seric goto noident; 94658951Seric } 94758951Seric while (isascii(*++p) && isspace(*p)) 94858951Seric continue; 94958951Seric if (strncasecmp(p, "userid", 6) != 0) 95058951Seric { 95158951Seric /* presumably an error string */ 95258951Seric goto noident; 95358951Seric } 95458951Seric p += 6; 95558951Seric while (isascii(*p) && isspace(*p)) 95658951Seric p++; 95758951Seric if (*p++ != ':') 95858951Seric { 95958951Seric /* either useridxx or malformed response */ 96058951Seric goto noident; 96158951Seric } 96258951Seric 96358951Seric /* p now points to the OSTYPE field */ 96458951Seric p = strchr(p, ':'); 96558951Seric if (p == NULL) 96658951Seric { 96758951Seric /* malformed response */ 96858951Seric goto noident; 96958951Seric } 97058951Seric 97158957Seric /* 1413 says don't do this -- but it's broken otherwise */ 97258957Seric while (isascii(*++p) && isspace(*p)) 97358957Seric continue; 97458957Seric 97558951Seric /* p now points to the authenticated name */ 97658951Seric (void) sprintf(hbuf, "%s@%s", p, RealHostName); 97758957Seric goto finish; 97858957Seric 97958957Seric #endif /* IDENTPROTO */ 98058957Seric 98158957Seric noident: 98258957Seric (void) strcpy(hbuf, RealHostName); 98358957Seric 98458957Seric finish: 98558951Seric if (RealHostName[0] != '[') 98658951Seric { 98758951Seric p = &hbuf[strlen(hbuf)]; 98858951Seric (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); 98958951Seric } 99058957Seric if (tTd(9, 1)) 99158951Seric printf("getauthinfo: %s\n", hbuf); 99258308Seric return hbuf; 99358308Seric } 99458308Seric /* 99560089Seric ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 99653751Seric ** 99753751Seric ** Parameters: 99856823Seric ** map -- a pointer to this map (unused). 99960089Seric ** name -- the (presumably unqualified) hostname. 100060257Seric ** av -- unused -- for compatibility with other mapping 100155019Seric ** functions. 100259084Seric ** statp -- an exit status (out parameter) -- set to 100359084Seric ** EX_TEMPFAIL if the name server is unavailable. 100453751Seric ** 100553751Seric ** Returns: 100653751Seric ** The mapping, if found. 100753751Seric ** NULL if no mapping found. 100853751Seric ** 100953751Seric ** Side Effects: 101053751Seric ** Looks up the host specified in hbuf. If it is not 101153751Seric ** the canonical name for that host, return the canonical 101253751Seric ** name. 101353751Seric */ 101451315Seric 101553751Seric char * 101660257Seric host_map_lookup(map, name, av, statp) 101756823Seric MAP *map; 101860089Seric char *name; 101960257Seric char **av; 102059084Seric int *statp; 102116911Seric { 102216911Seric register struct hostent *hp; 102333932Sbostic u_long in_addr; 102456823Seric char *cp; 102558110Seric int i; 102659671Seric register STAB *s; 102764797Seric char *timeoutmsg = "Recipient domain nameserver timed out"; 102860257Seric char hbuf[MAXNAME]; 102959671Seric extern struct hostent *gethostbyaddr(); 103059671Seric extern int h_errno; 103116911Seric 103225574Smiriam /* 103359671Seric ** See if we have already looked up this name. If so, just 103459671Seric ** return it. 103559671Seric */ 103653751Seric 103760089Seric s = stab(name, ST_NAMECANON, ST_ENTER); 103859671Seric if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 103959671Seric { 104059986Seric if (tTd(9, 1)) 104160089Seric printf("host_map_lookup(%s) => CACHE %s\n", 104260089Seric name, s->s_namecanon.nc_cname); 104359671Seric errno = s->s_namecanon.nc_errno; 104459671Seric h_errno = s->s_namecanon.nc_herrno; 104559671Seric *statp = s->s_namecanon.nc_stat; 104664797Seric if (CurEnv->e_message == NULL && *statp == EX_TEMPFAIL) 104764797Seric CurEnv->e_message = newstr(timeoutmsg); 104859671Seric return s->s_namecanon.nc_cname; 104959671Seric } 105059671Seric 105159671Seric /* 105259671Seric ** If first character is a bracket, then it is an address 105359671Seric ** lookup. Address is copied into a temporary buffer to 105460089Seric ** strip the brackets and to preserve name if address is 105559671Seric ** unknown. 105659671Seric */ 105759671Seric 105860089Seric if (*name != '[') 105953751Seric { 106055019Seric extern bool getcanonname(); 106155019Seric 106258798Seric if (tTd(9, 1)) 106360089Seric printf("host_map_lookup(%s) => ", name); 106459671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 106560089Seric (void) strcpy(hbuf, name); 106663842Seric if (getcanonname(hbuf, sizeof hbuf - 1, TRUE)) 106758796Seric { 106858796Seric if (tTd(9, 1)) 106958796Seric printf("%s\n", hbuf); 107060257Seric cp = map_rewrite(map, hbuf, strlen(hbuf), av); 107160257Seric s->s_namecanon.nc_cname = newstr(cp); 107260257Seric return cp; 107358796Seric } 107453751Seric else 107558796Seric { 107659084Seric register struct hostent *hp; 107759084Seric 107858796Seric if (tTd(9, 1)) 107959084Seric printf("FAIL (%d)\n", h_errno); 108059671Seric s->s_namecanon.nc_errno = errno; 108159671Seric s->s_namecanon.nc_herrno = h_errno; 108259084Seric switch (h_errno) 108359084Seric { 108459084Seric case TRY_AGAIN: 108559596Seric if (UseNameServer) 108659734Seric { 108764797Seric message(timeoutmsg); 108859734Seric if (CurEnv->e_message == NULL) 108964797Seric CurEnv->e_message = newstr(timeoutmsg); 109059734Seric } 109159084Seric *statp = EX_TEMPFAIL; 109259084Seric break; 109359084Seric 109459084Seric case HOST_NOT_FOUND: 109559084Seric *statp = EX_NOHOST; 109659084Seric break; 109759084Seric 109859084Seric case NO_RECOVERY: 109959084Seric *statp = EX_SOFTWARE; 110059084Seric break; 110159084Seric 110259084Seric default: 110359084Seric *statp = EX_UNAVAILABLE; 110459084Seric break; 110559084Seric } 110659671Seric s->s_namecanon.nc_stat = *statp; 110759084Seric if (*statp != EX_TEMPFAIL || UseNameServer) 110859084Seric return NULL; 110959084Seric 111059084Seric /* 111159084Seric ** Try to look it up in /etc/hosts 111259084Seric */ 111359084Seric 111460089Seric hp = gethostbyname(name); 111559084Seric if (hp == NULL) 111659084Seric { 111759084Seric /* no dice there either */ 111859671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 111959084Seric return NULL; 112059084Seric } 112159084Seric 112259671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 112360257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 112460257Seric s->s_namecanon.nc_cname = newstr(cp); 112560257Seric return cp; 112658796Seric } 112753751Seric } 112860089Seric if ((cp = strchr(name, ']')) == NULL) 112953751Seric return (NULL); 113040994Sbostic *cp = '\0'; 113160089Seric in_addr = inet_addr(&name[1]); 113258110Seric 113358110Seric /* nope -- ask the name server */ 113433932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 113559671Seric s->s_namecanon.nc_errno = errno; 113659671Seric s->s_namecanon.nc_herrno = h_errno; 113759671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 113833932Sbostic if (hp == NULL) 113959671Seric { 114059671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 114153751Seric return (NULL); 114259671Seric } 114353751Seric 114458110Seric /* found a match -- copy out */ 114560257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 114659671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 114760257Seric s->s_namecanon.nc_cname = newstr(cp); 114860257Seric return cp; 114933932Sbostic } 115058755Seric /* 115158755Seric ** ANYNET_NTOA -- convert a network address to printable form. 115258755Seric ** 115358755Seric ** Parameters: 115458755Seric ** sap -- a pointer to a sockaddr structure. 115558755Seric ** 115658755Seric ** Returns: 115758755Seric ** A printable version of that sockaddr. 115858755Seric */ 115916911Seric 116058755Seric char * 116158755Seric anynet_ntoa(sap) 116258755Seric register SOCKADDR *sap; 116358755Seric { 116458755Seric register char *bp; 116558755Seric register char *ap; 116658755Seric int l; 116764734Seric static char buf[100]; 116858755Seric 116958798Seric /* check for null/zero family */ 117058798Seric if (sap == NULL) 117158798Seric return "NULLADDR"; 117258798Seric if (sap->sa.sa_family == 0) 117358798Seric return "0"; 117458798Seric 117564734Seric switch (sap->sa.sa_family) 117664734Seric { 117764734Seric #ifdef MAYBENEXTRELEASE /*** UNTESTED *** UNTESTED *** UNTESTED ***/ 117864821Seric #ifdef NETUNIX 117964734Seric case AF_UNIX: 118064758Seric if (sap->sunix.sun_path[0] != '\0') 118164758Seric sprintf(buf, "[UNIX: %.64s]", sap->sunix.sun_path); 118264734Seric else 118364734Seric sprintf(buf, "[UNIX: localhost]"); 118464734Seric return buf; 118564734Seric #endif 118664821Seric #endif 118764734Seric 118858778Seric #ifdef NETINET 118964734Seric case AF_INET: 119058755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 119158778Seric #endif 119258755Seric 119364734Seric default: 119464734Seric /* this case is only to ensure syntactic correctness */ 119564734Seric break; 119664734Seric } 119764734Seric 119858755Seric /* unknown family -- just dump bytes */ 119958778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 120058755Seric bp = &buf[strlen(buf)]; 120158778Seric ap = sap->sa.sa_data; 120258778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 120358755Seric { 120458755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 120558755Seric bp += 3; 120658755Seric } 120758755Seric *--bp = '\0'; 120858755Seric return buf; 120958755Seric } 121058951Seric /* 121158951Seric ** HOSTNAMEBYANYADDR -- return name of host based on address 121258951Seric ** 121358951Seric ** Parameters: 121458951Seric ** sap -- SOCKADDR pointer 121558951Seric ** 121658951Seric ** Returns: 121758951Seric ** text representation of host name. 121858951Seric ** 121958951Seric ** Side Effects: 122058951Seric ** none. 122158951Seric */ 122258755Seric 122358951Seric char * 122458951Seric hostnamebyanyaddr(sap) 122558951Seric register SOCKADDR *sap; 122658951Seric { 122758951Seric register struct hostent *hp; 122864734Seric int saveretry; 122958951Seric 123059042Seric #ifdef NAMED_BIND 123159042Seric /* shorten name server timeout to avoid higher level timeouts */ 123259042Seric saveretry = _res.retry; 123359042Seric _res.retry = 3; 123459042Seric #endif /* NAMED_BIND */ 123559042Seric 123658951Seric switch (sap->sa.sa_family) 123758951Seric { 123858951Seric #ifdef NETINET 123958951Seric case AF_INET: 124058951Seric hp = gethostbyaddr((char *) &sap->sin.sin_addr, 124158951Seric sizeof sap->sin.sin_addr, 124258951Seric AF_INET); 124358951Seric break; 124458951Seric #endif 124558951Seric 124658951Seric #ifdef NETISO 124758951Seric case AF_ISO: 124858951Seric hp = gethostbyaddr((char *) &sap->siso.siso_addr, 124958951Seric sizeof sap->siso.siso_addr, 125058951Seric AF_ISO); 125158951Seric break; 125258951Seric #endif 125358951Seric 125464734Seric #ifdef MAYBENEXTRELEASE /*** UNTESTED *** UNTESTED *** UNTESTED ***/ 125564734Seric case AF_UNIX: 125664734Seric hp = NULL; 125764734Seric break; 125864734Seric #endif 125964734Seric 126058951Seric default: 126158951Seric hp = gethostbyaddr(sap->sa.sa_data, 126258951Seric sizeof sap->sa.sa_data, 126358951Seric sap->sa.sa_family); 126458951Seric break; 126558951Seric } 126658951Seric 126759042Seric #ifdef NAMED_BIND 126859042Seric _res.retry = saveretry; 126959042Seric #endif /* NAMED_BIND */ 127059042Seric 127158951Seric if (hp != NULL) 127258951Seric return hp->h_name; 127358951Seric else 127458951Seric { 127558951Seric /* produce a dotted quad */ 127658951Seric static char buf[512]; 127758951Seric 127858951Seric (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); 127958951Seric return buf; 128058951Seric } 128158951Seric } 128258951Seric 128356795Seric # else /* DAEMON */ 128416911Seric /* code for systems without sophisticated networking */ 128510758Seric 128610758Seric /* 128710758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 128811297Seric ** 128911297Seric ** Can't convert to upper case here because might be a UUCP name. 129012313Seric ** 129112313Seric ** Mark, you can change this to be anything you want...... 129210758Seric */ 129310758Seric 129410758Seric char ** 129512313Seric myhostname(hostbuf, size) 129610758Seric char hostbuf[]; 129712313Seric int size; 129810758Seric { 129910758Seric register FILE *f; 130010758Seric 130110758Seric hostbuf[0] = '\0'; 130210758Seric f = fopen("/usr/include/whoami", "r"); 130310758Seric if (f != NULL) 130410758Seric { 130512313Seric (void) fgets(hostbuf, size, f); 130610758Seric fixcrlf(hostbuf, TRUE); 130710758Seric (void) fclose(f); 130810758Seric } 130910758Seric return (NULL); 131010758Seric } 131116911Seric /* 131258951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 131358308Seric ** 131458308Seric ** Parameters: 131558308Seric ** fd -- the descriptor 131658308Seric ** 131758308Seric ** Returns: 131858308Seric ** The host name associated with this descriptor, if it can 131958308Seric ** be determined. 132058308Seric ** NULL otherwise. 132158308Seric ** 132258308Seric ** Side Effects: 132358308Seric ** none 132458308Seric */ 132558308Seric 132658308Seric char * 132758951Seric getauthinfo(fd) 132858308Seric int fd; 132958308Seric { 133058308Seric return NULL; 133158308Seric } 133258308Seric /* 133316911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 133416911Seric ** 133516911Seric ** Parameters: 133656823Seric ** map -- a pointer to the database map. 133760089Seric ** name -- a buffer containing a hostname. 133853751Seric ** avp -- a pointer to a (cf file defined) argument vector. 133959084Seric ** statp -- an exit status (out parameter). 134016911Seric ** 134116911Seric ** Returns: 134253751Seric ** mapped host name 134351315Seric ** FALSE otherwise. 134416911Seric ** 134516911Seric ** Side Effects: 134660089Seric ** Looks up the host specified in name. If it is not 134716911Seric ** the canonical name for that host, replace it with 134816911Seric ** the canonical name. If the name is unknown, or it 134916911Seric ** is already the canonical name, leave it unchanged. 135016911Seric */ 135110758Seric 135216911Seric /*ARGSUSED*/ 135353751Seric char * 135460089Seric host_map_lookup(map, name, avp, statp) 135556823Seric MAP *map; 135660089Seric char *name; 135753751Seric char **avp; 135859084Seric char *statp; 135916911Seric { 136059084Seric register struct hostent *hp; 136159084Seric 136260089Seric hp = gethostbyname(name); 136359084Seric if (hp != NULL) 136459084Seric return hp->h_name; 136559084Seric *statp = EX_NOHOST; 136653751Seric return NULL; 136716911Seric } 136816911Seric 136956795Seric #endif /* DAEMON */ 1370