122700Sdist /* 234920Sbostic * Copyright (c) 1983 Eric P. Allman 333780Sbostic * Copyright (c) 1988 Regents of the University of California. 433780Sbostic * All rights reserved. 533780Sbostic * 642825Sbostic * %sccs.include.redist.c% 733780Sbostic */ 822700Sdist 933932Sbostic #include <errno.h> 1058153Seric #include <signal.h> 1140962Sbostic #include "sendmail.h" 124535Seric 1333780Sbostic #ifndef lint 1433780Sbostic #ifdef DAEMON 15*58906Seric static char sccsid[] = "@(#)daemon.c 6.30 (Berkeley) 04/01/93 (with daemon mode)"; 1633780Sbostic #else 17*58906Seric static char sccsid[] = "@(#)daemon.c 6.30 (Berkeley) 04/01/93 (without daemon mode)"; 1833780Sbostic #endif 1933780Sbostic #endif /* not lint */ 204535Seric 2133780Sbostic #ifdef DAEMON 2233780Sbostic 2323120Seric # include <netdb.h> 2423120Seric # include <sys/wait.h> 2523120Seric # include <sys/time.h> 265978Seric 274535Seric /* 284535Seric ** DAEMON.C -- routines to use when running as a daemon. 297556Seric ** 307556Seric ** This entire file is highly dependent on the 4.2 BSD 317556Seric ** interprocess communication primitives. No attempt has 327556Seric ** been made to make this file portable to Version 7, 337556Seric ** Version 6, MPX files, etc. If you should try such a 347556Seric ** thing yourself, I recommend chucking the entire file 357556Seric ** and starting from scratch. Basic semantics are: 367556Seric ** 377556Seric ** getrequests() 387556Seric ** Opens a port and initiates a connection. 397556Seric ** Returns in a child. Must set InChannel and 407556Seric ** OutChannel appropriately. 4110206Seric ** clrdaemon() 4210206Seric ** Close any open files associated with getting 4310206Seric ** the connection; this is used when running the queue, 4410206Seric ** etc., to avoid having extra file descriptors during 4510206Seric ** the queue run and to avoid confusing the network 4610206Seric ** code (if it cares). 4752106Seric ** makeconnection(host, port, outfile, infile, usesecureport) 487556Seric ** Make a connection to the named host on the given 497556Seric ** port. Set *outfile and *infile to the files 507556Seric ** appropriate for communication. Returns zero on 517556Seric ** success, else an exit status describing the 527556Seric ** error. 5356823Seric ** maphostname(map, hbuf, hbufsiz, avp) 5456823Seric ** Convert the entry in hbuf into a canonical form. 554535Seric */ 5658755Seric 5758755Seric extern char *anynet_ntoa(); 584535Seric /* 594535Seric ** GETREQUESTS -- open mail IPC port and get requests. 604535Seric ** 614535Seric ** Parameters: 624535Seric ** none. 634535Seric ** 644535Seric ** Returns: 654535Seric ** none. 664535Seric ** 674535Seric ** Side Effects: 684535Seric ** Waits until some interesting activity occurs. When 694535Seric ** it does, a child is created to process it, and the 704535Seric ** parent waits for completion. Return from this 719886Seric ** routine is always in the child. The file pointers 729886Seric ** "InChannel" and "OutChannel" should be set to point 739886Seric ** to the communication channel. 744535Seric */ 754535Seric 7658849Seric int DaemonSocket = -1; /* fd describing socket */ 7758849Seric SOCKADDR DaemonAddr; /* socket for incoming */ 7816144Seric 794535Seric getrequests() 804535Seric { 819610Seric int t; 829610Seric register struct servent *sp; 8325027Seric int on = 1; 8453751Seric bool refusingconnections = TRUE; 8558419Seric FILE *pidf; 8646928Sbostic extern void reapchild(); 877117Seric 889610Seric /* 899610Seric ** Set up the address for the mailer. 909610Seric */ 919610Seric 9258849Seric if (DaemonAddr.sin.sin_family == 0) 9358849Seric DaemonAddr.sin.sin_family = AF_INET; 9458849Seric if (DaemonAddr.sin.sin_addr.s_addr == 0) 9558849Seric DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; 9658849Seric if (DaemonAddr.sin.sin_port == 0) 979610Seric { 9858849Seric sp = getservbyname("smtp", "tcp"); 9958849Seric if (sp == NULL) 10058849Seric { 10158849Seric syserr("554 server \"smtp\" unknown"); 10258849Seric goto severe; 10358849Seric } 10458849Seric DaemonAddr.sin.sin_port = sp->s_port; 1059610Seric } 1069610Seric 1079610Seric /* 1089610Seric ** Try to actually open the connection. 1099610Seric */ 1109610Seric 1119610Seric if (tTd(15, 1)) 11258849Seric printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); 1139610Seric 1149610Seric /* get a socket for the SMTP connection */ 11523120Seric DaemonSocket = socket(AF_INET, SOCK_STREAM, 0); 11610206Seric if (DaemonSocket < 0) 1179610Seric { 1189610Seric /* probably another daemon already */ 1199610Seric syserr("getrequests: can't create socket"); 1209610Seric severe: 1219610Seric # ifdef LOG 1229610Seric if (LogLevel > 0) 12357663Seric syslog(LOG_ALERT, "problem creating SMTP socket"); 12456795Seric # endif /* LOG */ 1259610Seric finis(); 1269610Seric } 12710347Seric 12810347Seric /* turn on network debugging? */ 12956328Seric if (tTd(15, 101)) 13024945Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 13110347Seric 13225027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 13325027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 13425027Seric 13558849Seric if (bind(DaemonSocket, &DaemonAddr.sa, sizeof DaemonAddr) < 0) 1369610Seric { 1379610Seric syserr("getrequests: cannot bind"); 13810206Seric (void) close(DaemonSocket); 1399610Seric goto severe; 1409610Seric } 1419610Seric 14224955Seric (void) signal(SIGCHLD, reapchild); 14324945Seric 14458419Seric /* write the pid to the log file for posterity */ 14558419Seric pidf = fopen(PidFile, "w"); 14658419Seric if (pidf != NULL) 14758419Seric { 14858419Seric fprintf(pidf, "%d\n", getpid()); 14958419Seric fclose(pidf); 15058419Seric } 15158419Seric 15258419Seric 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 { 16653751Seric if (!refusingconnections) 16753751Seric { 16853751Seric /* don't queue so peer will fail quickly */ 16953751Seric (void) listen(DaemonSocket, 0); 17053751Seric refusingconnections = TRUE; 17153751Seric } 17257385Seric setproctitle("rejecting connections: load average: %d", 17357385Seric CurrentLA); 17414875Seric sleep(5); 17553751Seric continue; 17636584Sbostic } 17714875Seric 17853751Seric if (refusingconnections) 17953751Seric { 18053751Seric /* start listening again */ 18153751Seric if (listen(DaemonSocket, 10) < 0) 18253751Seric { 18353751Seric syserr("getrequests: cannot listen"); 18453751Seric (void) close(DaemonSocket); 18553751Seric goto severe; 18653751Seric } 18753751Seric setproctitle("accepting connections"); 18853751Seric refusingconnections = FALSE; 18953751Seric } 19053751Seric 1919610Seric /* wait for a connection */ 1929610Seric do 1939610Seric { 1949610Seric errno = 0; 19536230Skarels lotherend = sizeof RealHostAddr; 19646928Sbostic t = accept(DaemonSocket, 19746928Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 1989610Seric } while (t < 0 && errno == EINTR); 1999610Seric if (t < 0) 2005978Seric { 2019610Seric syserr("getrequests: accept"); 2029610Seric sleep(5); 2039610Seric continue; 2045978Seric } 2054631Seric 2065978Seric /* 2075978Seric ** Create a subprocess to process the mail. 2085978Seric */ 2095978Seric 2107677Seric if (tTd(15, 2)) 2119610Seric printf("getrequests: forking (fd = %d)\n", t); 2125978Seric 2134636Seric pid = fork(); 2144636Seric if (pid < 0) 2154631Seric { 2164636Seric syserr("daemon: cannot fork"); 2174636Seric sleep(10); 2189610Seric (void) close(t); 2194636Seric continue; 2204631Seric } 2214631Seric 2224636Seric if (pid == 0) 2234631Seric { 22411147Seric extern struct hostent *gethostbyaddr(); 22511147Seric register struct hostent *hp; 22611147Seric char buf[MAXNAME]; 22711147Seric 2284636Seric /* 2294636Seric ** CHILD -- return to caller. 23011147Seric ** Collect verified idea of sending host. 2314636Seric ** Verify calling user id if possible here. 2324636Seric */ 2334631Seric 23424955Seric (void) signal(SIGCHLD, SIG_DFL); 23524950Seric 23611147Seric /* determine host name */ 23758778Seric switch (RealHostAddr.sa.sa_family) 23858778Seric { 23958778Seric #ifdef NETINET 24058778Seric case AF_INET: 24158778Seric hp = gethostbyaddr((char *) &RealHostAddr.sin.sin_addr, 24258778Seric sizeof RealHostAddr.sin.sin_addr, 24358778Seric AF_INET); 24458778Seric break; 24558778Seric #endif 24658778Seric 24758778Seric #ifdef NETISO 24858778Seric case AF_ISO: 24958778Seric hp = gethostbyaddr((char *) &RealHostAddr.siso.siso_addr, 25058778Seric sizeof RealHostAddr.siso.siso_addr, 25158778Seric AF_ISO); 25258778Seric break; 25358778Seric #endif 25458778Seric 25558778Seric default: 25658778Seric hp = gethostbyaddr(RealHostAddr.sa.sa_data, 25758778Seric sizeof RealHostAddr.sa.sa_data, 25858778Seric RealHostAddr.sa.sa_family); 25958778Seric break; 26058778Seric } 26158778Seric 26211147Seric if (hp != NULL) 26323104Seric (void) strcpy(buf, hp->h_name); 26411147Seric else 26516884Seric { 26616884Seric /* produce a dotted quad */ 26716884Seric (void) sprintf(buf, "[%s]", 26858755Seric anynet_ntoa(&RealHostAddr)); 26916884Seric } 27016884Seric 27155173Seric #ifdef LOG 27257977Seric if (LogLevel > 10) 27355173Seric { 27455173Seric /* log connection information */ 27555173Seric syslog(LOG_INFO, "connect from %s (%s)", 27658755Seric buf, anynet_ntoa(&RealHostAddr)); 27755173Seric } 27855173Seric #endif 27955173Seric 28016884Seric /* should we check for illegal connection here? XXX */ 28116884Seric 28211147Seric RealHostName = newstr(buf); 28311147Seric 28410206Seric (void) close(DaemonSocket); 2859610Seric InChannel = fdopen(t, "r"); 28621062Seric OutChannel = fdopen(dup(t), "w"); 2877677Seric if (tTd(15, 2)) 2885978Seric printf("getreq: returning\n"); 2894636Seric return; 2904631Seric } 2914631Seric 2927117Seric /* close the port so that others will hang (for a while) */ 2939610Seric (void) close(t); 2944631Seric } 2959886Seric /*NOTREACHED*/ 2964631Seric } 2975978Seric /* 29810206Seric ** CLRDAEMON -- reset the daemon connection 29910206Seric ** 30010206Seric ** Parameters: 30110206Seric ** none. 30210206Seric ** 30310206Seric ** Returns: 30410206Seric ** none. 30510206Seric ** 30610206Seric ** Side Effects: 30710206Seric ** releases any resources used by the passive daemon. 30810206Seric */ 30910206Seric 31010206Seric clrdaemon() 31110206Seric { 31210206Seric if (DaemonSocket >= 0) 31310206Seric (void) close(DaemonSocket); 31410206Seric DaemonSocket = -1; 31510206Seric } 31610206Seric /* 31758849Seric ** SETDAEMONOPTIONS -- set options for running the daemon 31858849Seric ** 31958849Seric ** Parameters: 32058849Seric ** p -- the options line. 32158849Seric ** 32258849Seric ** Returns: 32358849Seric ** none. 32458849Seric */ 32558849Seric 32658849Seric setdaemonoptions(p) 32758849Seric register char *p; 32858849Seric { 32958873Seric if (DaemonAddr.sa.sa_family == AF_UNSPEC) 33058873Seric DaemonAddr.sa.sa_family = AF_INET; 33158873Seric 33258849Seric while (p != NULL) 33358849Seric { 33458849Seric register char *f; 33558849Seric register char *v; 33658849Seric 33758849Seric while (isascii(*p) && isspace(*p)) 33858849Seric p++; 33958849Seric if (*p == '\0') 34058849Seric break; 34158849Seric f = p; 34258849Seric p = strchr(p, ','); 34358849Seric if (p != NULL) 34458849Seric *p++ = '\0'; 34558849Seric v = strchr(f, '='); 34658849Seric if (v == NULL) 34758849Seric continue; 34858849Seric while (isascii(*++v) && isspace(*v)) 34958849Seric continue; 35058849Seric 35158849Seric switch (*f) 35258849Seric { 35358873Seric case 'F': /* address family */ 35458849Seric if (isascii(*v) && isdigit(*v)) 35558873Seric DaemonAddr.sa.sa_family = atoi(v); 35658873Seric #ifdef NETINET 35758873Seric else if (strcasecmp(v, "inet") == 0) 35858873Seric DaemonAddr.sa.sa_family = AF_INET; 35958873Seric #endif 36058873Seric #ifdef NETISO 36158873Seric else if (strcasecmp(v, "iso") == 0) 36258873Seric DaemonAddr.sa.sa_family = AF_ISO; 36358873Seric #endif 36458873Seric #ifdef NETNS 36558873Seric else if (strcasecmp(v, "ns") == 0) 36658873Seric DaemonAddr.sa.sa_family = AF_NS; 36758873Seric #endif 36858873Seric #ifdef NETX25 36958873Seric else if (strcasecmp(v, "x.25") == 0) 37058873Seric DaemonAddr.sa.sa_family = AF_CCITT; 37158873Seric #endif 37258849Seric else 37358873Seric syserr("554 Unknown address family %s in Family=option", v); 37458873Seric break; 37558873Seric 37658873Seric case 'A': /* address */ 37758873Seric switch (DaemonAddr.sa.sa_family) 37858849Seric { 37958873Seric #ifdef NETINET 38058873Seric case AF_INET: 38158873Seric if (isascii(*v) && isdigit(*v)) 38258873Seric DaemonAddr.sin.sin_addr.s_addr = inet_network(v); 38358873Seric else 38458873Seric { 38558873Seric register struct netent *np; 38658849Seric 38758873Seric np = getnetbyname(v); 38858873Seric if (np == NULL) 38958873Seric syserr("554 network \"%s\" unknown", v); 39058873Seric else 39158873Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 39258873Seric } 39358873Seric break; 39458873Seric #endif 39558873Seric 39658873Seric default: 39758873Seric syserr("554 Address= option unsupported for family %d", 39858873Seric DaemonAddr.sa.sa_family); 39958873Seric break; 40058849Seric } 40158849Seric break; 40258849Seric 40358873Seric case 'P': /* port */ 40458873Seric switch (DaemonAddr.sa.sa_family) 40558849Seric { 40658873Seric short port; 40758849Seric 40858873Seric #ifdef NETINET 40958873Seric case AF_INET: 41058873Seric if (isascii(*v) && isdigit(*v)) 41158873Seric DaemonAddr.sin.sin_port = atoi(v); 41258849Seric else 41358873Seric { 41458873Seric register struct servent *sp; 41558873Seric 41658873Seric sp = getservbyname(v, "tcp"); 41758873Seric if (sp == NULL) 41858873Seric syserr("554 server \"%s\" unknown", v); 41958873Seric else 42058873Seric DaemonAddr.sin.sin_port = sp->s_port; 42158873Seric } 42258873Seric break; 42358873Seric #endif 42458873Seric 42558873Seric #ifdef NETISO 42658873Seric case AF_ISO: 42758873Seric /* assume two byte transport selector */ 42858873Seric if (isascii(*v) && isdigit(*v)) 42958873Seric port = atoi(v); 43058873Seric else 43158873Seric { 43258873Seric register struct servent *sp; 43358873Seric 43458873Seric sp = getservbyname(v, "tcp"); 43558873Seric if (sp == NULL) 43658873Seric syserr("554 server \"%s\" unknown", v); 43758873Seric else 43858873Seric port = sp->s_port; 43958873Seric } 44058873Seric bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 44158873Seric break; 44258873Seric #endif 44358873Seric 44458873Seric default: 44558873Seric syserr("554 Port= option unsupported for family %d", 44658873Seric DaemonAddr.sa.sa_family); 44758873Seric break; 44858849Seric } 44958849Seric break; 45058849Seric } 45158849Seric } 45258849Seric } 45358849Seric /* 4546039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 4556039Seric ** 4566039Seric ** Parameters: 4576039Seric ** host -- the name of the host. 4586633Seric ** port -- the port number to connect to. 45953739Seric ** mci -- a pointer to the mail connection information 46053739Seric ** structure to be filled in. 46152106Seric ** usesecureport -- if set, use a low numbered (reserved) 46252106Seric ** port to provide some rudimentary authentication. 4636039Seric ** 4646039Seric ** Returns: 4656039Seric ** An exit code telling whether the connection could be 4666039Seric ** made and if not why not. 4676039Seric ** 4686039Seric ** Side Effects: 4696039Seric ** none. 4706039Seric */ 4715978Seric 47258755Seric SOCKADDR CurHostAddr; /* address of current host */ 47358305Seric 47454967Seric int 47553739Seric makeconnection(host, port, mci, usesecureport) 4766039Seric char *host; 4777286Seric u_short port; 47854967Seric register MCI *mci; 47952106Seric bool usesecureport; 4806039Seric { 48129430Sbloom register int i, s; 48229430Sbloom register struct hostent *hp = (struct hostent *)NULL; 48358755Seric SOCKADDR addr; 48452106Seric int sav_errno; 48558755Seric int addrlen; 48635651Seric #ifdef NAMED_BIND 48735651Seric extern int h_errno; 48835651Seric #endif 4896039Seric 4906039Seric /* 4916039Seric ** Set up the address for the mailer. 4929308Seric ** Accept "[a.b.c.d]" syntax for host name. 4936039Seric */ 4946039Seric 49535651Seric #ifdef NAMED_BIND 49625475Smiriam h_errno = 0; 49735651Seric #endif 49825475Smiriam errno = 0; 49958864Seric bzero(&CurHostAddr, sizeof CurHostAddr); 500*58906Seric CurHostName = host; 50125475Smiriam 5029308Seric if (host[0] == '[') 5039308Seric { 50411147Seric long hid; 50556795Seric register char *p = strchr(host, ']'); 5069308Seric 50711147Seric if (p != NULL) 5089308Seric { 50911147Seric *p = '\0'; 51011147Seric hid = inet_addr(&host[1]); 51158360Seric if (hid == -1) 51258360Seric { 51358360Seric /* try it as a host name (avoid MX lookup) */ 51458360Seric hp = gethostbyname(&host[1]); 51558360Seric *p = ']'; 51658360Seric goto gothostent; 51758360Seric } 51811147Seric *p = ']'; 5199308Seric } 52058360Seric if (p == NULL) 5219308Seric { 52258151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 5239308Seric return (EX_NOHOST); 5249308Seric } 52558778Seric addr.sin.sin_family = AF_INET; 52658778Seric addr.sin.sin_addr.s_addr = hid; 5279308Seric } 5289610Seric else 5299610Seric { 53029430Sbloom hp = gethostbyname(host); 53158360Seric gothostent: 53225475Smiriam if (hp == NULL) 53324945Seric { 53435651Seric #ifdef NAMED_BIND 53525475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 53625475Smiriam return (EX_TEMPFAIL); 53725657Seric 53835651Seric /* if name server is specified, assume temp fail */ 53935651Seric if (errno == ECONNREFUSED && UseNameServer) 54035651Seric return (EX_TEMPFAIL); 54135651Seric #endif 54225475Smiriam return (EX_NOHOST); 54324945Seric } 54458778Seric addr.sa.sa_family = hp->h_addrtype; 54558778Seric switch (hp->h_addrtype) 54658778Seric { 54758778Seric #ifdef NETINET 54858778Seric case AF_INET: 54958755Seric bcopy(hp->h_addr, 55058778Seric &addr.sin.sin_addr, 55158755Seric hp->h_length); 55258778Seric break; 55358778Seric #endif 55458778Seric 55558778Seric default: 55658755Seric bcopy(hp->h_addr, 55758778Seric addr.sa.sa_data, 55858755Seric hp->h_length); 55958778Seric break; 56058778Seric } 56129430Sbloom i = 1; 5629610Seric } 5639610Seric 5649610Seric /* 5659610Seric ** Determine the port number. 5669610Seric */ 5679610Seric 56810011Seric if (port != 0) 56958755Seric port = htons(port); 57010011Seric else 5719610Seric { 5729610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 5739610Seric 5749610Seric if (sp == NULL) 5759610Seric { 57658151Seric syserr("554 makeconnection: server \"smtp\" unknown"); 57757977Seric return (EX_OSERR); 5789610Seric } 57958755Seric port = sp->s_port; 5809610Seric } 5816039Seric 58258778Seric switch (addr.sa.sa_family) 58358755Seric { 58458755Seric case AF_INET: 58558778Seric addr.sin.sin_port = port; 58658755Seric addrlen = sizeof (struct sockaddr_in); 58758755Seric break; 58858755Seric 58958755Seric #ifdef NETISO 59058755Seric case AF_ISO: 59158755Seric /* assume two byte transport selector */ 59258755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 59358755Seric addrlen = sizeof (struct sockaddr_iso); 59458755Seric break; 59558755Seric #endif 59658755Seric 59758755Seric default: 59858778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 59958755Seric return (EX_NOHOST); 60058755Seric } 60158755Seric 6026039Seric /* 6036039Seric ** Try to actually open the connection. 6046039Seric */ 6056039Seric 60657736Seric for (;;) 60752106Seric { 60857736Seric if (tTd(16, 1)) 60958755Seric printf("makeconnection (%s [%s])\n", 61058755Seric host, anynet_ntoa(&addr)); 61152106Seric 61258588Seric /* save for logging */ 61358588Seric CurHostAddr = addr; 61458588Seric 61557736Seric if (usesecureport) 61657736Seric { 61757736Seric int rport = IPPORT_RESERVED - 1; 6186039Seric 61957736Seric s = rresvport(&rport); 62057736Seric } 62157736Seric else 62257736Seric { 62357736Seric s = socket(AF_INET, SOCK_STREAM, 0); 62457736Seric } 62557736Seric if (s < 0) 62657736Seric { 62757736Seric sav_errno = errno; 62857736Seric syserr("makeconnection: no socket"); 62957736Seric goto failure; 63057736Seric } 63110347Seric 63257736Seric if (tTd(16, 1)) 63357736Seric printf("makeconnection: fd=%d\n", s); 63457736Seric 63557736Seric /* turn on network debugging? */ 63657736Seric if (tTd(16, 101)) 63757736Seric { 63857736Seric int on = 1; 63957736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 64057736Seric (char *)&on, sizeof on); 64157736Seric } 64257736Seric if (CurEnv->e_xfp != NULL) 64357736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 64457736Seric errno = 0; /* for debugging */ 64558755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 64657736Seric break; 64757736Seric 64857736Seric /* couldn't connect.... figure out why */ 64927744Sbloom sav_errno = errno; 65027744Sbloom (void) close(s); 65129430Sbloom if (hp && hp->h_addr_list[i]) 65229430Sbloom { 65358755Seric extern char *errstring(); 65458755Seric 65557736Seric if (tTd(16, 1)) 65658755Seric printf("Connect failed (%s); trying new address....\n", 65758755Seric errstring(sav_errno)); 65858778Seric switch (addr.sa.sa_family) 65958778Seric { 66058778Seric #ifdef NETINET 66158778Seric case AF_INET: 66258755Seric bcopy(hp->h_addr_list[i++], 66358778Seric &addr.sin.sin_addr, 66458755Seric hp->h_length); 66558778Seric break; 66658778Seric #endif 66758778Seric 66858778Seric default: 66958755Seric bcopy(hp->h_addr_list[i++], 67058778Seric addr.sa.sa_data, 67152106Seric hp->h_length); 67258778Seric break; 67358778Seric } 67457736Seric continue; 67529430Sbloom } 67629430Sbloom 6776039Seric /* failure, decide if temporary or not */ 6786039Seric failure: 67958542Seric if (transienterror(sav_errno)) 68058542Seric return EX_TEMPFAIL; 68158542Seric else 68258542Seric { 68358542Seric extern char *errstring(); 68411147Seric 68558542Seric message("%s", errstring(sav_errno)); 68658542Seric return (EX_UNAVAILABLE); 6876039Seric } 6886039Seric } 6896039Seric 6906039Seric /* connection ok, put it into canonical form */ 69153739Seric mci->mci_out = fdopen(s, "w"); 69253739Seric mci->mci_in = fdopen(dup(s), "r"); 6936039Seric 69410098Seric return (EX_OK); 6956039Seric } 69610758Seric /* 69710758Seric ** MYHOSTNAME -- return the name of this host. 69810758Seric ** 69910758Seric ** Parameters: 70010758Seric ** hostbuf -- a place to return the name of this host. 70112313Seric ** size -- the size of hostbuf. 70210758Seric ** 70310758Seric ** Returns: 70410758Seric ** A list of aliases for this host. 70510758Seric ** 70610758Seric ** Side Effects: 70758110Seric ** Sets the MyIpAddrs buffer to a list of my IP addresses. 70810758Seric */ 7096039Seric 71058110Seric struct in_addr MyIpAddrs[MAXIPADDR + 1]; 71158110Seric 71210758Seric char ** 71312313Seric myhostname(hostbuf, size) 71410758Seric char hostbuf[]; 71512313Seric int size; 71610758Seric { 71758110Seric register struct hostent *hp; 71810758Seric extern struct hostent *gethostbyname(); 71910758Seric 72023120Seric if (gethostname(hostbuf, size) < 0) 72123120Seric { 72223120Seric (void) strcpy(hostbuf, "localhost"); 72323120Seric } 72411147Seric hp = gethostbyname(hostbuf); 72511147Seric if (hp != NULL) 72616877Seric { 72758110Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 72858110Seric hostbuf[size - 1] = '\0'; 72958110Seric 73058110Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 73158110Seric { 73258110Seric register int i; 73358110Seric 73458110Seric for (i = 0; i < MAXIPADDR; i++) 73558110Seric { 73658110Seric if (hp->h_addr_list[i] == NULL) 73758110Seric break; 73858110Seric MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i]; 73958110Seric } 74058110Seric MyIpAddrs[i].s_addr = 0; 74158110Seric } 74258110Seric 74311147Seric return (hp->h_aliases); 74416877Seric } 74510758Seric else 74610758Seric return (NULL); 74710758Seric } 74851315Seric /* 74958308Seric ** GETREALHOSTNAME -- get the real host name asociated with a file descriptor 75058308Seric ** 75158308Seric ** Parameters: 75258308Seric ** fd -- the descriptor 75358308Seric ** 75458308Seric ** Returns: 75558308Seric ** The host name associated with this descriptor, if it can 75658308Seric ** be determined. 75758308Seric ** NULL otherwise. 75858308Seric ** 75958308Seric ** Side Effects: 76058308Seric ** none 76158308Seric */ 76258308Seric 76358308Seric char * 76458308Seric getrealhostname(fd) 76558308Seric int fd; 76658308Seric { 76758308Seric register struct hostent *hp; 76858786Seric SOCKADDR sa; 76958755Seric int salen; 77058308Seric char hbuf[MAXNAME]; 77158308Seric extern struct hostent *gethostbyaddr(); 77258308Seric 77358755Seric salen = sizeof sa; 77458787Seric if (getsockname(fd, &sa.sa, &salen) < 0 || salen <= 0) 77558308Seric return NULL; 77658787Seric hp = gethostbyaddr(sa.sa.sa_data, salen, sa.sa.sa_family); 77758308Seric if (hp != NULL) 77858308Seric (void) strcpy(hbuf, hp->h_name); 77958308Seric else 78058755Seric (void) sprintf(hbuf, "[%s]", anynet_ntoa(&sa)); 78158308Seric return hbuf; 78258308Seric } 78358308Seric /* 78453751Seric ** MAPHOSTNAME -- turn a hostname into canonical form 78553751Seric ** 78653751Seric ** Parameters: 78756823Seric ** map -- a pointer to this map (unused). 78853751Seric ** hbuf -- a buffer containing a hostname. 78953751Seric ** hbsize -- the size of hbuf. 79055019Seric ** avp -- unused -- for compatibility with other mapping 79155019Seric ** functions. 79253751Seric ** 79353751Seric ** Returns: 79453751Seric ** The mapping, if found. 79553751Seric ** NULL if no mapping found. 79653751Seric ** 79753751Seric ** Side Effects: 79853751Seric ** Looks up the host specified in hbuf. If it is not 79953751Seric ** the canonical name for that host, return the canonical 80053751Seric ** name. 80153751Seric */ 80251315Seric 80353751Seric char * 80456823Seric maphostname(map, hbuf, hbsize, avp) 80556823Seric MAP *map; 80616911Seric char *hbuf; 80716911Seric int hbsize; 80853751Seric char **avp; 80916911Seric { 81016911Seric register struct hostent *hp; 81133932Sbostic u_long in_addr; 81256823Seric char *cp; 81358110Seric int i; 81433932Sbostic struct hostent *gethostbyaddr(); 81516911Seric 81656836Seric /* allow room for null */ 81756823Seric hbsize--; 81853751Seric 81925574Smiriam /* 82033932Sbostic * If first character is a bracket, then it is an address 82133932Sbostic * lookup. Address is copied into a temporary buffer to 82233932Sbostic * strip the brackets and to preserve hbuf if address is 82333932Sbostic * unknown. 82433932Sbostic */ 82553751Seric 82651315Seric if (*hbuf != '[') 82753751Seric { 82855019Seric extern bool getcanonname(); 82955019Seric 83058798Seric if (tTd(9, 1)) 83158798Seric printf("maphostname(%s, %d) => ", hbuf, hbsize); 83258674Seric if (getcanonname(hbuf, hbsize)) 83358796Seric { 83458796Seric if (tTd(9, 1)) 83558796Seric printf("%s\n", hbuf); 83653751Seric return hbuf; 83758796Seric } 83853751Seric else 83958796Seric { 84058796Seric if (tTd(9, 1)) 84158796Seric printf("FAIL\n"); 84253751Seric return NULL; 84358796Seric } 84453751Seric } 84556823Seric if ((cp = strchr(hbuf, ']')) == NULL) 84653751Seric return (NULL); 84740994Sbostic *cp = '\0'; 84856823Seric in_addr = inet_addr(&hbuf[1]); 84958110Seric 85058110Seric /* check to see if this is one of our addresses */ 85158110Seric for (i = 0; MyIpAddrs[i].s_addr != 0; i++) 85258110Seric { 85358110Seric if (MyIpAddrs[i].s_addr == in_addr) 85458110Seric { 85558110Seric strncpy(hbuf, MyHostName, hbsize); 85658110Seric hbuf[hbsize] = '\0'; 85758110Seric return hbuf; 85858110Seric } 85958110Seric } 86058110Seric 86158110Seric /* nope -- ask the name server */ 86233932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 86333932Sbostic if (hp == NULL) 86453751Seric return (NULL); 86553751Seric 86658110Seric /* found a match -- copy out */ 86756823Seric if (strlen(hp->h_name) > hbsize) 86856823Seric hp->h_name[hbsize] = '\0'; 86953751Seric (void) strcpy(hbuf, hp->h_name); 87053751Seric return hbuf; 87133932Sbostic } 87258755Seric /* 87358755Seric ** ANYNET_NTOA -- convert a network address to printable form. 87458755Seric ** 87558755Seric ** Parameters: 87658755Seric ** sap -- a pointer to a sockaddr structure. 87758755Seric ** 87858755Seric ** Returns: 87958755Seric ** A printable version of that sockaddr. 88058755Seric */ 88116911Seric 88258755Seric char * 88358755Seric anynet_ntoa(sap) 88458755Seric register SOCKADDR *sap; 88558755Seric { 88658755Seric register char *bp; 88758755Seric register char *ap; 88858755Seric int l; 88958755Seric static char buf[80]; 89058755Seric 89158798Seric /* check for null/zero family */ 89258798Seric if (sap == NULL) 89358798Seric return "NULLADDR"; 89458798Seric if (sap->sa.sa_family == 0) 89558798Seric return "0"; 89658798Seric 89758778Seric #ifdef NETINET 89858778Seric if (sap->sa.sa_family == AF_INET) 89958755Seric { 90058755Seric extern char *inet_ntoa(); 90158755Seric 90258755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 90358755Seric } 90458778Seric #endif 90558755Seric 90658755Seric /* unknown family -- just dump bytes */ 90758778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 90858755Seric bp = &buf[strlen(buf)]; 90958778Seric ap = sap->sa.sa_data; 91058778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 91158755Seric { 91258755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 91358755Seric bp += 3; 91458755Seric } 91558755Seric *--bp = '\0'; 91658755Seric return buf; 91758755Seric } 91858755Seric 91956795Seric # else /* DAEMON */ 92016911Seric /* code for systems without sophisticated networking */ 92110758Seric 92210758Seric /* 92310758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 92411297Seric ** 92511297Seric ** Can't convert to upper case here because might be a UUCP name. 92612313Seric ** 92712313Seric ** Mark, you can change this to be anything you want...... 92810758Seric */ 92910758Seric 93010758Seric char ** 93112313Seric myhostname(hostbuf, size) 93210758Seric char hostbuf[]; 93312313Seric int size; 93410758Seric { 93510758Seric register FILE *f; 93610758Seric 93710758Seric hostbuf[0] = '\0'; 93810758Seric f = fopen("/usr/include/whoami", "r"); 93910758Seric if (f != NULL) 94010758Seric { 94112313Seric (void) fgets(hostbuf, size, f); 94210758Seric fixcrlf(hostbuf, TRUE); 94310758Seric (void) fclose(f); 94410758Seric } 94510758Seric return (NULL); 94610758Seric } 94716911Seric /* 94858308Seric ** GETREALHOSTNAME -- get the real host name asociated with a file descriptor 94958308Seric ** 95058308Seric ** Parameters: 95158308Seric ** fd -- the descriptor 95258308Seric ** 95358308Seric ** Returns: 95458308Seric ** The host name associated with this descriptor, if it can 95558308Seric ** be determined. 95658308Seric ** NULL otherwise. 95758308Seric ** 95858308Seric ** Side Effects: 95958308Seric ** none 96058308Seric */ 96158308Seric 96258308Seric char * 96358308Seric getrealhostname(fd) 96458308Seric int fd; 96558308Seric { 96658308Seric return NULL; 96758308Seric } 96858308Seric /* 96916911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 97016911Seric ** 97116911Seric ** Parameters: 97256823Seric ** map -- a pointer to the database map. 97316911Seric ** hbuf -- a buffer containing a hostname. 97453751Seric ** avp -- a pointer to a (cf file defined) argument vector. 97516911Seric ** 97616911Seric ** Returns: 97753751Seric ** mapped host name 97851315Seric ** FALSE otherwise. 97916911Seric ** 98016911Seric ** Side Effects: 98116911Seric ** Looks up the host specified in hbuf. If it is not 98216911Seric ** the canonical name for that host, replace it with 98316911Seric ** the canonical name. If the name is unknown, or it 98416911Seric ** is already the canonical name, leave it unchanged. 98516911Seric */ 98610758Seric 98716911Seric /*ARGSUSED*/ 98853751Seric char * 98956823Seric maphostname(map, hbuf, hbsize, avp) 99056823Seric MAP *map; 99116911Seric char *hbuf; 99216911Seric int hbsize; 99353751Seric char **avp; 99416911Seric { 99553751Seric return NULL; 99616911Seric } 99716911Seric 99856795Seric #endif /* DAEMON */ 999