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*64724Seric static char sccsid[] = "@(#)daemon.c 8.16 (Berkeley) 10/16/93 (with daemon mode)"; 1533780Sbostic #else 16*64724Seric static char sccsid[] = "@(#)daemon.c 8.16 (Berkeley) 10/16/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; 9146928Sbostic extern void reapchild(); 927117Seric 939610Seric /* 949610Seric ** Set up the address for the mailer. 959610Seric */ 969610Seric 9758849Seric if (DaemonAddr.sin.sin_family == 0) 9858849Seric DaemonAddr.sin.sin_family = AF_INET; 9958849Seric if (DaemonAddr.sin.sin_addr.s_addr == 0) 10058849Seric DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; 10158849Seric if (DaemonAddr.sin.sin_port == 0) 1029610Seric { 10358849Seric sp = getservbyname("smtp", "tcp"); 10458849Seric if (sp == NULL) 10558849Seric { 10658909Seric syserr("554 service \"smtp\" unknown"); 10758849Seric goto severe; 10858849Seric } 10958849Seric DaemonAddr.sin.sin_port = sp->s_port; 1109610Seric } 1119610Seric 1129610Seric /* 1139610Seric ** Try to actually open the connection. 1149610Seric */ 1159610Seric 1169610Seric if (tTd(15, 1)) 11758849Seric printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); 1189610Seric 1199610Seric /* get a socket for the SMTP connection */ 12059041Seric DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0); 12110206Seric if (DaemonSocket < 0) 1229610Seric { 1239610Seric /* probably another daemon already */ 1249610Seric syserr("getrequests: can't create socket"); 1259610Seric severe: 1269610Seric # ifdef LOG 1279610Seric if (LogLevel > 0) 12857663Seric syslog(LOG_ALERT, "problem creating SMTP socket"); 12956795Seric # endif /* LOG */ 1309610Seric finis(); 1319610Seric } 13210347Seric 13310347Seric /* turn on network debugging? */ 13456328Seric if (tTd(15, 101)) 13524945Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 13610347Seric 13725027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 13825027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 13925027Seric 14064391Seric #ifdef SO_RCVBUF 14164391Seric if (TcpRcvBufferSize > 0) 14264391Seric { 14364391Seric if (setsockopt(DaemonSocket, SOL_SOCKET, SO_RCVBUF, 14464561Seric (char *) &TcpRcvBufferSize, 14564391Seric sizeof(TcpRcvBufferSize)) < 0) 14664391Seric syserr("getrequests: setsockopt(SO_RCVBUF)"); 14764391Seric } 14864391Seric #endif 14964391Seric 15059041Seric switch (DaemonAddr.sa.sa_family) 1519610Seric { 15259041Seric # ifdef NETINET 15359041Seric case AF_INET: 15459041Seric t = sizeof DaemonAddr.sin; 15559041Seric break; 15659041Seric # endif 15759041Seric 15859041Seric # ifdef NETISO 15959041Seric case AF_ISO: 16059041Seric t = sizeof DaemonAddr.siso; 16159041Seric break; 16259041Seric # endif 16359041Seric 16459041Seric default: 16559041Seric t = sizeof DaemonAddr; 16659041Seric break; 16759041Seric } 16859041Seric 16959041Seric if (bind(DaemonSocket, &DaemonAddr.sa, t) < 0) 17059041Seric { 1719610Seric syserr("getrequests: cannot bind"); 17210206Seric (void) close(DaemonSocket); 1739610Seric goto severe; 1749610Seric } 1759610Seric 17664035Seric (void) setsignal(SIGCHLD, reapchild); 17724945Seric 17858419Seric /* write the pid to the log file for posterity */ 17958419Seric pidf = fopen(PidFile, "w"); 18058419Seric if (pidf != NULL) 18158419Seric { 18263863Seric extern char *CommandLineArgs; 18363863Seric 18463863Seric /* write the process id on line 1 */ 18558419Seric fprintf(pidf, "%d\n", getpid()); 18663863Seric 18763863Seric /* line 2 contains all command line flags */ 18863863Seric fprintf(pidf, "%s\n", CommandLineArgs); 18963863Seric 19063863Seric /* flush and close */ 19158419Seric fclose(pidf); 19258419Seric } 19358419Seric 19458419Seric 1959610Seric if (tTd(15, 1)) 19610206Seric printf("getrequests: %d\n", DaemonSocket); 1979610Seric 1984631Seric for (;;) 1994631Seric { 20014875Seric register int pid; 20111147Seric auto int lotherend; 20253751Seric extern bool refuseconnections(); 20311147Seric 20414875Seric /* see if we are rejecting connections */ 20553751Seric CurrentLA = getla(); 20653751Seric if (refuseconnections()) 20736584Sbostic { 20853751Seric if (!refusingconnections) 20953751Seric { 21053751Seric /* don't queue so peer will fail quickly */ 21153751Seric (void) listen(DaemonSocket, 0); 21253751Seric refusingconnections = TRUE; 21353751Seric } 21457385Seric setproctitle("rejecting connections: load average: %d", 21557385Seric CurrentLA); 21614875Seric sleep(5); 21753751Seric continue; 21836584Sbostic } 21914875Seric 22053751Seric if (refusingconnections) 22153751Seric { 22253751Seric /* start listening again */ 22359783Seric if (listen(DaemonSocket, ListenQueueSize) < 0) 22453751Seric { 22553751Seric syserr("getrequests: cannot listen"); 22653751Seric (void) close(DaemonSocket); 22753751Seric goto severe; 22853751Seric } 22953751Seric setproctitle("accepting connections"); 23053751Seric refusingconnections = FALSE; 23153751Seric } 23253751Seric 2339610Seric /* wait for a connection */ 2349610Seric do 2359610Seric { 2369610Seric errno = 0; 23736230Skarels lotherend = sizeof RealHostAddr; 23846928Sbostic t = accept(DaemonSocket, 23946928Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 2409610Seric } while (t < 0 && errno == EINTR); 2419610Seric if (t < 0) 2425978Seric { 2439610Seric syserr("getrequests: accept"); 2449610Seric sleep(5); 2459610Seric continue; 2465978Seric } 2474631Seric 2485978Seric /* 2495978Seric ** Create a subprocess to process the mail. 2505978Seric */ 2515978Seric 2527677Seric if (tTd(15, 2)) 2539610Seric printf("getrequests: forking (fd = %d)\n", t); 2545978Seric 2554636Seric pid = fork(); 2564636Seric if (pid < 0) 2574631Seric { 2584636Seric syserr("daemon: cannot fork"); 2594636Seric sleep(10); 2609610Seric (void) close(t); 2614636Seric continue; 2624631Seric } 2634631Seric 2644636Seric if (pid == 0) 2654631Seric { 26664086Seric char *p; 26758951Seric extern char *hostnamebyanyaddr(); 26811147Seric 2694636Seric /* 2704636Seric ** CHILD -- return to caller. 27111147Seric ** Collect verified idea of sending host. 2724636Seric ** Verify calling user id if possible here. 2734636Seric */ 2744631Seric 27564035Seric (void) setsignal(SIGCHLD, SIG_DFL); 27659156Seric OpMode = MD_SMTP; 27724950Seric 27811147Seric /* determine host name */ 27964086Seric p = hostnamebyanyaddr(&RealHostAddr); 28064086Seric RealHostName = newstr(p); 28158778Seric 28255173Seric #ifdef LOG 28363842Seric if (LogLevel > 11) 28455173Seric { 28555173Seric /* log connection information */ 28655173Seric syslog(LOG_INFO, "connect from %s (%s)", 28758951Seric RealHostName, anynet_ntoa(&RealHostAddr)); 28855173Seric } 28955173Seric #endif 29055173Seric 29159254Seric (void) close(DaemonSocket); 292*64724Seric if ((InChannel = fdopen(t, "r")) == NULL || 293*64724Seric (t = dup(t)) < 0 || 294*64724Seric (OutChannel = fdopen(t, "w")) == NULL) 295*64724Seric { 296*64724Seric syserr("cannot open SMTP server channel, fd=%d", t); 297*64724Seric exit(0); 298*64724Seric } 29959254Seric 30016884Seric /* should we check for illegal connection here? XXX */ 30159156Seric #ifdef XLA 30259156Seric if (!xla_host_ok(RealHostName)) 30359156Seric { 30459254Seric message("421 Too many SMTP sessions for this host"); 30559156Seric exit(0); 30659156Seric } 30759156Seric #endif 30816884Seric 3097677Seric if (tTd(15, 2)) 3105978Seric printf("getreq: returning\n"); 3114636Seric return; 3124631Seric } 3134631Seric 3147117Seric /* close the port so that others will hang (for a while) */ 3159610Seric (void) close(t); 3164631Seric } 3179886Seric /*NOTREACHED*/ 3184631Seric } 3195978Seric /* 32010206Seric ** CLRDAEMON -- reset the daemon connection 32110206Seric ** 32210206Seric ** Parameters: 32310206Seric ** none. 32410206Seric ** 32510206Seric ** Returns: 32610206Seric ** none. 32710206Seric ** 32810206Seric ** Side Effects: 32910206Seric ** releases any resources used by the passive daemon. 33010206Seric */ 33110206Seric 33210206Seric clrdaemon() 33310206Seric { 33410206Seric if (DaemonSocket >= 0) 33510206Seric (void) close(DaemonSocket); 33610206Seric DaemonSocket = -1; 33710206Seric } 33810206Seric /* 33958849Seric ** SETDAEMONOPTIONS -- set options for running the daemon 34058849Seric ** 34158849Seric ** Parameters: 34258849Seric ** p -- the options line. 34358849Seric ** 34458849Seric ** Returns: 34558849Seric ** none. 34658849Seric */ 34758849Seric 34858849Seric setdaemonoptions(p) 34958849Seric register char *p; 35058849Seric { 35158873Seric if (DaemonAddr.sa.sa_family == AF_UNSPEC) 35258873Seric DaemonAddr.sa.sa_family = AF_INET; 35358873Seric 35458849Seric while (p != NULL) 35558849Seric { 35658849Seric register char *f; 35758849Seric register char *v; 35858849Seric 35958849Seric while (isascii(*p) && isspace(*p)) 36058849Seric p++; 36158849Seric if (*p == '\0') 36258849Seric break; 36358849Seric f = p; 36458849Seric p = strchr(p, ','); 36558849Seric if (p != NULL) 36658849Seric *p++ = '\0'; 36758849Seric v = strchr(f, '='); 36858849Seric if (v == NULL) 36958849Seric continue; 37058849Seric while (isascii(*++v) && isspace(*v)) 37158849Seric continue; 37258849Seric 37358849Seric switch (*f) 37458849Seric { 37558873Seric case 'F': /* address family */ 37658849Seric if (isascii(*v) && isdigit(*v)) 37758873Seric DaemonAddr.sa.sa_family = atoi(v); 37858873Seric #ifdef NETINET 37958873Seric else if (strcasecmp(v, "inet") == 0) 38058873Seric DaemonAddr.sa.sa_family = AF_INET; 38158873Seric #endif 38258873Seric #ifdef NETISO 38358873Seric else if (strcasecmp(v, "iso") == 0) 38458873Seric DaemonAddr.sa.sa_family = AF_ISO; 38558873Seric #endif 38658873Seric #ifdef NETNS 38758873Seric else if (strcasecmp(v, "ns") == 0) 38858873Seric DaemonAddr.sa.sa_family = AF_NS; 38958873Seric #endif 39058873Seric #ifdef NETX25 39158873Seric else if (strcasecmp(v, "x.25") == 0) 39258873Seric DaemonAddr.sa.sa_family = AF_CCITT; 39358873Seric #endif 39458849Seric else 39558873Seric syserr("554 Unknown address family %s in Family=option", v); 39658873Seric break; 39758873Seric 39858873Seric case 'A': /* address */ 39958873Seric switch (DaemonAddr.sa.sa_family) 40058849Seric { 40158873Seric #ifdef NETINET 40258873Seric case AF_INET: 40358873Seric if (isascii(*v) && isdigit(*v)) 40458873Seric DaemonAddr.sin.sin_addr.s_addr = inet_network(v); 40558873Seric else 40658873Seric { 40758873Seric register struct netent *np; 40858849Seric 40958873Seric np = getnetbyname(v); 41058873Seric if (np == NULL) 41158873Seric syserr("554 network \"%s\" unknown", v); 41258873Seric else 41358873Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 41458873Seric } 41558873Seric break; 41658873Seric #endif 41758873Seric 41858873Seric default: 41958873Seric syserr("554 Address= option unsupported for family %d", 42058873Seric DaemonAddr.sa.sa_family); 42158873Seric break; 42258849Seric } 42358849Seric break; 42458849Seric 42558873Seric case 'P': /* port */ 42658873Seric switch (DaemonAddr.sa.sa_family) 42758849Seric { 42858873Seric short port; 42958849Seric 43058873Seric #ifdef NETINET 43158873Seric case AF_INET: 43258873Seric if (isascii(*v) && isdigit(*v)) 43364366Seric DaemonAddr.sin.sin_port = htons(atoi(v)); 43458849Seric else 43558873Seric { 43658873Seric register struct servent *sp; 43758873Seric 43858873Seric sp = getservbyname(v, "tcp"); 43958873Seric if (sp == NULL) 44058909Seric syserr("554 service \"%s\" unknown", v); 44158873Seric else 44258873Seric DaemonAddr.sin.sin_port = sp->s_port; 44358873Seric } 44458873Seric break; 44558873Seric #endif 44658873Seric 44758873Seric #ifdef NETISO 44858873Seric case AF_ISO: 44958873Seric /* assume two byte transport selector */ 45058873Seric if (isascii(*v) && isdigit(*v)) 45164366Seric port = htons(atoi(v)); 45258873Seric else 45358873Seric { 45458873Seric register struct servent *sp; 45558873Seric 45658873Seric sp = getservbyname(v, "tcp"); 45758873Seric if (sp == NULL) 45858909Seric syserr("554 service \"%s\" unknown", v); 45958873Seric else 46058873Seric port = sp->s_port; 46158873Seric } 46258873Seric bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 46358873Seric break; 46458873Seric #endif 46558873Seric 46658873Seric default: 46758873Seric syserr("554 Port= option unsupported for family %d", 46858873Seric DaemonAddr.sa.sa_family); 46958873Seric break; 47058849Seric } 47158849Seric break; 47259783Seric 47359783Seric case 'L': /* listen queue size */ 47459783Seric ListenQueueSize = atoi(v); 47559783Seric break; 47664381Seric 47764381Seric case 'S': /* send buffer size */ 47864381Seric TcpSndBufferSize = atoi(v); 47964381Seric break; 48064381Seric 48164381Seric case 'R': /* receive buffer size */ 48264381Seric TcpRcvBufferSize = atoi(v); 48364381Seric break; 48458849Seric } 48558849Seric } 48658849Seric } 48758849Seric /* 4886039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 4896039Seric ** 4906039Seric ** Parameters: 4916039Seric ** host -- the name of the host. 4926633Seric ** port -- the port number to connect to. 49353739Seric ** mci -- a pointer to the mail connection information 49453739Seric ** structure to be filled in. 49552106Seric ** usesecureport -- if set, use a low numbered (reserved) 49652106Seric ** port to provide some rudimentary authentication. 4976039Seric ** 4986039Seric ** Returns: 4996039Seric ** An exit code telling whether the connection could be 5006039Seric ** made and if not why not. 5016039Seric ** 5026039Seric ** Side Effects: 5036039Seric ** none. 5046039Seric */ 5055978Seric 50658755Seric SOCKADDR CurHostAddr; /* address of current host */ 50758305Seric 50854967Seric int 50953739Seric makeconnection(host, port, mci, usesecureport) 5106039Seric char *host; 5117286Seric u_short port; 51254967Seric register MCI *mci; 51352106Seric bool usesecureport; 5146039Seric { 51529430Sbloom register int i, s; 51629430Sbloom register struct hostent *hp = (struct hostent *)NULL; 51758755Seric SOCKADDR addr; 51852106Seric int sav_errno; 51958755Seric int addrlen; 52035651Seric #ifdef NAMED_BIND 52135651Seric extern int h_errno; 52235651Seric #endif 5236039Seric 5246039Seric /* 5256039Seric ** Set up the address for the mailer. 5269308Seric ** Accept "[a.b.c.d]" syntax for host name. 5276039Seric */ 5286039Seric 52935651Seric #ifdef NAMED_BIND 53025475Smiriam h_errno = 0; 53135651Seric #endif 53225475Smiriam errno = 0; 53358864Seric bzero(&CurHostAddr, sizeof CurHostAddr); 53464334Seric SmtpPhase = mci->mci_phase = "initial connection"; 53558906Seric CurHostName = host; 53625475Smiriam 5379308Seric if (host[0] == '[') 5389308Seric { 53911147Seric long hid; 54056795Seric register char *p = strchr(host, ']'); 5419308Seric 54211147Seric if (p != NULL) 5439308Seric { 54411147Seric *p = '\0'; 54559884Seric #ifdef NETINET 54611147Seric hid = inet_addr(&host[1]); 54758360Seric if (hid == -1) 54859884Seric #endif 54958360Seric { 55058360Seric /* try it as a host name (avoid MX lookup) */ 55158360Seric hp = gethostbyname(&host[1]); 55258360Seric *p = ']'; 55358360Seric goto gothostent; 55458360Seric } 55511147Seric *p = ']'; 5569308Seric } 55758360Seric if (p == NULL) 5589308Seric { 55958151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 5609308Seric return (EX_NOHOST); 5619308Seric } 56259884Seric #ifdef NETINET 56359884Seric addr.sin.sin_family = AF_INET; /*XXX*/ 56458778Seric addr.sin.sin_addr.s_addr = hid; 56559884Seric #endif 5669308Seric } 5679610Seric else 5689610Seric { 56929430Sbloom hp = gethostbyname(host); 57058360Seric gothostent: 57125475Smiriam if (hp == NULL) 57224945Seric { 57335651Seric #ifdef NAMED_BIND 57425475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 57525475Smiriam return (EX_TEMPFAIL); 57625657Seric 57735651Seric /* if name server is specified, assume temp fail */ 57835651Seric if (errno == ECONNREFUSED && UseNameServer) 57935651Seric return (EX_TEMPFAIL); 58035651Seric #endif 58125475Smiriam return (EX_NOHOST); 58224945Seric } 58358778Seric addr.sa.sa_family = hp->h_addrtype; 58458778Seric switch (hp->h_addrtype) 58558778Seric { 58658778Seric #ifdef NETINET 58758778Seric case AF_INET: 58858755Seric bcopy(hp->h_addr, 58958778Seric &addr.sin.sin_addr, 59058755Seric hp->h_length); 59158778Seric break; 59258778Seric #endif 59358778Seric 59458778Seric default: 59558755Seric bcopy(hp->h_addr, 59658778Seric addr.sa.sa_data, 59758755Seric hp->h_length); 59858778Seric break; 59958778Seric } 60029430Sbloom i = 1; 6019610Seric } 6029610Seric 6039610Seric /* 6049610Seric ** Determine the port number. 6059610Seric */ 6069610Seric 60710011Seric if (port != 0) 60858755Seric port = htons(port); 60910011Seric else 6109610Seric { 6119610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 6129610Seric 6139610Seric if (sp == NULL) 6149610Seric { 61558909Seric syserr("554 makeconnection: service \"smtp\" unknown"); 61657977Seric return (EX_OSERR); 6179610Seric } 61858755Seric port = sp->s_port; 6199610Seric } 6206039Seric 62158778Seric switch (addr.sa.sa_family) 62258755Seric { 62359884Seric #ifdef NETINET 62458755Seric case AF_INET: 62558778Seric addr.sin.sin_port = port; 62658755Seric addrlen = sizeof (struct sockaddr_in); 62758755Seric break; 62859884Seric #endif 62958755Seric 63058755Seric #ifdef NETISO 63158755Seric case AF_ISO: 63258755Seric /* assume two byte transport selector */ 63358755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 63458755Seric addrlen = sizeof (struct sockaddr_iso); 63558755Seric break; 63658755Seric #endif 63758755Seric 63858755Seric default: 63958778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 64058755Seric return (EX_NOHOST); 64158755Seric } 64258755Seric 6436039Seric /* 6446039Seric ** Try to actually open the connection. 6456039Seric */ 6466039Seric 64759156Seric #ifdef XLA 64859156Seric /* if too many connections, don't bother trying */ 64959156Seric if (!xla_noqueue_ok(host)) 65059156Seric return EX_TEMPFAIL; 65159156Seric #endif 65259156Seric 65357736Seric for (;;) 65452106Seric { 65557736Seric if (tTd(16, 1)) 65658755Seric printf("makeconnection (%s [%s])\n", 65758755Seric host, anynet_ntoa(&addr)); 65852106Seric 65958588Seric /* save for logging */ 66058588Seric CurHostAddr = addr; 66158588Seric 66257736Seric if (usesecureport) 66357736Seric { 66457736Seric int rport = IPPORT_RESERVED - 1; 6656039Seric 66657736Seric s = rresvport(&rport); 66757736Seric } 66857736Seric else 66957736Seric { 67057736Seric s = socket(AF_INET, SOCK_STREAM, 0); 67157736Seric } 67257736Seric if (s < 0) 67357736Seric { 67457736Seric sav_errno = errno; 67557736Seric syserr("makeconnection: no socket"); 67657736Seric goto failure; 67757736Seric } 67810347Seric 67964381Seric #ifdef SO_SNDBUF 68064381Seric if (TcpSndBufferSize > 0) 68164381Seric { 68264381Seric if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 68364561Seric (char *) &TcpSndBufferSize, 68464381Seric sizeof(TcpSndBufferSize)) < 0) 68564381Seric syserr("makeconnection: setsockopt(SO_SNDBUF)"); 68664381Seric } 68764381Seric #endif 68864381Seric 68957736Seric if (tTd(16, 1)) 69057736Seric printf("makeconnection: fd=%d\n", s); 69157736Seric 69257736Seric /* turn on network debugging? */ 69357736Seric if (tTd(16, 101)) 69457736Seric { 69557736Seric int on = 1; 69657736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 69757736Seric (char *)&on, sizeof on); 69857736Seric } 69957736Seric if (CurEnv->e_xfp != NULL) 70057736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 70157736Seric errno = 0; /* for debugging */ 70258755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 70357736Seric break; 70457736Seric 70557736Seric /* couldn't connect.... figure out why */ 70627744Sbloom sav_errno = errno; 70727744Sbloom (void) close(s); 70829430Sbloom if (hp && hp->h_addr_list[i]) 70929430Sbloom { 71057736Seric if (tTd(16, 1)) 71158755Seric printf("Connect failed (%s); trying new address....\n", 71258755Seric errstring(sav_errno)); 71358778Seric switch (addr.sa.sa_family) 71458778Seric { 71558778Seric #ifdef NETINET 71658778Seric case AF_INET: 71758755Seric bcopy(hp->h_addr_list[i++], 71858778Seric &addr.sin.sin_addr, 71958755Seric hp->h_length); 72058778Seric break; 72158778Seric #endif 72258778Seric 72358778Seric default: 72458755Seric bcopy(hp->h_addr_list[i++], 72558778Seric addr.sa.sa_data, 72652106Seric hp->h_length); 72758778Seric break; 72858778Seric } 72957736Seric continue; 73029430Sbloom } 73129430Sbloom 7326039Seric /* failure, decide if temporary or not */ 7336039Seric failure: 73459254Seric #ifdef XLA 73559254Seric xla_host_end(host); 73659254Seric #endif 73758542Seric if (transienterror(sav_errno)) 73858542Seric return EX_TEMPFAIL; 73958542Seric else 74058542Seric { 74158542Seric message("%s", errstring(sav_errno)); 74258542Seric return (EX_UNAVAILABLE); 7436039Seric } 7446039Seric } 7456039Seric 7466039Seric /* connection ok, put it into canonical form */ 747*64724Seric if ((mci->mci_out = fdopen(s, "w")) == NULL || 748*64724Seric (s = dup(s)) < 0 || 749*64724Seric (mci->mci_in = fdopen(dup(s), "r")) == NULL) 750*64724Seric { 751*64724Seric syserr("cannot open SMTP client channel, fd=%d", s); 752*64724Seric return EX_TEMPFAIL; 753*64724Seric } 7546039Seric 75510098Seric return (EX_OK); 7566039Seric } 75710758Seric /* 75810758Seric ** MYHOSTNAME -- return the name of this host. 75910758Seric ** 76010758Seric ** Parameters: 76110758Seric ** hostbuf -- a place to return the name of this host. 76212313Seric ** size -- the size of hostbuf. 76310758Seric ** 76410758Seric ** Returns: 76510758Seric ** A list of aliases for this host. 76610758Seric ** 76710758Seric ** Side Effects: 76864338Seric ** Adds numeric codes to $=w. 76910758Seric */ 7706039Seric 77110758Seric char ** 77212313Seric myhostname(hostbuf, size) 77310758Seric char hostbuf[]; 77412313Seric int size; 77510758Seric { 77658110Seric register struct hostent *hp; 77710758Seric extern struct hostent *gethostbyname(); 77810758Seric 77923120Seric if (gethostname(hostbuf, size) < 0) 78023120Seric { 78123120Seric (void) strcpy(hostbuf, "localhost"); 78223120Seric } 78311147Seric hp = gethostbyname(hostbuf); 78411147Seric if (hp != NULL) 78516877Seric { 78658110Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 78758110Seric hostbuf[size - 1] = '\0'; 78858110Seric 78958110Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 79058110Seric { 79158110Seric register int i; 79258110Seric 79364338Seric for (i = 0; hp->h_addr_list[i] != NULL; i++) 79458110Seric { 79564338Seric char ipbuf[100]; 79664338Seric 79764338Seric sprintf(ipbuf, "[%s]", 79864338Seric inet_ntoa(*((struct in_addr *) hp->h_addr_list[i]))); 79964338Seric setclass('w', ipbuf); 80058110Seric } 80158110Seric } 80258110Seric 80311147Seric return (hp->h_aliases); 80416877Seric } 80510758Seric else 80610758Seric return (NULL); 80710758Seric } 80851315Seric /* 80958951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 81058308Seric ** 81158951Seric ** Uses RFC1413 protocol to try to get info from the other end. 81258951Seric ** 81358308Seric ** Parameters: 81458308Seric ** fd -- the descriptor 81558308Seric ** 81658308Seric ** Returns: 81758951Seric ** The user@host information associated with this descriptor. 81858308Seric ** 81958308Seric ** Side Effects: 82058951Seric ** Sets RealHostName to the name of the host at the other end. 82158308Seric */ 82258308Seric 82358951Seric #ifdef 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; 84258951Seric #ifdef 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; 85558951Seric if (getpeername(fd, &fa.sa, &falen) < 0 || falen <= 0) 85658951Seric { 85758951Seric RealHostName = "localhost"; 85858951Seric (void) sprintf(hbuf, "%s@localhost", RealUserName); 85958957Seric if (tTd(9, 1)) 86058951Seric printf("getauthinfo: %s\n", hbuf); 86158951Seric return hbuf; 86258951Seric } 86358951Seric 86464086Seric p = hostnamebyanyaddr(&fa); 86564086Seric RealHostName = newstr(p); 86658951Seric RealHostAddr = fa; 86758951Seric 86858951Seric #ifdef IDENTPROTO 86958951Seric lalen = sizeof la; 87058951Seric if (fa.sa.sa_family != AF_INET || 87158951Seric getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || 87258951Seric la.sa.sa_family != AF_INET) 87358951Seric { 87458951Seric /* no ident info */ 87558951Seric goto noident; 87658951Seric } 87758951Seric 87858951Seric /* create ident query */ 87960489Seric (void) sprintf(hbuf, "%d,%d\r\n", 88060489Seric ntohs(fa.sin.sin_port), ntohs(la.sin.sin_port)); 88158951Seric 88258951Seric /* create local address */ 88358951Seric bzero(&la, sizeof la); 88458951Seric 88558951Seric /* create foreign address */ 88658951Seric sp = getservbyname("auth", "tcp"); 88758951Seric if (sp != NULL) 88858951Seric fa.sin.sin_port = sp->s_port; 88958308Seric else 89059097Seric fa.sin.sin_port = htons(113); 89158951Seric 89258951Seric s = -1; 89358951Seric if (setjmp(CtxAuthTimeout) != 0) 89458951Seric { 89558951Seric if (s >= 0) 89658951Seric (void) close(s); 89758951Seric goto noident; 89858951Seric } 89958951Seric 90058951Seric /* put a timeout around the whole thing */ 90164255Seric ev = setevent(TimeOuts.to_ident, authtimeout, 0); 90258951Seric 90358951Seric /* connect to foreign IDENT server */ 90458951Seric s = socket(AF_INET, SOCK_STREAM, 0); 90558951Seric if (s < 0) 90658951Seric { 90758951Seric clrevent(ev); 90858951Seric goto noident; 90958951Seric } 91058951Seric if (connect(s, &fa.sa, sizeof fa.sin) < 0) 91158951Seric { 91258951Seric closeident: 91358951Seric (void) close(s); 91458951Seric clrevent(ev); 91558951Seric goto noident; 91658951Seric } 91758951Seric 91858957Seric if (tTd(9, 10)) 91958951Seric printf("getauthinfo: sent %s", hbuf); 92058951Seric 92158951Seric /* send query */ 92258951Seric if (write(s, hbuf, strlen(hbuf)) < 0) 92358951Seric goto closeident; 92458951Seric 92558951Seric /* get result */ 92658951Seric i = read(s, hbuf, sizeof hbuf); 92758951Seric (void) close(s); 92858951Seric clrevent(ev); 92958951Seric if (i <= 0) 93058951Seric goto noident; 93158951Seric if (hbuf[--i] == '\n' && hbuf[--i] == '\r') 93258951Seric i--; 93358951Seric hbuf[++i] = '\0'; 93458951Seric 93558957Seric if (tTd(9, 3)) 93658951Seric printf("getauthinfo: got %s\n", hbuf); 93758951Seric 93858951Seric /* parse result */ 93958951Seric p = strchr(hbuf, ':'); 94058951Seric if (p == NULL) 94158951Seric { 94258951Seric /* malformed response */ 94358951Seric goto noident; 94458951Seric } 94558951Seric while (isascii(*++p) && isspace(*p)) 94658951Seric continue; 94758951Seric if (strncasecmp(p, "userid", 6) != 0) 94858951Seric { 94958951Seric /* presumably an error string */ 95058951Seric goto noident; 95158951Seric } 95258951Seric p += 6; 95358951Seric while (isascii(*p) && isspace(*p)) 95458951Seric p++; 95558951Seric if (*p++ != ':') 95658951Seric { 95758951Seric /* either useridxx or malformed response */ 95858951Seric goto noident; 95958951Seric } 96058951Seric 96158951Seric /* p now points to the OSTYPE field */ 96258951Seric p = strchr(p, ':'); 96358951Seric if (p == NULL) 96458951Seric { 96558951Seric /* malformed response */ 96658951Seric goto noident; 96758951Seric } 96858951Seric 96958957Seric /* 1413 says don't do this -- but it's broken otherwise */ 97058957Seric while (isascii(*++p) && isspace(*p)) 97158957Seric continue; 97258957Seric 97358951Seric /* p now points to the authenticated name */ 97458951Seric (void) sprintf(hbuf, "%s@%s", p, RealHostName); 97558957Seric goto finish; 97658957Seric 97758957Seric #endif /* IDENTPROTO */ 97858957Seric 97958957Seric noident: 98058957Seric (void) strcpy(hbuf, RealHostName); 98158957Seric 98258957Seric finish: 98358951Seric if (RealHostName[0] != '[') 98458951Seric { 98558951Seric p = &hbuf[strlen(hbuf)]; 98658951Seric (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); 98758951Seric } 98858957Seric if (tTd(9, 1)) 98958951Seric printf("getauthinfo: %s\n", hbuf); 99058308Seric return hbuf; 99158308Seric } 99258308Seric /* 99360089Seric ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 99453751Seric ** 99553751Seric ** Parameters: 99656823Seric ** map -- a pointer to this map (unused). 99760089Seric ** name -- the (presumably unqualified) hostname. 99860257Seric ** av -- unused -- for compatibility with other mapping 99955019Seric ** functions. 100059084Seric ** statp -- an exit status (out parameter) -- set to 100159084Seric ** EX_TEMPFAIL if the name server is unavailable. 100253751Seric ** 100353751Seric ** Returns: 100453751Seric ** The mapping, if found. 100553751Seric ** NULL if no mapping found. 100653751Seric ** 100753751Seric ** Side Effects: 100853751Seric ** Looks up the host specified in hbuf. If it is not 100953751Seric ** the canonical name for that host, return the canonical 101053751Seric ** name. 101153751Seric */ 101251315Seric 101353751Seric char * 101460257Seric host_map_lookup(map, name, av, statp) 101556823Seric MAP *map; 101660089Seric char *name; 101760257Seric char **av; 101859084Seric int *statp; 101916911Seric { 102016911Seric register struct hostent *hp; 102133932Sbostic u_long in_addr; 102256823Seric char *cp; 102358110Seric int i; 102459671Seric register STAB *s; 102560257Seric char hbuf[MAXNAME]; 102659671Seric extern struct hostent *gethostbyaddr(); 102759671Seric extern int h_errno; 102816911Seric 102925574Smiriam /* 103059671Seric ** See if we have already looked up this name. If so, just 103159671Seric ** return it. 103259671Seric */ 103353751Seric 103460089Seric s = stab(name, ST_NAMECANON, ST_ENTER); 103559671Seric if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 103659671Seric { 103759986Seric if (tTd(9, 1)) 103860089Seric printf("host_map_lookup(%s) => CACHE %s\n", 103960089Seric name, s->s_namecanon.nc_cname); 104059671Seric errno = s->s_namecanon.nc_errno; 104159671Seric h_errno = s->s_namecanon.nc_herrno; 104259671Seric *statp = s->s_namecanon.nc_stat; 104359671Seric return s->s_namecanon.nc_cname; 104459671Seric } 104559671Seric 104659671Seric /* 104759671Seric ** If first character is a bracket, then it is an address 104859671Seric ** lookup. Address is copied into a temporary buffer to 104960089Seric ** strip the brackets and to preserve name if address is 105059671Seric ** unknown. 105159671Seric */ 105259671Seric 105360089Seric if (*name != '[') 105453751Seric { 105555019Seric extern bool getcanonname(); 105655019Seric 105758798Seric if (tTd(9, 1)) 105860089Seric printf("host_map_lookup(%s) => ", name); 105959671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 106060089Seric (void) strcpy(hbuf, name); 106163842Seric if (getcanonname(hbuf, sizeof hbuf - 1, TRUE)) 106258796Seric { 106358796Seric if (tTd(9, 1)) 106458796Seric printf("%s\n", hbuf); 106560257Seric cp = map_rewrite(map, hbuf, strlen(hbuf), av); 106660257Seric s->s_namecanon.nc_cname = newstr(cp); 106760257Seric return cp; 106858796Seric } 106953751Seric else 107058796Seric { 107159084Seric register struct hostent *hp; 107259084Seric 107358796Seric if (tTd(9, 1)) 107459084Seric printf("FAIL (%d)\n", h_errno); 107559671Seric s->s_namecanon.nc_errno = errno; 107659671Seric s->s_namecanon.nc_herrno = h_errno; 107759084Seric switch (h_errno) 107859084Seric { 107959084Seric case TRY_AGAIN: 108059596Seric if (UseNameServer) 108159734Seric { 108259734Seric char *msg = "Recipient domain nameserver timed out"; 108359734Seric 108459734Seric message(msg); 108559734Seric if (CurEnv->e_message == NULL) 108660009Seric CurEnv->e_message = newstr(msg); 108759734Seric } 108859084Seric *statp = EX_TEMPFAIL; 108959084Seric break; 109059084Seric 109159084Seric case HOST_NOT_FOUND: 109259084Seric *statp = EX_NOHOST; 109359084Seric break; 109459084Seric 109559084Seric case NO_RECOVERY: 109659084Seric *statp = EX_SOFTWARE; 109759084Seric break; 109859084Seric 109959084Seric default: 110059084Seric *statp = EX_UNAVAILABLE; 110159084Seric break; 110259084Seric } 110359671Seric s->s_namecanon.nc_stat = *statp; 110459084Seric if (*statp != EX_TEMPFAIL || UseNameServer) 110559084Seric return NULL; 110659084Seric 110759084Seric /* 110859084Seric ** Try to look it up in /etc/hosts 110959084Seric */ 111059084Seric 111160089Seric hp = gethostbyname(name); 111259084Seric if (hp == NULL) 111359084Seric { 111459084Seric /* no dice there either */ 111559671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 111659084Seric return NULL; 111759084Seric } 111859084Seric 111959671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 112060257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 112160257Seric s->s_namecanon.nc_cname = newstr(cp); 112260257Seric return cp; 112358796Seric } 112453751Seric } 112560089Seric if ((cp = strchr(name, ']')) == NULL) 112653751Seric return (NULL); 112740994Sbostic *cp = '\0'; 112860089Seric in_addr = inet_addr(&name[1]); 112958110Seric 113058110Seric /* nope -- ask the name server */ 113133932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 113259671Seric s->s_namecanon.nc_errno = errno; 113359671Seric s->s_namecanon.nc_herrno = h_errno; 113459671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 113533932Sbostic if (hp == NULL) 113659671Seric { 113759671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 113853751Seric return (NULL); 113959671Seric } 114053751Seric 114158110Seric /* found a match -- copy out */ 114260257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 114359671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 114460257Seric s->s_namecanon.nc_cname = newstr(cp); 114560257Seric return cp; 114633932Sbostic } 114758755Seric /* 114858755Seric ** ANYNET_NTOA -- convert a network address to printable form. 114958755Seric ** 115058755Seric ** Parameters: 115158755Seric ** sap -- a pointer to a sockaddr structure. 115258755Seric ** 115358755Seric ** Returns: 115458755Seric ** A printable version of that sockaddr. 115558755Seric */ 115616911Seric 115758755Seric char * 115858755Seric anynet_ntoa(sap) 115958755Seric register SOCKADDR *sap; 116058755Seric { 116158755Seric register char *bp; 116258755Seric register char *ap; 116358755Seric int l; 116458755Seric static char buf[80]; 116558755Seric 116658798Seric /* check for null/zero family */ 116758798Seric if (sap == NULL) 116858798Seric return "NULLADDR"; 116958798Seric if (sap->sa.sa_family == 0) 117058798Seric return "0"; 117158798Seric 117258778Seric #ifdef NETINET 117358778Seric if (sap->sa.sa_family == AF_INET) 117458755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 117558778Seric #endif 117658755Seric 117758755Seric /* unknown family -- just dump bytes */ 117858778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 117958755Seric bp = &buf[strlen(buf)]; 118058778Seric ap = sap->sa.sa_data; 118158778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 118258755Seric { 118358755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 118458755Seric bp += 3; 118558755Seric } 118658755Seric *--bp = '\0'; 118758755Seric return buf; 118858755Seric } 118958951Seric /* 119058951Seric ** HOSTNAMEBYANYADDR -- return name of host based on address 119158951Seric ** 119258951Seric ** Parameters: 119358951Seric ** sap -- SOCKADDR pointer 119458951Seric ** 119558951Seric ** Returns: 119658951Seric ** text representation of host name. 119758951Seric ** 119858951Seric ** Side Effects: 119958951Seric ** none. 120058951Seric */ 120158755Seric 120258951Seric char * 120358951Seric hostnamebyanyaddr(sap) 120458951Seric register SOCKADDR *sap; 120558951Seric { 120658951Seric register struct hostent *hp; 120758951Seric 120859042Seric #ifdef NAMED_BIND 120959042Seric int saveretry; 121059042Seric 121159042Seric /* shorten name server timeout to avoid higher level timeouts */ 121259042Seric saveretry = _res.retry; 121359042Seric _res.retry = 3; 121459042Seric #endif /* NAMED_BIND */ 121559042Seric 121658951Seric switch (sap->sa.sa_family) 121758951Seric { 121858951Seric #ifdef NETINET 121958951Seric case AF_INET: 122058951Seric hp = gethostbyaddr((char *) &sap->sin.sin_addr, 122158951Seric sizeof sap->sin.sin_addr, 122258951Seric AF_INET); 122358951Seric break; 122458951Seric #endif 122558951Seric 122658951Seric #ifdef NETISO 122758951Seric case AF_ISO: 122858951Seric hp = gethostbyaddr((char *) &sap->siso.siso_addr, 122958951Seric sizeof sap->siso.siso_addr, 123058951Seric AF_ISO); 123158951Seric break; 123258951Seric #endif 123358951Seric 123458951Seric default: 123558951Seric hp = gethostbyaddr(sap->sa.sa_data, 123658951Seric sizeof sap->sa.sa_data, 123758951Seric sap->sa.sa_family); 123858951Seric break; 123958951Seric } 124058951Seric 124159042Seric #ifdef NAMED_BIND 124259042Seric _res.retry = saveretry; 124359042Seric #endif /* NAMED_BIND */ 124459042Seric 124558951Seric if (hp != NULL) 124658951Seric return hp->h_name; 124758951Seric else 124858951Seric { 124958951Seric /* produce a dotted quad */ 125058951Seric static char buf[512]; 125158951Seric 125258951Seric (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); 125358951Seric return buf; 125458951Seric } 125558951Seric } 125658951Seric 125756795Seric # else /* DAEMON */ 125816911Seric /* code for systems without sophisticated networking */ 125910758Seric 126010758Seric /* 126110758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 126211297Seric ** 126311297Seric ** Can't convert to upper case here because might be a UUCP name. 126412313Seric ** 126512313Seric ** Mark, you can change this to be anything you want...... 126610758Seric */ 126710758Seric 126810758Seric char ** 126912313Seric myhostname(hostbuf, size) 127010758Seric char hostbuf[]; 127112313Seric int size; 127210758Seric { 127310758Seric register FILE *f; 127410758Seric 127510758Seric hostbuf[0] = '\0'; 127610758Seric f = fopen("/usr/include/whoami", "r"); 127710758Seric if (f != NULL) 127810758Seric { 127912313Seric (void) fgets(hostbuf, size, f); 128010758Seric fixcrlf(hostbuf, TRUE); 128110758Seric (void) fclose(f); 128210758Seric } 128310758Seric return (NULL); 128410758Seric } 128516911Seric /* 128658951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 128758308Seric ** 128858308Seric ** Parameters: 128958308Seric ** fd -- the descriptor 129058308Seric ** 129158308Seric ** Returns: 129258308Seric ** The host name associated with this descriptor, if it can 129358308Seric ** be determined. 129458308Seric ** NULL otherwise. 129558308Seric ** 129658308Seric ** Side Effects: 129758308Seric ** none 129858308Seric */ 129958308Seric 130058308Seric char * 130158951Seric getauthinfo(fd) 130258308Seric int fd; 130358308Seric { 130458308Seric return NULL; 130558308Seric } 130658308Seric /* 130716911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 130816911Seric ** 130916911Seric ** Parameters: 131056823Seric ** map -- a pointer to the database map. 131160089Seric ** name -- a buffer containing a hostname. 131253751Seric ** avp -- a pointer to a (cf file defined) argument vector. 131359084Seric ** statp -- an exit status (out parameter). 131416911Seric ** 131516911Seric ** Returns: 131653751Seric ** mapped host name 131751315Seric ** FALSE otherwise. 131816911Seric ** 131916911Seric ** Side Effects: 132060089Seric ** Looks up the host specified in name. If it is not 132116911Seric ** the canonical name for that host, replace it with 132216911Seric ** the canonical name. If the name is unknown, or it 132316911Seric ** is already the canonical name, leave it unchanged. 132416911Seric */ 132510758Seric 132616911Seric /*ARGSUSED*/ 132753751Seric char * 132860089Seric host_map_lookup(map, name, avp, statp) 132956823Seric MAP *map; 133060089Seric char *name; 133153751Seric char **avp; 133259084Seric char *statp; 133316911Seric { 133459084Seric register struct hostent *hp; 133559084Seric 133660089Seric hp = gethostbyname(name); 133759084Seric if (hp != NULL) 133859084Seric return hp->h_name; 133959084Seric *statp = EX_NOHOST; 134053751Seric return NULL; 134116911Seric } 134216911Seric 134356795Seric #endif /* DAEMON */ 1344