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*66854Seric static char sccsid[] = "@(#)daemon.c 8.46 (Berkeley) 04/17/94 (with daemon mode)"; 1533780Sbostic #else 16*66854Seric static char sccsid[] = "@(#)daemon.c 8.46 (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 */ 124*66854Seric socksize = opendaemonsocket(TRUE); 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 */ 182*66854Seric (void) opendaemonsocket(FALSE); 18353751Seric setproctitle("accepting connections"); 18453751Seric refusingconnections = FALSE; 18553751Seric } 18653751Seric 18766793Seric #ifdef XDEBUG 18866793Seric /* check for disaster */ 18966793Seric { 19066793Seric register STAB *s; 19166812Seric char jbuf[MAXHOSTNAMELEN]; 19266793Seric 19366812Seric expand("\201j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv); 19466812Seric if ((s = stab(jbuf, ST_CLASS, ST_FIND)) == NULL || 19566793Seric !bitnset('w', s->s_class)) 19666793Seric { 19766793Seric dumpstate("daemon lost $j"); 19866793Seric syslog(LOG_ALERT, "daemon process doesn't have $j in $=w; see syslog"); 19966793Seric abort(); 20066793Seric } 20166812Seric else if (j_has_dot && strchr(jbuf, '.') == NULL) 20266793Seric { 20366793Seric dumpstate("daemon $j lost dot"); 20466793Seric syslog(LOG_ALERT, "daemon process $j lost dot; see syslog"); 20566793Seric abort(); 20666793Seric } 20766793Seric } 20866793Seric #endif 20966793Seric 2109610Seric /* wait for a connection */ 2119610Seric do 2129610Seric { 2139610Seric errno = 0; 21464828Seric lotherend = socksize; 21546928Sbostic t = accept(DaemonSocket, 21646928Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 2179610Seric } while (t < 0 && errno == EINTR); 2189610Seric if (t < 0) 2195978Seric { 2209610Seric syserr("getrequests: accept"); 2219610Seric sleep(5); 2229610Seric continue; 2235978Seric } 2244631Seric 2255978Seric /* 2265978Seric ** Create a subprocess to process the mail. 2275978Seric */ 2285978Seric 2297677Seric if (tTd(15, 2)) 2309610Seric printf("getrequests: forking (fd = %d)\n", t); 2315978Seric 2324636Seric pid = fork(); 2334636Seric if (pid < 0) 2344631Seric { 2354636Seric syserr("daemon: cannot fork"); 2364636Seric sleep(10); 2379610Seric (void) close(t); 2384636Seric continue; 2394631Seric } 2404631Seric 2414636Seric if (pid == 0) 2424631Seric { 24364086Seric char *p; 24458951Seric extern char *hostnamebyanyaddr(); 24511147Seric 2464636Seric /* 2474636Seric ** CHILD -- return to caller. 24811147Seric ** Collect verified idea of sending host. 2494636Seric ** Verify calling user id if possible here. 2504636Seric */ 2514631Seric 25264035Seric (void) setsignal(SIGCHLD, SIG_DFL); 25366017Seric DisConnected = FALSE; 25424950Seric 25566032Seric setproctitle("startup with %s", 25666032Seric anynet_ntoa(&RealHostAddr)); 25766032Seric 25811147Seric /* determine host name */ 25964086Seric p = hostnamebyanyaddr(&RealHostAddr); 26064086Seric RealHostName = newstr(p); 26166032Seric setproctitle("startup with %s", p); 26258778Seric 26355173Seric #ifdef LOG 26463842Seric if (LogLevel > 11) 26555173Seric { 26655173Seric /* log connection information */ 26755173Seric syslog(LOG_INFO, "connect from %s (%s)", 26858951Seric RealHostName, anynet_ntoa(&RealHostAddr)); 26955173Seric } 27055173Seric #endif 27155173Seric 27259254Seric (void) close(DaemonSocket); 27364724Seric if ((InChannel = fdopen(t, "r")) == NULL || 27464724Seric (t = dup(t)) < 0 || 27564724Seric (OutChannel = fdopen(t, "w")) == NULL) 27664724Seric { 27764724Seric syserr("cannot open SMTP server channel, fd=%d", t); 27864724Seric exit(0); 27964724Seric } 28059254Seric 28116884Seric /* should we check for illegal connection here? XXX */ 28259156Seric #ifdef XLA 28359156Seric if (!xla_host_ok(RealHostName)) 28459156Seric { 28559254Seric message("421 Too many SMTP sessions for this host"); 28659156Seric exit(0); 28759156Seric } 28859156Seric #endif 28916884Seric 2907677Seric if (tTd(15, 2)) 2915978Seric printf("getreq: returning\n"); 2924636Seric return; 2934631Seric } 2944631Seric 2957117Seric /* close the port so that others will hang (for a while) */ 2969610Seric (void) close(t); 2974631Seric } 2989886Seric /*NOTREACHED*/ 2994631Seric } 3005978Seric /* 30166845Seric ** OPENDAEMONSOCKET -- open the SMTP socket 30266845Seric ** 30366845Seric ** Deals with setting all appropriate options. DaemonAddr must 30466845Seric ** be set up in advance. 30566845Seric ** 30666845Seric ** Parameters: 307*66854Seric ** firsttime -- set if this is the initial open. 30866845Seric ** 30966845Seric ** Returns: 31066845Seric ** Size in bytes of the daemon socket addr. 31166845Seric ** 31266845Seric ** Side Effects: 31366845Seric ** Leaves DaemonSocket set to the open socket. 31466845Seric ** Exits if the socket cannot be created. 31566845Seric */ 31666845Seric 31766845Seric int 318*66854Seric opendaemonsocket(firsttime) 319*66854Seric bool firsttime; 32066845Seric { 32166845Seric int on = 1; 32266845Seric int socksize; 32366845Seric 32466845Seric if (tTd(15, 2)) 32566845Seric printf("opendaemonsocket()\n"); 32666845Seric 327*66854Seric if (firsttime || DaemonSocket < 0) 32866845Seric { 329*66854Seric DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0); 330*66854Seric if (DaemonSocket < 0) 331*66854Seric { 332*66854Seric /* probably another daemon already */ 333*66854Seric syserr("opendaemonsocket: can't create server SMTP socket"); 334*66854Seric severe: 33566845Seric # ifdef LOG 336*66854Seric if (LogLevel > 0) 337*66854Seric syslog(LOG_ALERT, "problem creating SMTP socket"); 33866845Seric # endif /* LOG */ 339*66854Seric finis(); 340*66854Seric } 34166845Seric 342*66854Seric /* turn on network debugging? */ 343*66854Seric if (tTd(15, 101)) 344*66854Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 34566845Seric 346*66854Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 347*66854Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 34866845Seric 34966845Seric #ifdef SO_RCVBUF 350*66854Seric if (TcpRcvBufferSize > 0) 351*66854Seric { 352*66854Seric if (setsockopt(DaemonSocket, SOL_SOCKET, SO_RCVBUF, 353*66854Seric (char *) &TcpRcvBufferSize, 354*66854Seric sizeof(TcpRcvBufferSize)) < 0) 355*66854Seric syserr("getrequests: setsockopt(SO_RCVBUF)"); 356*66854Seric } 35766845Seric #endif 35866845Seric 359*66854Seric switch (DaemonAddr.sa.sa_family) 360*66854Seric { 36166845Seric # ifdef NETINET 362*66854Seric case AF_INET: 363*66854Seric socksize = sizeof DaemonAddr.sin; 364*66854Seric break; 36566845Seric # endif 36666845Seric 36766845Seric # ifdef NETISO 368*66854Seric case AF_ISO: 369*66854Seric socksize = sizeof DaemonAddr.siso; 370*66854Seric break; 37166845Seric # endif 37266845Seric 373*66854Seric default: 374*66854Seric socksize = sizeof DaemonAddr; 375*66854Seric break; 376*66854Seric } 37766845Seric 378*66854Seric if (bind(DaemonSocket, &DaemonAddr.sa, socksize) < 0) 379*66854Seric { 380*66854Seric syserr("getrequests: cannot bind"); 381*66854Seric (void) close(DaemonSocket); 382*66854Seric goto severe; 383*66854Seric } 38466845Seric } 385*66854Seric if (!firsttime && listen(DaemonSocket, ListenQueueSize) < 0) 38666845Seric { 38766845Seric syserr("getrequests: cannot listen"); 38866845Seric (void) close(DaemonSocket); 38966845Seric goto severe; 39066845Seric } 39166845Seric return socksize; 39266845Seric } 39366845Seric /* 39410206Seric ** CLRDAEMON -- reset the daemon connection 39510206Seric ** 39610206Seric ** Parameters: 39710206Seric ** none. 39810206Seric ** 39910206Seric ** Returns: 40010206Seric ** none. 40110206Seric ** 40210206Seric ** Side Effects: 40310206Seric ** releases any resources used by the passive daemon. 40410206Seric */ 40510206Seric 40610206Seric clrdaemon() 40710206Seric { 40810206Seric if (DaemonSocket >= 0) 40910206Seric (void) close(DaemonSocket); 41010206Seric DaemonSocket = -1; 41110206Seric } 41210206Seric /* 41358849Seric ** SETDAEMONOPTIONS -- set options for running the daemon 41458849Seric ** 41558849Seric ** Parameters: 41658849Seric ** p -- the options line. 41758849Seric ** 41858849Seric ** Returns: 41958849Seric ** none. 42058849Seric */ 42158849Seric 42258849Seric setdaemonoptions(p) 42358849Seric register char *p; 42458849Seric { 42558873Seric if (DaemonAddr.sa.sa_family == AF_UNSPEC) 42658873Seric DaemonAddr.sa.sa_family = AF_INET; 42758873Seric 42858849Seric while (p != NULL) 42958849Seric { 43058849Seric register char *f; 43158849Seric register char *v; 43258849Seric 43358849Seric while (isascii(*p) && isspace(*p)) 43458849Seric p++; 43558849Seric if (*p == '\0') 43658849Seric break; 43758849Seric f = p; 43858849Seric p = strchr(p, ','); 43958849Seric if (p != NULL) 44058849Seric *p++ = '\0'; 44158849Seric v = strchr(f, '='); 44258849Seric if (v == NULL) 44358849Seric continue; 44458849Seric while (isascii(*++v) && isspace(*v)) 44558849Seric continue; 44658849Seric 44758849Seric switch (*f) 44858849Seric { 44958873Seric case 'F': /* address family */ 45058849Seric if (isascii(*v) && isdigit(*v)) 45158873Seric DaemonAddr.sa.sa_family = atoi(v); 45258873Seric #ifdef NETINET 45358873Seric else if (strcasecmp(v, "inet") == 0) 45458873Seric DaemonAddr.sa.sa_family = AF_INET; 45558873Seric #endif 45658873Seric #ifdef NETISO 45758873Seric else if (strcasecmp(v, "iso") == 0) 45858873Seric DaemonAddr.sa.sa_family = AF_ISO; 45958873Seric #endif 46058873Seric #ifdef NETNS 46158873Seric else if (strcasecmp(v, "ns") == 0) 46258873Seric DaemonAddr.sa.sa_family = AF_NS; 46358873Seric #endif 46458873Seric #ifdef NETX25 46558873Seric else if (strcasecmp(v, "x.25") == 0) 46658873Seric DaemonAddr.sa.sa_family = AF_CCITT; 46758873Seric #endif 46858849Seric else 46958873Seric syserr("554 Unknown address family %s in Family=option", v); 47058873Seric break; 47158873Seric 47258873Seric case 'A': /* address */ 47358873Seric switch (DaemonAddr.sa.sa_family) 47458849Seric { 47558873Seric #ifdef NETINET 47658873Seric case AF_INET: 47758873Seric if (isascii(*v) && isdigit(*v)) 47858873Seric DaemonAddr.sin.sin_addr.s_addr = inet_network(v); 47958873Seric else 48058873Seric { 48158873Seric register struct netent *np; 48258849Seric 48358873Seric np = getnetbyname(v); 48458873Seric if (np == NULL) 48558873Seric syserr("554 network \"%s\" unknown", v); 48658873Seric else 48758873Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 48858873Seric } 48958873Seric break; 49058873Seric #endif 49158873Seric 49258873Seric default: 49358873Seric syserr("554 Address= option unsupported for family %d", 49458873Seric DaemonAddr.sa.sa_family); 49558873Seric break; 49658849Seric } 49758849Seric break; 49858849Seric 49958873Seric case 'P': /* port */ 50058873Seric switch (DaemonAddr.sa.sa_family) 50158849Seric { 50258873Seric short port; 50358849Seric 50458873Seric #ifdef NETINET 50558873Seric case AF_INET: 50658873Seric if (isascii(*v) && isdigit(*v)) 50764366Seric DaemonAddr.sin.sin_port = htons(atoi(v)); 50858849Seric else 50958873Seric { 51058873Seric register struct servent *sp; 51158873Seric 51258873Seric sp = getservbyname(v, "tcp"); 51358873Seric if (sp == NULL) 51458909Seric syserr("554 service \"%s\" unknown", v); 51558873Seric else 51658873Seric DaemonAddr.sin.sin_port = sp->s_port; 51758873Seric } 51858873Seric break; 51958873Seric #endif 52058873Seric 52158873Seric #ifdef NETISO 52258873Seric case AF_ISO: 52358873Seric /* assume two byte transport selector */ 52458873Seric if (isascii(*v) && isdigit(*v)) 52564366Seric port = htons(atoi(v)); 52658873Seric else 52758873Seric { 52858873Seric register struct servent *sp; 52958873Seric 53058873Seric sp = getservbyname(v, "tcp"); 53158873Seric if (sp == NULL) 53258909Seric syserr("554 service \"%s\" unknown", v); 53358873Seric else 53458873Seric port = sp->s_port; 53558873Seric } 53658873Seric bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 53758873Seric break; 53858873Seric #endif 53958873Seric 54058873Seric default: 54158873Seric syserr("554 Port= option unsupported for family %d", 54258873Seric DaemonAddr.sa.sa_family); 54358873Seric break; 54458849Seric } 54558849Seric break; 54659783Seric 54759783Seric case 'L': /* listen queue size */ 54859783Seric ListenQueueSize = atoi(v); 54959783Seric break; 55064381Seric 55164381Seric case 'S': /* send buffer size */ 55264381Seric TcpSndBufferSize = atoi(v); 55364381Seric break; 55464381Seric 55564381Seric case 'R': /* receive buffer size */ 55664381Seric TcpRcvBufferSize = atoi(v); 55764381Seric break; 55858849Seric } 55958849Seric } 56058849Seric } 56158849Seric /* 5626039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 5636039Seric ** 5646039Seric ** Parameters: 5656039Seric ** host -- the name of the host. 5666633Seric ** port -- the port number to connect to. 56753739Seric ** mci -- a pointer to the mail connection information 56853739Seric ** structure to be filled in. 56952106Seric ** usesecureport -- if set, use a low numbered (reserved) 57052106Seric ** port to provide some rudimentary authentication. 5716039Seric ** 5726039Seric ** Returns: 5736039Seric ** An exit code telling whether the connection could be 5746039Seric ** made and if not why not. 5756039Seric ** 5766039Seric ** Side Effects: 5776039Seric ** none. 5786039Seric */ 5795978Seric 58058755Seric SOCKADDR CurHostAddr; /* address of current host */ 58158305Seric 58254967Seric int 58353739Seric makeconnection(host, port, mci, usesecureport) 5846039Seric char *host; 5857286Seric u_short port; 58654967Seric register MCI *mci; 58752106Seric bool usesecureport; 5886039Seric { 58929430Sbloom register int i, s; 59029430Sbloom register struct hostent *hp = (struct hostent *)NULL; 59158755Seric SOCKADDR addr; 59252106Seric int sav_errno; 59358755Seric int addrlen; 59466334Seric #if NAMED_BIND 59535651Seric extern int h_errno; 59635651Seric #endif 5976039Seric 5986039Seric /* 5996039Seric ** Set up the address for the mailer. 6009308Seric ** Accept "[a.b.c.d]" syntax for host name. 6016039Seric */ 6026039Seric 60366334Seric #if NAMED_BIND 60425475Smiriam h_errno = 0; 60535651Seric #endif 60625475Smiriam errno = 0; 60758864Seric bzero(&CurHostAddr, sizeof CurHostAddr); 60864334Seric SmtpPhase = mci->mci_phase = "initial connection"; 60958906Seric CurHostName = host; 61025475Smiriam 6119308Seric if (host[0] == '[') 6129308Seric { 61311147Seric long hid; 61456795Seric register char *p = strchr(host, ']'); 6159308Seric 61611147Seric if (p != NULL) 6179308Seric { 61811147Seric *p = '\0'; 61959884Seric #ifdef NETINET 62011147Seric hid = inet_addr(&host[1]); 62158360Seric if (hid == -1) 62259884Seric #endif 62358360Seric { 62458360Seric /* try it as a host name (avoid MX lookup) */ 62558360Seric hp = gethostbyname(&host[1]); 62666349Seric if (hp == NULL && p[-1] == '.') 62766349Seric { 62866349Seric p[-1] = '\0'; 62966349Seric hp = gethostbyname(&host[1]); 63066349Seric p[-1] = '.'; 63166349Seric } 63258360Seric *p = ']'; 63358360Seric goto gothostent; 63458360Seric } 63511147Seric *p = ']'; 6369308Seric } 63758360Seric if (p == NULL) 6389308Seric { 63958151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 6409308Seric return (EX_NOHOST); 6419308Seric } 64259884Seric #ifdef NETINET 64359884Seric addr.sin.sin_family = AF_INET; /*XXX*/ 64458778Seric addr.sin.sin_addr.s_addr = hid; 64559884Seric #endif 6469308Seric } 6479610Seric else 6489610Seric { 64966349Seric register char *p = &host[strlen(host) - 1]; 65066349Seric 65129430Sbloom hp = gethostbyname(host); 65266349Seric if (hp == NULL && *p == '.') 65366349Seric { 65466349Seric *p = '\0'; 65566349Seric hp = gethostbyname(host); 65666349Seric *p = '.'; 65766349Seric } 65858360Seric gothostent: 65925475Smiriam if (hp == NULL) 66024945Seric { 66166334Seric #if NAMED_BIND 66225475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 66325475Smiriam return (EX_TEMPFAIL); 66425657Seric 66535651Seric /* if name server is specified, assume temp fail */ 66635651Seric if (errno == ECONNREFUSED && UseNameServer) 66735651Seric return (EX_TEMPFAIL); 66835651Seric #endif 66925475Smiriam return (EX_NOHOST); 67024945Seric } 67158778Seric addr.sa.sa_family = hp->h_addrtype; 67258778Seric switch (hp->h_addrtype) 67358778Seric { 67458778Seric #ifdef NETINET 67558778Seric case AF_INET: 67658755Seric bcopy(hp->h_addr, 67758778Seric &addr.sin.sin_addr, 67864943Seric sizeof addr.sin.sin_addr); 67958778Seric break; 68058778Seric #endif 68158778Seric 68258778Seric default: 68358755Seric bcopy(hp->h_addr, 68458778Seric addr.sa.sa_data, 68558755Seric hp->h_length); 68658778Seric break; 68758778Seric } 68829430Sbloom i = 1; 6899610Seric } 6909610Seric 6919610Seric /* 6929610Seric ** Determine the port number. 6939610Seric */ 6949610Seric 69510011Seric if (port != 0) 69658755Seric port = htons(port); 69710011Seric else 6989610Seric { 6999610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 7009610Seric 7019610Seric if (sp == NULL) 7029610Seric { 70358909Seric syserr("554 makeconnection: service \"smtp\" unknown"); 70465169Seric port = htons(25); 7059610Seric } 70665169Seric else 70765169Seric port = sp->s_port; 7089610Seric } 7096039Seric 71058778Seric switch (addr.sa.sa_family) 71158755Seric { 71259884Seric #ifdef NETINET 71358755Seric case AF_INET: 71458778Seric addr.sin.sin_port = port; 71558755Seric addrlen = sizeof (struct sockaddr_in); 71658755Seric break; 71759884Seric #endif 71858755Seric 71958755Seric #ifdef NETISO 72058755Seric case AF_ISO: 72158755Seric /* assume two byte transport selector */ 72258755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 72358755Seric addrlen = sizeof (struct sockaddr_iso); 72458755Seric break; 72558755Seric #endif 72658755Seric 72758755Seric default: 72858778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 72958755Seric return (EX_NOHOST); 73058755Seric } 73158755Seric 7326039Seric /* 7336039Seric ** Try to actually open the connection. 7346039Seric */ 7356039Seric 73659156Seric #ifdef XLA 73759156Seric /* if too many connections, don't bother trying */ 73859156Seric if (!xla_noqueue_ok(host)) 73959156Seric return EX_TEMPFAIL; 74059156Seric #endif 74159156Seric 74257736Seric for (;;) 74352106Seric { 74457736Seric if (tTd(16, 1)) 74558755Seric printf("makeconnection (%s [%s])\n", 74658755Seric host, anynet_ntoa(&addr)); 74752106Seric 74858588Seric /* save for logging */ 74958588Seric CurHostAddr = addr; 75058588Seric 75157736Seric if (usesecureport) 75257736Seric { 75357736Seric int rport = IPPORT_RESERVED - 1; 7546039Seric 75557736Seric s = rresvport(&rport); 75657736Seric } 75757736Seric else 75857736Seric { 75957736Seric s = socket(AF_INET, SOCK_STREAM, 0); 76057736Seric } 76157736Seric if (s < 0) 76257736Seric { 76357736Seric sav_errno = errno; 76457736Seric syserr("makeconnection: no socket"); 76557736Seric goto failure; 76657736Seric } 76710347Seric 76864381Seric #ifdef SO_SNDBUF 76964381Seric if (TcpSndBufferSize > 0) 77064381Seric { 77164381Seric if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 77264561Seric (char *) &TcpSndBufferSize, 77364381Seric sizeof(TcpSndBufferSize)) < 0) 77464381Seric syserr("makeconnection: setsockopt(SO_SNDBUF)"); 77564381Seric } 77664381Seric #endif 77764381Seric 77857736Seric if (tTd(16, 1)) 77957736Seric printf("makeconnection: fd=%d\n", s); 78057736Seric 78157736Seric /* turn on network debugging? */ 78257736Seric if (tTd(16, 101)) 78357736Seric { 78457736Seric int on = 1; 78557736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 78657736Seric (char *)&on, sizeof on); 78757736Seric } 78857736Seric if (CurEnv->e_xfp != NULL) 78957736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 79057736Seric errno = 0; /* for debugging */ 79158755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 79257736Seric break; 79357736Seric 79457736Seric /* couldn't connect.... figure out why */ 79527744Sbloom sav_errno = errno; 79627744Sbloom (void) close(s); 79729430Sbloom if (hp && hp->h_addr_list[i]) 79829430Sbloom { 79957736Seric if (tTd(16, 1)) 80058755Seric printf("Connect failed (%s); trying new address....\n", 80158755Seric errstring(sav_errno)); 80258778Seric switch (addr.sa.sa_family) 80358778Seric { 80458778Seric #ifdef NETINET 80558778Seric case AF_INET: 80658755Seric bcopy(hp->h_addr_list[i++], 80758778Seric &addr.sin.sin_addr, 80864943Seric sizeof addr.sin.sin_addr); 80958778Seric break; 81058778Seric #endif 81158778Seric 81258778Seric default: 81358755Seric bcopy(hp->h_addr_list[i++], 81458778Seric addr.sa.sa_data, 81552106Seric hp->h_length); 81658778Seric break; 81758778Seric } 81857736Seric continue; 81929430Sbloom } 82029430Sbloom 8216039Seric /* failure, decide if temporary or not */ 8226039Seric failure: 82359254Seric #ifdef XLA 82459254Seric xla_host_end(host); 82559254Seric #endif 82658542Seric if (transienterror(sav_errno)) 82758542Seric return EX_TEMPFAIL; 82858542Seric else 82958542Seric { 83058542Seric message("%s", errstring(sav_errno)); 83158542Seric return (EX_UNAVAILABLE); 8326039Seric } 8336039Seric } 8346039Seric 8356039Seric /* connection ok, put it into canonical form */ 83664724Seric if ((mci->mci_out = fdopen(s, "w")) == NULL || 83764724Seric (s = dup(s)) < 0 || 83864725Seric (mci->mci_in = fdopen(s, "r")) == NULL) 83964724Seric { 84064724Seric syserr("cannot open SMTP client channel, fd=%d", s); 84164724Seric return EX_TEMPFAIL; 84264724Seric } 8436039Seric 84410098Seric return (EX_OK); 8456039Seric } 84610758Seric /* 84710758Seric ** MYHOSTNAME -- return the name of this host. 84810758Seric ** 84910758Seric ** Parameters: 85010758Seric ** hostbuf -- a place to return the name of this host. 85112313Seric ** size -- the size of hostbuf. 85210758Seric ** 85310758Seric ** Returns: 85410758Seric ** A list of aliases for this host. 85510758Seric ** 85610758Seric ** Side Effects: 85764338Seric ** Adds numeric codes to $=w. 85810758Seric */ 8596039Seric 86010758Seric char ** 86112313Seric myhostname(hostbuf, size) 86210758Seric char hostbuf[]; 86312313Seric int size; 86410758Seric { 86558110Seric register struct hostent *hp; 86610758Seric extern struct hostent *gethostbyname(); 86710758Seric 86823120Seric if (gethostname(hostbuf, size) < 0) 86923120Seric { 87023120Seric (void) strcpy(hostbuf, "localhost"); 87123120Seric } 87211147Seric hp = gethostbyname(hostbuf); 87366853Seric if (hp == NULL) 87416877Seric { 87566853Seric syserr("!My host name (%s) does not seem to exist!", hostbuf); 87666853Seric } 87766853Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 87866853Seric hostbuf[size - 1] = '\0'; 87966853Seric 88066853Seric #if NAMED_BIND 88166853Seric /* if still no dot, try DNS directly (i.e., avoid NIS problems) */ 88266853Seric if (strchr(hostbuf, '.') == NULL) 88366853Seric { 88466853Seric extern bool getcanonname(); 88566853Seric extern int h_errno; 88666853Seric 88766853Seric /* try twice in case name server not yet started up */ 88866853Seric if (!getcanonname(hostbuf, size, TRUE) && 88966853Seric UseNameServer && 89066853Seric (h_errno != TRY_AGAIN || 89166853Seric (sleep(30), !getcanonname(hostbuf, size, TRUE)))) 89266777Seric { 89366853Seric errno = h_errno + E_DNSBASE; 89466853Seric syserr("!My host name (%s) not known to DNS", 89566853Seric hostbuf); 89666777Seric } 89766853Seric } 89866777Seric #endif 89966777Seric 90066853Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 90166853Seric { 90266853Seric register int i; 90366853Seric 90466853Seric for (i = 0; hp->h_addr_list[i] != NULL; i++) 90558110Seric { 90666853Seric char ipbuf[100]; 90758110Seric 90866853Seric sprintf(ipbuf, "[%s]", 90966853Seric inet_ntoa(*((struct in_addr *) hp->h_addr_list[i]))); 91066853Seric setclass('w', ipbuf); 91158110Seric } 91266853Seric } 91358110Seric 91466853Seric return (hp->h_aliases); 91510758Seric } 91651315Seric /* 91758951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 91858308Seric ** 91958951Seric ** Uses RFC1413 protocol to try to get info from the other end. 92058951Seric ** 92158308Seric ** Parameters: 92258308Seric ** fd -- the descriptor 92358308Seric ** 92458308Seric ** Returns: 92558951Seric ** The user@host information associated with this descriptor. 92658308Seric */ 92758308Seric 92864927Seric #if IDENTPROTO 92958951Seric 93058951Seric static jmp_buf CtxAuthTimeout; 93158951Seric 93258951Seric static 93358951Seric authtimeout() 93458951Seric { 93558951Seric longjmp(CtxAuthTimeout, 1); 93658951Seric } 93758951Seric 93858951Seric #endif 93958951Seric 94058308Seric char * 94158951Seric getauthinfo(fd) 94258308Seric int fd; 94358308Seric { 94458951Seric int falen; 94559104Seric register char *p; 94664927Seric #if IDENTPROTO 94758951Seric SOCKADDR la; 94858951Seric int lalen; 94958951Seric register struct servent *sp; 95058951Seric int s; 95158951Seric int i; 95258951Seric EVENT *ev; 95358951Seric #endif 95458951Seric static char hbuf[MAXNAME * 2 + 2]; 95558951Seric extern char *hostnamebyanyaddr(); 95658951Seric extern char RealUserName[]; /* main.c */ 95758308Seric 95866761Seric falen = sizeof RealHostAddr; 95966761Seric if (getpeername(fd, &RealHostAddr.sa, &falen) < 0 || falen <= 0 || 96066761Seric RealHostAddr.sa.sa_family == 0) 96158951Seric { 96258951Seric (void) sprintf(hbuf, "%s@localhost", RealUserName); 96358957Seric if (tTd(9, 1)) 96458951Seric printf("getauthinfo: %s\n", hbuf); 96558951Seric return hbuf; 96658951Seric } 96758951Seric 96866761Seric if (RealHostName == NULL) 96966761Seric { 97066761Seric /* translate that to a host name */ 97166761Seric RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 97266761Seric } 97366761Seric 97464927Seric #if IDENTPROTO 97565831Seric if (TimeOuts.to_ident == 0) 97665831Seric goto noident; 97765831Seric 97858951Seric lalen = sizeof la; 97966761Seric if (RealHostAddr.sa.sa_family != AF_INET || 98058951Seric getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || 98158951Seric la.sa.sa_family != AF_INET) 98258951Seric { 98358951Seric /* no ident info */ 98458951Seric goto noident; 98558951Seric } 98658951Seric 98758951Seric /* create ident query */ 98860489Seric (void) sprintf(hbuf, "%d,%d\r\n", 98966761Seric ntohs(RealHostAddr.sin.sin_port), ntohs(la.sin.sin_port)); 99058951Seric 99158951Seric /* create local address */ 99264747Seric la.sin.sin_port = 0; 99358951Seric 99458951Seric /* create foreign address */ 99558951Seric sp = getservbyname("auth", "tcp"); 99658951Seric if (sp != NULL) 99766761Seric RealHostAddr.sin.sin_port = sp->s_port; 99858308Seric else 99966761Seric RealHostAddr.sin.sin_port = htons(113); 100058951Seric 100158951Seric s = -1; 100258951Seric if (setjmp(CtxAuthTimeout) != 0) 100358951Seric { 100458951Seric if (s >= 0) 100558951Seric (void) close(s); 100658951Seric goto noident; 100758951Seric } 100858951Seric 100958951Seric /* put a timeout around the whole thing */ 101064255Seric ev = setevent(TimeOuts.to_ident, authtimeout, 0); 101158951Seric 101264747Seric /* connect to foreign IDENT server using same address as SMTP socket */ 101358951Seric s = socket(AF_INET, SOCK_STREAM, 0); 101458951Seric if (s < 0) 101558951Seric { 101658951Seric clrevent(ev); 101758951Seric goto noident; 101858951Seric } 101964747Seric if (bind(s, &la.sa, sizeof la.sin) < 0 || 102066761Seric connect(s, &RealHostAddr.sa, sizeof RealHostAddr.sin) < 0) 102158951Seric { 102266011Seric goto closeident; 102358951Seric } 102458951Seric 102558957Seric if (tTd(9, 10)) 102658951Seric printf("getauthinfo: sent %s", hbuf); 102758951Seric 102858951Seric /* send query */ 102958951Seric if (write(s, hbuf, strlen(hbuf)) < 0) 103058951Seric goto closeident; 103158951Seric 103258951Seric /* get result */ 103358951Seric i = read(s, hbuf, sizeof hbuf); 103458951Seric (void) close(s); 103558951Seric clrevent(ev); 103658951Seric if (i <= 0) 103758951Seric goto noident; 103858951Seric if (hbuf[--i] == '\n' && hbuf[--i] == '\r') 103958951Seric i--; 104058951Seric hbuf[++i] = '\0'; 104158951Seric 104258957Seric if (tTd(9, 3)) 104358951Seric printf("getauthinfo: got %s\n", hbuf); 104458951Seric 104558951Seric /* parse result */ 104658951Seric p = strchr(hbuf, ':'); 104758951Seric if (p == NULL) 104858951Seric { 104958951Seric /* malformed response */ 105058951Seric goto noident; 105158951Seric } 105258951Seric while (isascii(*++p) && isspace(*p)) 105358951Seric continue; 105458951Seric if (strncasecmp(p, "userid", 6) != 0) 105558951Seric { 105658951Seric /* presumably an error string */ 105758951Seric goto noident; 105858951Seric } 105958951Seric p += 6; 106058951Seric while (isascii(*p) && isspace(*p)) 106158951Seric p++; 106258951Seric if (*p++ != ':') 106358951Seric { 106458951Seric /* either useridxx or malformed response */ 106558951Seric goto noident; 106658951Seric } 106758951Seric 106858951Seric /* p now points to the OSTYPE field */ 106958951Seric p = strchr(p, ':'); 107058951Seric if (p == NULL) 107158951Seric { 107258951Seric /* malformed response */ 107358951Seric goto noident; 107458951Seric } 107558951Seric 107658957Seric /* 1413 says don't do this -- but it's broken otherwise */ 107758957Seric while (isascii(*++p) && isspace(*p)) 107858957Seric continue; 107958957Seric 108058951Seric /* p now points to the authenticated name */ 108166003Seric (void) sprintf(hbuf, "%s@%s", 108266003Seric p, RealHostName == NULL ? "localhost" : RealHostName); 108358957Seric goto finish; 108458957Seric 108566011Seric closeident: 108666011Seric (void) close(s); 108766011Seric clrevent(ev); 108866011Seric 108958957Seric #endif /* IDENTPROTO */ 109058957Seric 109158957Seric noident: 109266003Seric if (RealHostName == NULL) 109366003Seric { 109466003Seric if (tTd(9, 1)) 109566003Seric printf("getauthinfo: NULL\n"); 109666003Seric return NULL; 109766003Seric } 109858957Seric (void) strcpy(hbuf, RealHostName); 109958957Seric 110058957Seric finish: 110166003Seric if (RealHostName != NULL && RealHostName[0] != '[') 110258951Seric { 110358951Seric p = &hbuf[strlen(hbuf)]; 110458951Seric (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); 110558951Seric } 110658957Seric if (tTd(9, 1)) 110758951Seric printf("getauthinfo: %s\n", hbuf); 110858308Seric return hbuf; 110958308Seric } 111058308Seric /* 111160089Seric ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 111253751Seric ** 111353751Seric ** Parameters: 111456823Seric ** map -- a pointer to this map (unused). 111560089Seric ** name -- the (presumably unqualified) hostname. 111660257Seric ** av -- unused -- for compatibility with other mapping 111755019Seric ** functions. 111859084Seric ** statp -- an exit status (out parameter) -- set to 111959084Seric ** EX_TEMPFAIL if the name server is unavailable. 112053751Seric ** 112153751Seric ** Returns: 112253751Seric ** The mapping, if found. 112353751Seric ** NULL if no mapping found. 112453751Seric ** 112553751Seric ** Side Effects: 112653751Seric ** Looks up the host specified in hbuf. If it is not 112753751Seric ** the canonical name for that host, return the canonical 112853751Seric ** name. 112953751Seric */ 113051315Seric 113153751Seric char * 113260257Seric host_map_lookup(map, name, av, statp) 113356823Seric MAP *map; 113460089Seric char *name; 113560257Seric char **av; 113659084Seric int *statp; 113716911Seric { 113816911Seric register struct hostent *hp; 113933932Sbostic u_long in_addr; 114056823Seric char *cp; 114158110Seric int i; 114259671Seric register STAB *s; 114360257Seric char hbuf[MAXNAME]; 114459671Seric extern struct hostent *gethostbyaddr(); 114566334Seric #if NAMED_BIND 114659671Seric extern int h_errno; 114766029Seric #endif 114816911Seric 114925574Smiriam /* 115059671Seric ** See if we have already looked up this name. If so, just 115159671Seric ** return it. 115259671Seric */ 115353751Seric 115460089Seric s = stab(name, ST_NAMECANON, ST_ENTER); 115559671Seric if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 115659671Seric { 115759986Seric if (tTd(9, 1)) 115860089Seric printf("host_map_lookup(%s) => CACHE %s\n", 115960089Seric name, s->s_namecanon.nc_cname); 116059671Seric errno = s->s_namecanon.nc_errno; 116166334Seric #if NAMED_BIND 116259671Seric h_errno = s->s_namecanon.nc_herrno; 116366029Seric #endif 116459671Seric *statp = s->s_namecanon.nc_stat; 116564797Seric if (CurEnv->e_message == NULL && *statp == EX_TEMPFAIL) 116665199Seric { 116765199Seric sprintf(hbuf, "%s: Name server timeout", 116865199Seric shortenstring(name, 33)); 116965199Seric CurEnv->e_message = newstr(hbuf); 117065199Seric } 117159671Seric return s->s_namecanon.nc_cname; 117259671Seric } 117359671Seric 117459671Seric /* 117559671Seric ** If first character is a bracket, then it is an address 117659671Seric ** lookup. Address is copied into a temporary buffer to 117760089Seric ** strip the brackets and to preserve name if address is 117859671Seric ** unknown. 117959671Seric */ 118059671Seric 118160089Seric if (*name != '[') 118253751Seric { 118355019Seric extern bool getcanonname(); 118455019Seric 118558798Seric if (tTd(9, 1)) 118660089Seric printf("host_map_lookup(%s) => ", name); 118759671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 118860089Seric (void) strcpy(hbuf, name); 118963842Seric if (getcanonname(hbuf, sizeof hbuf - 1, TRUE)) 119058796Seric { 119158796Seric if (tTd(9, 1)) 119258796Seric printf("%s\n", hbuf); 119360257Seric cp = map_rewrite(map, hbuf, strlen(hbuf), av); 119460257Seric s->s_namecanon.nc_cname = newstr(cp); 119560257Seric return cp; 119658796Seric } 119753751Seric else 119858796Seric { 119959084Seric register struct hostent *hp; 120059084Seric 120166029Seric s->s_namecanon.nc_errno = errno; 120266334Seric #if NAMED_BIND 120366029Seric s->s_namecanon.nc_herrno = h_errno; 120458796Seric if (tTd(9, 1)) 120559084Seric printf("FAIL (%d)\n", h_errno); 120659084Seric switch (h_errno) 120759084Seric { 120859084Seric case TRY_AGAIN: 120959596Seric if (UseNameServer) 121059734Seric { 121165202Seric sprintf(hbuf, "%s: Name server timeout", 121265199Seric shortenstring(name, 33)); 121365202Seric message("%s", hbuf); 121459734Seric if (CurEnv->e_message == NULL) 121565202Seric CurEnv->e_message = newstr(hbuf); 121659734Seric } 121759084Seric *statp = EX_TEMPFAIL; 121859084Seric break; 121959084Seric 122059084Seric case HOST_NOT_FOUND: 122159084Seric *statp = EX_NOHOST; 122259084Seric break; 122359084Seric 122459084Seric case NO_RECOVERY: 122559084Seric *statp = EX_SOFTWARE; 122659084Seric break; 122759084Seric 122859084Seric default: 122959084Seric *statp = EX_UNAVAILABLE; 123059084Seric break; 123159084Seric } 123266029Seric #else 123366029Seric if (tTd(9, 1)) 123466029Seric printf("FAIL\n"); 123566029Seric *statp = EX_NOHOST; 123666029Seric #endif 123759671Seric s->s_namecanon.nc_stat = *statp; 123859084Seric if (*statp != EX_TEMPFAIL || UseNameServer) 123959084Seric return NULL; 124059084Seric 124159084Seric /* 124259084Seric ** Try to look it up in /etc/hosts 124359084Seric */ 124459084Seric 124560089Seric hp = gethostbyname(name); 124659084Seric if (hp == NULL) 124759084Seric { 124859084Seric /* no dice there either */ 124959671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 125059084Seric return NULL; 125159084Seric } 125259084Seric 125359671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 125460257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 125560257Seric s->s_namecanon.nc_cname = newstr(cp); 125660257Seric return cp; 125758796Seric } 125853751Seric } 125960089Seric if ((cp = strchr(name, ']')) == NULL) 126053751Seric return (NULL); 126140994Sbostic *cp = '\0'; 126260089Seric in_addr = inet_addr(&name[1]); 126358110Seric 126458110Seric /* nope -- ask the name server */ 126533932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 126659671Seric s->s_namecanon.nc_errno = errno; 126766334Seric #if NAMED_BIND 126859671Seric s->s_namecanon.nc_herrno = h_errno; 126966029Seric #endif 127059671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 127133932Sbostic if (hp == NULL) 127259671Seric { 127359671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 127453751Seric return (NULL); 127559671Seric } 127653751Seric 127758110Seric /* found a match -- copy out */ 127860257Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 127959671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 128060257Seric s->s_namecanon.nc_cname = newstr(cp); 128160257Seric return cp; 128233932Sbostic } 128358755Seric /* 128458755Seric ** ANYNET_NTOA -- convert a network address to printable form. 128558755Seric ** 128658755Seric ** Parameters: 128758755Seric ** sap -- a pointer to a sockaddr structure. 128858755Seric ** 128958755Seric ** Returns: 129058755Seric ** A printable version of that sockaddr. 129158755Seric */ 129216911Seric 129358755Seric char * 129458755Seric anynet_ntoa(sap) 129558755Seric register SOCKADDR *sap; 129658755Seric { 129758755Seric register char *bp; 129858755Seric register char *ap; 129958755Seric int l; 130064734Seric static char buf[100]; 130158755Seric 130258798Seric /* check for null/zero family */ 130358798Seric if (sap == NULL) 130458798Seric return "NULLADDR"; 130558798Seric if (sap->sa.sa_family == 0) 130658798Seric return "0"; 130758798Seric 130864734Seric switch (sap->sa.sa_family) 130964734Seric { 131064734Seric #ifdef MAYBENEXTRELEASE /*** UNTESTED *** UNTESTED *** UNTESTED ***/ 131164821Seric #ifdef NETUNIX 131264734Seric case AF_UNIX: 131364758Seric if (sap->sunix.sun_path[0] != '\0') 131464758Seric sprintf(buf, "[UNIX: %.64s]", sap->sunix.sun_path); 131564734Seric else 131664734Seric sprintf(buf, "[UNIX: localhost]"); 131764734Seric return buf; 131864734Seric #endif 131964821Seric #endif 132064734Seric 132158778Seric #ifdef NETINET 132264734Seric case AF_INET: 132358755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 132458778Seric #endif 132558755Seric 132664734Seric default: 132764734Seric /* this case is only to ensure syntactic correctness */ 132864734Seric break; 132964734Seric } 133064734Seric 133158755Seric /* unknown family -- just dump bytes */ 133258778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 133358755Seric bp = &buf[strlen(buf)]; 133458778Seric ap = sap->sa.sa_data; 133558778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 133658755Seric { 133758755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 133858755Seric bp += 3; 133958755Seric } 134058755Seric *--bp = '\0'; 134158755Seric return buf; 134258755Seric } 134358951Seric /* 134458951Seric ** HOSTNAMEBYANYADDR -- return name of host based on address 134558951Seric ** 134658951Seric ** Parameters: 134758951Seric ** sap -- SOCKADDR pointer 134858951Seric ** 134958951Seric ** Returns: 135058951Seric ** text representation of host name. 135158951Seric ** 135258951Seric ** Side Effects: 135358951Seric ** none. 135458951Seric */ 135558755Seric 135658951Seric char * 135758951Seric hostnamebyanyaddr(sap) 135858951Seric register SOCKADDR *sap; 135958951Seric { 136058951Seric register struct hostent *hp; 136164734Seric int saveretry; 136258951Seric 136366334Seric #if NAMED_BIND 136459042Seric /* shorten name server timeout to avoid higher level timeouts */ 136559042Seric saveretry = _res.retry; 136659042Seric _res.retry = 3; 136759042Seric #endif /* NAMED_BIND */ 136859042Seric 136958951Seric switch (sap->sa.sa_family) 137058951Seric { 137158951Seric #ifdef NETINET 137258951Seric case AF_INET: 137358951Seric hp = gethostbyaddr((char *) &sap->sin.sin_addr, 137458951Seric sizeof sap->sin.sin_addr, 137558951Seric AF_INET); 137658951Seric break; 137758951Seric #endif 137858951Seric 137958951Seric #ifdef NETISO 138058951Seric case AF_ISO: 138158951Seric hp = gethostbyaddr((char *) &sap->siso.siso_addr, 138258951Seric sizeof sap->siso.siso_addr, 138358951Seric AF_ISO); 138458951Seric break; 138558951Seric #endif 138658951Seric 138764734Seric #ifdef MAYBENEXTRELEASE /*** UNTESTED *** UNTESTED *** UNTESTED ***/ 138864734Seric case AF_UNIX: 138964734Seric hp = NULL; 139064734Seric break; 139164734Seric #endif 139264734Seric 139358951Seric default: 139458951Seric hp = gethostbyaddr(sap->sa.sa_data, 139558951Seric sizeof sap->sa.sa_data, 139658951Seric sap->sa.sa_family); 139758951Seric break; 139858951Seric } 139958951Seric 140066334Seric #if NAMED_BIND 140159042Seric _res.retry = saveretry; 140259042Seric #endif /* NAMED_BIND */ 140359042Seric 140458951Seric if (hp != NULL) 140558951Seric return hp->h_name; 140658951Seric else 140758951Seric { 140858951Seric /* produce a dotted quad */ 140958951Seric static char buf[512]; 141058951Seric 141158951Seric (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); 141258951Seric return buf; 141358951Seric } 141458951Seric } 141558951Seric 141656795Seric # else /* DAEMON */ 141716911Seric /* code for systems without sophisticated networking */ 141810758Seric 141910758Seric /* 142010758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 142111297Seric ** 142211297Seric ** Can't convert to upper case here because might be a UUCP name. 142312313Seric ** 142412313Seric ** Mark, you can change this to be anything you want...... 142510758Seric */ 142610758Seric 142710758Seric char ** 142812313Seric myhostname(hostbuf, size) 142910758Seric char hostbuf[]; 143012313Seric int size; 143110758Seric { 143210758Seric register FILE *f; 143310758Seric 143410758Seric hostbuf[0] = '\0'; 143510758Seric f = fopen("/usr/include/whoami", "r"); 143610758Seric if (f != NULL) 143710758Seric { 143812313Seric (void) fgets(hostbuf, size, f); 143910758Seric fixcrlf(hostbuf, TRUE); 144010758Seric (void) fclose(f); 144110758Seric } 144210758Seric return (NULL); 144310758Seric } 144416911Seric /* 144558951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 144658308Seric ** 144758308Seric ** Parameters: 144858308Seric ** fd -- the descriptor 144958308Seric ** 145058308Seric ** Returns: 145158308Seric ** The host name associated with this descriptor, if it can 145258308Seric ** be determined. 145358308Seric ** NULL otherwise. 145458308Seric ** 145558308Seric ** Side Effects: 145658308Seric ** none 145758308Seric */ 145858308Seric 145958308Seric char * 146058951Seric getauthinfo(fd) 146158308Seric int fd; 146258308Seric { 146358308Seric return NULL; 146458308Seric } 146558308Seric /* 146616911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 146716911Seric ** 146816911Seric ** Parameters: 146956823Seric ** map -- a pointer to the database map. 147060089Seric ** name -- a buffer containing a hostname. 147153751Seric ** avp -- a pointer to a (cf file defined) argument vector. 147259084Seric ** statp -- an exit status (out parameter). 147316911Seric ** 147416911Seric ** Returns: 147553751Seric ** mapped host name 147651315Seric ** FALSE otherwise. 147716911Seric ** 147816911Seric ** Side Effects: 147960089Seric ** Looks up the host specified in name. If it is not 148016911Seric ** the canonical name for that host, replace it with 148116911Seric ** the canonical name. If the name is unknown, or it 148216911Seric ** is already the canonical name, leave it unchanged. 148316911Seric */ 148410758Seric 148516911Seric /*ARGSUSED*/ 148653751Seric char * 148760089Seric host_map_lookup(map, name, avp, statp) 148856823Seric MAP *map; 148960089Seric char *name; 149053751Seric char **avp; 149159084Seric char *statp; 149216911Seric { 149359084Seric register struct hostent *hp; 149459084Seric 149560089Seric hp = gethostbyname(name); 149659084Seric if (hp != NULL) 149759084Seric return hp->h_name; 149859084Seric *statp = EX_NOHOST; 149953751Seric return NULL; 150016911Seric } 150116911Seric 150256795Seric #endif /* DAEMON */ 1503