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*66853Seric static char sccsid[] = "@(#)daemon.c 8.45 (Berkeley) 04/17/94 (with daemon mode)"; 1533780Sbostic #else 16*66853Seric static char sccsid[] = "@(#)daemon.c 8.45 (Berkeley) 04/17/94 (without daemon mode)"; 1733780Sbostic #endif 1833780Sbostic #endif /* not lint */ 194535Seric 2033780Sbostic #ifdef DAEMON 2133780Sbostic 2223120Seric # include <netdb.h> 2364338Seric # include <arpa/inet.h> 245978Seric 2566334Seric #if NAMED_BIND 2659042Seric # include <arpa/nameser.h> 2759042Seric # include <resolv.h> 2859042Seric #endif 2959042Seric 304535Seric /* 314535Seric ** DAEMON.C -- routines to use when running as a daemon. 327556Seric ** 337556Seric ** This entire file is highly dependent on the 4.2 BSD 347556Seric ** interprocess communication primitives. No attempt has 357556Seric ** been made to make this file portable to Version 7, 367556Seric ** Version 6, MPX files, etc. If you should try such a 377556Seric ** thing yourself, I recommend chucking the entire file 387556Seric ** and starting from scratch. Basic semantics are: 397556Seric ** 407556Seric ** getrequests() 417556Seric ** Opens a port and initiates a connection. 427556Seric ** Returns in a child. Must set InChannel and 437556Seric ** OutChannel appropriately. 4410206Seric ** clrdaemon() 4510206Seric ** Close any open files associated with getting 4610206Seric ** the connection; this is used when running the queue, 4710206Seric ** etc., to avoid having extra file descriptors during 4810206Seric ** the queue run and to avoid confusing the network 4910206Seric ** code (if it cares). 5052106Seric ** makeconnection(host, port, outfile, infile, usesecureport) 517556Seric ** Make a connection to the named host on the given 527556Seric ** port. Set *outfile and *infile to the files 537556Seric ** appropriate for communication. Returns zero on 547556Seric ** success, else an exit status describing the 557556Seric ** error. 5660089Seric ** host_map_lookup(map, hbuf, avp, pstat) 5756823Seric ** Convert the entry in hbuf into a canonical form. 584535Seric */ 594535Seric /* 604535Seric ** GETREQUESTS -- open mail IPC port and get requests. 614535Seric ** 624535Seric ** Parameters: 634535Seric ** none. 644535Seric ** 654535Seric ** Returns: 664535Seric ** none. 674535Seric ** 684535Seric ** Side Effects: 694535Seric ** Waits until some interesting activity occurs. When 704535Seric ** it does, a child is created to process it, and the 714535Seric ** parent waits for completion. Return from this 729886Seric ** routine is always in the child. The file pointers 739886Seric ** "InChannel" and "OutChannel" should be set to point 749886Seric ** to the communication channel. 754535Seric */ 764535Seric 7758849Seric int DaemonSocket = -1; /* fd describing socket */ 7858849Seric SOCKADDR DaemonAddr; /* socket for incoming */ 7959783Seric int ListenQueueSize = 10; /* size of listen queue */ 8064381Seric int TcpRcvBufferSize = 0; /* size of TCP receive buffer */ 8164381Seric int TcpSndBufferSize = 0; /* size of TCP send buffer */ 8216144Seric 834535Seric getrequests() 844535Seric { 859610Seric int t; 8653751Seric bool refusingconnections = TRUE; 8758419Seric FILE *pidf; 8864828Seric int socksize; 8966793Seric #ifdef XDEBUG 9066793Seric bool j_has_dot; 9166793Seric #endif 9246928Sbostic extern void reapchild(); 937117Seric 949610Seric /* 959610Seric ** Set up the address for the mailer. 969610Seric */ 979610Seric 9858849Seric if (DaemonAddr.sin.sin_family == 0) 9958849Seric DaemonAddr.sin.sin_family = AF_INET; 10058849Seric if (DaemonAddr.sin.sin_addr.s_addr == 0) 10158849Seric DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; 10258849Seric if (DaemonAddr.sin.sin_port == 0) 1039610Seric { 10465169Seric register struct servent *sp; 10565169Seric 10658849Seric sp = getservbyname("smtp", "tcp"); 10758849Seric if (sp == NULL) 10858849Seric { 10958909Seric syserr("554 service \"smtp\" unknown"); 11065169Seric DaemonAddr.sin.sin_port = htons(25); 11158849Seric } 11265169Seric else 11365169Seric DaemonAddr.sin.sin_port = sp->s_port; 1149610Seric } 1159610Seric 1169610Seric /* 1179610Seric ** Try to actually open the connection. 1189610Seric */ 1199610Seric 1209610Seric if (tTd(15, 1)) 12158849Seric printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); 1229610Seric 1239610Seric /* get a socket for the SMTP connection */ 12466845Seric socksize = opendaemonsocket(); 12510347Seric 12664035Seric (void) setsignal(SIGCHLD, reapchild); 12724945Seric 12858419Seric /* write the pid to the log file for posterity */ 12958419Seric pidf = fopen(PidFile, "w"); 13058419Seric if (pidf != NULL) 13158419Seric { 13263863Seric extern char *CommandLineArgs; 13363863Seric 13463863Seric /* write the process id on line 1 */ 13558419Seric fprintf(pidf, "%d\n", getpid()); 13663863Seric 13763863Seric /* line 2 contains all command line flags */ 13863863Seric fprintf(pidf, "%s\n", CommandLineArgs); 13963863Seric 14063863Seric /* flush and close */ 14158419Seric fclose(pidf); 14258419Seric } 14358419Seric 14466793Seric #ifdef XDEBUG 14566793Seric { 14666812Seric char jbuf[MAXHOSTNAMELEN]; 14758419Seric 14866812Seric expand("\201j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv); 14966812Seric j_has_dot = strchr(jbuf, '.') != NULL; 15066793Seric } 15166793Seric #endif 15266793Seric 1539610Seric if (tTd(15, 1)) 15410206Seric printf("getrequests: %d\n", DaemonSocket); 1559610Seric 1564631Seric for (;;) 1574631Seric { 15814875Seric register int pid; 15911147Seric auto int lotherend; 16053751Seric extern bool refuseconnections(); 16111147Seric 16214875Seric /* see if we are rejecting connections */ 16353751Seric CurrentLA = getla(); 16453751Seric if (refuseconnections()) 16536584Sbostic { 16666845Seric if (DaemonSocket >= 0) 16753751Seric { 16866845Seric /* close socket so peer will fail quickly */ 16966845Seric (void) close(DaemonSocket); 17066845Seric DaemonSocket = -1; 17153751Seric } 17266845Seric refusingconnections = TRUE; 17357385Seric setproctitle("rejecting connections: load average: %d", 17457385Seric CurrentLA); 17566845Seric sleep(15); 17653751Seric continue; 17736584Sbostic } 17814875Seric 17953751Seric if (refusingconnections) 18053751Seric { 18153751Seric /* start listening again */ 18266845Seric if (DaemonSocket < 0) 18366845Seric (void) opendaemonsocket(); 18453751Seric setproctitle("accepting connections"); 18553751Seric refusingconnections = FALSE; 18653751Seric } 18753751Seric 18866793Seric #ifdef XDEBUG 18966793Seric /* check for disaster */ 19066793Seric { 19166793Seric register STAB *s; 19266812Seric char jbuf[MAXHOSTNAMELEN]; 19366793Seric 19466812Seric expand("\201j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv); 19566812Seric if ((s = stab(jbuf, ST_CLASS, ST_FIND)) == NULL || 19666793Seric !bitnset('w', s->s_class)) 19766793Seric { 19866793Seric dumpstate("daemon lost $j"); 19966793Seric syslog(LOG_ALERT, "daemon process doesn't have $j in $=w; see syslog"); 20066793Seric abort(); 20166793Seric } 20266812Seric else if (j_has_dot && strchr(jbuf, '.') == NULL) 20366793Seric { 20466793Seric dumpstate("daemon $j lost dot"); 20566793Seric syslog(LOG_ALERT, "daemon process $j lost dot; see syslog"); 20666793Seric abort(); 20766793Seric } 20866793Seric } 20966793Seric #endif 21066793Seric 2119610Seric /* wait for a connection */ 2129610Seric do 2139610Seric { 2149610Seric errno = 0; 21564828Seric lotherend = socksize; 21646928Sbostic t = accept(DaemonSocket, 21746928Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 2189610Seric } while (t < 0 && errno == EINTR); 2199610Seric if (t < 0) 2205978Seric { 2219610Seric syserr("getrequests: accept"); 2229610Seric sleep(5); 2239610Seric continue; 2245978Seric } 2254631Seric 2265978Seric /* 2275978Seric ** Create a subprocess to process the mail. 2285978Seric */ 2295978Seric 2307677Seric if (tTd(15, 2)) 2319610Seric printf("getrequests: forking (fd = %d)\n", t); 2325978Seric 2334636Seric pid = fork(); 2344636Seric if (pid < 0) 2354631Seric { 2364636Seric syserr("daemon: cannot fork"); 2374636Seric sleep(10); 2389610Seric (void) close(t); 2394636Seric continue; 2404631Seric } 2414631Seric 2424636Seric if (pid == 0) 2434631Seric { 24464086Seric char *p; 24558951Seric extern char *hostnamebyanyaddr(); 24611147Seric 2474636Seric /* 2484636Seric ** CHILD -- return to caller. 24911147Seric ** Collect verified idea of sending host. 2504636Seric ** Verify calling user id if possible here. 2514636Seric */ 2524631Seric 25364035Seric (void) setsignal(SIGCHLD, SIG_DFL); 25466017Seric DisConnected = FALSE; 25524950Seric 25666032Seric setproctitle("startup with %s", 25766032Seric anynet_ntoa(&RealHostAddr)); 25866032Seric 25911147Seric /* determine host name */ 26064086Seric p = hostnamebyanyaddr(&RealHostAddr); 26164086Seric RealHostName = newstr(p); 26266032Seric setproctitle("startup with %s", p); 26358778Seric 26455173Seric #ifdef LOG 26563842Seric if (LogLevel > 11) 26655173Seric { 26755173Seric /* log connection information */ 26855173Seric syslog(LOG_INFO, "connect from %s (%s)", 26958951Seric RealHostName, anynet_ntoa(&RealHostAddr)); 27055173Seric } 27155173Seric #endif 27255173Seric 27359254Seric (void) close(DaemonSocket); 27464724Seric if ((InChannel = fdopen(t, "r")) == NULL || 27564724Seric (t = dup(t)) < 0 || 27664724Seric (OutChannel = fdopen(t, "w")) == NULL) 27764724Seric { 27864724Seric syserr("cannot open SMTP server channel, fd=%d", t); 27964724Seric exit(0); 28064724Seric } 28159254Seric 28216884Seric /* should we check for illegal connection here? XXX */ 28359156Seric #ifdef XLA 28459156Seric if (!xla_host_ok(RealHostName)) 28559156Seric { 28659254Seric message("421 Too many SMTP sessions for this host"); 28759156Seric exit(0); 28859156Seric } 28959156Seric #endif 29016884Seric 2917677Seric if (tTd(15, 2)) 2925978Seric printf("getreq: returning\n"); 2934636Seric return; 2944631Seric } 2954631Seric 2967117Seric /* close the port so that others will hang (for a while) */ 2979610Seric (void) close(t); 2984631Seric } 2999886Seric /*NOTREACHED*/ 3004631Seric } 3015978Seric /* 30266845Seric ** OPENDAEMONSOCKET -- open the SMTP socket 30366845Seric ** 30466845Seric ** Deals with setting all appropriate options. DaemonAddr must 30566845Seric ** be set up in advance. 30666845Seric ** 30766845Seric ** Parameters: 30866845Seric ** none 30966845Seric ** 31066845Seric ** Returns: 31166845Seric ** Size in bytes of the daemon socket addr. 31266845Seric ** 31366845Seric ** Side Effects: 31466845Seric ** Leaves DaemonSocket set to the open socket. 31566845Seric ** Exits if the socket cannot be created. 31666845Seric */ 31766845Seric 31866845Seric int 31966845Seric opendaemonsocket() 32066845Seric { 32166845Seric int on = 1; 32266845Seric int socksize; 32366845Seric 32466845Seric if (tTd(15, 2)) 32566845Seric printf("opendaemonsocket()\n"); 32666845Seric 32766845Seric DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0); 32866845Seric if (DaemonSocket < 0) 32966845Seric { 33066845Seric /* probably another daemon already */ 33166845Seric syserr("opendaemonsocket: can't create server SMTP socket"); 33266845Seric severe: 33366845Seric # ifdef LOG 33466845Seric if (LogLevel > 0) 33566845Seric syslog(LOG_ALERT, "problem creating SMTP socket"); 33666845Seric # endif /* LOG */ 33766845Seric finis(); 33866845Seric } 33966845Seric 34066845Seric /* turn on network debugging? */ 34166845Seric if (tTd(15, 101)) 34266845Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 34366845Seric 34466845Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 34566845Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 34666845Seric 34766845Seric #ifdef SO_RCVBUF 34866845Seric if (TcpRcvBufferSize > 0) 34966845Seric { 35066845Seric if (setsockopt(DaemonSocket, SOL_SOCKET, SO_RCVBUF, 35166845Seric (char *) &TcpRcvBufferSize, 35266845Seric sizeof(TcpRcvBufferSize)) < 0) 35366845Seric syserr("getrequests: setsockopt(SO_RCVBUF)"); 35466845Seric } 35566845Seric #endif 35666845Seric 35766845Seric switch (DaemonAddr.sa.sa_family) 35866845Seric { 35966845Seric # ifdef NETINET 36066845Seric case AF_INET: 36166845Seric socksize = sizeof DaemonAddr.sin; 36266845Seric break; 36366845Seric # endif 36466845Seric 36566845Seric # ifdef NETISO 36666845Seric case AF_ISO: 36766845Seric socksize = sizeof DaemonAddr.siso; 36866845Seric break; 36966845Seric # endif 37066845Seric 37166845Seric default: 37266845Seric socksize = sizeof DaemonAddr; 37366845Seric break; 37466845Seric } 37566845Seric 37666845Seric if (bind(DaemonSocket, &DaemonAddr.sa, socksize) < 0) 37766845Seric { 37866845Seric syserr("getrequests: cannot bind"); 37966845Seric (void) close(DaemonSocket); 38066845Seric goto severe; 38166845Seric } 38266845Seric if (listen(DaemonSocket, ListenQueueSize) < 0) 38366845Seric { 38466845Seric syserr("getrequests: cannot listen"); 38566845Seric (void) close(DaemonSocket); 38666845Seric goto severe; 38766845Seric } 38866845Seric return socksize; 38966845Seric } 39066845Seric /* 39110206Seric ** CLRDAEMON -- reset the daemon connection 39210206Seric ** 39310206Seric ** Parameters: 39410206Seric ** none. 39510206Seric ** 39610206Seric ** Returns: 39710206Seric ** none. 39810206Seric ** 39910206Seric ** Side Effects: 40010206Seric ** releases any resources used by the passive daemon. 40110206Seric */ 40210206Seric 40310206Seric clrdaemon() 40410206Seric { 40510206Seric if (DaemonSocket >= 0) 40610206Seric (void) close(DaemonSocket); 40710206Seric DaemonSocket = -1; 40810206Seric } 40910206Seric /* 41058849Seric ** SETDAEMONOPTIONS -- set options for running the daemon 41158849Seric ** 41258849Seric ** Parameters: 41358849Seric ** p -- the options line. 41458849Seric ** 41558849Seric ** Returns: 41658849Seric ** none. 41758849Seric */ 41858849Seric 41958849Seric setdaemonoptions(p) 42058849Seric register char *p; 42158849Seric { 42258873Seric if (DaemonAddr.sa.sa_family == AF_UNSPEC) 42358873Seric DaemonAddr.sa.sa_family = AF_INET; 42458873Seric 42558849Seric while (p != NULL) 42658849Seric { 42758849Seric register char *f; 42858849Seric register char *v; 42958849Seric 43058849Seric while (isascii(*p) && isspace(*p)) 43158849Seric p++; 43258849Seric if (*p == '\0') 43358849Seric break; 43458849Seric f = p; 43558849Seric p = strchr(p, ','); 43658849Seric if (p != NULL) 43758849Seric *p++ = '\0'; 43858849Seric v = strchr(f, '='); 43958849Seric if (v == NULL) 44058849Seric continue; 44158849Seric while (isascii(*++v) && isspace(*v)) 44258849Seric continue; 44358849Seric 44458849Seric switch (*f) 44558849Seric { 44658873Seric case 'F': /* address family */ 44758849Seric if (isascii(*v) && isdigit(*v)) 44858873Seric DaemonAddr.sa.sa_family = atoi(v); 44958873Seric #ifdef NETINET 45058873Seric else if (strcasecmp(v, "inet") == 0) 45158873Seric DaemonAddr.sa.sa_family = AF_INET; 45258873Seric #endif 45358873Seric #ifdef NETISO 45458873Seric else if (strcasecmp(v, "iso") == 0) 45558873Seric DaemonAddr.sa.sa_family = AF_ISO; 45658873Seric #endif 45758873Seric #ifdef NETNS 45858873Seric else if (strcasecmp(v, "ns") == 0) 45958873Seric DaemonAddr.sa.sa_family = AF_NS; 46058873Seric #endif 46158873Seric #ifdef NETX25 46258873Seric else if (strcasecmp(v, "x.25") == 0) 46358873Seric DaemonAddr.sa.sa_family = AF_CCITT; 46458873Seric #endif 46558849Seric else 46658873Seric syserr("554 Unknown address family %s in Family=option", v); 46758873Seric break; 46858873Seric 46958873Seric case 'A': /* address */ 47058873Seric switch (DaemonAddr.sa.sa_family) 47158849Seric { 47258873Seric #ifdef NETINET 47358873Seric case AF_INET: 47458873Seric if (isascii(*v) && isdigit(*v)) 47558873Seric DaemonAddr.sin.sin_addr.s_addr = inet_network(v); 47658873Seric else 47758873Seric { 47858873Seric register struct netent *np; 47958849Seric 48058873Seric np = getnetbyname(v); 48158873Seric if (np == NULL) 48258873Seric syserr("554 network \"%s\" unknown", v); 48358873Seric else 48458873Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 48558873Seric } 48658873Seric break; 48758873Seric #endif 48858873Seric 48958873Seric default: 49058873Seric syserr("554 Address= option unsupported for family %d", 49158873Seric DaemonAddr.sa.sa_family); 49258873Seric break; 49358849Seric } 49458849Seric break; 49558849Seric 49658873Seric case 'P': /* port */ 49758873Seric switch (DaemonAddr.sa.sa_family) 49858849Seric { 49958873Seric short port; 50058849Seric 50158873Seric #ifdef NETINET 50258873Seric case AF_INET: 50358873Seric if (isascii(*v) && isdigit(*v)) 50464366Seric DaemonAddr.sin.sin_port = htons(atoi(v)); 50558849Seric else 50658873Seric { 50758873Seric register struct servent *sp; 50858873Seric 50958873Seric sp = getservbyname(v, "tcp"); 51058873Seric if (sp == NULL) 51158909Seric syserr("554 service \"%s\" unknown", v); 51258873Seric else 51358873Seric DaemonAddr.sin.sin_port = sp->s_port; 51458873Seric } 51558873Seric break; 51658873Seric #endif 51758873Seric 51858873Seric #ifdef NETISO 51958873Seric case AF_ISO: 52058873Seric /* assume two byte transport selector */ 52158873Seric if (isascii(*v) && isdigit(*v)) 52264366Seric port = htons(atoi(v)); 52358873Seric else 52458873Seric { 52558873Seric register struct servent *sp; 52658873Seric 52758873Seric sp = getservbyname(v, "tcp"); 52858873Seric if (sp == NULL) 52958909Seric syserr("554 service \"%s\" unknown", v); 53058873Seric else 53158873Seric port = sp->s_port; 53258873Seric } 53358873Seric bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 53458873Seric break; 53558873Seric #endif 53658873Seric 53758873Seric default: 53858873Seric syserr("554 Port= option unsupported for family %d", 53958873Seric DaemonAddr.sa.sa_family); 54058873Seric break; 54158849Seric } 54258849Seric break; 54359783Seric 54459783Seric case 'L': /* listen queue size */ 54559783Seric ListenQueueSize = atoi(v); 54659783Seric break; 54764381Seric 54864381Seric case 'S': /* send buffer size */ 54964381Seric TcpSndBufferSize = atoi(v); 55064381Seric break; 55164381Seric 55264381Seric case 'R': /* receive buffer size */ 55364381Seric TcpRcvBufferSize = atoi(v); 55464381Seric break; 55558849Seric } 55658849Seric } 55758849Seric } 55858849Seric /* 5596039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 5606039Seric ** 5616039Seric ** Parameters: 5626039Seric ** host -- the name of the host. 5636633Seric ** port -- the port number to connect to. 56453739Seric ** mci -- a pointer to the mail connection information 56553739Seric ** structure to be filled in. 56652106Seric ** usesecureport -- if set, use a low numbered (reserved) 56752106Seric ** port to provide some rudimentary authentication. 5686039Seric ** 5696039Seric ** Returns: 5706039Seric ** An exit code telling whether the connection could be 5716039Seric ** made and if not why not. 5726039Seric ** 5736039Seric ** Side Effects: 5746039Seric ** none. 5756039Seric */ 5765978Seric 57758755Seric SOCKADDR CurHostAddr; /* address of current host */ 57858305Seric 57954967Seric int 58053739Seric makeconnection(host, port, mci, usesecureport) 5816039Seric char *host; 5827286Seric u_short port; 58354967Seric register MCI *mci; 58452106Seric bool usesecureport; 5856039Seric { 58629430Sbloom register int i, s; 58729430Sbloom register struct hostent *hp = (struct hostent *)NULL; 58858755Seric SOCKADDR addr; 58952106Seric int sav_errno; 59058755Seric int addrlen; 59166334Seric #if NAMED_BIND 59235651Seric extern int h_errno; 59335651Seric #endif 5946039Seric 5956039Seric /* 5966039Seric ** Set up the address for the mailer. 5979308Seric ** Accept "[a.b.c.d]" syntax for host name. 5986039Seric */ 5996039Seric 60066334Seric #if NAMED_BIND 60125475Smiriam h_errno = 0; 60235651Seric #endif 60325475Smiriam errno = 0; 60458864Seric bzero(&CurHostAddr, sizeof CurHostAddr); 60564334Seric SmtpPhase = mci->mci_phase = "initial connection"; 60658906Seric CurHostName = host; 60725475Smiriam 6089308Seric if (host[0] == '[') 6099308Seric { 61011147Seric long hid; 61156795Seric register char *p = strchr(host, ']'); 6129308Seric 61311147Seric if (p != NULL) 6149308Seric { 61511147Seric *p = '\0'; 61659884Seric #ifdef NETINET 61711147Seric hid = inet_addr(&host[1]); 61858360Seric if (hid == -1) 61959884Seric #endif 62058360Seric { 62158360Seric /* try it as a host name (avoid MX lookup) */ 62258360Seric hp = gethostbyname(&host[1]); 62366349Seric if (hp == NULL && p[-1] == '.') 62466349Seric { 62566349Seric p[-1] = '\0'; 62666349Seric hp = gethostbyname(&host[1]); 62766349Seric p[-1] = '.'; 62866349Seric } 62958360Seric *p = ']'; 63058360Seric goto gothostent; 63158360Seric } 63211147Seric *p = ']'; 6339308Seric } 63458360Seric if (p == NULL) 6359308Seric { 63658151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 6379308Seric return (EX_NOHOST); 6389308Seric } 63959884Seric #ifdef NETINET 64059884Seric addr.sin.sin_family = AF_INET; /*XXX*/ 64158778Seric addr.sin.sin_addr.s_addr = hid; 64259884Seric #endif 6439308Seric } 6449610Seric else 6459610Seric { 64666349Seric register char *p = &host[strlen(host) - 1]; 64766349Seric 64829430Sbloom hp = gethostbyname(host); 64966349Seric if (hp == NULL && *p == '.') 65066349Seric { 65166349Seric *p = '\0'; 65266349Seric hp = gethostbyname(host); 65366349Seric *p = '.'; 65466349Seric } 65558360Seric gothostent: 65625475Smiriam if (hp == NULL) 65724945Seric { 65866334Seric #if NAMED_BIND 65925475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 66025475Smiriam return (EX_TEMPFAIL); 66125657Seric 66235651Seric /* if name server is specified, assume temp fail */ 66335651Seric if (errno == ECONNREFUSED && UseNameServer) 66435651Seric return (EX_TEMPFAIL); 66535651Seric #endif 66625475Smiriam return (EX_NOHOST); 66724945Seric } 66858778Seric addr.sa.sa_family = hp->h_addrtype; 66958778Seric switch (hp->h_addrtype) 67058778Seric { 67158778Seric #ifdef NETINET 67258778Seric case AF_INET: 67358755Seric bcopy(hp->h_addr, 67458778Seric &addr.sin.sin_addr, 67564943Seric sizeof addr.sin.sin_addr); 67658778Seric break; 67758778Seric #endif 67858778Seric 67958778Seric default: 68058755Seric bcopy(hp->h_addr, 68158778Seric addr.sa.sa_data, 68258755Seric hp->h_length); 68358778Seric break; 68458778Seric } 68529430Sbloom i = 1; 6869610Seric } 6879610Seric 6889610Seric /* 6899610Seric ** Determine the port number. 6909610Seric */ 6919610Seric 69210011Seric if (port != 0) 69358755Seric port = htons(port); 69410011Seric else 6959610Seric { 6969610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 6979610Seric 6989610Seric if (sp == NULL) 6999610Seric { 70058909Seric syserr("554 makeconnection: service \"smtp\" unknown"); 70165169Seric port = htons(25); 7029610Seric } 70365169Seric else 70465169Seric port = sp->s_port; 7059610Seric } 7066039Seric 70758778Seric switch (addr.sa.sa_family) 70858755Seric { 70959884Seric #ifdef NETINET 71058755Seric case AF_INET: 71158778Seric addr.sin.sin_port = port; 71258755Seric addrlen = sizeof (struct sockaddr_in); 71358755Seric break; 71459884Seric #endif 71558755Seric 71658755Seric #ifdef NETISO 71758755Seric case AF_ISO: 71858755Seric /* assume two byte transport selector */ 71958755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 72058755Seric addrlen = sizeof (struct sockaddr_iso); 72158755Seric break; 72258755Seric #endif 72358755Seric 72458755Seric default: 72558778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 72658755Seric return (EX_NOHOST); 72758755Seric } 72858755Seric 7296039Seric /* 7306039Seric ** Try to actually open the connection. 7316039Seric */ 7326039Seric 73359156Seric #ifdef XLA 73459156Seric /* if too many connections, don't bother trying */ 73559156Seric if (!xla_noqueue_ok(host)) 73659156Seric return EX_TEMPFAIL; 73759156Seric #endif 73859156Seric 73957736Seric for (;;) 74052106Seric { 74157736Seric if (tTd(16, 1)) 74258755Seric printf("makeconnection (%s [%s])\n", 74358755Seric host, anynet_ntoa(&addr)); 74452106Seric 74558588Seric /* save for logging */ 74658588Seric CurHostAddr = addr; 74758588Seric 74857736Seric if (usesecureport) 74957736Seric { 75057736Seric int rport = IPPORT_RESERVED - 1; 7516039Seric 75257736Seric s = rresvport(&rport); 75357736Seric } 75457736Seric else 75557736Seric { 75657736Seric s = socket(AF_INET, SOCK_STREAM, 0); 75757736Seric } 75857736Seric if (s < 0) 75957736Seric { 76057736Seric sav_errno = errno; 76157736Seric syserr("makeconnection: no socket"); 76257736Seric goto failure; 76357736Seric } 76410347Seric 76564381Seric #ifdef SO_SNDBUF 76664381Seric if (TcpSndBufferSize > 0) 76764381Seric { 76864381Seric if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 76964561Seric (char *) &TcpSndBufferSize, 77064381Seric sizeof(TcpSndBufferSize)) < 0) 77164381Seric syserr("makeconnection: setsockopt(SO_SNDBUF)"); 77264381Seric } 77364381Seric #endif 77464381Seric 77557736Seric if (tTd(16, 1)) 77657736Seric printf("makeconnection: fd=%d\n", s); 77757736Seric 77857736Seric /* turn on network debugging? */ 77957736Seric if (tTd(16, 101)) 78057736Seric { 78157736Seric int on = 1; 78257736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 78357736Seric (char *)&on, sizeof on); 78457736Seric } 78557736Seric if (CurEnv->e_xfp != NULL) 78657736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 78757736Seric errno = 0; /* for debugging */ 78858755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 78957736Seric break; 79057736Seric 79157736Seric /* couldn't connect.... figure out why */ 79227744Sbloom sav_errno = errno; 79327744Sbloom (void) close(s); 79429430Sbloom if (hp && hp->h_addr_list[i]) 79529430Sbloom { 79657736Seric if (tTd(16, 1)) 79758755Seric printf("Connect failed (%s); trying new address....\n", 79858755Seric errstring(sav_errno)); 79958778Seric switch (addr.sa.sa_family) 80058778Seric { 80158778Seric #ifdef NETINET 80258778Seric case AF_INET: 80358755Seric bcopy(hp->h_addr_list[i++], 80458778Seric &addr.sin.sin_addr, 80564943Seric sizeof addr.sin.sin_addr); 80658778Seric break; 80758778Seric #endif 80858778Seric 80958778Seric default: 81058755Seric bcopy(hp->h_addr_list[i++], 81158778Seric addr.sa.sa_data, 81252106Seric hp->h_length); 81358778Seric break; 81458778Seric } 81557736Seric continue; 81629430Sbloom } 81729430Sbloom 8186039Seric /* failure, decide if temporary or not */ 8196039Seric failure: 82059254Seric #ifdef XLA 82159254Seric xla_host_end(host); 82259254Seric #endif 82358542Seric if (transienterror(sav_errno)) 82458542Seric return EX_TEMPFAIL; 82558542Seric else 82658542Seric { 82758542Seric message("%s", errstring(sav_errno)); 82858542Seric return (EX_UNAVAILABLE); 8296039Seric } 8306039Seric } 8316039Seric 8326039Seric /* connection ok, put it into canonical form */ 83364724Seric if ((mci->mci_out = fdopen(s, "w")) == NULL || 83464724Seric (s = dup(s)) < 0 || 83564725Seric (mci->mci_in = fdopen(s, "r")) == NULL) 83664724Seric { 83764724Seric syserr("cannot open SMTP client channel, fd=%d", s); 83864724Seric return EX_TEMPFAIL; 83964724Seric } 8406039Seric 84110098Seric return (EX_OK); 8426039Seric } 84310758Seric /* 84410758Seric ** MYHOSTNAME -- return the name of this host. 84510758Seric ** 84610758Seric ** Parameters: 84710758Seric ** hostbuf -- a place to return the name of this host. 84812313Seric ** size -- the size of hostbuf. 84910758Seric ** 85010758Seric ** Returns: 85110758Seric ** A list of aliases for this host. 85210758Seric ** 85310758Seric ** Side Effects: 85464338Seric ** Adds numeric codes to $=w. 85510758Seric */ 8566039Seric 85710758Seric char ** 85812313Seric myhostname(hostbuf, size) 85910758Seric char hostbuf[]; 86012313Seric int size; 86110758Seric { 86258110Seric register struct hostent *hp; 86310758Seric extern struct hostent *gethostbyname(); 86410758Seric 86523120Seric if (gethostname(hostbuf, size) < 0) 86623120Seric { 86723120Seric (void) strcpy(hostbuf, "localhost"); 86823120Seric } 86911147Seric hp = gethostbyname(hostbuf); 870*66853Seric if (hp == NULL) 87116877Seric { 872*66853Seric syserr("!My host name (%s) does not seem to exist!", hostbuf); 873*66853Seric } 874*66853Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 875*66853Seric hostbuf[size - 1] = '\0'; 876*66853Seric 877*66853Seric #if NAMED_BIND 878*66853Seric /* if still no dot, try DNS directly (i.e., avoid NIS problems) */ 879*66853Seric if (strchr(hostbuf, '.') == NULL) 880*66853Seric { 881*66853Seric extern bool getcanonname(); 882*66853Seric extern int h_errno; 883*66853Seric 884*66853Seric /* try twice in case name server not yet started up */ 885*66853Seric if (!getcanonname(hostbuf, size, TRUE) && 886*66853Seric UseNameServer && 887*66853Seric (h_errno != TRY_AGAIN || 888*66853Seric (sleep(30), !getcanonname(hostbuf, size, TRUE)))) 88966777Seric { 890*66853Seric errno = h_errno + E_DNSBASE; 891*66853Seric syserr("!My host name (%s) not known to DNS", 892*66853Seric hostbuf); 89366777Seric } 894*66853Seric } 89566777Seric #endif 89666777Seric 897*66853Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 898*66853Seric { 899*66853Seric register int i; 900*66853Seric 901*66853Seric for (i = 0; hp->h_addr_list[i] != NULL; i++) 90258110Seric { 903*66853Seric char ipbuf[100]; 90458110Seric 905*66853Seric sprintf(ipbuf, "[%s]", 906*66853Seric inet_ntoa(*((struct in_addr *) hp->h_addr_list[i]))); 907*66853Seric setclass('w', ipbuf); 90858110Seric } 909*66853Seric } 91058110Seric 911*66853Seric return (hp->h_aliases); 91210758Seric } 91351315Seric /* 91458951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 91558308Seric ** 91658951Seric ** Uses RFC1413 protocol to try to get info from the other end. 91758951Seric ** 91858308Seric ** Parameters: 91958308Seric ** fd -- the descriptor 92058308Seric ** 92158308Seric ** Returns: 92258951Seric ** The user@host information associated with this descriptor. 92358308Seric */ 92458308Seric 92564927Seric #if IDENTPROTO 92658951Seric 92758951Seric static jmp_buf CtxAuthTimeout; 92858951Seric 92958951Seric static 93058951Seric authtimeout() 93158951Seric { 93258951Seric longjmp(CtxAuthTimeout, 1); 93358951Seric } 93458951Seric 93558951Seric #endif 93658951Seric 93758308Seric char * 93858951Seric getauthinfo(fd) 93958308Seric int fd; 94058308Seric { 94158951Seric int falen; 94259104Seric register char *p; 94364927Seric #if IDENTPROTO 94458951Seric SOCKADDR la; 94558951Seric int lalen; 94658951Seric register struct servent *sp; 94758951Seric int s; 94858951Seric int i; 94958951Seric EVENT *ev; 95058951Seric #endif 95158951Seric static char hbuf[MAXNAME * 2 + 2]; 95258951Seric extern char *hostnamebyanyaddr(); 95358951Seric extern char RealUserName[]; /* main.c */ 95458308Seric 95566761Seric falen = sizeof RealHostAddr; 95666761Seric if (getpeername(fd, &RealHostAddr.sa, &falen) < 0 || falen <= 0 || 95766761Seric RealHostAddr.sa.sa_family == 0) 95858951Seric { 95958951Seric (void) sprintf(hbuf, "%s@localhost", RealUserName); 96058957Seric if (tTd(9, 1)) 96158951Seric printf("getauthinfo: %s\n", hbuf); 96258951Seric return hbuf; 96358951Seric } 96458951Seric 96566761Seric if (RealHostName == NULL) 96666761Seric { 96766761Seric /* translate that to a host name */ 96866761Seric RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 96966761Seric } 97066761Seric 97164927Seric #if IDENTPROTO 97265831Seric if (TimeOuts.to_ident == 0) 97365831Seric goto noident; 97465831Seric 97558951Seric lalen = sizeof la; 97666761Seric if (RealHostAddr.sa.sa_family != AF_INET || 97758951Seric getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || 97858951Seric la.sa.sa_family != AF_INET) 97958951Seric { 98058951Seric /* no ident info */ 98158951Seric goto noident; 98258951Seric } 98358951Seric 98458951Seric /* create ident query */ 98560489Seric (void) sprintf(hbuf, "%d,%d\r\n", 98666761Seric ntohs(RealHostAddr.sin.sin_port), ntohs(la.sin.sin_port)); 98758951Seric 98858951Seric /* create local address */ 98964747Seric la.sin.sin_port = 0; 99058951Seric 99158951Seric /* create foreign address */ 99258951Seric sp = getservbyname("auth", "tcp"); 99358951Seric if (sp != NULL) 99466761Seric RealHostAddr.sin.sin_port = sp->s_port; 99558308Seric else 99666761Seric RealHostAddr.sin.sin_port = htons(113); 99758951Seric 99858951Seric s = -1; 99958951Seric if (setjmp(CtxAuthTimeout) != 0) 100058951Seric { 100158951Seric if (s >= 0) 100258951Seric (void) close(s); 100358951Seric goto noident; 100458951Seric } 100558951Seric 100658951Seric /* put a timeout around the whole thing */ 100764255Seric ev = setevent(TimeOuts.to_ident, authtimeout, 0); 100858951Seric 100964747Seric /* connect to foreign IDENT server using same address as SMTP socket */ 101058951Seric s = socket(AF_INET, SOCK_STREAM, 0); 101158951Seric if (s < 0) 101258951Seric { 101358951Seric clrevent(ev); 101458951Seric goto noident; 101558951Seric } 101664747Seric if (bind(s, &la.sa, sizeof la.sin) < 0 || 101766761Seric connect(s, &RealHostAddr.sa, sizeof RealHostAddr.sin) < 0) 101858951Seric { 101966011Seric goto closeident; 102058951Seric } 102158951Seric 102258957Seric if (tTd(9, 10)) 102358951Seric printf("getauthinfo: sent %s", hbuf); 102458951Seric 102558951Seric /* send query */ 102658951Seric if (write(s, hbuf, strlen(hbuf)) < 0) 102758951Seric goto closeident; 102858951Seric 102958951Seric /* get result */ 103058951Seric i = read(s, hbuf, sizeof hbuf); 103158951Seric (void) close(s); 103258951Seric clrevent(ev); 103358951Seric if (i <= 0) 103458951Seric goto noident; 103558951Seric if (hbuf[--i] == '\n' && hbuf[--i] == '\r') 103658951Seric i--; 103758951Seric hbuf[++i] = '\0'; 103858951Seric 103958957Seric if (tTd(9, 3)) 104058951Seric printf("getauthinfo: got %s\n", hbuf); 104158951Seric 104258951Seric /* parse result */ 104358951Seric p = strchr(hbuf, ':'); 104458951Seric if (p == NULL) 104558951Seric { 104658951Seric /* malformed response */ 104758951Seric goto noident; 104858951Seric } 104958951Seric while (isascii(*++p) && isspace(*p)) 105058951Seric continue; 105158951Seric if (strncasecmp(p, "userid", 6) != 0) 105258951Seric { 105358951Seric /* presumably an error string */ 105458951Seric goto noident; 105558951Seric } 105658951Seric p += 6; 105758951Seric while (isascii(*p) && isspace(*p)) 105858951Seric p++; 105958951Seric if (*p++ != ':') 106058951Seric { 106158951Seric /* either useridxx or malformed response */ 106258951Seric goto noident; 106358951Seric } 106458951Seric 106558951Seric /* p now points to the OSTYPE field */ 106658951Seric p = strchr(p, ':'); 106758951Seric if (p == NULL) 106858951Seric { 106958951Seric /* malformed response */ 107058951Seric goto noident; 107158951Seric } 107258951Seric 107358957Seric /* 1413 says don't do this -- but it's broken otherwise */ 107458957Seric while (isascii(*++p) && isspace(*p)) 107558957Seric continue; 107658957Seric 107758951Seric /* p now points to the authenticated name */ 107866003Seric (void) sprintf(hbuf, "%s@%s", 107966003Seric p, RealHostName == NULL ? "localhost" : RealHostName); 108058957Seric goto finish; 108158957Seric 108266011Seric closeident: 108366011Seric (void) close(s); 108466011Seric clrevent(ev); 108566011Seric 108658957Seric #endif /* IDENTPROTO */ 108758957Seric 108858957Seric noident: 108966003Seric if (RealHostName == NULL) 109066003Seric { 109166003Seric if (tTd(9, 1)) 109266003Seric printf("getauthinfo: NULL\n"); 109366003Seric return NULL; 109466003Seric } 109558957Seric (void) strcpy(hbuf, RealHostName); 109658957Seric 109758957Seric finish: 109866003Seric if (RealHostName != NULL && RealHostName[0] != '[') 109958951Seric { 110058951Seric p = &hbuf[strlen(hbuf)]; 110158951Seric (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); 110258951Seric } 110358957Seric if (tTd(9, 1)) 110458951Seric printf("getauthinfo: %s\n", hbuf); 110558308Seric return hbuf; 110658308Seric } 110758308Seric /* 110860089Seric ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 110953751Seric ** 111053751Seric ** Parameters: 111156823Seric ** map -- a pointer to this map (unused). 111260089Seric ** name -- the (presumably unqualified) hostname. 111360257Seric ** av -- unused -- for compatibility with other mapping 111455019Seric ** functions. 111559084Seric ** statp -- an exit status (out parameter) -- set to 111659084Seric ** EX_TEMPFAIL if the name server is unavailable. 111753751Seric ** 111853751Seric ** Returns: 111953751Seric ** The mapping, if found. 112053751Seric ** NULL if no mapping found. 112153751Seric ** 112253751Seric ** Side Effects: 112353751Seric ** Looks up the host specified in hbuf. If it is not 112453751Seric ** the canonical name for that host, return the canonical 112553751Seric ** name. 112653751Seric */ 112751315Seric 112853751Seric char * 112960257Seric host_map_lookup(map, name, av, statp) 113056823Seric MAP *map; 113160089Seric char *name; 113260257Seric char **av; 113359084Seric int *statp; 113416911Seric { 113516911Seric register struct hostent *hp; 113633932Sbostic u_long in_addr; 113756823Seric char *cp; 113858110Seric int i; 113959671Seric register STAB *s; 114060257Seric char hbuf[MAXNAME]; 114159671Seric extern struct hostent *gethostbyaddr(); 114266334Seric #if NAMED_BIND 114359671Seric extern int h_errno; 114466029Seric #endif 114516911Seric 114625574Smiriam /* 114759671Seric ** See if we have already looked up this name. If so, just 114859671Seric ** return it. 114959671Seric */ 115053751Seric 115160089Seric s = stab(name, ST_NAMECANON, ST_ENTER); 115259671Seric if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 115359671Seric { 115459986Seric if (tTd(9, 1)) 115560089Seric printf("host_map_lookup(%s) => CACHE %s\n", 115660089Seric name, s->s_namecanon.nc_cname); 115759671Seric errno = s->s_namecanon.nc_errno; 115866334Seric #if NAMED_BIND 115959671Seric h_errno = s->s_namecanon.nc_herrno; 116066029Seric #endif 116159671Seric *statp = s->s_namecanon.nc_stat; 116264797Seric if (CurEnv->e_message == NULL && *statp == EX_TEMPFAIL) 116365199Seric { 116465199Seric sprintf(hbuf, "%s: Name server timeout", 116565199Seric shortenstring(name, 33)); 116665199Seric CurEnv->e_message = newstr(hbuf); 116765199Seric } 116859671Seric return s->s_namecanon.nc_cname; 116959671Seric } 117059671Seric 117159671Seric /* 117259671Seric ** If first character is a bracket, then it is an address 117359671Seric ** lookup. Address is copied into a temporary buffer to 117460089Seric ** strip the brackets and to preserve name if address is 117559671Seric ** unknown. 117659671Seric */ 117759671Seric 117860089Seric if (*name != '[') 117953751Seric { 118055019Seric extern bool getcanonname(); 118155019Seric 118258798Seric if (tTd(9, 1)) 118360089Seric printf("host_map_lookup(%s) => ", name); 118459671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 118560089Seric (void) strcpy(hbuf, name); 118663842Seric if (getcanonname(hbuf, sizeof hbuf - 1, TRUE)) 118758796Seric { 118858796Seric if (tTd(9, 1)) 118958796Seric printf("%s\n", hbuf); 119060257Seric cp = map_rewrite(map, hbuf, strlen(hbuf), av); 119160257Seric s->s_namecanon.nc_cname = newstr(cp); 119260257Seric return cp; 119358796Seric } 119453751Seric else 119558796Seric { 119659084Seric register struct hostent *hp; 119759084Seric 119866029Seric s->s_namecanon.nc_errno = errno; 119966334Seric #if NAMED_BIND 120066029Seric s->s_namecanon.nc_herrno = h_errno; 120158796Seric if (tTd(9, 1)) 120259084Seric printf("FAIL (%d)\n", h_errno); 120359084Seric switch (h_errno) 120459084Seric { 120559084Seric case TRY_AGAIN: 120659596Seric if (UseNameServer) 120759734Seric { 120865202Seric sprintf(hbuf, "%s: Name server timeout", 120965199Seric shortenstring(name, 33)); 121065202Seric message("%s", hbuf); 121159734Seric if (CurEnv->e_message == NULL) 121265202Seric CurEnv->e_message = newstr(hbuf); 121359734Seric } 121459084Seric *statp = EX_TEMPFAIL; 121559084Seric break; 121659084Seric 121759084Seric case HOST_NOT_FOUND: 121859084Seric *statp = EX_NOHOST; 121959084Seric break; 122059084Seric 122159084Seric case NO_RECOVERY: 122259084Seric *statp = EX_SOFTWARE; 122359084Seric break; 122459084Seric 122559084Seric default: 122659084Seric *statp = EX_UNAVAILABLE; 122759084Seric break; 122859084Seric } 122966029Seric #else 123066029Seric if (tTd(9, 1)) 123166029Seric printf("FAIL\n"); 123266029Seric *statp = EX_NOHOST; 123366029Seric #endif 123459671Seric s->s_namecanon.nc_stat = *statp; 123559084Seric if (*statp != EX_TEMPFAIL || UseNameServer) 123659084Seric return NULL; 123759084Seric 123859084Seric /* 123959084Seric ** Try to look it up in /etc/hosts 124059084Seric */ 124159084Seric 124260089Seric hp = gethostbyname(name); 124359084Seric if (hp == NULL) 124459084Seric { 124559084Seric /* no dice there either */ 124659671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 124759084Seric return NULL; 124859084Seric } 124959084Seric 125059671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 125160257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 125260257Seric s->s_namecanon.nc_cname = newstr(cp); 125360257Seric return cp; 125458796Seric } 125553751Seric } 125660089Seric if ((cp = strchr(name, ']')) == NULL) 125753751Seric return (NULL); 125840994Sbostic *cp = '\0'; 125960089Seric in_addr = inet_addr(&name[1]); 126058110Seric 126158110Seric /* nope -- ask the name server */ 126233932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 126359671Seric s->s_namecanon.nc_errno = errno; 126466334Seric #if NAMED_BIND 126559671Seric s->s_namecanon.nc_herrno = h_errno; 126666029Seric #endif 126759671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 126833932Sbostic if (hp == NULL) 126959671Seric { 127059671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 127153751Seric return (NULL); 127259671Seric } 127353751Seric 127458110Seric /* found a match -- copy out */ 127560257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 127659671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 127760257Seric s->s_namecanon.nc_cname = newstr(cp); 127860257Seric return cp; 127933932Sbostic } 128058755Seric /* 128158755Seric ** ANYNET_NTOA -- convert a network address to printable form. 128258755Seric ** 128358755Seric ** Parameters: 128458755Seric ** sap -- a pointer to a sockaddr structure. 128558755Seric ** 128658755Seric ** Returns: 128758755Seric ** A printable version of that sockaddr. 128858755Seric */ 128916911Seric 129058755Seric char * 129158755Seric anynet_ntoa(sap) 129258755Seric register SOCKADDR *sap; 129358755Seric { 129458755Seric register char *bp; 129558755Seric register char *ap; 129658755Seric int l; 129764734Seric static char buf[100]; 129858755Seric 129958798Seric /* check for null/zero family */ 130058798Seric if (sap == NULL) 130158798Seric return "NULLADDR"; 130258798Seric if (sap->sa.sa_family == 0) 130358798Seric return "0"; 130458798Seric 130564734Seric switch (sap->sa.sa_family) 130664734Seric { 130764734Seric #ifdef MAYBENEXTRELEASE /*** UNTESTED *** UNTESTED *** UNTESTED ***/ 130864821Seric #ifdef NETUNIX 130964734Seric case AF_UNIX: 131064758Seric if (sap->sunix.sun_path[0] != '\0') 131164758Seric sprintf(buf, "[UNIX: %.64s]", sap->sunix.sun_path); 131264734Seric else 131364734Seric sprintf(buf, "[UNIX: localhost]"); 131464734Seric return buf; 131564734Seric #endif 131664821Seric #endif 131764734Seric 131858778Seric #ifdef NETINET 131964734Seric case AF_INET: 132058755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 132158778Seric #endif 132258755Seric 132364734Seric default: 132464734Seric /* this case is only to ensure syntactic correctness */ 132564734Seric break; 132664734Seric } 132764734Seric 132858755Seric /* unknown family -- just dump bytes */ 132958778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 133058755Seric bp = &buf[strlen(buf)]; 133158778Seric ap = sap->sa.sa_data; 133258778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 133358755Seric { 133458755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 133558755Seric bp += 3; 133658755Seric } 133758755Seric *--bp = '\0'; 133858755Seric return buf; 133958755Seric } 134058951Seric /* 134158951Seric ** HOSTNAMEBYANYADDR -- return name of host based on address 134258951Seric ** 134358951Seric ** Parameters: 134458951Seric ** sap -- SOCKADDR pointer 134558951Seric ** 134658951Seric ** Returns: 134758951Seric ** text representation of host name. 134858951Seric ** 134958951Seric ** Side Effects: 135058951Seric ** none. 135158951Seric */ 135258755Seric 135358951Seric char * 135458951Seric hostnamebyanyaddr(sap) 135558951Seric register SOCKADDR *sap; 135658951Seric { 135758951Seric register struct hostent *hp; 135864734Seric int saveretry; 135958951Seric 136066334Seric #if NAMED_BIND 136159042Seric /* shorten name server timeout to avoid higher level timeouts */ 136259042Seric saveretry = _res.retry; 136359042Seric _res.retry = 3; 136459042Seric #endif /* NAMED_BIND */ 136559042Seric 136658951Seric switch (sap->sa.sa_family) 136758951Seric { 136858951Seric #ifdef NETINET 136958951Seric case AF_INET: 137058951Seric hp = gethostbyaddr((char *) &sap->sin.sin_addr, 137158951Seric sizeof sap->sin.sin_addr, 137258951Seric AF_INET); 137358951Seric break; 137458951Seric #endif 137558951Seric 137658951Seric #ifdef NETISO 137758951Seric case AF_ISO: 137858951Seric hp = gethostbyaddr((char *) &sap->siso.siso_addr, 137958951Seric sizeof sap->siso.siso_addr, 138058951Seric AF_ISO); 138158951Seric break; 138258951Seric #endif 138358951Seric 138464734Seric #ifdef MAYBENEXTRELEASE /*** UNTESTED *** UNTESTED *** UNTESTED ***/ 138564734Seric case AF_UNIX: 138664734Seric hp = NULL; 138764734Seric break; 138864734Seric #endif 138964734Seric 139058951Seric default: 139158951Seric hp = gethostbyaddr(sap->sa.sa_data, 139258951Seric sizeof sap->sa.sa_data, 139358951Seric sap->sa.sa_family); 139458951Seric break; 139558951Seric } 139658951Seric 139766334Seric #if NAMED_BIND 139859042Seric _res.retry = saveretry; 139959042Seric #endif /* NAMED_BIND */ 140059042Seric 140158951Seric if (hp != NULL) 140258951Seric return hp->h_name; 140358951Seric else 140458951Seric { 140558951Seric /* produce a dotted quad */ 140658951Seric static char buf[512]; 140758951Seric 140858951Seric (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); 140958951Seric return buf; 141058951Seric } 141158951Seric } 141258951Seric 141356795Seric # else /* DAEMON */ 141416911Seric /* code for systems without sophisticated networking */ 141510758Seric 141610758Seric /* 141710758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 141811297Seric ** 141911297Seric ** Can't convert to upper case here because might be a UUCP name. 142012313Seric ** 142112313Seric ** Mark, you can change this to be anything you want...... 142210758Seric */ 142310758Seric 142410758Seric char ** 142512313Seric myhostname(hostbuf, size) 142610758Seric char hostbuf[]; 142712313Seric int size; 142810758Seric { 142910758Seric register FILE *f; 143010758Seric 143110758Seric hostbuf[0] = '\0'; 143210758Seric f = fopen("/usr/include/whoami", "r"); 143310758Seric if (f != NULL) 143410758Seric { 143512313Seric (void) fgets(hostbuf, size, f); 143610758Seric fixcrlf(hostbuf, TRUE); 143710758Seric (void) fclose(f); 143810758Seric } 143910758Seric return (NULL); 144010758Seric } 144116911Seric /* 144258951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 144358308Seric ** 144458308Seric ** Parameters: 144558308Seric ** fd -- the descriptor 144658308Seric ** 144758308Seric ** Returns: 144858308Seric ** The host name associated with this descriptor, if it can 144958308Seric ** be determined. 145058308Seric ** NULL otherwise. 145158308Seric ** 145258308Seric ** Side Effects: 145358308Seric ** none 145458308Seric */ 145558308Seric 145658308Seric char * 145758951Seric getauthinfo(fd) 145858308Seric int fd; 145958308Seric { 146058308Seric return NULL; 146158308Seric } 146258308Seric /* 146316911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 146416911Seric ** 146516911Seric ** Parameters: 146656823Seric ** map -- a pointer to the database map. 146760089Seric ** name -- a buffer containing a hostname. 146853751Seric ** avp -- a pointer to a (cf file defined) argument vector. 146959084Seric ** statp -- an exit status (out parameter). 147016911Seric ** 147116911Seric ** Returns: 147253751Seric ** mapped host name 147351315Seric ** FALSE otherwise. 147416911Seric ** 147516911Seric ** Side Effects: 147660089Seric ** Looks up the host specified in name. If it is not 147716911Seric ** the canonical name for that host, replace it with 147816911Seric ** the canonical name. If the name is unknown, or it 147916911Seric ** is already the canonical name, leave it unchanged. 148016911Seric */ 148110758Seric 148216911Seric /*ARGSUSED*/ 148353751Seric char * 148460089Seric host_map_lookup(map, name, avp, statp) 148556823Seric MAP *map; 148660089Seric char *name; 148753751Seric char **avp; 148859084Seric char *statp; 148916911Seric { 149059084Seric register struct hostent *hp; 149159084Seric 149260089Seric hp = gethostbyname(name); 149359084Seric if (hp != NULL) 149459084Seric return hp->h_name; 149559084Seric *statp = EX_NOHOST; 149653751Seric return NULL; 149716911Seric } 149816911Seric 149956795Seric #endif /* DAEMON */ 1500