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*66017Seric static char sccsid[] = "@(#)daemon.c 8.35 (Berkeley) 02/06/94 (with daemon mode)"; 1533780Sbostic #else 16*66017Seric static char sccsid[] = "@(#)daemon.c 8.35 (Berkeley) 02/06/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 2559042Seric #ifdef 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); 278*66017Seric DisConnected = FALSE; 27924950Seric 28011147Seric /* determine host name */ 28164086Seric p = hostnamebyanyaddr(&RealHostAddr); 28264086Seric RealHostName = newstr(p); 28358778Seric 28455173Seric #ifdef LOG 28563842Seric if (LogLevel > 11) 28655173Seric { 28755173Seric /* log connection information */ 28855173Seric syslog(LOG_INFO, "connect from %s (%s)", 28958951Seric RealHostName, anynet_ntoa(&RealHostAddr)); 29055173Seric } 29155173Seric #endif 29255173Seric 29359254Seric (void) close(DaemonSocket); 29464724Seric if ((InChannel = fdopen(t, "r")) == NULL || 29564724Seric (t = dup(t)) < 0 || 29664724Seric (OutChannel = fdopen(t, "w")) == NULL) 29764724Seric { 29864724Seric syserr("cannot open SMTP server channel, fd=%d", t); 29964724Seric exit(0); 30064724Seric } 30159254Seric 30216884Seric /* should we check for illegal connection here? XXX */ 30359156Seric #ifdef XLA 30459156Seric if (!xla_host_ok(RealHostName)) 30559156Seric { 30659254Seric message("421 Too many SMTP sessions for this host"); 30759156Seric exit(0); 30859156Seric } 30959156Seric #endif 31016884Seric 3117677Seric if (tTd(15, 2)) 3125978Seric printf("getreq: returning\n"); 3134636Seric return; 3144631Seric } 3154631Seric 3167117Seric /* close the port so that others will hang (for a while) */ 3179610Seric (void) close(t); 3184631Seric } 3199886Seric /*NOTREACHED*/ 3204631Seric } 3215978Seric /* 32210206Seric ** CLRDAEMON -- reset the daemon connection 32310206Seric ** 32410206Seric ** Parameters: 32510206Seric ** none. 32610206Seric ** 32710206Seric ** Returns: 32810206Seric ** none. 32910206Seric ** 33010206Seric ** Side Effects: 33110206Seric ** releases any resources used by the passive daemon. 33210206Seric */ 33310206Seric 33410206Seric clrdaemon() 33510206Seric { 33610206Seric if (DaemonSocket >= 0) 33710206Seric (void) close(DaemonSocket); 33810206Seric DaemonSocket = -1; 33910206Seric } 34010206Seric /* 34158849Seric ** SETDAEMONOPTIONS -- set options for running the daemon 34258849Seric ** 34358849Seric ** Parameters: 34458849Seric ** p -- the options line. 34558849Seric ** 34658849Seric ** Returns: 34758849Seric ** none. 34858849Seric */ 34958849Seric 35058849Seric setdaemonoptions(p) 35158849Seric register char *p; 35258849Seric { 35358873Seric if (DaemonAddr.sa.sa_family == AF_UNSPEC) 35458873Seric DaemonAddr.sa.sa_family = AF_INET; 35558873Seric 35658849Seric while (p != NULL) 35758849Seric { 35858849Seric register char *f; 35958849Seric register char *v; 36058849Seric 36158849Seric while (isascii(*p) && isspace(*p)) 36258849Seric p++; 36358849Seric if (*p == '\0') 36458849Seric break; 36558849Seric f = p; 36658849Seric p = strchr(p, ','); 36758849Seric if (p != NULL) 36858849Seric *p++ = '\0'; 36958849Seric v = strchr(f, '='); 37058849Seric if (v == NULL) 37158849Seric continue; 37258849Seric while (isascii(*++v) && isspace(*v)) 37358849Seric continue; 37458849Seric 37558849Seric switch (*f) 37658849Seric { 37758873Seric case 'F': /* address family */ 37858849Seric if (isascii(*v) && isdigit(*v)) 37958873Seric DaemonAddr.sa.sa_family = atoi(v); 38058873Seric #ifdef NETINET 38158873Seric else if (strcasecmp(v, "inet") == 0) 38258873Seric DaemonAddr.sa.sa_family = AF_INET; 38358873Seric #endif 38458873Seric #ifdef NETISO 38558873Seric else if (strcasecmp(v, "iso") == 0) 38658873Seric DaemonAddr.sa.sa_family = AF_ISO; 38758873Seric #endif 38858873Seric #ifdef NETNS 38958873Seric else if (strcasecmp(v, "ns") == 0) 39058873Seric DaemonAddr.sa.sa_family = AF_NS; 39158873Seric #endif 39258873Seric #ifdef NETX25 39358873Seric else if (strcasecmp(v, "x.25") == 0) 39458873Seric DaemonAddr.sa.sa_family = AF_CCITT; 39558873Seric #endif 39658849Seric else 39758873Seric syserr("554 Unknown address family %s in Family=option", v); 39858873Seric break; 39958873Seric 40058873Seric case 'A': /* address */ 40158873Seric switch (DaemonAddr.sa.sa_family) 40258849Seric { 40358873Seric #ifdef NETINET 40458873Seric case AF_INET: 40558873Seric if (isascii(*v) && isdigit(*v)) 40658873Seric DaemonAddr.sin.sin_addr.s_addr = inet_network(v); 40758873Seric else 40858873Seric { 40958873Seric register struct netent *np; 41058849Seric 41158873Seric np = getnetbyname(v); 41258873Seric if (np == NULL) 41358873Seric syserr("554 network \"%s\" unknown", v); 41458873Seric else 41558873Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 41658873Seric } 41758873Seric break; 41858873Seric #endif 41958873Seric 42058873Seric default: 42158873Seric syserr("554 Address= option unsupported for family %d", 42258873Seric DaemonAddr.sa.sa_family); 42358873Seric break; 42458849Seric } 42558849Seric break; 42658849Seric 42758873Seric case 'P': /* port */ 42858873Seric switch (DaemonAddr.sa.sa_family) 42958849Seric { 43058873Seric short port; 43158849Seric 43258873Seric #ifdef NETINET 43358873Seric case AF_INET: 43458873Seric if (isascii(*v) && isdigit(*v)) 43564366Seric DaemonAddr.sin.sin_port = htons(atoi(v)); 43658849Seric else 43758873Seric { 43858873Seric register struct servent *sp; 43958873Seric 44058873Seric sp = getservbyname(v, "tcp"); 44158873Seric if (sp == NULL) 44258909Seric syserr("554 service \"%s\" unknown", v); 44358873Seric else 44458873Seric DaemonAddr.sin.sin_port = sp->s_port; 44558873Seric } 44658873Seric break; 44758873Seric #endif 44858873Seric 44958873Seric #ifdef NETISO 45058873Seric case AF_ISO: 45158873Seric /* assume two byte transport selector */ 45258873Seric if (isascii(*v) && isdigit(*v)) 45364366Seric port = htons(atoi(v)); 45458873Seric else 45558873Seric { 45658873Seric register struct servent *sp; 45758873Seric 45858873Seric sp = getservbyname(v, "tcp"); 45958873Seric if (sp == NULL) 46058909Seric syserr("554 service \"%s\" unknown", v); 46158873Seric else 46258873Seric port = sp->s_port; 46358873Seric } 46458873Seric bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 46558873Seric break; 46658873Seric #endif 46758873Seric 46858873Seric default: 46958873Seric syserr("554 Port= option unsupported for family %d", 47058873Seric DaemonAddr.sa.sa_family); 47158873Seric break; 47258849Seric } 47358849Seric break; 47459783Seric 47559783Seric case 'L': /* listen queue size */ 47659783Seric ListenQueueSize = atoi(v); 47759783Seric break; 47864381Seric 47964381Seric case 'S': /* send buffer size */ 48064381Seric TcpSndBufferSize = atoi(v); 48164381Seric break; 48264381Seric 48364381Seric case 'R': /* receive buffer size */ 48464381Seric TcpRcvBufferSize = atoi(v); 48564381Seric break; 48658849Seric } 48758849Seric } 48858849Seric } 48958849Seric /* 4906039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 4916039Seric ** 4926039Seric ** Parameters: 4936039Seric ** host -- the name of the host. 4946633Seric ** port -- the port number to connect to. 49553739Seric ** mci -- a pointer to the mail connection information 49653739Seric ** structure to be filled in. 49752106Seric ** usesecureport -- if set, use a low numbered (reserved) 49852106Seric ** port to provide some rudimentary authentication. 4996039Seric ** 5006039Seric ** Returns: 5016039Seric ** An exit code telling whether the connection could be 5026039Seric ** made and if not why not. 5036039Seric ** 5046039Seric ** Side Effects: 5056039Seric ** none. 5066039Seric */ 5075978Seric 50858755Seric SOCKADDR CurHostAddr; /* address of current host */ 50958305Seric 51054967Seric int 51153739Seric makeconnection(host, port, mci, usesecureport) 5126039Seric char *host; 5137286Seric u_short port; 51454967Seric register MCI *mci; 51552106Seric bool usesecureport; 5166039Seric { 51729430Sbloom register int i, s; 51829430Sbloom register struct hostent *hp = (struct hostent *)NULL; 51958755Seric SOCKADDR addr; 52052106Seric int sav_errno; 52158755Seric int addrlen; 52235651Seric #ifdef NAMED_BIND 52335651Seric extern int h_errno; 52435651Seric #endif 5256039Seric 5266039Seric /* 5276039Seric ** Set up the address for the mailer. 5289308Seric ** Accept "[a.b.c.d]" syntax for host name. 5296039Seric */ 5306039Seric 53135651Seric #ifdef NAMED_BIND 53225475Smiriam h_errno = 0; 53335651Seric #endif 53425475Smiriam errno = 0; 53558864Seric bzero(&CurHostAddr, sizeof CurHostAddr); 53664334Seric SmtpPhase = mci->mci_phase = "initial connection"; 53758906Seric CurHostName = host; 53825475Smiriam 5399308Seric if (host[0] == '[') 5409308Seric { 54111147Seric long hid; 54256795Seric register char *p = strchr(host, ']'); 5439308Seric 54411147Seric if (p != NULL) 5459308Seric { 54611147Seric *p = '\0'; 54759884Seric #ifdef NETINET 54811147Seric hid = inet_addr(&host[1]); 54958360Seric if (hid == -1) 55059884Seric #endif 55158360Seric { 55258360Seric /* try it as a host name (avoid MX lookup) */ 55358360Seric hp = gethostbyname(&host[1]); 55458360Seric *p = ']'; 55558360Seric goto gothostent; 55658360Seric } 55711147Seric *p = ']'; 5589308Seric } 55958360Seric if (p == NULL) 5609308Seric { 56158151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 5629308Seric return (EX_NOHOST); 5639308Seric } 56459884Seric #ifdef NETINET 56559884Seric addr.sin.sin_family = AF_INET; /*XXX*/ 56658778Seric addr.sin.sin_addr.s_addr = hid; 56759884Seric #endif 5689308Seric } 5699610Seric else 5709610Seric { 57129430Sbloom hp = gethostbyname(host); 57258360Seric gothostent: 57325475Smiriam if (hp == NULL) 57424945Seric { 57535651Seric #ifdef NAMED_BIND 57625475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 57725475Smiriam return (EX_TEMPFAIL); 57825657Seric 57935651Seric /* if name server is specified, assume temp fail */ 58035651Seric if (errno == ECONNREFUSED && UseNameServer) 58135651Seric return (EX_TEMPFAIL); 58235651Seric #endif 58325475Smiriam return (EX_NOHOST); 58424945Seric } 58558778Seric addr.sa.sa_family = hp->h_addrtype; 58658778Seric switch (hp->h_addrtype) 58758778Seric { 58858778Seric #ifdef NETINET 58958778Seric case AF_INET: 59058755Seric bcopy(hp->h_addr, 59158778Seric &addr.sin.sin_addr, 59264943Seric sizeof addr.sin.sin_addr); 59358778Seric break; 59458778Seric #endif 59558778Seric 59658778Seric default: 59758755Seric bcopy(hp->h_addr, 59858778Seric addr.sa.sa_data, 59958755Seric hp->h_length); 60058778Seric break; 60158778Seric } 60229430Sbloom i = 1; 6039610Seric } 6049610Seric 6059610Seric /* 6069610Seric ** Determine the port number. 6079610Seric */ 6089610Seric 60910011Seric if (port != 0) 61058755Seric port = htons(port); 61110011Seric else 6129610Seric { 6139610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 6149610Seric 6159610Seric if (sp == NULL) 6169610Seric { 61758909Seric syserr("554 makeconnection: service \"smtp\" unknown"); 61865169Seric port = htons(25); 6199610Seric } 62065169Seric else 62165169Seric port = sp->s_port; 6229610Seric } 6236039Seric 62458778Seric switch (addr.sa.sa_family) 62558755Seric { 62659884Seric #ifdef NETINET 62758755Seric case AF_INET: 62858778Seric addr.sin.sin_port = port; 62958755Seric addrlen = sizeof (struct sockaddr_in); 63058755Seric break; 63159884Seric #endif 63258755Seric 63358755Seric #ifdef NETISO 63458755Seric case AF_ISO: 63558755Seric /* assume two byte transport selector */ 63658755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 63758755Seric addrlen = sizeof (struct sockaddr_iso); 63858755Seric break; 63958755Seric #endif 64058755Seric 64158755Seric default: 64258778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 64358755Seric return (EX_NOHOST); 64458755Seric } 64558755Seric 6466039Seric /* 6476039Seric ** Try to actually open the connection. 6486039Seric */ 6496039Seric 65059156Seric #ifdef XLA 65159156Seric /* if too many connections, don't bother trying */ 65259156Seric if (!xla_noqueue_ok(host)) 65359156Seric return EX_TEMPFAIL; 65459156Seric #endif 65559156Seric 65657736Seric for (;;) 65752106Seric { 65857736Seric if (tTd(16, 1)) 65958755Seric printf("makeconnection (%s [%s])\n", 66058755Seric host, anynet_ntoa(&addr)); 66152106Seric 66258588Seric /* save for logging */ 66358588Seric CurHostAddr = addr; 66458588Seric 66557736Seric if (usesecureport) 66657736Seric { 66757736Seric int rport = IPPORT_RESERVED - 1; 6686039Seric 66957736Seric s = rresvport(&rport); 67057736Seric } 67157736Seric else 67257736Seric { 67357736Seric s = socket(AF_INET, SOCK_STREAM, 0); 67457736Seric } 67557736Seric if (s < 0) 67657736Seric { 67757736Seric sav_errno = errno; 67857736Seric syserr("makeconnection: no socket"); 67957736Seric goto failure; 68057736Seric } 68110347Seric 68264381Seric #ifdef SO_SNDBUF 68364381Seric if (TcpSndBufferSize > 0) 68464381Seric { 68564381Seric if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 68664561Seric (char *) &TcpSndBufferSize, 68764381Seric sizeof(TcpSndBufferSize)) < 0) 68864381Seric syserr("makeconnection: setsockopt(SO_SNDBUF)"); 68964381Seric } 69064381Seric #endif 69164381Seric 69257736Seric if (tTd(16, 1)) 69357736Seric printf("makeconnection: fd=%d\n", s); 69457736Seric 69557736Seric /* turn on network debugging? */ 69657736Seric if (tTd(16, 101)) 69757736Seric { 69857736Seric int on = 1; 69957736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 70057736Seric (char *)&on, sizeof on); 70157736Seric } 70257736Seric if (CurEnv->e_xfp != NULL) 70357736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 70457736Seric errno = 0; /* for debugging */ 70558755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 70657736Seric break; 70757736Seric 70857736Seric /* couldn't connect.... figure out why */ 70927744Sbloom sav_errno = errno; 71027744Sbloom (void) close(s); 71129430Sbloom if (hp && hp->h_addr_list[i]) 71229430Sbloom { 71357736Seric if (tTd(16, 1)) 71458755Seric printf("Connect failed (%s); trying new address....\n", 71558755Seric errstring(sav_errno)); 71658778Seric switch (addr.sa.sa_family) 71758778Seric { 71858778Seric #ifdef NETINET 71958778Seric case AF_INET: 72058755Seric bcopy(hp->h_addr_list[i++], 72158778Seric &addr.sin.sin_addr, 72264943Seric sizeof addr.sin.sin_addr); 72358778Seric break; 72458778Seric #endif 72558778Seric 72658778Seric default: 72758755Seric bcopy(hp->h_addr_list[i++], 72858778Seric addr.sa.sa_data, 72952106Seric hp->h_length); 73058778Seric break; 73158778Seric } 73257736Seric continue; 73329430Sbloom } 73429430Sbloom 7356039Seric /* failure, decide if temporary or not */ 7366039Seric failure: 73759254Seric #ifdef XLA 73859254Seric xla_host_end(host); 73959254Seric #endif 74058542Seric if (transienterror(sav_errno)) 74158542Seric return EX_TEMPFAIL; 74258542Seric else 74358542Seric { 74458542Seric message("%s", errstring(sav_errno)); 74558542Seric return (EX_UNAVAILABLE); 7466039Seric } 7476039Seric } 7486039Seric 7496039Seric /* connection ok, put it into canonical form */ 75064724Seric if ((mci->mci_out = fdopen(s, "w")) == NULL || 75164724Seric (s = dup(s)) < 0 || 75264725Seric (mci->mci_in = fdopen(s, "r")) == NULL) 75364724Seric { 75464724Seric syserr("cannot open SMTP client channel, fd=%d", s); 75564724Seric return EX_TEMPFAIL; 75664724Seric } 7576039Seric 75810098Seric return (EX_OK); 7596039Seric } 76010758Seric /* 76110758Seric ** MYHOSTNAME -- return the name of this host. 76210758Seric ** 76310758Seric ** Parameters: 76410758Seric ** hostbuf -- a place to return the name of this host. 76512313Seric ** size -- the size of hostbuf. 76610758Seric ** 76710758Seric ** Returns: 76810758Seric ** A list of aliases for this host. 76910758Seric ** 77010758Seric ** Side Effects: 77164338Seric ** Adds numeric codes to $=w. 77210758Seric */ 7736039Seric 77410758Seric char ** 77512313Seric myhostname(hostbuf, size) 77610758Seric char hostbuf[]; 77712313Seric int size; 77810758Seric { 77958110Seric register struct hostent *hp; 78010758Seric extern struct hostent *gethostbyname(); 78110758Seric 78223120Seric if (gethostname(hostbuf, size) < 0) 78323120Seric { 78423120Seric (void) strcpy(hostbuf, "localhost"); 78523120Seric } 78611147Seric hp = gethostbyname(hostbuf); 78711147Seric if (hp != NULL) 78816877Seric { 78958110Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 79058110Seric hostbuf[size - 1] = '\0'; 79158110Seric 79258110Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 79358110Seric { 79458110Seric register int i; 79558110Seric 79664338Seric for (i = 0; hp->h_addr_list[i] != NULL; i++) 79758110Seric { 79864338Seric char ipbuf[100]; 79964338Seric 80064338Seric sprintf(ipbuf, "[%s]", 80164338Seric inet_ntoa(*((struct in_addr *) hp->h_addr_list[i]))); 80264338Seric setclass('w', ipbuf); 80358110Seric } 80458110Seric } 80558110Seric 80611147Seric return (hp->h_aliases); 80716877Seric } 80810758Seric else 80910758Seric return (NULL); 81010758Seric } 81151315Seric /* 81258951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 81358308Seric ** 81458951Seric ** Uses RFC1413 protocol to try to get info from the other end. 81558951Seric ** 81658308Seric ** Parameters: 81758308Seric ** fd -- the descriptor 81858308Seric ** 81958308Seric ** Returns: 82058951Seric ** The user@host information associated with this descriptor. 82158308Seric */ 82258308Seric 82364927Seric #if IDENTPROTO 82458951Seric 82558951Seric static jmp_buf CtxAuthTimeout; 82658951Seric 82758951Seric static 82858951Seric authtimeout() 82958951Seric { 83058951Seric longjmp(CtxAuthTimeout, 1); 83158951Seric } 83258951Seric 83358951Seric #endif 83458951Seric 83558308Seric char * 83658951Seric getauthinfo(fd) 83758308Seric int fd; 83858308Seric { 83958951Seric SOCKADDR fa; 84058951Seric int falen; 84159104Seric register char *p; 84264927Seric #if IDENTPROTO 84358951Seric SOCKADDR la; 84458951Seric int lalen; 84558951Seric register struct servent *sp; 84658951Seric int s; 84758951Seric int i; 84858951Seric EVENT *ev; 84958951Seric #endif 85058951Seric static char hbuf[MAXNAME * 2 + 2]; 85158951Seric extern char *hostnamebyanyaddr(); 85258951Seric extern char RealUserName[]; /* main.c */ 85358308Seric 85458951Seric falen = sizeof fa; 85564845Seric if (getpeername(fd, &fa.sa, &falen) < 0 || falen <= 0 || 85664845Seric fa.sa.sa_family == 0) 85758951Seric { 85858951Seric (void) sprintf(hbuf, "%s@localhost", RealUserName); 85958957Seric if (tTd(9, 1)) 86058951Seric printf("getauthinfo: %s\n", hbuf); 86158951Seric return hbuf; 86258951Seric } 86358951Seric 86464927Seric #if IDENTPROTO 86565831Seric if (TimeOuts.to_ident == 0) 86665831Seric goto noident; 86765831Seric 86858951Seric lalen = sizeof la; 86958951Seric if (fa.sa.sa_family != AF_INET || 87058951Seric getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || 87158951Seric la.sa.sa_family != AF_INET) 87258951Seric { 87358951Seric /* no ident info */ 87458951Seric goto noident; 87558951Seric } 87658951Seric 87758951Seric /* create ident query */ 87860489Seric (void) sprintf(hbuf, "%d,%d\r\n", 87960489Seric ntohs(fa.sin.sin_port), ntohs(la.sin.sin_port)); 88058951Seric 88158951Seric /* create local address */ 88264747Seric la.sin.sin_port = 0; 88358951Seric 88458951Seric /* create foreign address */ 88558951Seric sp = getservbyname("auth", "tcp"); 88658951Seric if (sp != NULL) 88758951Seric fa.sin.sin_port = sp->s_port; 88858308Seric else 88959097Seric fa.sin.sin_port = htons(113); 89058951Seric 89158951Seric s = -1; 89258951Seric if (setjmp(CtxAuthTimeout) != 0) 89358951Seric { 89458951Seric if (s >= 0) 89558951Seric (void) close(s); 89658951Seric goto noident; 89758951Seric } 89858951Seric 89958951Seric /* put a timeout around the whole thing */ 90064255Seric ev = setevent(TimeOuts.to_ident, authtimeout, 0); 90158951Seric 90264747Seric /* connect to foreign IDENT server using same address as SMTP socket */ 90358951Seric s = socket(AF_INET, SOCK_STREAM, 0); 90458951Seric if (s < 0) 90558951Seric { 90658951Seric clrevent(ev); 90758951Seric goto noident; 90858951Seric } 90964747Seric if (bind(s, &la.sa, sizeof la.sin) < 0 || 91064747Seric connect(s, &fa.sa, sizeof fa.sin) < 0) 91158951Seric { 91266011Seric goto closeident; 91358951Seric } 91458951Seric 91558957Seric if (tTd(9, 10)) 91658951Seric printf("getauthinfo: sent %s", hbuf); 91758951Seric 91858951Seric /* send query */ 91958951Seric if (write(s, hbuf, strlen(hbuf)) < 0) 92058951Seric goto closeident; 92158951Seric 92258951Seric /* get result */ 92358951Seric i = read(s, hbuf, sizeof hbuf); 92458951Seric (void) close(s); 92558951Seric clrevent(ev); 92658951Seric if (i <= 0) 92758951Seric goto noident; 92858951Seric if (hbuf[--i] == '\n' && hbuf[--i] == '\r') 92958951Seric i--; 93058951Seric hbuf[++i] = '\0'; 93158951Seric 93258957Seric if (tTd(9, 3)) 93358951Seric printf("getauthinfo: got %s\n", hbuf); 93458951Seric 93558951Seric /* parse result */ 93658951Seric p = strchr(hbuf, ':'); 93758951Seric if (p == NULL) 93858951Seric { 93958951Seric /* malformed response */ 94058951Seric goto noident; 94158951Seric } 94258951Seric while (isascii(*++p) && isspace(*p)) 94358951Seric continue; 94458951Seric if (strncasecmp(p, "userid", 6) != 0) 94558951Seric { 94658951Seric /* presumably an error string */ 94758951Seric goto noident; 94858951Seric } 94958951Seric p += 6; 95058951Seric while (isascii(*p) && isspace(*p)) 95158951Seric p++; 95258951Seric if (*p++ != ':') 95358951Seric { 95458951Seric /* either useridxx or malformed response */ 95558951Seric goto noident; 95658951Seric } 95758951Seric 95858951Seric /* p now points to the OSTYPE field */ 95958951Seric p = strchr(p, ':'); 96058951Seric if (p == NULL) 96158951Seric { 96258951Seric /* malformed response */ 96358951Seric goto noident; 96458951Seric } 96558951Seric 96658957Seric /* 1413 says don't do this -- but it's broken otherwise */ 96758957Seric while (isascii(*++p) && isspace(*p)) 96858957Seric continue; 96958957Seric 97058951Seric /* p now points to the authenticated name */ 97166003Seric (void) sprintf(hbuf, "%s@%s", 97266003Seric p, RealHostName == NULL ? "localhost" : RealHostName); 97358957Seric goto finish; 97458957Seric 97566011Seric closeident: 97666011Seric (void) close(s); 97766011Seric clrevent(ev); 97866011Seric 97958957Seric #endif /* IDENTPROTO */ 98058957Seric 98158957Seric noident: 98266003Seric if (RealHostName == NULL) 98366003Seric { 98466003Seric if (tTd(9, 1)) 98566003Seric printf("getauthinfo: NULL\n"); 98666003Seric return NULL; 98766003Seric } 98858957Seric (void) strcpy(hbuf, RealHostName); 98958957Seric 99058957Seric finish: 99166003Seric if (RealHostName != NULL && RealHostName[0] != '[') 99258951Seric { 99358951Seric p = &hbuf[strlen(hbuf)]; 99458951Seric (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); 99558951Seric } 99658957Seric if (tTd(9, 1)) 99758951Seric printf("getauthinfo: %s\n", hbuf); 99858308Seric return hbuf; 99958308Seric } 100058308Seric /* 100160089Seric ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 100253751Seric ** 100353751Seric ** Parameters: 100456823Seric ** map -- a pointer to this map (unused). 100560089Seric ** name -- the (presumably unqualified) hostname. 100660257Seric ** av -- unused -- for compatibility with other mapping 100755019Seric ** functions. 100859084Seric ** statp -- an exit status (out parameter) -- set to 100959084Seric ** EX_TEMPFAIL if the name server is unavailable. 101053751Seric ** 101153751Seric ** Returns: 101253751Seric ** The mapping, if found. 101353751Seric ** NULL if no mapping found. 101453751Seric ** 101553751Seric ** Side Effects: 101653751Seric ** Looks up the host specified in hbuf. If it is not 101753751Seric ** the canonical name for that host, return the canonical 101853751Seric ** name. 101953751Seric */ 102051315Seric 102153751Seric char * 102260257Seric host_map_lookup(map, name, av, statp) 102356823Seric MAP *map; 102460089Seric char *name; 102560257Seric char **av; 102659084Seric int *statp; 102716911Seric { 102816911Seric register struct hostent *hp; 102933932Sbostic u_long in_addr; 103056823Seric char *cp; 103158110Seric int i; 103259671Seric register STAB *s; 103360257Seric char hbuf[MAXNAME]; 103459671Seric extern struct hostent *gethostbyaddr(); 103559671Seric extern int h_errno; 103616911Seric 103725574Smiriam /* 103859671Seric ** See if we have already looked up this name. If so, just 103959671Seric ** return it. 104059671Seric */ 104153751Seric 104260089Seric s = stab(name, ST_NAMECANON, ST_ENTER); 104359671Seric if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 104459671Seric { 104559986Seric if (tTd(9, 1)) 104660089Seric printf("host_map_lookup(%s) => CACHE %s\n", 104760089Seric name, s->s_namecanon.nc_cname); 104859671Seric errno = s->s_namecanon.nc_errno; 104959671Seric h_errno = s->s_namecanon.nc_herrno; 105059671Seric *statp = s->s_namecanon.nc_stat; 105164797Seric if (CurEnv->e_message == NULL && *statp == EX_TEMPFAIL) 105265199Seric { 105365199Seric sprintf(hbuf, "%s: Name server timeout", 105465199Seric shortenstring(name, 33)); 105565199Seric CurEnv->e_message = newstr(hbuf); 105665199Seric } 105759671Seric return s->s_namecanon.nc_cname; 105859671Seric } 105959671Seric 106059671Seric /* 106159671Seric ** If first character is a bracket, then it is an address 106259671Seric ** lookup. Address is copied into a temporary buffer to 106360089Seric ** strip the brackets and to preserve name if address is 106459671Seric ** unknown. 106559671Seric */ 106659671Seric 106760089Seric if (*name != '[') 106853751Seric { 106955019Seric extern bool getcanonname(); 107055019Seric 107158798Seric if (tTd(9, 1)) 107260089Seric printf("host_map_lookup(%s) => ", name); 107359671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 107460089Seric (void) strcpy(hbuf, name); 107563842Seric if (getcanonname(hbuf, sizeof hbuf - 1, TRUE)) 107658796Seric { 107758796Seric if (tTd(9, 1)) 107858796Seric printf("%s\n", hbuf); 107960257Seric cp = map_rewrite(map, hbuf, strlen(hbuf), av); 108060257Seric s->s_namecanon.nc_cname = newstr(cp); 108160257Seric return cp; 108258796Seric } 108353751Seric else 108458796Seric { 108559084Seric register struct hostent *hp; 108659084Seric 108758796Seric if (tTd(9, 1)) 108859084Seric printf("FAIL (%d)\n", h_errno); 108959671Seric s->s_namecanon.nc_errno = errno; 109059671Seric s->s_namecanon.nc_herrno = h_errno; 109159084Seric switch (h_errno) 109259084Seric { 109359084Seric case TRY_AGAIN: 109459596Seric if (UseNameServer) 109559734Seric { 109665202Seric sprintf(hbuf, "%s: Name server timeout", 109765199Seric shortenstring(name, 33)); 109865202Seric message("%s", hbuf); 109959734Seric if (CurEnv->e_message == NULL) 110065202Seric CurEnv->e_message = newstr(hbuf); 110159734Seric } 110259084Seric *statp = EX_TEMPFAIL; 110359084Seric break; 110459084Seric 110559084Seric case HOST_NOT_FOUND: 110659084Seric *statp = EX_NOHOST; 110759084Seric break; 110859084Seric 110959084Seric case NO_RECOVERY: 111059084Seric *statp = EX_SOFTWARE; 111159084Seric break; 111259084Seric 111359084Seric default: 111459084Seric *statp = EX_UNAVAILABLE; 111559084Seric break; 111659084Seric } 111759671Seric s->s_namecanon.nc_stat = *statp; 111859084Seric if (*statp != EX_TEMPFAIL || UseNameServer) 111959084Seric return NULL; 112059084Seric 112159084Seric /* 112259084Seric ** Try to look it up in /etc/hosts 112359084Seric */ 112459084Seric 112560089Seric hp = gethostbyname(name); 112659084Seric if (hp == NULL) 112759084Seric { 112859084Seric /* no dice there either */ 112959671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 113059084Seric return NULL; 113159084Seric } 113259084Seric 113359671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 113460257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 113560257Seric s->s_namecanon.nc_cname = newstr(cp); 113660257Seric return cp; 113758796Seric } 113853751Seric } 113960089Seric if ((cp = strchr(name, ']')) == NULL) 114053751Seric return (NULL); 114140994Sbostic *cp = '\0'; 114260089Seric in_addr = inet_addr(&name[1]); 114358110Seric 114458110Seric /* nope -- ask the name server */ 114533932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 114659671Seric s->s_namecanon.nc_errno = errno; 114759671Seric s->s_namecanon.nc_herrno = h_errno; 114859671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 114933932Sbostic if (hp == NULL) 115059671Seric { 115159671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 115253751Seric return (NULL); 115359671Seric } 115453751Seric 115558110Seric /* found a match -- copy out */ 115660257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 115759671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 115860257Seric s->s_namecanon.nc_cname = newstr(cp); 115960257Seric return cp; 116033932Sbostic } 116158755Seric /* 116258755Seric ** ANYNET_NTOA -- convert a network address to printable form. 116358755Seric ** 116458755Seric ** Parameters: 116558755Seric ** sap -- a pointer to a sockaddr structure. 116658755Seric ** 116758755Seric ** Returns: 116858755Seric ** A printable version of that sockaddr. 116958755Seric */ 117016911Seric 117158755Seric char * 117258755Seric anynet_ntoa(sap) 117358755Seric register SOCKADDR *sap; 117458755Seric { 117558755Seric register char *bp; 117658755Seric register char *ap; 117758755Seric int l; 117864734Seric static char buf[100]; 117958755Seric 118058798Seric /* check for null/zero family */ 118158798Seric if (sap == NULL) 118258798Seric return "NULLADDR"; 118358798Seric if (sap->sa.sa_family == 0) 118458798Seric return "0"; 118558798Seric 118664734Seric switch (sap->sa.sa_family) 118764734Seric { 118864734Seric #ifdef MAYBENEXTRELEASE /*** UNTESTED *** UNTESTED *** UNTESTED ***/ 118964821Seric #ifdef NETUNIX 119064734Seric case AF_UNIX: 119164758Seric if (sap->sunix.sun_path[0] != '\0') 119264758Seric sprintf(buf, "[UNIX: %.64s]", sap->sunix.sun_path); 119364734Seric else 119464734Seric sprintf(buf, "[UNIX: localhost]"); 119564734Seric return buf; 119664734Seric #endif 119764821Seric #endif 119864734Seric 119958778Seric #ifdef NETINET 120064734Seric case AF_INET: 120158755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 120258778Seric #endif 120358755Seric 120464734Seric default: 120564734Seric /* this case is only to ensure syntactic correctness */ 120664734Seric break; 120764734Seric } 120864734Seric 120958755Seric /* unknown family -- just dump bytes */ 121058778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 121158755Seric bp = &buf[strlen(buf)]; 121258778Seric ap = sap->sa.sa_data; 121358778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 121458755Seric { 121558755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 121658755Seric bp += 3; 121758755Seric } 121858755Seric *--bp = '\0'; 121958755Seric return buf; 122058755Seric } 122158951Seric /* 122258951Seric ** HOSTNAMEBYANYADDR -- return name of host based on address 122358951Seric ** 122458951Seric ** Parameters: 122558951Seric ** sap -- SOCKADDR pointer 122658951Seric ** 122758951Seric ** Returns: 122858951Seric ** text representation of host name. 122958951Seric ** 123058951Seric ** Side Effects: 123158951Seric ** none. 123258951Seric */ 123358755Seric 123458951Seric char * 123558951Seric hostnamebyanyaddr(sap) 123658951Seric register SOCKADDR *sap; 123758951Seric { 123858951Seric register struct hostent *hp; 123964734Seric int saveretry; 124058951Seric 124159042Seric #ifdef NAMED_BIND 124259042Seric /* shorten name server timeout to avoid higher level timeouts */ 124359042Seric saveretry = _res.retry; 124459042Seric _res.retry = 3; 124559042Seric #endif /* NAMED_BIND */ 124659042Seric 124758951Seric switch (sap->sa.sa_family) 124858951Seric { 124958951Seric #ifdef NETINET 125058951Seric case AF_INET: 125158951Seric hp = gethostbyaddr((char *) &sap->sin.sin_addr, 125258951Seric sizeof sap->sin.sin_addr, 125358951Seric AF_INET); 125458951Seric break; 125558951Seric #endif 125658951Seric 125758951Seric #ifdef NETISO 125858951Seric case AF_ISO: 125958951Seric hp = gethostbyaddr((char *) &sap->siso.siso_addr, 126058951Seric sizeof sap->siso.siso_addr, 126158951Seric AF_ISO); 126258951Seric break; 126358951Seric #endif 126458951Seric 126564734Seric #ifdef MAYBENEXTRELEASE /*** UNTESTED *** UNTESTED *** UNTESTED ***/ 126664734Seric case AF_UNIX: 126764734Seric hp = NULL; 126864734Seric break; 126964734Seric #endif 127064734Seric 127158951Seric default: 127258951Seric hp = gethostbyaddr(sap->sa.sa_data, 127358951Seric sizeof sap->sa.sa_data, 127458951Seric sap->sa.sa_family); 127558951Seric break; 127658951Seric } 127758951Seric 127859042Seric #ifdef NAMED_BIND 127959042Seric _res.retry = saveretry; 128059042Seric #endif /* NAMED_BIND */ 128159042Seric 128258951Seric if (hp != NULL) 128358951Seric return hp->h_name; 128458951Seric else 128558951Seric { 128658951Seric /* produce a dotted quad */ 128758951Seric static char buf[512]; 128858951Seric 128958951Seric (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); 129058951Seric return buf; 129158951Seric } 129258951Seric } 129358951Seric 129456795Seric # else /* DAEMON */ 129516911Seric /* code for systems without sophisticated networking */ 129610758Seric 129710758Seric /* 129810758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 129911297Seric ** 130011297Seric ** Can't convert to upper case here because might be a UUCP name. 130112313Seric ** 130212313Seric ** Mark, you can change this to be anything you want...... 130310758Seric */ 130410758Seric 130510758Seric char ** 130612313Seric myhostname(hostbuf, size) 130710758Seric char hostbuf[]; 130812313Seric int size; 130910758Seric { 131010758Seric register FILE *f; 131110758Seric 131210758Seric hostbuf[0] = '\0'; 131310758Seric f = fopen("/usr/include/whoami", "r"); 131410758Seric if (f != NULL) 131510758Seric { 131612313Seric (void) fgets(hostbuf, size, f); 131710758Seric fixcrlf(hostbuf, TRUE); 131810758Seric (void) fclose(f); 131910758Seric } 132010758Seric return (NULL); 132110758Seric } 132216911Seric /* 132358951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 132458308Seric ** 132558308Seric ** Parameters: 132658308Seric ** fd -- the descriptor 132758308Seric ** 132858308Seric ** Returns: 132958308Seric ** The host name associated with this descriptor, if it can 133058308Seric ** be determined. 133158308Seric ** NULL otherwise. 133258308Seric ** 133358308Seric ** Side Effects: 133458308Seric ** none 133558308Seric */ 133658308Seric 133758308Seric char * 133858951Seric getauthinfo(fd) 133958308Seric int fd; 134058308Seric { 134158308Seric return NULL; 134258308Seric } 134358308Seric /* 134416911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 134516911Seric ** 134616911Seric ** Parameters: 134756823Seric ** map -- a pointer to the database map. 134860089Seric ** name -- a buffer containing a hostname. 134953751Seric ** avp -- a pointer to a (cf file defined) argument vector. 135059084Seric ** statp -- an exit status (out parameter). 135116911Seric ** 135216911Seric ** Returns: 135353751Seric ** mapped host name 135451315Seric ** FALSE otherwise. 135516911Seric ** 135616911Seric ** Side Effects: 135760089Seric ** Looks up the host specified in name. If it is not 135816911Seric ** the canonical name for that host, replace it with 135916911Seric ** the canonical name. If the name is unknown, or it 136016911Seric ** is already the canonical name, leave it unchanged. 136116911Seric */ 136210758Seric 136316911Seric /*ARGSUSED*/ 136453751Seric char * 136560089Seric host_map_lookup(map, name, avp, statp) 136656823Seric MAP *map; 136760089Seric char *name; 136853751Seric char **avp; 136959084Seric char *statp; 137016911Seric { 137159084Seric register struct hostent *hp; 137259084Seric 137360089Seric hp = gethostbyname(name); 137459084Seric if (hp != NULL) 137559084Seric return hp->h_name; 137659084Seric *statp = EX_NOHOST; 137753751Seric return NULL; 137816911Seric } 137916911Seric 138056795Seric #endif /* DAEMON */ 1381