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*66761Seric static char sccsid[] = "@(#)daemon.c 8.40 (Berkeley) 04/12/94 (with daemon mode)"; 1533780Sbostic #else 16*66761Seric static char sccsid[] = "@(#)daemon.c 8.40 (Berkeley) 04/12/94 (without daemon mode)"; 1733780Sbostic #endif 1833780Sbostic #endif /* not lint */ 194535Seric 2033780Sbostic #ifdef DAEMON 2133780Sbostic 2223120Seric # include <netdb.h> 2364338Seric # include <arpa/inet.h> 245978Seric 2566334Seric #if NAMED_BIND 2659042Seric # include <arpa/nameser.h> 2759042Seric # include <resolv.h> 2859042Seric #endif 2959042Seric 304535Seric /* 314535Seric ** DAEMON.C -- routines to use when running as a daemon. 327556Seric ** 337556Seric ** This entire file is highly dependent on the 4.2 BSD 347556Seric ** interprocess communication primitives. No attempt has 357556Seric ** been made to make this file portable to Version 7, 367556Seric ** Version 6, MPX files, etc. If you should try such a 377556Seric ** thing yourself, I recommend chucking the entire file 387556Seric ** and starting from scratch. Basic semantics are: 397556Seric ** 407556Seric ** getrequests() 417556Seric ** Opens a port and initiates a connection. 427556Seric ** Returns in a child. Must set InChannel and 437556Seric ** OutChannel appropriately. 4410206Seric ** clrdaemon() 4510206Seric ** Close any open files associated with getting 4610206Seric ** the connection; this is used when running the queue, 4710206Seric ** etc., to avoid having extra file descriptors during 4810206Seric ** the queue run and to avoid confusing the network 4910206Seric ** code (if it cares). 5052106Seric ** makeconnection(host, port, outfile, infile, usesecureport) 517556Seric ** Make a connection to the named host on the given 527556Seric ** port. Set *outfile and *infile to the files 537556Seric ** appropriate for communication. Returns zero on 547556Seric ** success, else an exit status describing the 557556Seric ** error. 5660089Seric ** host_map_lookup(map, hbuf, avp, pstat) 5756823Seric ** Convert the entry in hbuf into a canonical form. 584535Seric */ 594535Seric /* 604535Seric ** GETREQUESTS -- open mail IPC port and get requests. 614535Seric ** 624535Seric ** Parameters: 634535Seric ** none. 644535Seric ** 654535Seric ** Returns: 664535Seric ** none. 674535Seric ** 684535Seric ** Side Effects: 694535Seric ** Waits until some interesting activity occurs. When 704535Seric ** it does, a child is created to process it, and the 714535Seric ** parent waits for completion. Return from this 729886Seric ** routine is always in the child. The file pointers 739886Seric ** "InChannel" and "OutChannel" should be set to point 749886Seric ** to the communication channel. 754535Seric */ 764535Seric 7758849Seric int DaemonSocket = -1; /* fd describing socket */ 7858849Seric SOCKADDR DaemonAddr; /* socket for incoming */ 7959783Seric int ListenQueueSize = 10; /* size of listen queue */ 8064381Seric int TcpRcvBufferSize = 0; /* size of TCP receive buffer */ 8164381Seric int TcpSndBufferSize = 0; /* size of TCP send buffer */ 8216144Seric 834535Seric getrequests() 844535Seric { 859610Seric int t; 8625027Seric int on = 1; 8753751Seric bool refusingconnections = TRUE; 8858419Seric FILE *pidf; 8964828Seric int socksize; 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 { 10265169Seric register struct servent *sp; 10365169Seric 10458849Seric sp = getservbyname("smtp", "tcp"); 10558849Seric if (sp == NULL) 10658849Seric { 10758909Seric syserr("554 service \"smtp\" unknown"); 10865169Seric DaemonAddr.sin.sin_port = htons(25); 10958849Seric } 11065169Seric else 11165169Seric DaemonAddr.sin.sin_port = sp->s_port; 1129610Seric } 1139610Seric 1149610Seric /* 1159610Seric ** Try to actually open the connection. 1169610Seric */ 1179610Seric 1189610Seric if (tTd(15, 1)) 11958849Seric printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); 1209610Seric 1219610Seric /* get a socket for the SMTP connection */ 12259041Seric DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0); 12310206Seric if (DaemonSocket < 0) 1249610Seric { 1259610Seric /* probably another daemon already */ 1269610Seric syserr("getrequests: can't create socket"); 1279610Seric severe: 1289610Seric # ifdef LOG 1299610Seric if (LogLevel > 0) 13057663Seric syslog(LOG_ALERT, "problem creating SMTP socket"); 13156795Seric # endif /* LOG */ 1329610Seric finis(); 1339610Seric } 13410347Seric 13510347Seric /* turn on network debugging? */ 13656328Seric if (tTd(15, 101)) 13724945Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 13810347Seric 13925027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 14025027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 14125027Seric 14264391Seric #ifdef SO_RCVBUF 14364391Seric if (TcpRcvBufferSize > 0) 14464391Seric { 14564391Seric if (setsockopt(DaemonSocket, SOL_SOCKET, SO_RCVBUF, 14664561Seric (char *) &TcpRcvBufferSize, 14764391Seric sizeof(TcpRcvBufferSize)) < 0) 14864391Seric syserr("getrequests: setsockopt(SO_RCVBUF)"); 14964391Seric } 15064391Seric #endif 15164391Seric 15259041Seric switch (DaemonAddr.sa.sa_family) 1539610Seric { 15459041Seric # ifdef NETINET 15559041Seric case AF_INET: 15664828Seric socksize = sizeof DaemonAddr.sin; 15759041Seric break; 15859041Seric # endif 15959041Seric 16059041Seric # ifdef NETISO 16159041Seric case AF_ISO: 16264828Seric socksize = sizeof DaemonAddr.siso; 16359041Seric break; 16459041Seric # endif 16559041Seric 16659041Seric default: 16764828Seric socksize = sizeof DaemonAddr; 16859041Seric break; 16959041Seric } 17059041Seric 17164828Seric if (bind(DaemonSocket, &DaemonAddr.sa, socksize) < 0) 17259041Seric { 1739610Seric syserr("getrequests: cannot bind"); 17410206Seric (void) close(DaemonSocket); 1759610Seric goto severe; 1769610Seric } 1779610Seric 17864035Seric (void) setsignal(SIGCHLD, reapchild); 17924945Seric 18058419Seric /* write the pid to the log file for posterity */ 18158419Seric pidf = fopen(PidFile, "w"); 18258419Seric if (pidf != NULL) 18358419Seric { 18463863Seric extern char *CommandLineArgs; 18563863Seric 18663863Seric /* write the process id on line 1 */ 18758419Seric fprintf(pidf, "%d\n", getpid()); 18863863Seric 18963863Seric /* line 2 contains all command line flags */ 19063863Seric fprintf(pidf, "%s\n", CommandLineArgs); 19163863Seric 19263863Seric /* flush and close */ 19358419Seric fclose(pidf); 19458419Seric } 19558419Seric 19658419Seric 1979610Seric if (tTd(15, 1)) 19810206Seric printf("getrequests: %d\n", DaemonSocket); 1999610Seric 2004631Seric for (;;) 2014631Seric { 20214875Seric register int pid; 20311147Seric auto int lotherend; 20453751Seric extern bool refuseconnections(); 20511147Seric 20614875Seric /* see if we are rejecting connections */ 20753751Seric CurrentLA = getla(); 20853751Seric if (refuseconnections()) 20936584Sbostic { 21053751Seric if (!refusingconnections) 21153751Seric { 21253751Seric /* don't queue so peer will fail quickly */ 21353751Seric (void) listen(DaemonSocket, 0); 21453751Seric refusingconnections = TRUE; 21553751Seric } 21657385Seric setproctitle("rejecting connections: load average: %d", 21757385Seric CurrentLA); 21814875Seric sleep(5); 21953751Seric continue; 22036584Sbostic } 22114875Seric 22253751Seric if (refusingconnections) 22353751Seric { 22453751Seric /* start listening again */ 22559783Seric if (listen(DaemonSocket, ListenQueueSize) < 0) 22653751Seric { 22753751Seric syserr("getrequests: cannot listen"); 22853751Seric (void) close(DaemonSocket); 22953751Seric goto severe; 23053751Seric } 23153751Seric setproctitle("accepting connections"); 23253751Seric refusingconnections = FALSE; 23353751Seric } 23453751Seric 2359610Seric /* wait for a connection */ 2369610Seric do 2379610Seric { 2389610Seric errno = 0; 23964828Seric lotherend = socksize; 24046928Sbostic t = accept(DaemonSocket, 24146928Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 2429610Seric } while (t < 0 && errno == EINTR); 2439610Seric if (t < 0) 2445978Seric { 2459610Seric syserr("getrequests: accept"); 2469610Seric sleep(5); 2479610Seric continue; 2485978Seric } 2494631Seric 2505978Seric /* 2515978Seric ** Create a subprocess to process the mail. 2525978Seric */ 2535978Seric 2547677Seric if (tTd(15, 2)) 2559610Seric printf("getrequests: forking (fd = %d)\n", t); 2565978Seric 2574636Seric pid = fork(); 2584636Seric if (pid < 0) 2594631Seric { 2604636Seric syserr("daemon: cannot fork"); 2614636Seric sleep(10); 2629610Seric (void) close(t); 2634636Seric continue; 2644631Seric } 2654631Seric 2664636Seric if (pid == 0) 2674631Seric { 26864086Seric char *p; 26958951Seric extern char *hostnamebyanyaddr(); 27011147Seric 2714636Seric /* 2724636Seric ** CHILD -- return to caller. 27311147Seric ** Collect verified idea of sending host. 2744636Seric ** Verify calling user id if possible here. 2754636Seric */ 2764631Seric 27764035Seric (void) setsignal(SIGCHLD, SIG_DFL); 27866017Seric DisConnected = FALSE; 27924950Seric 28066032Seric setproctitle("startup with %s", 28166032Seric anynet_ntoa(&RealHostAddr)); 28266032Seric 28311147Seric /* determine host name */ 28464086Seric p = hostnamebyanyaddr(&RealHostAddr); 28564086Seric RealHostName = newstr(p); 28666032Seric setproctitle("startup with %s", p); 28758778Seric 28855173Seric #ifdef LOG 28963842Seric if (LogLevel > 11) 29055173Seric { 29155173Seric /* log connection information */ 29255173Seric syslog(LOG_INFO, "connect from %s (%s)", 29358951Seric RealHostName, anynet_ntoa(&RealHostAddr)); 29455173Seric } 29555173Seric #endif 29655173Seric 29759254Seric (void) close(DaemonSocket); 29864724Seric if ((InChannel = fdopen(t, "r")) == NULL || 29964724Seric (t = dup(t)) < 0 || 30064724Seric (OutChannel = fdopen(t, "w")) == NULL) 30164724Seric { 30264724Seric syserr("cannot open SMTP server channel, fd=%d", t); 30364724Seric exit(0); 30464724Seric } 30559254Seric 30616884Seric /* should we check for illegal connection here? XXX */ 30759156Seric #ifdef XLA 30859156Seric if (!xla_host_ok(RealHostName)) 30959156Seric { 31059254Seric message("421 Too many SMTP sessions for this host"); 31159156Seric exit(0); 31259156Seric } 31359156Seric #endif 31416884Seric 3157677Seric if (tTd(15, 2)) 3165978Seric printf("getreq: returning\n"); 3174636Seric return; 3184631Seric } 3194631Seric 3207117Seric /* close the port so that others will hang (for a while) */ 3219610Seric (void) close(t); 3224631Seric } 3239886Seric /*NOTREACHED*/ 3244631Seric } 3255978Seric /* 32610206Seric ** CLRDAEMON -- reset the daemon connection 32710206Seric ** 32810206Seric ** Parameters: 32910206Seric ** none. 33010206Seric ** 33110206Seric ** Returns: 33210206Seric ** none. 33310206Seric ** 33410206Seric ** Side Effects: 33510206Seric ** releases any resources used by the passive daemon. 33610206Seric */ 33710206Seric 33810206Seric clrdaemon() 33910206Seric { 34010206Seric if (DaemonSocket >= 0) 34110206Seric (void) close(DaemonSocket); 34210206Seric DaemonSocket = -1; 34310206Seric } 34410206Seric /* 34558849Seric ** SETDAEMONOPTIONS -- set options for running the daemon 34658849Seric ** 34758849Seric ** Parameters: 34858849Seric ** p -- the options line. 34958849Seric ** 35058849Seric ** Returns: 35158849Seric ** none. 35258849Seric */ 35358849Seric 35458849Seric setdaemonoptions(p) 35558849Seric register char *p; 35658849Seric { 35758873Seric if (DaemonAddr.sa.sa_family == AF_UNSPEC) 35858873Seric DaemonAddr.sa.sa_family = AF_INET; 35958873Seric 36058849Seric while (p != NULL) 36158849Seric { 36258849Seric register char *f; 36358849Seric register char *v; 36458849Seric 36558849Seric while (isascii(*p) && isspace(*p)) 36658849Seric p++; 36758849Seric if (*p == '\0') 36858849Seric break; 36958849Seric f = p; 37058849Seric p = strchr(p, ','); 37158849Seric if (p != NULL) 37258849Seric *p++ = '\0'; 37358849Seric v = strchr(f, '='); 37458849Seric if (v == NULL) 37558849Seric continue; 37658849Seric while (isascii(*++v) && isspace(*v)) 37758849Seric continue; 37858849Seric 37958849Seric switch (*f) 38058849Seric { 38158873Seric case 'F': /* address family */ 38258849Seric if (isascii(*v) && isdigit(*v)) 38358873Seric DaemonAddr.sa.sa_family = atoi(v); 38458873Seric #ifdef NETINET 38558873Seric else if (strcasecmp(v, "inet") == 0) 38658873Seric DaemonAddr.sa.sa_family = AF_INET; 38758873Seric #endif 38858873Seric #ifdef NETISO 38958873Seric else if (strcasecmp(v, "iso") == 0) 39058873Seric DaemonAddr.sa.sa_family = AF_ISO; 39158873Seric #endif 39258873Seric #ifdef NETNS 39358873Seric else if (strcasecmp(v, "ns") == 0) 39458873Seric DaemonAddr.sa.sa_family = AF_NS; 39558873Seric #endif 39658873Seric #ifdef NETX25 39758873Seric else if (strcasecmp(v, "x.25") == 0) 39858873Seric DaemonAddr.sa.sa_family = AF_CCITT; 39958873Seric #endif 40058849Seric else 40158873Seric syserr("554 Unknown address family %s in Family=option", v); 40258873Seric break; 40358873Seric 40458873Seric case 'A': /* address */ 40558873Seric switch (DaemonAddr.sa.sa_family) 40658849Seric { 40758873Seric #ifdef NETINET 40858873Seric case AF_INET: 40958873Seric if (isascii(*v) && isdigit(*v)) 41058873Seric DaemonAddr.sin.sin_addr.s_addr = inet_network(v); 41158873Seric else 41258873Seric { 41358873Seric register struct netent *np; 41458849Seric 41558873Seric np = getnetbyname(v); 41658873Seric if (np == NULL) 41758873Seric syserr("554 network \"%s\" unknown", v); 41858873Seric else 41958873Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 42058873Seric } 42158873Seric break; 42258873Seric #endif 42358873Seric 42458873Seric default: 42558873Seric syserr("554 Address= option unsupported for family %d", 42658873Seric DaemonAddr.sa.sa_family); 42758873Seric break; 42858849Seric } 42958849Seric break; 43058849Seric 43158873Seric case 'P': /* port */ 43258873Seric switch (DaemonAddr.sa.sa_family) 43358849Seric { 43458873Seric short port; 43558849Seric 43658873Seric #ifdef NETINET 43758873Seric case AF_INET: 43858873Seric if (isascii(*v) && isdigit(*v)) 43964366Seric DaemonAddr.sin.sin_port = htons(atoi(v)); 44058849Seric else 44158873Seric { 44258873Seric register struct servent *sp; 44358873Seric 44458873Seric sp = getservbyname(v, "tcp"); 44558873Seric if (sp == NULL) 44658909Seric syserr("554 service \"%s\" unknown", v); 44758873Seric else 44858873Seric DaemonAddr.sin.sin_port = sp->s_port; 44958873Seric } 45058873Seric break; 45158873Seric #endif 45258873Seric 45358873Seric #ifdef NETISO 45458873Seric case AF_ISO: 45558873Seric /* assume two byte transport selector */ 45658873Seric if (isascii(*v) && isdigit(*v)) 45764366Seric port = htons(atoi(v)); 45858873Seric else 45958873Seric { 46058873Seric register struct servent *sp; 46158873Seric 46258873Seric sp = getservbyname(v, "tcp"); 46358873Seric if (sp == NULL) 46458909Seric syserr("554 service \"%s\" unknown", v); 46558873Seric else 46658873Seric port = sp->s_port; 46758873Seric } 46858873Seric bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 46958873Seric break; 47058873Seric #endif 47158873Seric 47258873Seric default: 47358873Seric syserr("554 Port= option unsupported for family %d", 47458873Seric DaemonAddr.sa.sa_family); 47558873Seric break; 47658849Seric } 47758849Seric break; 47859783Seric 47959783Seric case 'L': /* listen queue size */ 48059783Seric ListenQueueSize = atoi(v); 48159783Seric break; 48264381Seric 48364381Seric case 'S': /* send buffer size */ 48464381Seric TcpSndBufferSize = atoi(v); 48564381Seric break; 48664381Seric 48764381Seric case 'R': /* receive buffer size */ 48864381Seric TcpRcvBufferSize = atoi(v); 48964381Seric break; 49058849Seric } 49158849Seric } 49258849Seric } 49358849Seric /* 4946039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 4956039Seric ** 4966039Seric ** Parameters: 4976039Seric ** host -- the name of the host. 4986633Seric ** port -- the port number to connect to. 49953739Seric ** mci -- a pointer to the mail connection information 50053739Seric ** structure to be filled in. 50152106Seric ** usesecureport -- if set, use a low numbered (reserved) 50252106Seric ** port to provide some rudimentary authentication. 5036039Seric ** 5046039Seric ** Returns: 5056039Seric ** An exit code telling whether the connection could be 5066039Seric ** made and if not why not. 5076039Seric ** 5086039Seric ** Side Effects: 5096039Seric ** none. 5106039Seric */ 5115978Seric 51258755Seric SOCKADDR CurHostAddr; /* address of current host */ 51358305Seric 51454967Seric int 51553739Seric makeconnection(host, port, mci, usesecureport) 5166039Seric char *host; 5177286Seric u_short port; 51854967Seric register MCI *mci; 51952106Seric bool usesecureport; 5206039Seric { 52129430Sbloom register int i, s; 52229430Sbloom register struct hostent *hp = (struct hostent *)NULL; 52358755Seric SOCKADDR addr; 52452106Seric int sav_errno; 52558755Seric int addrlen; 52666334Seric #if NAMED_BIND 52735651Seric extern int h_errno; 52835651Seric #endif 5296039Seric 5306039Seric /* 5316039Seric ** Set up the address for the mailer. 5329308Seric ** Accept "[a.b.c.d]" syntax for host name. 5336039Seric */ 5346039Seric 53566334Seric #if NAMED_BIND 53625475Smiriam h_errno = 0; 53735651Seric #endif 53825475Smiriam errno = 0; 53958864Seric bzero(&CurHostAddr, sizeof CurHostAddr); 54064334Seric SmtpPhase = mci->mci_phase = "initial connection"; 54158906Seric CurHostName = host; 54225475Smiriam 5439308Seric if (host[0] == '[') 5449308Seric { 54511147Seric long hid; 54656795Seric register char *p = strchr(host, ']'); 5479308Seric 54811147Seric if (p != NULL) 5499308Seric { 55011147Seric *p = '\0'; 55159884Seric #ifdef NETINET 55211147Seric hid = inet_addr(&host[1]); 55358360Seric if (hid == -1) 55459884Seric #endif 55558360Seric { 55658360Seric /* try it as a host name (avoid MX lookup) */ 55758360Seric hp = gethostbyname(&host[1]); 55866349Seric if (hp == NULL && p[-1] == '.') 55966349Seric { 56066349Seric p[-1] = '\0'; 56166349Seric hp = gethostbyname(&host[1]); 56266349Seric p[-1] = '.'; 56366349Seric } 56458360Seric *p = ']'; 56558360Seric goto gothostent; 56658360Seric } 56711147Seric *p = ']'; 5689308Seric } 56958360Seric if (p == NULL) 5709308Seric { 57158151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 5729308Seric return (EX_NOHOST); 5739308Seric } 57459884Seric #ifdef NETINET 57559884Seric addr.sin.sin_family = AF_INET; /*XXX*/ 57658778Seric addr.sin.sin_addr.s_addr = hid; 57759884Seric #endif 5789308Seric } 5799610Seric else 5809610Seric { 58166349Seric register char *p = &host[strlen(host) - 1]; 58266349Seric 58329430Sbloom hp = gethostbyname(host); 58466349Seric if (hp == NULL && *p == '.') 58566349Seric { 58666349Seric *p = '\0'; 58766349Seric hp = gethostbyname(host); 58866349Seric *p = '.'; 58966349Seric } 59058360Seric gothostent: 59125475Smiriam if (hp == NULL) 59224945Seric { 59366334Seric #if NAMED_BIND 59425475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 59525475Smiriam return (EX_TEMPFAIL); 59625657Seric 59735651Seric /* if name server is specified, assume temp fail */ 59835651Seric if (errno == ECONNREFUSED && UseNameServer) 59935651Seric return (EX_TEMPFAIL); 60035651Seric #endif 60125475Smiriam return (EX_NOHOST); 60224945Seric } 60358778Seric addr.sa.sa_family = hp->h_addrtype; 60458778Seric switch (hp->h_addrtype) 60558778Seric { 60658778Seric #ifdef NETINET 60758778Seric case AF_INET: 60858755Seric bcopy(hp->h_addr, 60958778Seric &addr.sin.sin_addr, 61064943Seric sizeof addr.sin.sin_addr); 61158778Seric break; 61258778Seric #endif 61358778Seric 61458778Seric default: 61558755Seric bcopy(hp->h_addr, 61658778Seric addr.sa.sa_data, 61758755Seric hp->h_length); 61858778Seric break; 61958778Seric } 62029430Sbloom i = 1; 6219610Seric } 6229610Seric 6239610Seric /* 6249610Seric ** Determine the port number. 6259610Seric */ 6269610Seric 62710011Seric if (port != 0) 62858755Seric port = htons(port); 62910011Seric else 6309610Seric { 6319610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 6329610Seric 6339610Seric if (sp == NULL) 6349610Seric { 63558909Seric syserr("554 makeconnection: service \"smtp\" unknown"); 63665169Seric port = htons(25); 6379610Seric } 63865169Seric else 63965169Seric port = sp->s_port; 6409610Seric } 6416039Seric 64258778Seric switch (addr.sa.sa_family) 64358755Seric { 64459884Seric #ifdef NETINET 64558755Seric case AF_INET: 64658778Seric addr.sin.sin_port = port; 64758755Seric addrlen = sizeof (struct sockaddr_in); 64858755Seric break; 64959884Seric #endif 65058755Seric 65158755Seric #ifdef NETISO 65258755Seric case AF_ISO: 65358755Seric /* assume two byte transport selector */ 65458755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 65558755Seric addrlen = sizeof (struct sockaddr_iso); 65658755Seric break; 65758755Seric #endif 65858755Seric 65958755Seric default: 66058778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 66158755Seric return (EX_NOHOST); 66258755Seric } 66358755Seric 6646039Seric /* 6656039Seric ** Try to actually open the connection. 6666039Seric */ 6676039Seric 66859156Seric #ifdef XLA 66959156Seric /* if too many connections, don't bother trying */ 67059156Seric if (!xla_noqueue_ok(host)) 67159156Seric return EX_TEMPFAIL; 67259156Seric #endif 67359156Seric 67457736Seric for (;;) 67552106Seric { 67657736Seric if (tTd(16, 1)) 67758755Seric printf("makeconnection (%s [%s])\n", 67858755Seric host, anynet_ntoa(&addr)); 67952106Seric 68058588Seric /* save for logging */ 68158588Seric CurHostAddr = addr; 68258588Seric 68357736Seric if (usesecureport) 68457736Seric { 68557736Seric int rport = IPPORT_RESERVED - 1; 6866039Seric 68757736Seric s = rresvport(&rport); 68857736Seric } 68957736Seric else 69057736Seric { 69157736Seric s = socket(AF_INET, SOCK_STREAM, 0); 69257736Seric } 69357736Seric if (s < 0) 69457736Seric { 69557736Seric sav_errno = errno; 69657736Seric syserr("makeconnection: no socket"); 69757736Seric goto failure; 69857736Seric } 69910347Seric 70064381Seric #ifdef SO_SNDBUF 70164381Seric if (TcpSndBufferSize > 0) 70264381Seric { 70364381Seric if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 70464561Seric (char *) &TcpSndBufferSize, 70564381Seric sizeof(TcpSndBufferSize)) < 0) 70664381Seric syserr("makeconnection: setsockopt(SO_SNDBUF)"); 70764381Seric } 70864381Seric #endif 70964381Seric 71057736Seric if (tTd(16, 1)) 71157736Seric printf("makeconnection: fd=%d\n", s); 71257736Seric 71357736Seric /* turn on network debugging? */ 71457736Seric if (tTd(16, 101)) 71557736Seric { 71657736Seric int on = 1; 71757736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 71857736Seric (char *)&on, sizeof on); 71957736Seric } 72057736Seric if (CurEnv->e_xfp != NULL) 72157736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 72257736Seric errno = 0; /* for debugging */ 72358755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 72457736Seric break; 72557736Seric 72657736Seric /* couldn't connect.... figure out why */ 72727744Sbloom sav_errno = errno; 72827744Sbloom (void) close(s); 72929430Sbloom if (hp && hp->h_addr_list[i]) 73029430Sbloom { 73157736Seric if (tTd(16, 1)) 73258755Seric printf("Connect failed (%s); trying new address....\n", 73358755Seric errstring(sav_errno)); 73458778Seric switch (addr.sa.sa_family) 73558778Seric { 73658778Seric #ifdef NETINET 73758778Seric case AF_INET: 73858755Seric bcopy(hp->h_addr_list[i++], 73958778Seric &addr.sin.sin_addr, 74064943Seric sizeof addr.sin.sin_addr); 74158778Seric break; 74258778Seric #endif 74358778Seric 74458778Seric default: 74558755Seric bcopy(hp->h_addr_list[i++], 74658778Seric addr.sa.sa_data, 74752106Seric hp->h_length); 74858778Seric break; 74958778Seric } 75057736Seric continue; 75129430Sbloom } 75229430Sbloom 7536039Seric /* failure, decide if temporary or not */ 7546039Seric failure: 75559254Seric #ifdef XLA 75659254Seric xla_host_end(host); 75759254Seric #endif 75858542Seric if (transienterror(sav_errno)) 75958542Seric return EX_TEMPFAIL; 76058542Seric else 76158542Seric { 76258542Seric message("%s", errstring(sav_errno)); 76358542Seric return (EX_UNAVAILABLE); 7646039Seric } 7656039Seric } 7666039Seric 7676039Seric /* connection ok, put it into canonical form */ 76864724Seric if ((mci->mci_out = fdopen(s, "w")) == NULL || 76964724Seric (s = dup(s)) < 0 || 77064725Seric (mci->mci_in = fdopen(s, "r")) == NULL) 77164724Seric { 77264724Seric syserr("cannot open SMTP client channel, fd=%d", s); 77364724Seric return EX_TEMPFAIL; 77464724Seric } 7756039Seric 77610098Seric return (EX_OK); 7776039Seric } 77810758Seric /* 77910758Seric ** MYHOSTNAME -- return the name of this host. 78010758Seric ** 78110758Seric ** Parameters: 78210758Seric ** hostbuf -- a place to return the name of this host. 78312313Seric ** size -- the size of hostbuf. 78410758Seric ** 78510758Seric ** Returns: 78610758Seric ** A list of aliases for this host. 78710758Seric ** 78810758Seric ** Side Effects: 78964338Seric ** Adds numeric codes to $=w. 79010758Seric */ 7916039Seric 79210758Seric char ** 79312313Seric myhostname(hostbuf, size) 79410758Seric char hostbuf[]; 79512313Seric int size; 79610758Seric { 79758110Seric register struct hostent *hp; 79810758Seric extern struct hostent *gethostbyname(); 79910758Seric 80023120Seric if (gethostname(hostbuf, size) < 0) 80123120Seric { 80223120Seric (void) strcpy(hostbuf, "localhost"); 80323120Seric } 80411147Seric hp = gethostbyname(hostbuf); 80511147Seric if (hp != NULL) 80616877Seric { 80758110Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 80858110Seric hostbuf[size - 1] = '\0'; 80958110Seric 81058110Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 81158110Seric { 81258110Seric register int i; 81358110Seric 81464338Seric for (i = 0; hp->h_addr_list[i] != NULL; i++) 81558110Seric { 81664338Seric char ipbuf[100]; 81764338Seric 81864338Seric sprintf(ipbuf, "[%s]", 81964338Seric inet_ntoa(*((struct in_addr *) hp->h_addr_list[i]))); 82064338Seric setclass('w', ipbuf); 82158110Seric } 82258110Seric } 82358110Seric 82411147Seric return (hp->h_aliases); 82516877Seric } 82610758Seric else 82710758Seric return (NULL); 82810758Seric } 82951315Seric /* 83058951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 83158308Seric ** 83258951Seric ** Uses RFC1413 protocol to try to get info from the other end. 83358951Seric ** 83458308Seric ** Parameters: 83558308Seric ** fd -- the descriptor 83658308Seric ** 83758308Seric ** Returns: 83858951Seric ** The user@host information associated with this descriptor. 83958308Seric */ 84058308Seric 84164927Seric #if IDENTPROTO 84258951Seric 84358951Seric static jmp_buf CtxAuthTimeout; 84458951Seric 84558951Seric static 84658951Seric authtimeout() 84758951Seric { 84858951Seric longjmp(CtxAuthTimeout, 1); 84958951Seric } 85058951Seric 85158951Seric #endif 85258951Seric 85358308Seric char * 85458951Seric getauthinfo(fd) 85558308Seric int fd; 85658308Seric { 85758951Seric int falen; 85859104Seric register char *p; 85964927Seric #if IDENTPROTO 86058951Seric SOCKADDR la; 86158951Seric int lalen; 86258951Seric register struct servent *sp; 86358951Seric int s; 86458951Seric int i; 86558951Seric EVENT *ev; 86658951Seric #endif 86758951Seric static char hbuf[MAXNAME * 2 + 2]; 86858951Seric extern char *hostnamebyanyaddr(); 86958951Seric extern char RealUserName[]; /* main.c */ 87058308Seric 871*66761Seric falen = sizeof RealHostAddr; 872*66761Seric if (getpeername(fd, &RealHostAddr.sa, &falen) < 0 || falen <= 0 || 873*66761Seric RealHostAddr.sa.sa_family == 0) 87458951Seric { 87558951Seric (void) sprintf(hbuf, "%s@localhost", RealUserName); 87658957Seric if (tTd(9, 1)) 87758951Seric printf("getauthinfo: %s\n", hbuf); 87858951Seric return hbuf; 87958951Seric } 88058951Seric 881*66761Seric if (RealHostName == NULL) 882*66761Seric { 883*66761Seric /* translate that to a host name */ 884*66761Seric RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 885*66761Seric } 886*66761Seric 88764927Seric #if IDENTPROTO 88865831Seric if (TimeOuts.to_ident == 0) 88965831Seric goto noident; 89065831Seric 89158951Seric lalen = sizeof la; 892*66761Seric if (RealHostAddr.sa.sa_family != AF_INET || 89358951Seric getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || 89458951Seric la.sa.sa_family != AF_INET) 89558951Seric { 89658951Seric /* no ident info */ 89758951Seric goto noident; 89858951Seric } 89958951Seric 90058951Seric /* create ident query */ 90160489Seric (void) sprintf(hbuf, "%d,%d\r\n", 902*66761Seric ntohs(RealHostAddr.sin.sin_port), ntohs(la.sin.sin_port)); 90358951Seric 90458951Seric /* create local address */ 90564747Seric la.sin.sin_port = 0; 90658951Seric 90758951Seric /* create foreign address */ 90858951Seric sp = getservbyname("auth", "tcp"); 90958951Seric if (sp != NULL) 910*66761Seric RealHostAddr.sin.sin_port = sp->s_port; 91158308Seric else 912*66761Seric RealHostAddr.sin.sin_port = htons(113); 91358951Seric 91458951Seric s = -1; 91558951Seric if (setjmp(CtxAuthTimeout) != 0) 91658951Seric { 91758951Seric if (s >= 0) 91858951Seric (void) close(s); 91958951Seric goto noident; 92058951Seric } 92158951Seric 92258951Seric /* put a timeout around the whole thing */ 92364255Seric ev = setevent(TimeOuts.to_ident, authtimeout, 0); 92458951Seric 92564747Seric /* connect to foreign IDENT server using same address as SMTP socket */ 92658951Seric s = socket(AF_INET, SOCK_STREAM, 0); 92758951Seric if (s < 0) 92858951Seric { 92958951Seric clrevent(ev); 93058951Seric goto noident; 93158951Seric } 93264747Seric if (bind(s, &la.sa, sizeof la.sin) < 0 || 933*66761Seric connect(s, &RealHostAddr.sa, sizeof RealHostAddr.sin) < 0) 93458951Seric { 93566011Seric goto closeident; 93658951Seric } 93758951Seric 93858957Seric if (tTd(9, 10)) 93958951Seric printf("getauthinfo: sent %s", hbuf); 94058951Seric 94158951Seric /* send query */ 94258951Seric if (write(s, hbuf, strlen(hbuf)) < 0) 94358951Seric goto closeident; 94458951Seric 94558951Seric /* get result */ 94658951Seric i = read(s, hbuf, sizeof hbuf); 94758951Seric (void) close(s); 94858951Seric clrevent(ev); 94958951Seric if (i <= 0) 95058951Seric goto noident; 95158951Seric if (hbuf[--i] == '\n' && hbuf[--i] == '\r') 95258951Seric i--; 95358951Seric hbuf[++i] = '\0'; 95458951Seric 95558957Seric if (tTd(9, 3)) 95658951Seric printf("getauthinfo: got %s\n", hbuf); 95758951Seric 95858951Seric /* parse result */ 95958951Seric p = strchr(hbuf, ':'); 96058951Seric if (p == NULL) 96158951Seric { 96258951Seric /* malformed response */ 96358951Seric goto noident; 96458951Seric } 96558951Seric while (isascii(*++p) && isspace(*p)) 96658951Seric continue; 96758951Seric if (strncasecmp(p, "userid", 6) != 0) 96858951Seric { 96958951Seric /* presumably an error string */ 97058951Seric goto noident; 97158951Seric } 97258951Seric p += 6; 97358951Seric while (isascii(*p) && isspace(*p)) 97458951Seric p++; 97558951Seric if (*p++ != ':') 97658951Seric { 97758951Seric /* either useridxx or malformed response */ 97858951Seric goto noident; 97958951Seric } 98058951Seric 98158951Seric /* p now points to the OSTYPE field */ 98258951Seric p = strchr(p, ':'); 98358951Seric if (p == NULL) 98458951Seric { 98558951Seric /* malformed response */ 98658951Seric goto noident; 98758951Seric } 98858951Seric 98958957Seric /* 1413 says don't do this -- but it's broken otherwise */ 99058957Seric while (isascii(*++p) && isspace(*p)) 99158957Seric continue; 99258957Seric 99358951Seric /* p now points to the authenticated name */ 99466003Seric (void) sprintf(hbuf, "%s@%s", 99566003Seric p, RealHostName == NULL ? "localhost" : RealHostName); 99658957Seric goto finish; 99758957Seric 99866011Seric closeident: 99966011Seric (void) close(s); 100066011Seric clrevent(ev); 100166011Seric 100258957Seric #endif /* IDENTPROTO */ 100358957Seric 100458957Seric noident: 100566003Seric if (RealHostName == NULL) 100666003Seric { 100766003Seric if (tTd(9, 1)) 100866003Seric printf("getauthinfo: NULL\n"); 100966003Seric return NULL; 101066003Seric } 101158957Seric (void) strcpy(hbuf, RealHostName); 101258957Seric 101358957Seric finish: 101466003Seric if (RealHostName != NULL && RealHostName[0] != '[') 101558951Seric { 101658951Seric p = &hbuf[strlen(hbuf)]; 101758951Seric (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); 101858951Seric } 101958957Seric if (tTd(9, 1)) 102058951Seric printf("getauthinfo: %s\n", hbuf); 102158308Seric return hbuf; 102258308Seric } 102358308Seric /* 102460089Seric ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 102553751Seric ** 102653751Seric ** Parameters: 102756823Seric ** map -- a pointer to this map (unused). 102860089Seric ** name -- the (presumably unqualified) hostname. 102960257Seric ** av -- unused -- for compatibility with other mapping 103055019Seric ** functions. 103159084Seric ** statp -- an exit status (out parameter) -- set to 103259084Seric ** EX_TEMPFAIL if the name server is unavailable. 103353751Seric ** 103453751Seric ** Returns: 103553751Seric ** The mapping, if found. 103653751Seric ** NULL if no mapping found. 103753751Seric ** 103853751Seric ** Side Effects: 103953751Seric ** Looks up the host specified in hbuf. If it is not 104053751Seric ** the canonical name for that host, return the canonical 104153751Seric ** name. 104253751Seric */ 104351315Seric 104453751Seric char * 104560257Seric host_map_lookup(map, name, av, statp) 104656823Seric MAP *map; 104760089Seric char *name; 104860257Seric char **av; 104959084Seric int *statp; 105016911Seric { 105116911Seric register struct hostent *hp; 105233932Sbostic u_long in_addr; 105356823Seric char *cp; 105458110Seric int i; 105559671Seric register STAB *s; 105660257Seric char hbuf[MAXNAME]; 105759671Seric extern struct hostent *gethostbyaddr(); 105866334Seric #if NAMED_BIND 105959671Seric extern int h_errno; 106066029Seric #endif 106116911Seric 106225574Smiriam /* 106359671Seric ** See if we have already looked up this name. If so, just 106459671Seric ** return it. 106559671Seric */ 106653751Seric 106760089Seric s = stab(name, ST_NAMECANON, ST_ENTER); 106859671Seric if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 106959671Seric { 107059986Seric if (tTd(9, 1)) 107160089Seric printf("host_map_lookup(%s) => CACHE %s\n", 107260089Seric name, s->s_namecanon.nc_cname); 107359671Seric errno = s->s_namecanon.nc_errno; 107466334Seric #if NAMED_BIND 107559671Seric h_errno = s->s_namecanon.nc_herrno; 107666029Seric #endif 107759671Seric *statp = s->s_namecanon.nc_stat; 107864797Seric if (CurEnv->e_message == NULL && *statp == EX_TEMPFAIL) 107965199Seric { 108065199Seric sprintf(hbuf, "%s: Name server timeout", 108165199Seric shortenstring(name, 33)); 108265199Seric CurEnv->e_message = newstr(hbuf); 108365199Seric } 108459671Seric return s->s_namecanon.nc_cname; 108559671Seric } 108659671Seric 108759671Seric /* 108859671Seric ** If first character is a bracket, then it is an address 108959671Seric ** lookup. Address is copied into a temporary buffer to 109060089Seric ** strip the brackets and to preserve name if address is 109159671Seric ** unknown. 109259671Seric */ 109359671Seric 109460089Seric if (*name != '[') 109553751Seric { 109655019Seric extern bool getcanonname(); 109755019Seric 109858798Seric if (tTd(9, 1)) 109960089Seric printf("host_map_lookup(%s) => ", name); 110059671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 110160089Seric (void) strcpy(hbuf, name); 110263842Seric if (getcanonname(hbuf, sizeof hbuf - 1, TRUE)) 110358796Seric { 110458796Seric if (tTd(9, 1)) 110558796Seric printf("%s\n", hbuf); 110660257Seric cp = map_rewrite(map, hbuf, strlen(hbuf), av); 110760257Seric s->s_namecanon.nc_cname = newstr(cp); 110860257Seric return cp; 110958796Seric } 111053751Seric else 111158796Seric { 111259084Seric register struct hostent *hp; 111359084Seric 111466029Seric s->s_namecanon.nc_errno = errno; 111566334Seric #if NAMED_BIND 111666029Seric s->s_namecanon.nc_herrno = h_errno; 111758796Seric if (tTd(9, 1)) 111859084Seric printf("FAIL (%d)\n", h_errno); 111959084Seric switch (h_errno) 112059084Seric { 112159084Seric case TRY_AGAIN: 112259596Seric if (UseNameServer) 112359734Seric { 112465202Seric sprintf(hbuf, "%s: Name server timeout", 112565199Seric shortenstring(name, 33)); 112665202Seric message("%s", hbuf); 112759734Seric if (CurEnv->e_message == NULL) 112865202Seric CurEnv->e_message = newstr(hbuf); 112959734Seric } 113059084Seric *statp = EX_TEMPFAIL; 113159084Seric break; 113259084Seric 113359084Seric case HOST_NOT_FOUND: 113459084Seric *statp = EX_NOHOST; 113559084Seric break; 113659084Seric 113759084Seric case NO_RECOVERY: 113859084Seric *statp = EX_SOFTWARE; 113959084Seric break; 114059084Seric 114159084Seric default: 114259084Seric *statp = EX_UNAVAILABLE; 114359084Seric break; 114459084Seric } 114566029Seric #else 114666029Seric if (tTd(9, 1)) 114766029Seric printf("FAIL\n"); 114866029Seric *statp = EX_NOHOST; 114966029Seric #endif 115059671Seric s->s_namecanon.nc_stat = *statp; 115159084Seric if (*statp != EX_TEMPFAIL || UseNameServer) 115259084Seric return NULL; 115359084Seric 115459084Seric /* 115559084Seric ** Try to look it up in /etc/hosts 115659084Seric */ 115759084Seric 115860089Seric hp = gethostbyname(name); 115959084Seric if (hp == NULL) 116059084Seric { 116159084Seric /* no dice there either */ 116259671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 116359084Seric return NULL; 116459084Seric } 116559084Seric 116659671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 116760257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 116860257Seric s->s_namecanon.nc_cname = newstr(cp); 116960257Seric return cp; 117058796Seric } 117153751Seric } 117260089Seric if ((cp = strchr(name, ']')) == NULL) 117353751Seric return (NULL); 117440994Sbostic *cp = '\0'; 117560089Seric in_addr = inet_addr(&name[1]); 117658110Seric 117758110Seric /* nope -- ask the name server */ 117833932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 117959671Seric s->s_namecanon.nc_errno = errno; 118066334Seric #if NAMED_BIND 118159671Seric s->s_namecanon.nc_herrno = h_errno; 118266029Seric #endif 118359671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 118433932Sbostic if (hp == NULL) 118559671Seric { 118659671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 118753751Seric return (NULL); 118859671Seric } 118953751Seric 119058110Seric /* found a match -- copy out */ 119160257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 119259671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 119360257Seric s->s_namecanon.nc_cname = newstr(cp); 119460257Seric return cp; 119533932Sbostic } 119658755Seric /* 119758755Seric ** ANYNET_NTOA -- convert a network address to printable form. 119858755Seric ** 119958755Seric ** Parameters: 120058755Seric ** sap -- a pointer to a sockaddr structure. 120158755Seric ** 120258755Seric ** Returns: 120358755Seric ** A printable version of that sockaddr. 120458755Seric */ 120516911Seric 120658755Seric char * 120758755Seric anynet_ntoa(sap) 120858755Seric register SOCKADDR *sap; 120958755Seric { 121058755Seric register char *bp; 121158755Seric register char *ap; 121258755Seric int l; 121364734Seric static char buf[100]; 121458755Seric 121558798Seric /* check for null/zero family */ 121658798Seric if (sap == NULL) 121758798Seric return "NULLADDR"; 121858798Seric if (sap->sa.sa_family == 0) 121958798Seric return "0"; 122058798Seric 122164734Seric switch (sap->sa.sa_family) 122264734Seric { 122364734Seric #ifdef MAYBENEXTRELEASE /*** UNTESTED *** UNTESTED *** UNTESTED ***/ 122464821Seric #ifdef NETUNIX 122564734Seric case AF_UNIX: 122664758Seric if (sap->sunix.sun_path[0] != '\0') 122764758Seric sprintf(buf, "[UNIX: %.64s]", sap->sunix.sun_path); 122864734Seric else 122964734Seric sprintf(buf, "[UNIX: localhost]"); 123064734Seric return buf; 123164734Seric #endif 123264821Seric #endif 123364734Seric 123458778Seric #ifdef NETINET 123564734Seric case AF_INET: 123658755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 123758778Seric #endif 123858755Seric 123964734Seric default: 124064734Seric /* this case is only to ensure syntactic correctness */ 124164734Seric break; 124264734Seric } 124364734Seric 124458755Seric /* unknown family -- just dump bytes */ 124558778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 124658755Seric bp = &buf[strlen(buf)]; 124758778Seric ap = sap->sa.sa_data; 124858778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 124958755Seric { 125058755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 125158755Seric bp += 3; 125258755Seric } 125358755Seric *--bp = '\0'; 125458755Seric return buf; 125558755Seric } 125658951Seric /* 125758951Seric ** HOSTNAMEBYANYADDR -- return name of host based on address 125858951Seric ** 125958951Seric ** Parameters: 126058951Seric ** sap -- SOCKADDR pointer 126158951Seric ** 126258951Seric ** Returns: 126358951Seric ** text representation of host name. 126458951Seric ** 126558951Seric ** Side Effects: 126658951Seric ** none. 126758951Seric */ 126858755Seric 126958951Seric char * 127058951Seric hostnamebyanyaddr(sap) 127158951Seric register SOCKADDR *sap; 127258951Seric { 127358951Seric register struct hostent *hp; 127464734Seric int saveretry; 127558951Seric 127666334Seric #if NAMED_BIND 127759042Seric /* shorten name server timeout to avoid higher level timeouts */ 127859042Seric saveretry = _res.retry; 127959042Seric _res.retry = 3; 128059042Seric #endif /* NAMED_BIND */ 128159042Seric 128258951Seric switch (sap->sa.sa_family) 128358951Seric { 128458951Seric #ifdef NETINET 128558951Seric case AF_INET: 128658951Seric hp = gethostbyaddr((char *) &sap->sin.sin_addr, 128758951Seric sizeof sap->sin.sin_addr, 128858951Seric AF_INET); 128958951Seric break; 129058951Seric #endif 129158951Seric 129258951Seric #ifdef NETISO 129358951Seric case AF_ISO: 129458951Seric hp = gethostbyaddr((char *) &sap->siso.siso_addr, 129558951Seric sizeof sap->siso.siso_addr, 129658951Seric AF_ISO); 129758951Seric break; 129858951Seric #endif 129958951Seric 130064734Seric #ifdef MAYBENEXTRELEASE /*** UNTESTED *** UNTESTED *** UNTESTED ***/ 130164734Seric case AF_UNIX: 130264734Seric hp = NULL; 130364734Seric break; 130464734Seric #endif 130564734Seric 130658951Seric default: 130758951Seric hp = gethostbyaddr(sap->sa.sa_data, 130858951Seric sizeof sap->sa.sa_data, 130958951Seric sap->sa.sa_family); 131058951Seric break; 131158951Seric } 131258951Seric 131366334Seric #if NAMED_BIND 131459042Seric _res.retry = saveretry; 131559042Seric #endif /* NAMED_BIND */ 131659042Seric 131758951Seric if (hp != NULL) 131858951Seric return hp->h_name; 131958951Seric else 132058951Seric { 132158951Seric /* produce a dotted quad */ 132258951Seric static char buf[512]; 132358951Seric 132458951Seric (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); 132558951Seric return buf; 132658951Seric } 132758951Seric } 132858951Seric 132956795Seric # else /* DAEMON */ 133016911Seric /* code for systems without sophisticated networking */ 133110758Seric 133210758Seric /* 133310758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 133411297Seric ** 133511297Seric ** Can't convert to upper case here because might be a UUCP name. 133612313Seric ** 133712313Seric ** Mark, you can change this to be anything you want...... 133810758Seric */ 133910758Seric 134010758Seric char ** 134112313Seric myhostname(hostbuf, size) 134210758Seric char hostbuf[]; 134312313Seric int size; 134410758Seric { 134510758Seric register FILE *f; 134610758Seric 134710758Seric hostbuf[0] = '\0'; 134810758Seric f = fopen("/usr/include/whoami", "r"); 134910758Seric if (f != NULL) 135010758Seric { 135112313Seric (void) fgets(hostbuf, size, f); 135210758Seric fixcrlf(hostbuf, TRUE); 135310758Seric (void) fclose(f); 135410758Seric } 135510758Seric return (NULL); 135610758Seric } 135716911Seric /* 135858951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 135958308Seric ** 136058308Seric ** Parameters: 136158308Seric ** fd -- the descriptor 136258308Seric ** 136358308Seric ** Returns: 136458308Seric ** The host name associated with this descriptor, if it can 136558308Seric ** be determined. 136658308Seric ** NULL otherwise. 136758308Seric ** 136858308Seric ** Side Effects: 136958308Seric ** none 137058308Seric */ 137158308Seric 137258308Seric char * 137358951Seric getauthinfo(fd) 137458308Seric int fd; 137558308Seric { 137658308Seric return NULL; 137758308Seric } 137858308Seric /* 137916911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 138016911Seric ** 138116911Seric ** Parameters: 138256823Seric ** map -- a pointer to the database map. 138360089Seric ** name -- a buffer containing a hostname. 138453751Seric ** avp -- a pointer to a (cf file defined) argument vector. 138559084Seric ** statp -- an exit status (out parameter). 138616911Seric ** 138716911Seric ** Returns: 138853751Seric ** mapped host name 138951315Seric ** FALSE otherwise. 139016911Seric ** 139116911Seric ** Side Effects: 139260089Seric ** Looks up the host specified in name. If it is not 139316911Seric ** the canonical name for that host, replace it with 139416911Seric ** the canonical name. If the name is unknown, or it 139516911Seric ** is already the canonical name, leave it unchanged. 139616911Seric */ 139710758Seric 139816911Seric /*ARGSUSED*/ 139953751Seric char * 140060089Seric host_map_lookup(map, name, avp, statp) 140156823Seric MAP *map; 140260089Seric char *name; 140353751Seric char **avp; 140459084Seric char *statp; 140516911Seric { 140659084Seric register struct hostent *hp; 140759084Seric 140860089Seric hp = gethostbyname(name); 140959084Seric if (hp != NULL) 141059084Seric return hp->h_name; 141159084Seric *statp = EX_NOHOST; 141253751Seric return NULL; 141316911Seric } 141416911Seric 141556795Seric #endif /* DAEMON */ 1416