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*65202Seric static char sccsid[] = "@(#)daemon.c 8.29 (Berkeley) 12/22/93 (with daemon mode)"; 1533780Sbostic #else 16*65202Seric static char sccsid[] = "@(#)daemon.c 8.29 (Berkeley) 12/22/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; 8725027Seric int on = 1; 8853751Seric bool refusingconnections = TRUE; 8958419Seric FILE *pidf; 9064828Seric int socksize; 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 { 10365169Seric register struct servent *sp; 10465169Seric 10558849Seric sp = getservbyname("smtp", "tcp"); 10658849Seric if (sp == NULL) 10758849Seric { 10858909Seric syserr("554 service \"smtp\" unknown"); 10965169Seric DaemonAddr.sin.sin_port = htons(25); 11058849Seric } 11165169Seric else 11265169Seric DaemonAddr.sin.sin_port = sp->s_port; 1139610Seric } 1149610Seric 1159610Seric /* 1169610Seric ** Try to actually open the connection. 1179610Seric */ 1189610Seric 1199610Seric if (tTd(15, 1)) 12058849Seric printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); 1219610Seric 1229610Seric /* get a socket for the SMTP connection */ 12359041Seric DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0); 12410206Seric if (DaemonSocket < 0) 1259610Seric { 1269610Seric /* probably another daemon already */ 1279610Seric syserr("getrequests: can't create socket"); 1289610Seric severe: 1299610Seric # ifdef LOG 1309610Seric if (LogLevel > 0) 13157663Seric syslog(LOG_ALERT, "problem creating SMTP socket"); 13256795Seric # endif /* LOG */ 1339610Seric finis(); 1349610Seric } 13510347Seric 13610347Seric /* turn on network debugging? */ 13756328Seric if (tTd(15, 101)) 13824945Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 13910347Seric 14025027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 14125027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 14225027Seric 14364391Seric #ifdef SO_RCVBUF 14464391Seric if (TcpRcvBufferSize > 0) 14564391Seric { 14664391Seric if (setsockopt(DaemonSocket, SOL_SOCKET, SO_RCVBUF, 14764561Seric (char *) &TcpRcvBufferSize, 14864391Seric sizeof(TcpRcvBufferSize)) < 0) 14964391Seric syserr("getrequests: setsockopt(SO_RCVBUF)"); 15064391Seric } 15164391Seric #endif 15264391Seric 15359041Seric switch (DaemonAddr.sa.sa_family) 1549610Seric { 15559041Seric # ifdef NETINET 15659041Seric case AF_INET: 15764828Seric socksize = sizeof DaemonAddr.sin; 15859041Seric break; 15959041Seric # endif 16059041Seric 16159041Seric # ifdef NETISO 16259041Seric case AF_ISO: 16364828Seric socksize = sizeof DaemonAddr.siso; 16459041Seric break; 16559041Seric # endif 16659041Seric 16759041Seric default: 16864828Seric socksize = sizeof DaemonAddr; 16959041Seric break; 17059041Seric } 17159041Seric 17264828Seric if (bind(DaemonSocket, &DaemonAddr.sa, socksize) < 0) 17359041Seric { 1749610Seric syserr("getrequests: cannot bind"); 17510206Seric (void) close(DaemonSocket); 1769610Seric goto severe; 1779610Seric } 1789610Seric 17964035Seric (void) setsignal(SIGCHLD, reapchild); 18024945Seric 18158419Seric /* write the pid to the log file for posterity */ 18258419Seric pidf = fopen(PidFile, "w"); 18358419Seric if (pidf != NULL) 18458419Seric { 18563863Seric extern char *CommandLineArgs; 18663863Seric 18763863Seric /* write the process id on line 1 */ 18858419Seric fprintf(pidf, "%d\n", getpid()); 18963863Seric 19063863Seric /* line 2 contains all command line flags */ 19163863Seric fprintf(pidf, "%s\n", CommandLineArgs); 19263863Seric 19363863Seric /* flush and close */ 19458419Seric fclose(pidf); 19558419Seric } 19658419Seric 19758419Seric 1989610Seric if (tTd(15, 1)) 19910206Seric printf("getrequests: %d\n", DaemonSocket); 2009610Seric 2014631Seric for (;;) 2024631Seric { 20314875Seric register int pid; 20411147Seric auto int lotherend; 20553751Seric extern bool refuseconnections(); 20611147Seric 20714875Seric /* see if we are rejecting connections */ 20853751Seric CurrentLA = getla(); 20953751Seric if (refuseconnections()) 21036584Sbostic { 21153751Seric if (!refusingconnections) 21253751Seric { 21353751Seric /* don't queue so peer will fail quickly */ 21453751Seric (void) listen(DaemonSocket, 0); 21553751Seric refusingconnections = TRUE; 21653751Seric } 21757385Seric setproctitle("rejecting connections: load average: %d", 21857385Seric CurrentLA); 21914875Seric sleep(5); 22053751Seric continue; 22136584Sbostic } 22214875Seric 22353751Seric if (refusingconnections) 22453751Seric { 22553751Seric /* start listening again */ 22659783Seric if (listen(DaemonSocket, ListenQueueSize) < 0) 22753751Seric { 22853751Seric syserr("getrequests: cannot listen"); 22953751Seric (void) close(DaemonSocket); 23053751Seric goto severe; 23153751Seric } 23253751Seric setproctitle("accepting connections"); 23353751Seric refusingconnections = FALSE; 23453751Seric } 23553751Seric 2369610Seric /* wait for a connection */ 2379610Seric do 2389610Seric { 2399610Seric errno = 0; 24064828Seric lotherend = socksize; 24146928Sbostic t = accept(DaemonSocket, 24246928Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 2439610Seric } while (t < 0 && errno == EINTR); 2449610Seric if (t < 0) 2455978Seric { 2469610Seric syserr("getrequests: accept"); 2479610Seric sleep(5); 2489610Seric continue; 2495978Seric } 2504631Seric 2515978Seric /* 2525978Seric ** Create a subprocess to process the mail. 2535978Seric */ 2545978Seric 2557677Seric if (tTd(15, 2)) 2569610Seric printf("getrequests: forking (fd = %d)\n", t); 2575978Seric 2584636Seric pid = fork(); 2594636Seric if (pid < 0) 2604631Seric { 2614636Seric syserr("daemon: cannot fork"); 2624636Seric sleep(10); 2639610Seric (void) close(t); 2644636Seric continue; 2654631Seric } 2664631Seric 2674636Seric if (pid == 0) 2684631Seric { 26964086Seric char *p; 27058951Seric extern char *hostnamebyanyaddr(); 27111147Seric 2724636Seric /* 2734636Seric ** CHILD -- return to caller. 27411147Seric ** Collect verified idea of sending host. 2754636Seric ** Verify calling user id if possible here. 2764636Seric */ 2774631Seric 27864035Seric (void) setsignal(SIGCHLD, SIG_DFL); 27959156Seric OpMode = MD_SMTP; 28024950Seric 28111147Seric /* determine host name */ 28264086Seric p = hostnamebyanyaddr(&RealHostAddr); 28364086Seric RealHostName = newstr(p); 28458778Seric 28555173Seric #ifdef LOG 28663842Seric if (LogLevel > 11) 28755173Seric { 28855173Seric /* log connection information */ 28955173Seric syslog(LOG_INFO, "connect from %s (%s)", 29058951Seric RealHostName, anynet_ntoa(&RealHostAddr)); 29155173Seric } 29255173Seric #endif 29355173Seric 29459254Seric (void) close(DaemonSocket); 29564724Seric if ((InChannel = fdopen(t, "r")) == NULL || 29664724Seric (t = dup(t)) < 0 || 29764724Seric (OutChannel = fdopen(t, "w")) == NULL) 29864724Seric { 29964724Seric syserr("cannot open SMTP server channel, fd=%d", t); 30064724Seric exit(0); 30164724Seric } 30259254Seric 30316884Seric /* should we check for illegal connection here? XXX */ 30459156Seric #ifdef XLA 30559156Seric if (!xla_host_ok(RealHostName)) 30659156Seric { 30759254Seric message("421 Too many SMTP sessions for this host"); 30859156Seric exit(0); 30959156Seric } 31059156Seric #endif 31116884Seric 3127677Seric if (tTd(15, 2)) 3135978Seric printf("getreq: returning\n"); 3144636Seric return; 3154631Seric } 3164631Seric 3177117Seric /* close the port so that others will hang (for a while) */ 3189610Seric (void) close(t); 3194631Seric } 3209886Seric /*NOTREACHED*/ 3214631Seric } 3225978Seric /* 32310206Seric ** CLRDAEMON -- reset the daemon connection 32410206Seric ** 32510206Seric ** Parameters: 32610206Seric ** none. 32710206Seric ** 32810206Seric ** Returns: 32910206Seric ** none. 33010206Seric ** 33110206Seric ** Side Effects: 33210206Seric ** releases any resources used by the passive daemon. 33310206Seric */ 33410206Seric 33510206Seric clrdaemon() 33610206Seric { 33710206Seric if (DaemonSocket >= 0) 33810206Seric (void) close(DaemonSocket); 33910206Seric DaemonSocket = -1; 34010206Seric } 34110206Seric /* 34258849Seric ** SETDAEMONOPTIONS -- set options for running the daemon 34358849Seric ** 34458849Seric ** Parameters: 34558849Seric ** p -- the options line. 34658849Seric ** 34758849Seric ** Returns: 34858849Seric ** none. 34958849Seric */ 35058849Seric 35158849Seric setdaemonoptions(p) 35258849Seric register char *p; 35358849Seric { 35458873Seric if (DaemonAddr.sa.sa_family == AF_UNSPEC) 35558873Seric DaemonAddr.sa.sa_family = AF_INET; 35658873Seric 35758849Seric while (p != NULL) 35858849Seric { 35958849Seric register char *f; 36058849Seric register char *v; 36158849Seric 36258849Seric while (isascii(*p) && isspace(*p)) 36358849Seric p++; 36458849Seric if (*p == '\0') 36558849Seric break; 36658849Seric f = p; 36758849Seric p = strchr(p, ','); 36858849Seric if (p != NULL) 36958849Seric *p++ = '\0'; 37058849Seric v = strchr(f, '='); 37158849Seric if (v == NULL) 37258849Seric continue; 37358849Seric while (isascii(*++v) && isspace(*v)) 37458849Seric continue; 37558849Seric 37658849Seric switch (*f) 37758849Seric { 37858873Seric case 'F': /* address family */ 37958849Seric if (isascii(*v) && isdigit(*v)) 38058873Seric DaemonAddr.sa.sa_family = atoi(v); 38158873Seric #ifdef NETINET 38258873Seric else if (strcasecmp(v, "inet") == 0) 38358873Seric DaemonAddr.sa.sa_family = AF_INET; 38458873Seric #endif 38558873Seric #ifdef NETISO 38658873Seric else if (strcasecmp(v, "iso") == 0) 38758873Seric DaemonAddr.sa.sa_family = AF_ISO; 38858873Seric #endif 38958873Seric #ifdef NETNS 39058873Seric else if (strcasecmp(v, "ns") == 0) 39158873Seric DaemonAddr.sa.sa_family = AF_NS; 39258873Seric #endif 39358873Seric #ifdef NETX25 39458873Seric else if (strcasecmp(v, "x.25") == 0) 39558873Seric DaemonAddr.sa.sa_family = AF_CCITT; 39658873Seric #endif 39758849Seric else 39858873Seric syserr("554 Unknown address family %s in Family=option", v); 39958873Seric break; 40058873Seric 40158873Seric case 'A': /* address */ 40258873Seric switch (DaemonAddr.sa.sa_family) 40358849Seric { 40458873Seric #ifdef NETINET 40558873Seric case AF_INET: 40658873Seric if (isascii(*v) && isdigit(*v)) 40758873Seric DaemonAddr.sin.sin_addr.s_addr = inet_network(v); 40858873Seric else 40958873Seric { 41058873Seric register struct netent *np; 41158849Seric 41258873Seric np = getnetbyname(v); 41358873Seric if (np == NULL) 41458873Seric syserr("554 network \"%s\" unknown", v); 41558873Seric else 41658873Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 41758873Seric } 41858873Seric break; 41958873Seric #endif 42058873Seric 42158873Seric default: 42258873Seric syserr("554 Address= option unsupported for family %d", 42358873Seric DaemonAddr.sa.sa_family); 42458873Seric break; 42558849Seric } 42658849Seric break; 42758849Seric 42858873Seric case 'P': /* port */ 42958873Seric switch (DaemonAddr.sa.sa_family) 43058849Seric { 43158873Seric short port; 43258849Seric 43358873Seric #ifdef NETINET 43458873Seric case AF_INET: 43558873Seric if (isascii(*v) && isdigit(*v)) 43664366Seric DaemonAddr.sin.sin_port = htons(atoi(v)); 43758849Seric else 43858873Seric { 43958873Seric register struct servent *sp; 44058873Seric 44158873Seric sp = getservbyname(v, "tcp"); 44258873Seric if (sp == NULL) 44358909Seric syserr("554 service \"%s\" unknown", v); 44458873Seric else 44558873Seric DaemonAddr.sin.sin_port = sp->s_port; 44658873Seric } 44758873Seric break; 44858873Seric #endif 44958873Seric 45058873Seric #ifdef NETISO 45158873Seric case AF_ISO: 45258873Seric /* assume two byte transport selector */ 45358873Seric if (isascii(*v) && isdigit(*v)) 45464366Seric port = htons(atoi(v)); 45558873Seric else 45658873Seric { 45758873Seric register struct servent *sp; 45858873Seric 45958873Seric sp = getservbyname(v, "tcp"); 46058873Seric if (sp == NULL) 46158909Seric syserr("554 service \"%s\" unknown", v); 46258873Seric else 46358873Seric port = sp->s_port; 46458873Seric } 46558873Seric bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 46658873Seric break; 46758873Seric #endif 46858873Seric 46958873Seric default: 47058873Seric syserr("554 Port= option unsupported for family %d", 47158873Seric DaemonAddr.sa.sa_family); 47258873Seric break; 47358849Seric } 47458849Seric break; 47559783Seric 47659783Seric case 'L': /* listen queue size */ 47759783Seric ListenQueueSize = atoi(v); 47859783Seric break; 47964381Seric 48064381Seric case 'S': /* send buffer size */ 48164381Seric TcpSndBufferSize = atoi(v); 48264381Seric break; 48364381Seric 48464381Seric case 'R': /* receive buffer size */ 48564381Seric TcpRcvBufferSize = atoi(v); 48664381Seric break; 48758849Seric } 48858849Seric } 48958849Seric } 49058849Seric /* 4916039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 4926039Seric ** 4936039Seric ** Parameters: 4946039Seric ** host -- the name of the host. 4956633Seric ** port -- the port number to connect to. 49653739Seric ** mci -- a pointer to the mail connection information 49753739Seric ** structure to be filled in. 49852106Seric ** usesecureport -- if set, use a low numbered (reserved) 49952106Seric ** port to provide some rudimentary authentication. 5006039Seric ** 5016039Seric ** Returns: 5026039Seric ** An exit code telling whether the connection could be 5036039Seric ** made and if not why not. 5046039Seric ** 5056039Seric ** Side Effects: 5066039Seric ** none. 5076039Seric */ 5085978Seric 50958755Seric SOCKADDR CurHostAddr; /* address of current host */ 51058305Seric 51154967Seric int 51253739Seric makeconnection(host, port, mci, usesecureport) 5136039Seric char *host; 5147286Seric u_short port; 51554967Seric register MCI *mci; 51652106Seric bool usesecureport; 5176039Seric { 51829430Sbloom register int i, s; 51929430Sbloom register struct hostent *hp = (struct hostent *)NULL; 52058755Seric SOCKADDR addr; 52152106Seric int sav_errno; 52258755Seric int addrlen; 52335651Seric #ifdef NAMED_BIND 52435651Seric extern int h_errno; 52535651Seric #endif 5266039Seric 5276039Seric /* 5286039Seric ** Set up the address for the mailer. 5299308Seric ** Accept "[a.b.c.d]" syntax for host name. 5306039Seric */ 5316039Seric 53235651Seric #ifdef NAMED_BIND 53325475Smiriam h_errno = 0; 53435651Seric #endif 53525475Smiriam errno = 0; 53658864Seric bzero(&CurHostAddr, sizeof CurHostAddr); 53764334Seric SmtpPhase = mci->mci_phase = "initial connection"; 53858906Seric CurHostName = host; 53925475Smiriam 5409308Seric if (host[0] == '[') 5419308Seric { 54211147Seric long hid; 54356795Seric register char *p = strchr(host, ']'); 5449308Seric 54511147Seric if (p != NULL) 5469308Seric { 54711147Seric *p = '\0'; 54859884Seric #ifdef NETINET 54911147Seric hid = inet_addr(&host[1]); 55058360Seric if (hid == -1) 55159884Seric #endif 55258360Seric { 55358360Seric /* try it as a host name (avoid MX lookup) */ 55458360Seric hp = gethostbyname(&host[1]); 55558360Seric *p = ']'; 55658360Seric goto gothostent; 55758360Seric } 55811147Seric *p = ']'; 5599308Seric } 56058360Seric if (p == NULL) 5619308Seric { 56258151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 5639308Seric return (EX_NOHOST); 5649308Seric } 56559884Seric #ifdef NETINET 56659884Seric addr.sin.sin_family = AF_INET; /*XXX*/ 56758778Seric addr.sin.sin_addr.s_addr = hid; 56859884Seric #endif 5699308Seric } 5709610Seric else 5719610Seric { 57229430Sbloom hp = gethostbyname(host); 57358360Seric gothostent: 57425475Smiriam if (hp == NULL) 57524945Seric { 57635651Seric #ifdef NAMED_BIND 57725475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 57825475Smiriam return (EX_TEMPFAIL); 57925657Seric 58035651Seric /* if name server is specified, assume temp fail */ 58135651Seric if (errno == ECONNREFUSED && UseNameServer) 58235651Seric return (EX_TEMPFAIL); 58335651Seric #endif 58425475Smiriam return (EX_NOHOST); 58524945Seric } 58658778Seric addr.sa.sa_family = hp->h_addrtype; 58758778Seric switch (hp->h_addrtype) 58858778Seric { 58958778Seric #ifdef NETINET 59058778Seric case AF_INET: 59158755Seric bcopy(hp->h_addr, 59258778Seric &addr.sin.sin_addr, 59364943Seric sizeof addr.sin.sin_addr); 59458778Seric break; 59558778Seric #endif 59658778Seric 59758778Seric default: 59858755Seric bcopy(hp->h_addr, 59958778Seric addr.sa.sa_data, 60058755Seric hp->h_length); 60158778Seric break; 60258778Seric } 60329430Sbloom i = 1; 6049610Seric } 6059610Seric 6069610Seric /* 6079610Seric ** Determine the port number. 6089610Seric */ 6099610Seric 61010011Seric if (port != 0) 61158755Seric port = htons(port); 61210011Seric else 6139610Seric { 6149610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 6159610Seric 6169610Seric if (sp == NULL) 6179610Seric { 61858909Seric syserr("554 makeconnection: service \"smtp\" unknown"); 61965169Seric port = htons(25); 6209610Seric } 62165169Seric else 62265169Seric port = sp->s_port; 6239610Seric } 6246039Seric 62558778Seric switch (addr.sa.sa_family) 62658755Seric { 62759884Seric #ifdef NETINET 62858755Seric case AF_INET: 62958778Seric addr.sin.sin_port = port; 63058755Seric addrlen = sizeof (struct sockaddr_in); 63158755Seric break; 63259884Seric #endif 63358755Seric 63458755Seric #ifdef NETISO 63558755Seric case AF_ISO: 63658755Seric /* assume two byte transport selector */ 63758755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 63858755Seric addrlen = sizeof (struct sockaddr_iso); 63958755Seric break; 64058755Seric #endif 64158755Seric 64258755Seric default: 64358778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 64458755Seric return (EX_NOHOST); 64558755Seric } 64658755Seric 6476039Seric /* 6486039Seric ** Try to actually open the connection. 6496039Seric */ 6506039Seric 65159156Seric #ifdef XLA 65259156Seric /* if too many connections, don't bother trying */ 65359156Seric if (!xla_noqueue_ok(host)) 65459156Seric return EX_TEMPFAIL; 65559156Seric #endif 65659156Seric 65757736Seric for (;;) 65852106Seric { 65957736Seric if (tTd(16, 1)) 66058755Seric printf("makeconnection (%s [%s])\n", 66158755Seric host, anynet_ntoa(&addr)); 66252106Seric 66358588Seric /* save for logging */ 66458588Seric CurHostAddr = addr; 66558588Seric 66657736Seric if (usesecureport) 66757736Seric { 66857736Seric int rport = IPPORT_RESERVED - 1; 6696039Seric 67057736Seric s = rresvport(&rport); 67157736Seric } 67257736Seric else 67357736Seric { 67457736Seric s = socket(AF_INET, SOCK_STREAM, 0); 67557736Seric } 67657736Seric if (s < 0) 67757736Seric { 67857736Seric sav_errno = errno; 67957736Seric syserr("makeconnection: no socket"); 68057736Seric goto failure; 68157736Seric } 68210347Seric 68364381Seric #ifdef SO_SNDBUF 68464381Seric if (TcpSndBufferSize > 0) 68564381Seric { 68664381Seric if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 68764561Seric (char *) &TcpSndBufferSize, 68864381Seric sizeof(TcpSndBufferSize)) < 0) 68964381Seric syserr("makeconnection: setsockopt(SO_SNDBUF)"); 69064381Seric } 69164381Seric #endif 69264381Seric 69357736Seric if (tTd(16, 1)) 69457736Seric printf("makeconnection: fd=%d\n", s); 69557736Seric 69657736Seric /* turn on network debugging? */ 69757736Seric if (tTd(16, 101)) 69857736Seric { 69957736Seric int on = 1; 70057736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 70157736Seric (char *)&on, sizeof on); 70257736Seric } 70357736Seric if (CurEnv->e_xfp != NULL) 70457736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 70557736Seric errno = 0; /* for debugging */ 70658755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 70757736Seric break; 70857736Seric 70957736Seric /* couldn't connect.... figure out why */ 71027744Sbloom sav_errno = errno; 71127744Sbloom (void) close(s); 71229430Sbloom if (hp && hp->h_addr_list[i]) 71329430Sbloom { 71457736Seric if (tTd(16, 1)) 71558755Seric printf("Connect failed (%s); trying new address....\n", 71658755Seric errstring(sav_errno)); 71758778Seric switch (addr.sa.sa_family) 71858778Seric { 71958778Seric #ifdef NETINET 72058778Seric case AF_INET: 72158755Seric bcopy(hp->h_addr_list[i++], 72258778Seric &addr.sin.sin_addr, 72364943Seric sizeof addr.sin.sin_addr); 72458778Seric break; 72558778Seric #endif 72658778Seric 72758778Seric default: 72858755Seric bcopy(hp->h_addr_list[i++], 72958778Seric addr.sa.sa_data, 73052106Seric hp->h_length); 73158778Seric break; 73258778Seric } 73357736Seric continue; 73429430Sbloom } 73529430Sbloom 7366039Seric /* failure, decide if temporary or not */ 7376039Seric failure: 73859254Seric #ifdef XLA 73959254Seric xla_host_end(host); 74059254Seric #endif 74158542Seric if (transienterror(sav_errno)) 74258542Seric return EX_TEMPFAIL; 74358542Seric else 74458542Seric { 74558542Seric message("%s", errstring(sav_errno)); 74658542Seric return (EX_UNAVAILABLE); 7476039Seric } 7486039Seric } 7496039Seric 7506039Seric /* connection ok, put it into canonical form */ 75164724Seric if ((mci->mci_out = fdopen(s, "w")) == NULL || 75264724Seric (s = dup(s)) < 0 || 75364725Seric (mci->mci_in = fdopen(s, "r")) == NULL) 75464724Seric { 75564724Seric syserr("cannot open SMTP client channel, fd=%d", s); 75664724Seric return EX_TEMPFAIL; 75764724Seric } 7586039Seric 75910098Seric return (EX_OK); 7606039Seric } 76110758Seric /* 76210758Seric ** MYHOSTNAME -- return the name of this host. 76310758Seric ** 76410758Seric ** Parameters: 76510758Seric ** hostbuf -- a place to return the name of this host. 76612313Seric ** size -- the size of hostbuf. 76710758Seric ** 76810758Seric ** Returns: 76910758Seric ** A list of aliases for this host. 77010758Seric ** 77110758Seric ** Side Effects: 77264338Seric ** Adds numeric codes to $=w. 77310758Seric */ 7746039Seric 77510758Seric char ** 77612313Seric myhostname(hostbuf, size) 77710758Seric char hostbuf[]; 77812313Seric int size; 77910758Seric { 78058110Seric register struct hostent *hp; 78110758Seric extern struct hostent *gethostbyname(); 78210758Seric 78323120Seric if (gethostname(hostbuf, size) < 0) 78423120Seric { 78523120Seric (void) strcpy(hostbuf, "localhost"); 78623120Seric } 78711147Seric hp = gethostbyname(hostbuf); 78811147Seric if (hp != NULL) 78916877Seric { 79058110Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 79158110Seric hostbuf[size - 1] = '\0'; 79258110Seric 79358110Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 79458110Seric { 79558110Seric register int i; 79658110Seric 79764338Seric for (i = 0; hp->h_addr_list[i] != NULL; i++) 79858110Seric { 79964338Seric char ipbuf[100]; 80064338Seric 80164338Seric sprintf(ipbuf, "[%s]", 80264338Seric inet_ntoa(*((struct in_addr *) hp->h_addr_list[i]))); 80364338Seric setclass('w', ipbuf); 80458110Seric } 80558110Seric } 80658110Seric 80711147Seric return (hp->h_aliases); 80816877Seric } 80910758Seric else 81010758Seric return (NULL); 81110758Seric } 81251315Seric /* 81358951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 81458308Seric ** 81558951Seric ** Uses RFC1413 protocol to try to get info from the other end. 81658951Seric ** 81758308Seric ** Parameters: 81858308Seric ** fd -- the descriptor 81958308Seric ** 82058308Seric ** Returns: 82158951Seric ** The user@host information associated with this descriptor. 82258308Seric ** 82358308Seric ** Side Effects: 82458951Seric ** Sets RealHostName to the name of the host at the other end. 82558308Seric */ 82658308Seric 82764927Seric #if IDENTPROTO 82858951Seric 82958951Seric static jmp_buf CtxAuthTimeout; 83058951Seric 83158951Seric static 83258951Seric authtimeout() 83358951Seric { 83458951Seric longjmp(CtxAuthTimeout, 1); 83558951Seric } 83658951Seric 83758951Seric #endif 83858951Seric 83958308Seric char * 84058951Seric getauthinfo(fd) 84158308Seric int fd; 84258308Seric { 84358951Seric SOCKADDR fa; 84458951Seric int falen; 84559104Seric register char *p; 84664927Seric #if IDENTPROTO 84758951Seric SOCKADDR la; 84858951Seric int lalen; 84958951Seric register struct servent *sp; 85058951Seric int s; 85158951Seric int i; 85258951Seric EVENT *ev; 85358951Seric #endif 85458951Seric static char hbuf[MAXNAME * 2 + 2]; 85558951Seric extern char *hostnamebyanyaddr(); 85658951Seric extern char RealUserName[]; /* main.c */ 85758308Seric 85858951Seric falen = sizeof fa; 85964845Seric if (getpeername(fd, &fa.sa, &falen) < 0 || falen <= 0 || 86064845Seric fa.sa.sa_family == 0) 86158951Seric { 86258951Seric RealHostName = "localhost"; 86358951Seric (void) sprintf(hbuf, "%s@localhost", RealUserName); 86458957Seric if (tTd(9, 1)) 86558951Seric printf("getauthinfo: %s\n", hbuf); 86658951Seric return hbuf; 86758951Seric } 86858951Seric 86964086Seric p = hostnamebyanyaddr(&fa); 87064086Seric RealHostName = newstr(p); 87158951Seric RealHostAddr = fa; 87258951Seric 87364927Seric #if IDENTPROTO 87458951Seric lalen = sizeof la; 87558951Seric if (fa.sa.sa_family != AF_INET || 87658951Seric getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || 87758951Seric la.sa.sa_family != AF_INET) 87858951Seric { 87958951Seric /* no ident info */ 88058951Seric goto noident; 88158951Seric } 88258951Seric 88358951Seric /* create ident query */ 88460489Seric (void) sprintf(hbuf, "%d,%d\r\n", 88560489Seric ntohs(fa.sin.sin_port), ntohs(la.sin.sin_port)); 88658951Seric 88758951Seric /* create local address */ 88864747Seric la.sin.sin_port = 0; 88958951Seric 89058951Seric /* create foreign address */ 89158951Seric sp = getservbyname("auth", "tcp"); 89258951Seric if (sp != NULL) 89358951Seric fa.sin.sin_port = sp->s_port; 89458308Seric else 89559097Seric fa.sin.sin_port = htons(113); 89658951Seric 89758951Seric s = -1; 89858951Seric if (setjmp(CtxAuthTimeout) != 0) 89958951Seric { 90058951Seric if (s >= 0) 90158951Seric (void) close(s); 90258951Seric goto noident; 90358951Seric } 90458951Seric 90558951Seric /* put a timeout around the whole thing */ 90664255Seric ev = setevent(TimeOuts.to_ident, authtimeout, 0); 90758951Seric 90864747Seric /* connect to foreign IDENT server using same address as SMTP socket */ 90958951Seric s = socket(AF_INET, SOCK_STREAM, 0); 91058951Seric if (s < 0) 91158951Seric { 91258951Seric clrevent(ev); 91358951Seric goto noident; 91458951Seric } 91564747Seric if (bind(s, &la.sa, sizeof la.sin) < 0 || 91664747Seric connect(s, &fa.sa, sizeof fa.sin) < 0) 91758951Seric { 91858951Seric closeident: 91958951Seric (void) close(s); 92058951Seric clrevent(ev); 92158951Seric goto noident; 92258951Seric } 92358951Seric 92458957Seric if (tTd(9, 10)) 92558951Seric printf("getauthinfo: sent %s", hbuf); 92658951Seric 92758951Seric /* send query */ 92858951Seric if (write(s, hbuf, strlen(hbuf)) < 0) 92958951Seric goto closeident; 93058951Seric 93158951Seric /* get result */ 93258951Seric i = read(s, hbuf, sizeof hbuf); 93358951Seric (void) close(s); 93458951Seric clrevent(ev); 93558951Seric if (i <= 0) 93658951Seric goto noident; 93758951Seric if (hbuf[--i] == '\n' && hbuf[--i] == '\r') 93858951Seric i--; 93958951Seric hbuf[++i] = '\0'; 94058951Seric 94158957Seric if (tTd(9, 3)) 94258951Seric printf("getauthinfo: got %s\n", hbuf); 94358951Seric 94458951Seric /* parse result */ 94558951Seric p = strchr(hbuf, ':'); 94658951Seric if (p == NULL) 94758951Seric { 94858951Seric /* malformed response */ 94958951Seric goto noident; 95058951Seric } 95158951Seric while (isascii(*++p) && isspace(*p)) 95258951Seric continue; 95358951Seric if (strncasecmp(p, "userid", 6) != 0) 95458951Seric { 95558951Seric /* presumably an error string */ 95658951Seric goto noident; 95758951Seric } 95858951Seric p += 6; 95958951Seric while (isascii(*p) && isspace(*p)) 96058951Seric p++; 96158951Seric if (*p++ != ':') 96258951Seric { 96358951Seric /* either useridxx or malformed response */ 96458951Seric goto noident; 96558951Seric } 96658951Seric 96758951Seric /* p now points to the OSTYPE field */ 96858951Seric p = strchr(p, ':'); 96958951Seric if (p == NULL) 97058951Seric { 97158951Seric /* malformed response */ 97258951Seric goto noident; 97358951Seric } 97458951Seric 97558957Seric /* 1413 says don't do this -- but it's broken otherwise */ 97658957Seric while (isascii(*++p) && isspace(*p)) 97758957Seric continue; 97858957Seric 97958951Seric /* p now points to the authenticated name */ 98058951Seric (void) sprintf(hbuf, "%s@%s", p, RealHostName); 98158957Seric goto finish; 98258957Seric 98358957Seric #endif /* IDENTPROTO */ 98458957Seric 98558957Seric noident: 98658957Seric (void) strcpy(hbuf, RealHostName); 98758957Seric 98858957Seric finish: 98958951Seric if (RealHostName[0] != '[') 99058951Seric { 99158951Seric p = &hbuf[strlen(hbuf)]; 99258951Seric (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); 99358951Seric } 99458957Seric if (tTd(9, 1)) 99558951Seric printf("getauthinfo: %s\n", hbuf); 99658308Seric return hbuf; 99758308Seric } 99858308Seric /* 99960089Seric ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 100053751Seric ** 100153751Seric ** Parameters: 100256823Seric ** map -- a pointer to this map (unused). 100360089Seric ** name -- the (presumably unqualified) hostname. 100460257Seric ** av -- unused -- for compatibility with other mapping 100555019Seric ** functions. 100659084Seric ** statp -- an exit status (out parameter) -- set to 100759084Seric ** EX_TEMPFAIL if the name server is unavailable. 100853751Seric ** 100953751Seric ** Returns: 101053751Seric ** The mapping, if found. 101153751Seric ** NULL if no mapping found. 101253751Seric ** 101353751Seric ** Side Effects: 101453751Seric ** Looks up the host specified in hbuf. If it is not 101553751Seric ** the canonical name for that host, return the canonical 101653751Seric ** name. 101753751Seric */ 101851315Seric 101953751Seric char * 102060257Seric host_map_lookup(map, name, av, statp) 102156823Seric MAP *map; 102260089Seric char *name; 102360257Seric char **av; 102459084Seric int *statp; 102516911Seric { 102616911Seric register struct hostent *hp; 102733932Sbostic u_long in_addr; 102856823Seric char *cp; 102958110Seric int i; 103059671Seric register STAB *s; 103160257Seric char hbuf[MAXNAME]; 103259671Seric extern struct hostent *gethostbyaddr(); 103359671Seric extern int h_errno; 103416911Seric 103525574Smiriam /* 103659671Seric ** See if we have already looked up this name. If so, just 103759671Seric ** return it. 103859671Seric */ 103953751Seric 104060089Seric s = stab(name, ST_NAMECANON, ST_ENTER); 104159671Seric if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 104259671Seric { 104359986Seric if (tTd(9, 1)) 104460089Seric printf("host_map_lookup(%s) => CACHE %s\n", 104560089Seric name, s->s_namecanon.nc_cname); 104659671Seric errno = s->s_namecanon.nc_errno; 104759671Seric h_errno = s->s_namecanon.nc_herrno; 104859671Seric *statp = s->s_namecanon.nc_stat; 104964797Seric if (CurEnv->e_message == NULL && *statp == EX_TEMPFAIL) 105065199Seric { 105165199Seric sprintf(hbuf, "%s: Name server timeout", 105265199Seric shortenstring(name, 33)); 105365199Seric CurEnv->e_message = newstr(hbuf); 105465199Seric } 105559671Seric return s->s_namecanon.nc_cname; 105659671Seric } 105759671Seric 105859671Seric /* 105959671Seric ** If first character is a bracket, then it is an address 106059671Seric ** lookup. Address is copied into a temporary buffer to 106160089Seric ** strip the brackets and to preserve name if address is 106259671Seric ** unknown. 106359671Seric */ 106459671Seric 106560089Seric if (*name != '[') 106653751Seric { 106755019Seric extern bool getcanonname(); 106855019Seric 106958798Seric if (tTd(9, 1)) 107060089Seric printf("host_map_lookup(%s) => ", name); 107159671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 107260089Seric (void) strcpy(hbuf, name); 107363842Seric if (getcanonname(hbuf, sizeof hbuf - 1, TRUE)) 107458796Seric { 107558796Seric if (tTd(9, 1)) 107658796Seric printf("%s\n", hbuf); 107760257Seric cp = map_rewrite(map, hbuf, strlen(hbuf), av); 107860257Seric s->s_namecanon.nc_cname = newstr(cp); 107960257Seric return cp; 108058796Seric } 108153751Seric else 108258796Seric { 108359084Seric register struct hostent *hp; 108459084Seric 108558796Seric if (tTd(9, 1)) 108659084Seric printf("FAIL (%d)\n", h_errno); 108759671Seric s->s_namecanon.nc_errno = errno; 108859671Seric s->s_namecanon.nc_herrno = h_errno; 108959084Seric switch (h_errno) 109059084Seric { 109159084Seric case TRY_AGAIN: 109259596Seric if (UseNameServer) 109359734Seric { 1094*65202Seric sprintf(hbuf, "%s: Name server timeout", 109565199Seric shortenstring(name, 33)); 1096*65202Seric message("%s", hbuf); 109759734Seric if (CurEnv->e_message == NULL) 1098*65202Seric CurEnv->e_message = newstr(hbuf); 109959734Seric } 110059084Seric *statp = EX_TEMPFAIL; 110159084Seric break; 110259084Seric 110359084Seric case HOST_NOT_FOUND: 110459084Seric *statp = EX_NOHOST; 110559084Seric break; 110659084Seric 110759084Seric case NO_RECOVERY: 110859084Seric *statp = EX_SOFTWARE; 110959084Seric break; 111059084Seric 111159084Seric default: 111259084Seric *statp = EX_UNAVAILABLE; 111359084Seric break; 111459084Seric } 111559671Seric s->s_namecanon.nc_stat = *statp; 111659084Seric if (*statp != EX_TEMPFAIL || UseNameServer) 111759084Seric return NULL; 111859084Seric 111959084Seric /* 112059084Seric ** Try to look it up in /etc/hosts 112159084Seric */ 112259084Seric 112360089Seric hp = gethostbyname(name); 112459084Seric if (hp == NULL) 112559084Seric { 112659084Seric /* no dice there either */ 112759671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 112859084Seric return NULL; 112959084Seric } 113059084Seric 113159671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 113260257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 113360257Seric s->s_namecanon.nc_cname = newstr(cp); 113460257Seric return cp; 113558796Seric } 113653751Seric } 113760089Seric if ((cp = strchr(name, ']')) == NULL) 113853751Seric return (NULL); 113940994Sbostic *cp = '\0'; 114060089Seric in_addr = inet_addr(&name[1]); 114158110Seric 114258110Seric /* nope -- ask the name server */ 114333932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 114459671Seric s->s_namecanon.nc_errno = errno; 114559671Seric s->s_namecanon.nc_herrno = h_errno; 114659671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 114733932Sbostic if (hp == NULL) 114859671Seric { 114959671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 115053751Seric return (NULL); 115159671Seric } 115253751Seric 115358110Seric /* found a match -- copy out */ 115460257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 115559671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 115660257Seric s->s_namecanon.nc_cname = newstr(cp); 115760257Seric return cp; 115833932Sbostic } 115958755Seric /* 116058755Seric ** ANYNET_NTOA -- convert a network address to printable form. 116158755Seric ** 116258755Seric ** Parameters: 116358755Seric ** sap -- a pointer to a sockaddr structure. 116458755Seric ** 116558755Seric ** Returns: 116658755Seric ** A printable version of that sockaddr. 116758755Seric */ 116816911Seric 116958755Seric char * 117058755Seric anynet_ntoa(sap) 117158755Seric register SOCKADDR *sap; 117258755Seric { 117358755Seric register char *bp; 117458755Seric register char *ap; 117558755Seric int l; 117664734Seric static char buf[100]; 117758755Seric 117858798Seric /* check for null/zero family */ 117958798Seric if (sap == NULL) 118058798Seric return "NULLADDR"; 118158798Seric if (sap->sa.sa_family == 0) 118258798Seric return "0"; 118358798Seric 118464734Seric switch (sap->sa.sa_family) 118564734Seric { 118664734Seric #ifdef MAYBENEXTRELEASE /*** UNTESTED *** UNTESTED *** UNTESTED ***/ 118764821Seric #ifdef NETUNIX 118864734Seric case AF_UNIX: 118964758Seric if (sap->sunix.sun_path[0] != '\0') 119064758Seric sprintf(buf, "[UNIX: %.64s]", sap->sunix.sun_path); 119164734Seric else 119264734Seric sprintf(buf, "[UNIX: localhost]"); 119364734Seric return buf; 119464734Seric #endif 119564821Seric #endif 119664734Seric 119758778Seric #ifdef NETINET 119864734Seric case AF_INET: 119958755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 120058778Seric #endif 120158755Seric 120264734Seric default: 120364734Seric /* this case is only to ensure syntactic correctness */ 120464734Seric break; 120564734Seric } 120664734Seric 120758755Seric /* unknown family -- just dump bytes */ 120858778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 120958755Seric bp = &buf[strlen(buf)]; 121058778Seric ap = sap->sa.sa_data; 121158778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 121258755Seric { 121358755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 121458755Seric bp += 3; 121558755Seric } 121658755Seric *--bp = '\0'; 121758755Seric return buf; 121858755Seric } 121958951Seric /* 122058951Seric ** HOSTNAMEBYANYADDR -- return name of host based on address 122158951Seric ** 122258951Seric ** Parameters: 122358951Seric ** sap -- SOCKADDR pointer 122458951Seric ** 122558951Seric ** Returns: 122658951Seric ** text representation of host name. 122758951Seric ** 122858951Seric ** Side Effects: 122958951Seric ** none. 123058951Seric */ 123158755Seric 123258951Seric char * 123358951Seric hostnamebyanyaddr(sap) 123458951Seric register SOCKADDR *sap; 123558951Seric { 123658951Seric register struct hostent *hp; 123764734Seric int saveretry; 123858951Seric 123959042Seric #ifdef NAMED_BIND 124059042Seric /* shorten name server timeout to avoid higher level timeouts */ 124159042Seric saveretry = _res.retry; 124259042Seric _res.retry = 3; 124359042Seric #endif /* NAMED_BIND */ 124459042Seric 124558951Seric switch (sap->sa.sa_family) 124658951Seric { 124758951Seric #ifdef NETINET 124858951Seric case AF_INET: 124958951Seric hp = gethostbyaddr((char *) &sap->sin.sin_addr, 125058951Seric sizeof sap->sin.sin_addr, 125158951Seric AF_INET); 125258951Seric break; 125358951Seric #endif 125458951Seric 125558951Seric #ifdef NETISO 125658951Seric case AF_ISO: 125758951Seric hp = gethostbyaddr((char *) &sap->siso.siso_addr, 125858951Seric sizeof sap->siso.siso_addr, 125958951Seric AF_ISO); 126058951Seric break; 126158951Seric #endif 126258951Seric 126364734Seric #ifdef MAYBENEXTRELEASE /*** UNTESTED *** UNTESTED *** UNTESTED ***/ 126464734Seric case AF_UNIX: 126564734Seric hp = NULL; 126664734Seric break; 126764734Seric #endif 126864734Seric 126958951Seric default: 127058951Seric hp = gethostbyaddr(sap->sa.sa_data, 127158951Seric sizeof sap->sa.sa_data, 127258951Seric sap->sa.sa_family); 127358951Seric break; 127458951Seric } 127558951Seric 127659042Seric #ifdef NAMED_BIND 127759042Seric _res.retry = saveretry; 127859042Seric #endif /* NAMED_BIND */ 127959042Seric 128058951Seric if (hp != NULL) 128158951Seric return hp->h_name; 128258951Seric else 128358951Seric { 128458951Seric /* produce a dotted quad */ 128558951Seric static char buf[512]; 128658951Seric 128758951Seric (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); 128858951Seric return buf; 128958951Seric } 129058951Seric } 129158951Seric 129256795Seric # else /* DAEMON */ 129316911Seric /* code for systems without sophisticated networking */ 129410758Seric 129510758Seric /* 129610758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 129711297Seric ** 129811297Seric ** Can't convert to upper case here because might be a UUCP name. 129912313Seric ** 130012313Seric ** Mark, you can change this to be anything you want...... 130110758Seric */ 130210758Seric 130310758Seric char ** 130412313Seric myhostname(hostbuf, size) 130510758Seric char hostbuf[]; 130612313Seric int size; 130710758Seric { 130810758Seric register FILE *f; 130910758Seric 131010758Seric hostbuf[0] = '\0'; 131110758Seric f = fopen("/usr/include/whoami", "r"); 131210758Seric if (f != NULL) 131310758Seric { 131412313Seric (void) fgets(hostbuf, size, f); 131510758Seric fixcrlf(hostbuf, TRUE); 131610758Seric (void) fclose(f); 131710758Seric } 131810758Seric return (NULL); 131910758Seric } 132016911Seric /* 132158951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 132258308Seric ** 132358308Seric ** Parameters: 132458308Seric ** fd -- the descriptor 132558308Seric ** 132658308Seric ** Returns: 132758308Seric ** The host name associated with this descriptor, if it can 132858308Seric ** be determined. 132958308Seric ** NULL otherwise. 133058308Seric ** 133158308Seric ** Side Effects: 133258308Seric ** none 133358308Seric */ 133458308Seric 133558308Seric char * 133658951Seric getauthinfo(fd) 133758308Seric int fd; 133858308Seric { 133958308Seric return NULL; 134058308Seric } 134158308Seric /* 134216911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 134316911Seric ** 134416911Seric ** Parameters: 134556823Seric ** map -- a pointer to the database map. 134660089Seric ** name -- a buffer containing a hostname. 134753751Seric ** avp -- a pointer to a (cf file defined) argument vector. 134859084Seric ** statp -- an exit status (out parameter). 134916911Seric ** 135016911Seric ** Returns: 135153751Seric ** mapped host name 135251315Seric ** FALSE otherwise. 135316911Seric ** 135416911Seric ** Side Effects: 135560089Seric ** Looks up the host specified in name. If it is not 135616911Seric ** the canonical name for that host, replace it with 135716911Seric ** the canonical name. If the name is unknown, or it 135816911Seric ** is already the canonical name, leave it unchanged. 135916911Seric */ 136010758Seric 136116911Seric /*ARGSUSED*/ 136253751Seric char * 136360089Seric host_map_lookup(map, name, avp, statp) 136456823Seric MAP *map; 136560089Seric char *name; 136653751Seric char **avp; 136759084Seric char *statp; 136816911Seric { 136959084Seric register struct hostent *hp; 137059084Seric 137160089Seric hp = gethostbyname(name); 137259084Seric if (hp != NULL) 137359084Seric return hp->h_name; 137459084Seric *statp = EX_NOHOST; 137553751Seric return NULL; 137616911Seric } 137716911Seric 137856795Seric #endif /* DAEMON */ 1379