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*58873Seric static char sccsid[] = "@(#)daemon.c 6.29 (Berkeley) 03/30/93 (with daemon mode)"; 1633780Sbostic #else 17*58873Seric static char sccsid[] = "@(#)daemon.c 6.29 (Berkeley) 03/30/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 { 329*58873Seric if (DaemonAddr.sa.sa_family == AF_UNSPEC) 330*58873Seric DaemonAddr.sa.sa_family = AF_INET; 331*58873Seric 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 { 353*58873Seric case 'F': /* address family */ 35458849Seric if (isascii(*v) && isdigit(*v)) 355*58873Seric DaemonAddr.sa.sa_family = atoi(v); 356*58873Seric #ifdef NETINET 357*58873Seric else if (strcasecmp(v, "inet") == 0) 358*58873Seric DaemonAddr.sa.sa_family = AF_INET; 359*58873Seric #endif 360*58873Seric #ifdef NETISO 361*58873Seric else if (strcasecmp(v, "iso") == 0) 362*58873Seric DaemonAddr.sa.sa_family = AF_ISO; 363*58873Seric #endif 364*58873Seric #ifdef NETNS 365*58873Seric else if (strcasecmp(v, "ns") == 0) 366*58873Seric DaemonAddr.sa.sa_family = AF_NS; 367*58873Seric #endif 368*58873Seric #ifdef NETX25 369*58873Seric else if (strcasecmp(v, "x.25") == 0) 370*58873Seric DaemonAddr.sa.sa_family = AF_CCITT; 371*58873Seric #endif 37258849Seric else 373*58873Seric syserr("554 Unknown address family %s in Family=option", v); 374*58873Seric break; 375*58873Seric 376*58873Seric case 'A': /* address */ 377*58873Seric switch (DaemonAddr.sa.sa_family) 37858849Seric { 379*58873Seric #ifdef NETINET 380*58873Seric case AF_INET: 381*58873Seric if (isascii(*v) && isdigit(*v)) 382*58873Seric DaemonAddr.sin.sin_addr.s_addr = inet_network(v); 383*58873Seric else 384*58873Seric { 385*58873Seric register struct netent *np; 38658849Seric 387*58873Seric np = getnetbyname(v); 388*58873Seric if (np == NULL) 389*58873Seric syserr("554 network \"%s\" unknown", v); 390*58873Seric else 391*58873Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 392*58873Seric } 393*58873Seric break; 394*58873Seric #endif 395*58873Seric 396*58873Seric default: 397*58873Seric syserr("554 Address= option unsupported for family %d", 398*58873Seric DaemonAddr.sa.sa_family); 399*58873Seric break; 40058849Seric } 40158849Seric break; 40258849Seric 403*58873Seric case 'P': /* port */ 404*58873Seric switch (DaemonAddr.sa.sa_family) 40558849Seric { 406*58873Seric short port; 40758849Seric 408*58873Seric #ifdef NETINET 409*58873Seric case AF_INET: 410*58873Seric if (isascii(*v) && isdigit(*v)) 411*58873Seric DaemonAddr.sin.sin_port = atoi(v); 41258849Seric else 413*58873Seric { 414*58873Seric register struct servent *sp; 415*58873Seric 416*58873Seric sp = getservbyname(v, "tcp"); 417*58873Seric if (sp == NULL) 418*58873Seric syserr("554 server \"%s\" unknown", v); 419*58873Seric else 420*58873Seric DaemonAddr.sin.sin_port = sp->s_port; 421*58873Seric } 422*58873Seric break; 423*58873Seric #endif 424*58873Seric 425*58873Seric #ifdef NETISO 426*58873Seric case AF_ISO: 427*58873Seric /* assume two byte transport selector */ 428*58873Seric if (isascii(*v) && isdigit(*v)) 429*58873Seric port = atoi(v); 430*58873Seric else 431*58873Seric { 432*58873Seric register struct servent *sp; 433*58873Seric 434*58873Seric sp = getservbyname(v, "tcp"); 435*58873Seric if (sp == NULL) 436*58873Seric syserr("554 server \"%s\" unknown", v); 437*58873Seric else 438*58873Seric port = sp->s_port; 439*58873Seric } 440*58873Seric bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 441*58873Seric break; 442*58873Seric #endif 443*58873Seric 444*58873Seric default: 445*58873Seric syserr("554 Port= option unsupported for family %d", 446*58873Seric DaemonAddr.sa.sa_family); 447*58873Seric 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); 50025475Smiriam 5019308Seric if (host[0] == '[') 5029308Seric { 50311147Seric long hid; 50456795Seric register char *p = strchr(host, ']'); 5059308Seric 50611147Seric if (p != NULL) 5079308Seric { 50811147Seric *p = '\0'; 50911147Seric hid = inet_addr(&host[1]); 51058360Seric if (hid == -1) 51158360Seric { 51258360Seric /* try it as a host name (avoid MX lookup) */ 51358360Seric hp = gethostbyname(&host[1]); 51458360Seric *p = ']'; 51558360Seric goto gothostent; 51658360Seric } 51711147Seric *p = ']'; 5189308Seric } 51958360Seric if (p == NULL) 5209308Seric { 52158151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 5229308Seric return (EX_NOHOST); 5239308Seric } 52458778Seric addr.sin.sin_family = AF_INET; 52558778Seric addr.sin.sin_addr.s_addr = hid; 5269308Seric } 5279610Seric else 5289610Seric { 52929430Sbloom hp = gethostbyname(host); 53058360Seric gothostent: 53125475Smiriam if (hp == NULL) 53224945Seric { 53335651Seric #ifdef NAMED_BIND 53425475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 53525475Smiriam return (EX_TEMPFAIL); 53625657Seric 53735651Seric /* if name server is specified, assume temp fail */ 53835651Seric if (errno == ECONNREFUSED && UseNameServer) 53935651Seric return (EX_TEMPFAIL); 54035651Seric #endif 54125475Smiriam return (EX_NOHOST); 54224945Seric } 54358778Seric addr.sa.sa_family = hp->h_addrtype; 54458778Seric switch (hp->h_addrtype) 54558778Seric { 54658778Seric #ifdef NETINET 54758778Seric case AF_INET: 54858755Seric bcopy(hp->h_addr, 54958778Seric &addr.sin.sin_addr, 55058755Seric hp->h_length); 55158778Seric break; 55258778Seric #endif 55358778Seric 55458778Seric default: 55558755Seric bcopy(hp->h_addr, 55658778Seric addr.sa.sa_data, 55758755Seric hp->h_length); 55858778Seric break; 55958778Seric } 56029430Sbloom i = 1; 5619610Seric } 5629610Seric 5639610Seric /* 5649610Seric ** Determine the port number. 5659610Seric */ 5669610Seric 56710011Seric if (port != 0) 56858755Seric port = htons(port); 56910011Seric else 5709610Seric { 5719610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 5729610Seric 5739610Seric if (sp == NULL) 5749610Seric { 57558151Seric syserr("554 makeconnection: server \"smtp\" unknown"); 57657977Seric return (EX_OSERR); 5779610Seric } 57858755Seric port = sp->s_port; 5799610Seric } 5806039Seric 58158778Seric switch (addr.sa.sa_family) 58258755Seric { 58358755Seric case AF_INET: 58458778Seric addr.sin.sin_port = port; 58558755Seric addrlen = sizeof (struct sockaddr_in); 58658755Seric break; 58758755Seric 58858755Seric #ifdef NETISO 58958755Seric case AF_ISO: 59058755Seric /* assume two byte transport selector */ 59158755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 59258755Seric addrlen = sizeof (struct sockaddr_iso); 59358755Seric break; 59458755Seric #endif 59558755Seric 59658755Seric default: 59758778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 59858755Seric return (EX_NOHOST); 59958755Seric } 60058755Seric 6016039Seric /* 6026039Seric ** Try to actually open the connection. 6036039Seric */ 6046039Seric 60557736Seric for (;;) 60652106Seric { 60757736Seric if (tTd(16, 1)) 60858755Seric printf("makeconnection (%s [%s])\n", 60958755Seric host, anynet_ntoa(&addr)); 61052106Seric 61158588Seric /* save for logging */ 61258588Seric CurHostAddr = addr; 61358588Seric 61457736Seric if (usesecureport) 61557736Seric { 61657736Seric int rport = IPPORT_RESERVED - 1; 6176039Seric 61857736Seric s = rresvport(&rport); 61957736Seric } 62057736Seric else 62157736Seric { 62257736Seric s = socket(AF_INET, SOCK_STREAM, 0); 62357736Seric } 62457736Seric if (s < 0) 62557736Seric { 62657736Seric sav_errno = errno; 62757736Seric syserr("makeconnection: no socket"); 62857736Seric goto failure; 62957736Seric } 63010347Seric 63157736Seric if (tTd(16, 1)) 63257736Seric printf("makeconnection: fd=%d\n", s); 63357736Seric 63457736Seric /* turn on network debugging? */ 63557736Seric if (tTd(16, 101)) 63657736Seric { 63757736Seric int on = 1; 63857736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 63957736Seric (char *)&on, sizeof on); 64057736Seric } 64157736Seric if (CurEnv->e_xfp != NULL) 64257736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 64357736Seric errno = 0; /* for debugging */ 64458755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 64557736Seric break; 64657736Seric 64757736Seric /* couldn't connect.... figure out why */ 64827744Sbloom sav_errno = errno; 64927744Sbloom (void) close(s); 65029430Sbloom if (hp && hp->h_addr_list[i]) 65129430Sbloom { 65258755Seric extern char *errstring(); 65358755Seric 65457736Seric if (tTd(16, 1)) 65558755Seric printf("Connect failed (%s); trying new address....\n", 65658755Seric errstring(sav_errno)); 65758778Seric switch (addr.sa.sa_family) 65858778Seric { 65958778Seric #ifdef NETINET 66058778Seric case AF_INET: 66158755Seric bcopy(hp->h_addr_list[i++], 66258778Seric &addr.sin.sin_addr, 66358755Seric hp->h_length); 66458778Seric break; 66558778Seric #endif 66658778Seric 66758778Seric default: 66858755Seric bcopy(hp->h_addr_list[i++], 66958778Seric addr.sa.sa_data, 67052106Seric hp->h_length); 67158778Seric break; 67258778Seric } 67357736Seric continue; 67429430Sbloom } 67529430Sbloom 6766039Seric /* failure, decide if temporary or not */ 6776039Seric failure: 67858542Seric if (transienterror(sav_errno)) 67958542Seric return EX_TEMPFAIL; 68058542Seric else 68158542Seric { 68258542Seric extern char *errstring(); 68311147Seric 68458542Seric message("%s", errstring(sav_errno)); 68558542Seric return (EX_UNAVAILABLE); 6866039Seric } 6876039Seric } 6886039Seric 6896039Seric /* connection ok, put it into canonical form */ 69053739Seric mci->mci_out = fdopen(s, "w"); 69153739Seric mci->mci_in = fdopen(dup(s), "r"); 6926039Seric 69310098Seric return (EX_OK); 6946039Seric } 69510758Seric /* 69610758Seric ** MYHOSTNAME -- return the name of this host. 69710758Seric ** 69810758Seric ** Parameters: 69910758Seric ** hostbuf -- a place to return the name of this host. 70012313Seric ** size -- the size of hostbuf. 70110758Seric ** 70210758Seric ** Returns: 70310758Seric ** A list of aliases for this host. 70410758Seric ** 70510758Seric ** Side Effects: 70658110Seric ** Sets the MyIpAddrs buffer to a list of my IP addresses. 70710758Seric */ 7086039Seric 70958110Seric struct in_addr MyIpAddrs[MAXIPADDR + 1]; 71058110Seric 71110758Seric char ** 71212313Seric myhostname(hostbuf, size) 71310758Seric char hostbuf[]; 71412313Seric int size; 71510758Seric { 71658110Seric register struct hostent *hp; 71710758Seric extern struct hostent *gethostbyname(); 71810758Seric 71923120Seric if (gethostname(hostbuf, size) < 0) 72023120Seric { 72123120Seric (void) strcpy(hostbuf, "localhost"); 72223120Seric } 72311147Seric hp = gethostbyname(hostbuf); 72411147Seric if (hp != NULL) 72516877Seric { 72658110Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 72758110Seric hostbuf[size - 1] = '\0'; 72858110Seric 72958110Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 73058110Seric { 73158110Seric register int i; 73258110Seric 73358110Seric for (i = 0; i < MAXIPADDR; i++) 73458110Seric { 73558110Seric if (hp->h_addr_list[i] == NULL) 73658110Seric break; 73758110Seric MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i]; 73858110Seric } 73958110Seric MyIpAddrs[i].s_addr = 0; 74058110Seric } 74158110Seric 74211147Seric return (hp->h_aliases); 74316877Seric } 74410758Seric else 74510758Seric return (NULL); 74610758Seric } 74751315Seric /* 74858308Seric ** GETREALHOSTNAME -- get the real host name asociated with a file descriptor 74958308Seric ** 75058308Seric ** Parameters: 75158308Seric ** fd -- the descriptor 75258308Seric ** 75358308Seric ** Returns: 75458308Seric ** The host name associated with this descriptor, if it can 75558308Seric ** be determined. 75658308Seric ** NULL otherwise. 75758308Seric ** 75858308Seric ** Side Effects: 75958308Seric ** none 76058308Seric */ 76158308Seric 76258308Seric char * 76358308Seric getrealhostname(fd) 76458308Seric int fd; 76558308Seric { 76658308Seric register struct hostent *hp; 76758786Seric SOCKADDR sa; 76858755Seric int salen; 76958308Seric char hbuf[MAXNAME]; 77058308Seric extern struct hostent *gethostbyaddr(); 77158308Seric 77258755Seric salen = sizeof sa; 77358787Seric if (getsockname(fd, &sa.sa, &salen) < 0 || salen <= 0) 77458308Seric return NULL; 77558787Seric hp = gethostbyaddr(sa.sa.sa_data, salen, sa.sa.sa_family); 77658308Seric if (hp != NULL) 77758308Seric (void) strcpy(hbuf, hp->h_name); 77858308Seric else 77958755Seric (void) sprintf(hbuf, "[%s]", anynet_ntoa(&sa)); 78058308Seric return hbuf; 78158308Seric } 78258308Seric /* 78353751Seric ** MAPHOSTNAME -- turn a hostname into canonical form 78453751Seric ** 78553751Seric ** Parameters: 78656823Seric ** map -- a pointer to this map (unused). 78753751Seric ** hbuf -- a buffer containing a hostname. 78853751Seric ** hbsize -- the size of hbuf. 78955019Seric ** avp -- unused -- for compatibility with other mapping 79055019Seric ** functions. 79153751Seric ** 79253751Seric ** Returns: 79353751Seric ** The mapping, if found. 79453751Seric ** NULL if no mapping found. 79553751Seric ** 79653751Seric ** Side Effects: 79753751Seric ** Looks up the host specified in hbuf. If it is not 79853751Seric ** the canonical name for that host, return the canonical 79953751Seric ** name. 80053751Seric */ 80151315Seric 80253751Seric char * 80356823Seric maphostname(map, hbuf, hbsize, avp) 80456823Seric MAP *map; 80516911Seric char *hbuf; 80616911Seric int hbsize; 80753751Seric char **avp; 80816911Seric { 80916911Seric register struct hostent *hp; 81033932Sbostic u_long in_addr; 81156823Seric char *cp; 81258110Seric int i; 81333932Sbostic struct hostent *gethostbyaddr(); 81416911Seric 81556836Seric /* allow room for null */ 81656823Seric hbsize--; 81753751Seric 81825574Smiriam /* 81933932Sbostic * If first character is a bracket, then it is an address 82033932Sbostic * lookup. Address is copied into a temporary buffer to 82133932Sbostic * strip the brackets and to preserve hbuf if address is 82233932Sbostic * unknown. 82333932Sbostic */ 82453751Seric 82551315Seric if (*hbuf != '[') 82653751Seric { 82755019Seric extern bool getcanonname(); 82855019Seric 82958798Seric if (tTd(9, 1)) 83058798Seric printf("maphostname(%s, %d) => ", hbuf, hbsize); 83158674Seric if (getcanonname(hbuf, hbsize)) 83258796Seric { 83358796Seric if (tTd(9, 1)) 83458796Seric printf("%s\n", hbuf); 83553751Seric return hbuf; 83658796Seric } 83753751Seric else 83858796Seric { 83958796Seric if (tTd(9, 1)) 84058796Seric printf("FAIL\n"); 84153751Seric return NULL; 84258796Seric } 84353751Seric } 84456823Seric if ((cp = strchr(hbuf, ']')) == NULL) 84553751Seric return (NULL); 84640994Sbostic *cp = '\0'; 84756823Seric in_addr = inet_addr(&hbuf[1]); 84858110Seric 84958110Seric /* check to see if this is one of our addresses */ 85058110Seric for (i = 0; MyIpAddrs[i].s_addr != 0; i++) 85158110Seric { 85258110Seric if (MyIpAddrs[i].s_addr == in_addr) 85358110Seric { 85458110Seric strncpy(hbuf, MyHostName, hbsize); 85558110Seric hbuf[hbsize] = '\0'; 85658110Seric return hbuf; 85758110Seric } 85858110Seric } 85958110Seric 86058110Seric /* nope -- ask the name server */ 86133932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 86233932Sbostic if (hp == NULL) 86353751Seric return (NULL); 86453751Seric 86558110Seric /* found a match -- copy out */ 86656823Seric if (strlen(hp->h_name) > hbsize) 86756823Seric hp->h_name[hbsize] = '\0'; 86853751Seric (void) strcpy(hbuf, hp->h_name); 86953751Seric return hbuf; 87033932Sbostic } 87158755Seric /* 87258755Seric ** ANYNET_NTOA -- convert a network address to printable form. 87358755Seric ** 87458755Seric ** Parameters: 87558755Seric ** sap -- a pointer to a sockaddr structure. 87658755Seric ** 87758755Seric ** Returns: 87858755Seric ** A printable version of that sockaddr. 87958755Seric */ 88016911Seric 88158755Seric char * 88258755Seric anynet_ntoa(sap) 88358755Seric register SOCKADDR *sap; 88458755Seric { 88558755Seric register char *bp; 88658755Seric register char *ap; 88758755Seric int l; 88858755Seric static char buf[80]; 88958755Seric 89058798Seric /* check for null/zero family */ 89158798Seric if (sap == NULL) 89258798Seric return "NULLADDR"; 89358798Seric if (sap->sa.sa_family == 0) 89458798Seric return "0"; 89558798Seric 89658778Seric #ifdef NETINET 89758778Seric if (sap->sa.sa_family == AF_INET) 89858755Seric { 89958755Seric extern char *inet_ntoa(); 90058755Seric 90158755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 90258755Seric } 90358778Seric #endif 90458755Seric 90558755Seric /* unknown family -- just dump bytes */ 90658778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 90758755Seric bp = &buf[strlen(buf)]; 90858778Seric ap = sap->sa.sa_data; 90958778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 91058755Seric { 91158755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 91258755Seric bp += 3; 91358755Seric } 91458755Seric *--bp = '\0'; 91558755Seric return buf; 91658755Seric } 91758755Seric 91856795Seric # else /* DAEMON */ 91916911Seric /* code for systems without sophisticated networking */ 92010758Seric 92110758Seric /* 92210758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 92311297Seric ** 92411297Seric ** Can't convert to upper case here because might be a UUCP name. 92512313Seric ** 92612313Seric ** Mark, you can change this to be anything you want...... 92710758Seric */ 92810758Seric 92910758Seric char ** 93012313Seric myhostname(hostbuf, size) 93110758Seric char hostbuf[]; 93212313Seric int size; 93310758Seric { 93410758Seric register FILE *f; 93510758Seric 93610758Seric hostbuf[0] = '\0'; 93710758Seric f = fopen("/usr/include/whoami", "r"); 93810758Seric if (f != NULL) 93910758Seric { 94012313Seric (void) fgets(hostbuf, size, f); 94110758Seric fixcrlf(hostbuf, TRUE); 94210758Seric (void) fclose(f); 94310758Seric } 94410758Seric return (NULL); 94510758Seric } 94616911Seric /* 94758308Seric ** GETREALHOSTNAME -- get the real host name asociated with a file descriptor 94858308Seric ** 94958308Seric ** Parameters: 95058308Seric ** fd -- the descriptor 95158308Seric ** 95258308Seric ** Returns: 95358308Seric ** The host name associated with this descriptor, if it can 95458308Seric ** be determined. 95558308Seric ** NULL otherwise. 95658308Seric ** 95758308Seric ** Side Effects: 95858308Seric ** none 95958308Seric */ 96058308Seric 96158308Seric char * 96258308Seric getrealhostname(fd) 96358308Seric int fd; 96458308Seric { 96558308Seric return NULL; 96658308Seric } 96758308Seric /* 96816911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 96916911Seric ** 97016911Seric ** Parameters: 97156823Seric ** map -- a pointer to the database map. 97216911Seric ** hbuf -- a buffer containing a hostname. 97353751Seric ** avp -- a pointer to a (cf file defined) argument vector. 97416911Seric ** 97516911Seric ** Returns: 97653751Seric ** mapped host name 97751315Seric ** FALSE otherwise. 97816911Seric ** 97916911Seric ** Side Effects: 98016911Seric ** Looks up the host specified in hbuf. If it is not 98116911Seric ** the canonical name for that host, replace it with 98216911Seric ** the canonical name. If the name is unknown, or it 98316911Seric ** is already the canonical name, leave it unchanged. 98416911Seric */ 98510758Seric 98616911Seric /*ARGSUSED*/ 98753751Seric char * 98856823Seric maphostname(map, hbuf, hbsize, avp) 98956823Seric MAP *map; 99016911Seric char *hbuf; 99116911Seric int hbsize; 99253751Seric char **avp; 99316911Seric { 99453751Seric return NULL; 99516911Seric } 99616911Seric 99756795Seric #endif /* DAEMON */ 998