1939f5b94Sdist /* 20942ea6aSbostic * Copyright (c) 1983 Eric P. Allman 3da1c6175Sbostic * Copyright (c) 1988 Regents of the University of California. 4da1c6175Sbostic * All rights reserved. 5da1c6175Sbostic * 63bc94712Sbostic * %sccs.include.redist.c% 7939f5b94Sdist */ 8939f5b94Sdist 97aa493c5Seric #include <errno.h> 10a8c080f0Seric #include <signal.h> 116c05f684Sbostic #include "sendmail.h" 127fa39d90Seric 13af5e902cSeric #ifndef lint 14da1c6175Sbostic #ifdef DAEMON 15*bfb80540Seric static char sccsid[] = "@(#)daemon.c 6.26 (Berkeley) 03/29/93 (with daemon mode)"; 16d0a9e852Seric #else 17*bfb80540Seric static char sccsid[] = "@(#)daemon.c 6.26 (Berkeley) 03/29/93 (without daemon mode)"; 18da1c6175Sbostic #endif 19da1c6175Sbostic #endif /* not lint */ 20da1c6175Sbostic 21da1c6175Sbostic #ifdef DAEMON 22d0a9e852Seric 231c71e510Seric # include <netdb.h> 241e1663f7Swnj # include <sys/wait.h> 25af5e902cSeric # include <sys/time.h> 26d0a9e852Seric 27e2f2f828Seric #ifdef NETISO 28e2f2f828Seric # include <netiso/iso.h> 29e2f2f828Seric #endif 30e2f2f828Seric 317fa39d90Seric /* 327fa39d90Seric ** DAEMON.C -- routines to use when running as a daemon. 3347b12ae1Seric ** 3447b12ae1Seric ** This entire file is highly dependent on the 4.2 BSD 3547b12ae1Seric ** interprocess communication primitives. No attempt has 3647b12ae1Seric ** been made to make this file portable to Version 7, 3747b12ae1Seric ** Version 6, MPX files, etc. If you should try such a 3847b12ae1Seric ** thing yourself, I recommend chucking the entire file 3947b12ae1Seric ** and starting from scratch. Basic semantics are: 4047b12ae1Seric ** 4147b12ae1Seric ** getrequests() 4247b12ae1Seric ** Opens a port and initiates a connection. 4347b12ae1Seric ** Returns in a child. Must set InChannel and 4447b12ae1Seric ** OutChannel appropriately. 45b7d7afcbSeric ** clrdaemon() 46b7d7afcbSeric ** Close any open files associated with getting 47b7d7afcbSeric ** the connection; this is used when running the queue, 48b7d7afcbSeric ** etc., to avoid having extra file descriptors during 49b7d7afcbSeric ** the queue run and to avoid confusing the network 50b7d7afcbSeric ** code (if it cares). 51914346b1Seric ** makeconnection(host, port, outfile, infile, usesecureport) 5247b12ae1Seric ** Make a connection to the named host on the given 5347b12ae1Seric ** port. Set *outfile and *infile to the files 5447b12ae1Seric ** appropriate for communication. Returns zero on 5547b12ae1Seric ** success, else an exit status describing the 5647b12ae1Seric ** error. 5705b57da8Seric ** maphostname(map, hbuf, hbufsiz, avp) 5805b57da8Seric ** Convert the entry in hbuf into a canonical form. 597fa39d90Seric */ 60e2f2f828Seric 61e2f2f828Seric extern char *anynet_ntoa(); 627fa39d90Seric /* 637fa39d90Seric ** GETREQUESTS -- open mail IPC port and get requests. 647fa39d90Seric ** 657fa39d90Seric ** Parameters: 667fa39d90Seric ** none. 677fa39d90Seric ** 687fa39d90Seric ** Returns: 697fa39d90Seric ** none. 707fa39d90Seric ** 717fa39d90Seric ** Side Effects: 727fa39d90Seric ** Waits until some interesting activity occurs. When 737fa39d90Seric ** it does, a child is created to process it, and the 747fa39d90Seric ** parent waits for completion. Return from this 75147303b1Seric ** routine is always in the child. The file pointers 76147303b1Seric ** "InChannel" and "OutChannel" should be set to point 77147303b1Seric ** to the communication channel. 787fa39d90Seric */ 797fa39d90Seric 80b7d7afcbSeric int DaemonSocket = -1; /* fd describing socket */ 81*bfb80540Seric SOCKADDR DaemonAddr; /* socket for incoming */ 821c71e510Seric 837fa39d90Seric getrequests() 847fa39d90Seric { 851c71e510Seric int t; 861c71e510Seric register struct servent *sp; 877868dfc2Seric int on = 1; 8815d084d5Seric bool refusingconnections = TRUE; 890aae1086Seric FILE *pidf; 909b100374Sbostic extern void reapchild(); 91eb889047Seric 92a8268164Seric /* 931c71e510Seric ** Set up the address for the mailer. 94eb889047Seric */ 95eb889047Seric 96*bfb80540Seric if (DaemonAddr.sin.sin_family == 0) 97*bfb80540Seric DaemonAddr.sin.sin_family = AF_INET; 98*bfb80540Seric if (DaemonAddr.sin.sin_addr.s_addr == 0) 99*bfb80540Seric DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; 100*bfb80540Seric if (DaemonAddr.sin.sin_port == 0) 101*bfb80540Seric { 1021c71e510Seric sp = getservbyname("smtp", "tcp"); 1031c71e510Seric if (sp == NULL) 104d0a9e852Seric { 10508b25121Seric syserr("554 server \"smtp\" unknown"); 106a1961f2aSeric goto severe; 1071c71e510Seric } 108*bfb80540Seric DaemonAddr.sin.sin_port = sp->s_port; 109*bfb80540Seric } 1101c71e510Seric 1111c71e510Seric /* 1121c71e510Seric ** Try to actually open the connection. 1131c71e510Seric */ 1141c71e510Seric 1151c71e510Seric if (tTd(15, 1)) 116*bfb80540Seric printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); 1171c71e510Seric 1181c71e510Seric /* get a socket for the SMTP connection */ 119af5e902cSeric DaemonSocket = socket(AF_INET, SOCK_STREAM, 0); 120b7d7afcbSeric if (DaemonSocket < 0) 1211c71e510Seric { 1221c71e510Seric /* probably another daemon already */ 1231c71e510Seric syserr("getrequests: can't create socket"); 1241c71e510Seric severe: 125b0ba8827Seric # ifdef LOG 126b0ba8827Seric if (LogLevel > 0) 1270c034190Seric syslog(LOG_ALERT, "problem creating SMTP socket"); 1286c2c3107Seric # endif /* LOG */ 12947b12ae1Seric finis(); 130d0a9e852Seric } 1311b6e4a15Seric 1321b6e4a15Seric /* turn on network debugging? */ 133a2ef5fa4Seric if (tTd(15, 101)) 13452308a50Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 1351b6e4a15Seric 1367868dfc2Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 1377868dfc2Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 1387868dfc2Seric 139*bfb80540Seric if (bind(DaemonSocket, &DaemonAddr.sa, sizeof DaemonAddr) < 0) 1401c71e510Seric { 1411c71e510Seric syserr("getrequests: cannot bind"); 142b7d7afcbSeric (void) close(DaemonSocket); 1431c71e510Seric goto severe; 1441c71e510Seric } 1451c71e510Seric 1461cd247eeSeric (void) signal(SIGCHLD, reapchild); 14752308a50Seric 1480aae1086Seric /* write the pid to the log file for posterity */ 1490aae1086Seric pidf = fopen(PidFile, "w"); 1500aae1086Seric if (pidf != NULL) 1510aae1086Seric { 1520aae1086Seric fprintf(pidf, "%d\n", getpid()); 1530aae1086Seric fclose(pidf); 1540aae1086Seric } 1550aae1086Seric 1560aae1086Seric 1571c71e510Seric if (tTd(15, 1)) 158b7d7afcbSeric printf("getrequests: %d\n", DaemonSocket); 1591c71e510Seric 1601c71e510Seric for (;;) 1611c71e510Seric { 1623a099713Seric register int pid; 163a44d5a5eSeric auto int lotherend; 16415d084d5Seric extern bool refuseconnections(); 1653a099713Seric 1663a099713Seric /* see if we are rejecting connections */ 16715d084d5Seric CurrentLA = getla(); 16815d084d5Seric if (refuseconnections()) 1696775ec03Sbostic { 17015d084d5Seric if (!refusingconnections) 17115d084d5Seric { 17215d084d5Seric /* don't queue so peer will fail quickly */ 17315d084d5Seric (void) listen(DaemonSocket, 0); 17415d084d5Seric refusingconnections = TRUE; 17515d084d5Seric } 17671e5e267Seric setproctitle("rejecting connections: load average: %d", 17771e5e267Seric CurrentLA); 1783a099713Seric sleep(5); 17915d084d5Seric continue; 18015d084d5Seric } 18115d084d5Seric 18215d084d5Seric if (refusingconnections) 18315d084d5Seric { 18415d084d5Seric /* start listening again */ 18515d084d5Seric if (listen(DaemonSocket, 10) < 0) 18615d084d5Seric { 18715d084d5Seric syserr("getrequests: cannot listen"); 18815d084d5Seric (void) close(DaemonSocket); 18915d084d5Seric goto severe; 19015d084d5Seric } 19115d084d5Seric setproctitle("accepting connections"); 19215d084d5Seric refusingconnections = FALSE; 1936775ec03Sbostic } 194a44d5a5eSeric 1951c71e510Seric /* wait for a connection */ 1961c71e510Seric do 1971c71e510Seric { 1981c71e510Seric errno = 0; 1999f9a15b6Skarels lotherend = sizeof RealHostAddr; 2009b100374Sbostic t = accept(DaemonSocket, 2019b100374Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 2021c71e510Seric } while (t < 0 && errno == EINTR); 2031c71e510Seric if (t < 0) 2041c71e510Seric { 2051c71e510Seric syserr("getrequests: accept"); 2061c71e510Seric sleep(5); 2071c71e510Seric continue; 2081c71e510Seric } 209d0a9e852Seric 210d0a9e852Seric /* 211d0a9e852Seric ** Create a subprocess to process the mail. 212d0a9e852Seric */ 213d0a9e852Seric 21461e4310fSeric if (tTd(15, 2)) 2151c71e510Seric printf("getrequests: forking (fd = %d)\n", t); 216eb889047Seric 217a8268164Seric pid = fork(); 218a8268164Seric if (pid < 0) 219a8268164Seric { 220a8268164Seric syserr("daemon: cannot fork"); 221a8268164Seric sleep(10); 2221c71e510Seric (void) close(t); 223a8268164Seric continue; 224a8268164Seric } 225a8268164Seric 226a8268164Seric if (pid == 0) 227a8268164Seric { 228a44d5a5eSeric extern struct hostent *gethostbyaddr(); 229a44d5a5eSeric register struct hostent *hp; 230a44d5a5eSeric char buf[MAXNAME]; 231a44d5a5eSeric 232a8268164Seric /* 233a8268164Seric ** CHILD -- return to caller. 234a44d5a5eSeric ** Collect verified idea of sending host. 235a8268164Seric ** Verify calling user id if possible here. 236a8268164Seric */ 237a8268164Seric 2381cd247eeSeric (void) signal(SIGCHLD, SIG_DFL); 239779ac194Seric 240a44d5a5eSeric /* determine host name */ 24183c1f4bcSeric switch (RealHostAddr.sa.sa_family) 24283c1f4bcSeric { 24383c1f4bcSeric #ifdef NETINET 24483c1f4bcSeric case AF_INET: 24583c1f4bcSeric hp = gethostbyaddr((char *) &RealHostAddr.sin.sin_addr, 24683c1f4bcSeric sizeof RealHostAddr.sin.sin_addr, 24783c1f4bcSeric AF_INET); 24883c1f4bcSeric break; 24983c1f4bcSeric #endif 25083c1f4bcSeric 25183c1f4bcSeric #ifdef NETISO 25283c1f4bcSeric case AF_ISO: 25383c1f4bcSeric hp = gethostbyaddr((char *) &RealHostAddr.siso.siso_addr, 25483c1f4bcSeric sizeof RealHostAddr.siso.siso_addr, 25583c1f4bcSeric AF_ISO); 25683c1f4bcSeric break; 25783c1f4bcSeric #endif 25883c1f4bcSeric 25983c1f4bcSeric default: 26083c1f4bcSeric hp = gethostbyaddr(RealHostAddr.sa.sa_data, 26183c1f4bcSeric sizeof RealHostAddr.sa.sa_data, 26283c1f4bcSeric RealHostAddr.sa.sa_family); 26383c1f4bcSeric break; 26483c1f4bcSeric } 26583c1f4bcSeric 266a44d5a5eSeric if (hp != NULL) 267fefbbe29Seric (void) strcpy(buf, hp->h_name); 268a44d5a5eSeric else 26929dcf4baSeric { 27029dcf4baSeric /* produce a dotted quad */ 27129dcf4baSeric (void) sprintf(buf, "[%s]", 272e2f2f828Seric anynet_ntoa(&RealHostAddr)); 27329dcf4baSeric } 27429dcf4baSeric 2752a6bc25bSeric #ifdef LOG 276845e533cSeric if (LogLevel > 10) 2772a6bc25bSeric { 2782a6bc25bSeric /* log connection information */ 2792a6bc25bSeric syslog(LOG_INFO, "connect from %s (%s)", 280e2f2f828Seric buf, anynet_ntoa(&RealHostAddr)); 2812a6bc25bSeric } 2822a6bc25bSeric #endif 2832a6bc25bSeric 28429dcf4baSeric /* should we check for illegal connection here? XXX */ 28529dcf4baSeric 286a44d5a5eSeric RealHostName = newstr(buf); 287a44d5a5eSeric 288b7d7afcbSeric (void) close(DaemonSocket); 2891c71e510Seric InChannel = fdopen(t, "r"); 2901d5bd586Seric OutChannel = fdopen(dup(t), "w"); 29161e4310fSeric if (tTd(15, 2)) 292d0a9e852Seric printf("getreq: returning\n"); 293a8268164Seric return; 294a8268164Seric } 295a8268164Seric 2963c154354Seric /* close the port so that others will hang (for a while) */ 2973c154354Seric (void) close(t); 2988e3e4b17Seric } 2993c154354Seric /*NOTREACHED*/ 3003c154354Seric } 3018e3e4b17Seric /* 302b7d7afcbSeric ** CLRDAEMON -- reset the daemon connection 303b7d7afcbSeric ** 304b7d7afcbSeric ** Parameters: 305b7d7afcbSeric ** none. 306b7d7afcbSeric ** 307b7d7afcbSeric ** Returns: 308b7d7afcbSeric ** none. 309b7d7afcbSeric ** 310b7d7afcbSeric ** Side Effects: 311b7d7afcbSeric ** releases any resources used by the passive daemon. 312b7d7afcbSeric */ 313b7d7afcbSeric 314b7d7afcbSeric clrdaemon() 315b7d7afcbSeric { 316b7d7afcbSeric if (DaemonSocket >= 0) 317b7d7afcbSeric (void) close(DaemonSocket); 318b7d7afcbSeric DaemonSocket = -1; 319b7d7afcbSeric } 320b7d7afcbSeric /* 321*bfb80540Seric ** SETDAEMONOPTIONS -- set options for running the daemon 322*bfb80540Seric ** 323*bfb80540Seric ** Parameters: 324*bfb80540Seric ** p -- the options line. 325*bfb80540Seric ** 326*bfb80540Seric ** Returns: 327*bfb80540Seric ** none. 328*bfb80540Seric */ 329*bfb80540Seric 330*bfb80540Seric setdaemonoptions(p) 331*bfb80540Seric register char *p; 332*bfb80540Seric { 333*bfb80540Seric while (p != NULL) 334*bfb80540Seric { 335*bfb80540Seric register char *f; 336*bfb80540Seric register char *v; 337*bfb80540Seric 338*bfb80540Seric while (isascii(*p) && isspace(*p)) 339*bfb80540Seric p++; 340*bfb80540Seric if (*p == '\0') 341*bfb80540Seric break; 342*bfb80540Seric f = p; 343*bfb80540Seric p = strchr(p, ','); 344*bfb80540Seric if (p != NULL) 345*bfb80540Seric *p++ = '\0'; 346*bfb80540Seric v = strchr(f, '='); 347*bfb80540Seric if (v == NULL) 348*bfb80540Seric continue; 349*bfb80540Seric while (isascii(*++v) && isspace(*v)) 350*bfb80540Seric continue; 351*bfb80540Seric 352*bfb80540Seric switch (*f) 353*bfb80540Seric { 354*bfb80540Seric case 'P': /* port */ 355*bfb80540Seric case 'p': 356*bfb80540Seric if (isascii(*v) && isdigit(*v)) 357*bfb80540Seric DaemonAddr.sin.sin_port = atoi(v); 358*bfb80540Seric else 359*bfb80540Seric { 360*bfb80540Seric register struct servent *sp; 361*bfb80540Seric 362*bfb80540Seric sp = getservbyname(v, "tcp"); 363*bfb80540Seric if (sp == NULL) 364*bfb80540Seric syserr("554 server \"%s\" unknown", v); 365*bfb80540Seric else 366*bfb80540Seric DaemonAddr.sin.sin_port = sp->s_port; 367*bfb80540Seric } 368*bfb80540Seric break; 369*bfb80540Seric 370*bfb80540Seric case 'A': /* address */ 371*bfb80540Seric case 'a': 372*bfb80540Seric if (isascii(*v) && isdigit(*v)) 373*bfb80540Seric (void) inet_aton(v, &DaemonAddr.sin.sin_addr); 374*bfb80540Seric else 375*bfb80540Seric { 376*bfb80540Seric register struct netent *np; 377*bfb80540Seric 378*bfb80540Seric np = getnetbyname(v); 379*bfb80540Seric if (np == NULL) 380*bfb80540Seric syserr("554 network \"%s\" unknown", v); 381*bfb80540Seric else 382*bfb80540Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 383*bfb80540Seric } 384*bfb80540Seric break; 385*bfb80540Seric } 386*bfb80540Seric } 387*bfb80540Seric } 388*bfb80540Seric /* 3897aa493c5Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 3907aa493c5Seric ** 3917aa493c5Seric ** Parameters: 3927aa493c5Seric ** host -- the name of the host. 39348ff0a9dSeric ** port -- the port number to connect to. 394655feedbSeric ** mci -- a pointer to the mail connection information 395655feedbSeric ** structure to be filled in. 396914346b1Seric ** usesecureport -- if set, use a low numbered (reserved) 397914346b1Seric ** port to provide some rudimentary authentication. 3987aa493c5Seric ** 3997aa493c5Seric ** Returns: 4007aa493c5Seric ** An exit code telling whether the connection could be 4017aa493c5Seric ** made and if not why not. 4027aa493c5Seric ** 4037aa493c5Seric ** Side Effects: 4047aa493c5Seric ** none. 4057aa493c5Seric */ 4067aa493c5Seric 407e2f2f828Seric SOCKADDR CurHostAddr; /* address of current host */ 40871ff6caaSeric 409b31e7f2bSeric int 410655feedbSeric makeconnection(host, port, mci, usesecureport) 4117aa493c5Seric char *host; 412210215eaSeric u_short port; 413b31e7f2bSeric register MCI *mci; 414914346b1Seric bool usesecureport; 4157aa493c5Seric { 41604344589Sbloom register int i, s; 41704344589Sbloom register struct hostent *hp = (struct hostent *)NULL; 418e2f2f828Seric SOCKADDR addr; 4196286bb75Sbloom int sav_errno; 420e2f2f828Seric int addrlen; 421134746fbSeric #ifdef NAMED_BIND 422134746fbSeric extern int h_errno; 423134746fbSeric #endif 4247aa493c5Seric 4257aa493c5Seric /* 4267aa493c5Seric ** Set up the address for the mailer. 42771096d12Seric ** Accept "[a.b.c.d]" syntax for host name. 4287aa493c5Seric */ 4297aa493c5Seric 430134746fbSeric #ifdef NAMED_BIND 431794bdbb9Smiriam h_errno = 0; 432134746fbSeric #endif 433794bdbb9Smiriam errno = 0; 434794bdbb9Smiriam 43571096d12Seric if (host[0] == '[') 43671096d12Seric { 437a44d5a5eSeric long hid; 4386c2c3107Seric register char *p = strchr(host, ']'); 43971096d12Seric 440a44d5a5eSeric if (p != NULL) 44171096d12Seric { 442a44d5a5eSeric *p = '\0'; 443a44d5a5eSeric hid = inet_addr(&host[1]); 444a7e21fe6Seric if (hid == -1) 445a7e21fe6Seric { 446a7e21fe6Seric /* try it as a host name (avoid MX lookup) */ 447a7e21fe6Seric hp = gethostbyname(&host[1]); 448a7e21fe6Seric *p = ']'; 449a7e21fe6Seric goto gothostent; 450a7e21fe6Seric } 451a44d5a5eSeric *p = ']'; 45271096d12Seric } 453a7e21fe6Seric if (p == NULL) 45471096d12Seric { 45508b25121Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 45671096d12Seric return (EX_NOHOST); 45771096d12Seric } 45883c1f4bcSeric addr.sin.sin_family = AF_INET; 45983c1f4bcSeric addr.sin.sin_addr.s_addr = hid; 46071096d12Seric } 4611c71e510Seric else 4621c71e510Seric { 46304344589Sbloom hp = gethostbyname(host); 464a7e21fe6Seric gothostent: 465794bdbb9Smiriam if (hp == NULL) 466794bdbb9Smiriam { 467134746fbSeric #ifdef NAMED_BIND 468794bdbb9Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 46952308a50Seric return (EX_TEMPFAIL); 47082e5d8ddSeric 471134746fbSeric /* if name server is specified, assume temp fail */ 472134746fbSeric if (errno == ECONNREFUSED && UseNameServer) 473134746fbSeric return (EX_TEMPFAIL); 474134746fbSeric #endif 4757aa493c5Seric return (EX_NOHOST); 476794bdbb9Smiriam } 47783c1f4bcSeric addr.sa.sa_family = hp->h_addrtype; 47883c1f4bcSeric switch (hp->h_addrtype) 47983c1f4bcSeric { 48083c1f4bcSeric #ifdef NETINET 48183c1f4bcSeric case AF_INET: 482e2f2f828Seric bcopy(hp->h_addr, 48383c1f4bcSeric &addr.sin.sin_addr, 484e2f2f828Seric hp->h_length); 48583c1f4bcSeric break; 48683c1f4bcSeric #endif 48783c1f4bcSeric 48883c1f4bcSeric default: 489e2f2f828Seric bcopy(hp->h_addr, 49083c1f4bcSeric addr.sa.sa_data, 491e2f2f828Seric hp->h_length); 49283c1f4bcSeric break; 49383c1f4bcSeric } 49404344589Sbloom i = 1; 4951c71e510Seric } 4961c71e510Seric 4971c71e510Seric /* 4981c71e510Seric ** Determine the port number. 4991c71e510Seric */ 5001c71e510Seric 501fd7c0790Seric if (port != 0) 502e2f2f828Seric port = htons(port); 503fd7c0790Seric else 5041c71e510Seric { 5051c71e510Seric register struct servent *sp = getservbyname("smtp", "tcp"); 5061c71e510Seric 5071c71e510Seric if (sp == NULL) 5081c71e510Seric { 50908b25121Seric syserr("554 makeconnection: server \"smtp\" unknown"); 510845e533cSeric return (EX_OSERR); 5111c71e510Seric } 512e2f2f828Seric port = sp->s_port; 513e2f2f828Seric } 514e2f2f828Seric 51583c1f4bcSeric switch (addr.sa.sa_family) 516e2f2f828Seric { 517e2f2f828Seric case AF_INET: 51883c1f4bcSeric addr.sin.sin_port = port; 519e2f2f828Seric addrlen = sizeof (struct sockaddr_in); 520e2f2f828Seric break; 521e2f2f828Seric 522e2f2f828Seric #ifdef NETISO 523e2f2f828Seric case AF_ISO: 524e2f2f828Seric /* assume two byte transport selector */ 525e2f2f828Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 526e2f2f828Seric addrlen = sizeof (struct sockaddr_iso); 527e2f2f828Seric break; 528e2f2f828Seric #endif 529e2f2f828Seric 530e2f2f828Seric default: 53183c1f4bcSeric syserr("Can't connect to address family %d", addr.sa.sa_family); 532e2f2f828Seric return (EX_NOHOST); 5331c71e510Seric } 5347aa493c5Seric 5357aa493c5Seric /* 5367aa493c5Seric ** Try to actually open the connection. 5377aa493c5Seric */ 5387aa493c5Seric 539aea02ca1Seric for (;;) 540aea02ca1Seric { 54161e4310fSeric if (tTd(16, 1)) 542e2f2f828Seric printf("makeconnection (%s [%s])\n", 543e2f2f828Seric host, anynet_ntoa(&addr)); 5447aa493c5Seric 545226e3022Seric /* save for logging */ 546226e3022Seric CurHostAddr = addr; 547226e3022Seric 548914346b1Seric if (usesecureport) 549914346b1Seric { 550914346b1Seric int rport = IPPORT_RESERVED - 1; 551914346b1Seric 552914346b1Seric s = rresvport(&rport); 553914346b1Seric } 554914346b1Seric else 555914346b1Seric { 556af5e902cSeric s = socket(AF_INET, SOCK_STREAM, 0); 557914346b1Seric } 5587aa493c5Seric if (s < 0) 5597aa493c5Seric { 5606286bb75Sbloom sav_errno = errno; 561914346b1Seric syserr("makeconnection: no socket"); 5627aa493c5Seric goto failure; 5637aa493c5Seric } 5647aa493c5Seric 56561e4310fSeric if (tTd(16, 1)) 566b31e7f2bSeric printf("makeconnection: fd=%d\n", s); 5671b6e4a15Seric 5681b6e4a15Seric /* turn on network debugging? */ 569a2ef5fa4Seric if (tTd(16, 101)) 57052308a50Seric { 57152308a50Seric int on = 1; 572aea02ca1Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 573aea02ca1Seric (char *)&on, sizeof on); 57452308a50Seric } 57587d6e633Srick if (CurEnv->e_xfp != NULL) 576877a6142Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 5774bd6a662Seric errno = 0; /* for debugging */ 578e2f2f828Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 579aea02ca1Seric break; 580aea02ca1Seric 581aea02ca1Seric /* couldn't connect.... figure out why */ 5826286bb75Sbloom sav_errno = errno; 5836286bb75Sbloom (void) close(s); 58404344589Sbloom if (hp && hp->h_addr_list[i]) 58504344589Sbloom { 586e2f2f828Seric extern char *errstring(); 587e2f2f828Seric 588aea02ca1Seric if (tTd(16, 1)) 589e2f2f828Seric printf("Connect failed (%s); trying new address....\n", 590e2f2f828Seric errstring(sav_errno)); 59183c1f4bcSeric switch (addr.sa.sa_family) 59283c1f4bcSeric { 59383c1f4bcSeric #ifdef NETINET 59483c1f4bcSeric case AF_INET: 595e2f2f828Seric bcopy(hp->h_addr_list[i++], 59683c1f4bcSeric &addr.sin.sin_addr, 597e2f2f828Seric hp->h_length); 59883c1f4bcSeric break; 59983c1f4bcSeric #endif 60083c1f4bcSeric 60183c1f4bcSeric default: 602e2f2f828Seric bcopy(hp->h_addr_list[i++], 60383c1f4bcSeric addr.sa.sa_data, 604914346b1Seric hp->h_length); 60583c1f4bcSeric break; 60683c1f4bcSeric } 607aea02ca1Seric continue; 60804344589Sbloom } 60904344589Sbloom 6107aa493c5Seric /* failure, decide if temporary or not */ 6117aa493c5Seric failure: 612e2de2524Seric if (transienterror(sav_errno)) 613e2de2524Seric return EX_TEMPFAIL; 614e2de2524Seric else 61587d6e633Srick { 61687d6e633Srick extern char *errstring(); 61787d6e633Srick 61808b25121Seric message("%s", errstring(sav_errno)); 6197aa493c5Seric return (EX_UNAVAILABLE); 6207aa493c5Seric } 6217aa493c5Seric } 6227aa493c5Seric 6237aa493c5Seric /* connection ok, put it into canonical form */ 624655feedbSeric mci->mci_out = fdopen(s, "w"); 625655feedbSeric mci->mci_in = fdopen(dup(s), "r"); 6267aa493c5Seric 627dca8e1f7Seric return (EX_OK); 6287aa493c5Seric } 629444eaf03Seric /* 630444eaf03Seric ** MYHOSTNAME -- return the name of this host. 631444eaf03Seric ** 632444eaf03Seric ** Parameters: 633444eaf03Seric ** hostbuf -- a place to return the name of this host. 634897f1869Seric ** size -- the size of hostbuf. 635444eaf03Seric ** 636444eaf03Seric ** Returns: 637444eaf03Seric ** A list of aliases for this host. 638444eaf03Seric ** 639444eaf03Seric ** Side Effects: 64038ad259dSeric ** Sets the MyIpAddrs buffer to a list of my IP addresses. 641444eaf03Seric */ 642444eaf03Seric 64338ad259dSeric struct in_addr MyIpAddrs[MAXIPADDR + 1]; 64438ad259dSeric 645444eaf03Seric char ** 646897f1869Seric myhostname(hostbuf, size) 647444eaf03Seric char hostbuf[]; 648897f1869Seric int size; 649444eaf03Seric { 65038ad259dSeric register struct hostent *hp; 651444eaf03Seric extern struct hostent *gethostbyname(); 652444eaf03Seric 653af5e902cSeric if (gethostname(hostbuf, size) < 0) 654af5e902cSeric { 655af5e902cSeric (void) strcpy(hostbuf, "localhost"); 656af5e902cSeric } 657a44d5a5eSeric hp = gethostbyname(hostbuf); 658a44d5a5eSeric if (hp != NULL) 6597364df9fSeric { 66038ad259dSeric (void) strncpy(hostbuf, hp->h_name, size - 1); 66138ad259dSeric hostbuf[size - 1] = '\0'; 66238ad259dSeric 66338ad259dSeric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 66438ad259dSeric { 66538ad259dSeric register int i; 66638ad259dSeric 66738ad259dSeric for (i = 0; i < MAXIPADDR; i++) 66838ad259dSeric { 66938ad259dSeric if (hp->h_addr_list[i] == NULL) 67038ad259dSeric break; 67138ad259dSeric MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i]; 67238ad259dSeric } 67338ad259dSeric MyIpAddrs[i].s_addr = 0; 67438ad259dSeric } 67538ad259dSeric 676a44d5a5eSeric return (hp->h_aliases); 6777364df9fSeric } 678444eaf03Seric else 679444eaf03Seric return (NULL); 680444eaf03Seric } 681cb452edcSeric /* 682320e0d1cSeric ** GETREALHOSTNAME -- get the real host name asociated with a file descriptor 683320e0d1cSeric ** 684320e0d1cSeric ** Parameters: 685320e0d1cSeric ** fd -- the descriptor 686320e0d1cSeric ** 687320e0d1cSeric ** Returns: 688320e0d1cSeric ** The host name associated with this descriptor, if it can 689320e0d1cSeric ** be determined. 690320e0d1cSeric ** NULL otherwise. 691320e0d1cSeric ** 692320e0d1cSeric ** Side Effects: 693320e0d1cSeric ** none 694320e0d1cSeric */ 695320e0d1cSeric 696320e0d1cSeric char * 697320e0d1cSeric getrealhostname(fd) 698320e0d1cSeric int fd; 699320e0d1cSeric { 700320e0d1cSeric register struct hostent *hp; 701e4a929e2Seric SOCKADDR sa; 702e2f2f828Seric int salen; 703320e0d1cSeric char hbuf[MAXNAME]; 704320e0d1cSeric extern struct hostent *gethostbyaddr(); 705320e0d1cSeric 706e2f2f828Seric salen = sizeof sa; 70725f5a145Seric if (getsockname(fd, &sa.sa, &salen) < 0 || salen <= 0) 708320e0d1cSeric return NULL; 70925f5a145Seric hp = gethostbyaddr(sa.sa.sa_data, salen, sa.sa.sa_family); 710320e0d1cSeric if (hp != NULL) 711320e0d1cSeric (void) strcpy(hbuf, hp->h_name); 712320e0d1cSeric else 713e2f2f828Seric (void) sprintf(hbuf, "[%s]", anynet_ntoa(&sa)); 714320e0d1cSeric return hbuf; 715320e0d1cSeric } 716320e0d1cSeric /* 71715d084d5Seric ** MAPHOSTNAME -- turn a hostname into canonical form 71815d084d5Seric ** 71915d084d5Seric ** Parameters: 72005b57da8Seric ** map -- a pointer to this map (unused). 72115d084d5Seric ** hbuf -- a buffer containing a hostname. 72215d084d5Seric ** hbsize -- the size of hbuf. 723d798a1deSeric ** avp -- unused -- for compatibility with other mapping 724d798a1deSeric ** functions. 72515d084d5Seric ** 72615d084d5Seric ** Returns: 72715d084d5Seric ** The mapping, if found. 72815d084d5Seric ** NULL if no mapping found. 72915d084d5Seric ** 73015d084d5Seric ** Side Effects: 73115d084d5Seric ** Looks up the host specified in hbuf. If it is not 73215d084d5Seric ** the canonical name for that host, return the canonical 73315d084d5Seric ** name. 734f36ede03Sbostic */ 735cb452edcSeric 73615d084d5Seric char * 73705b57da8Seric maphostname(map, hbuf, hbsize, avp) 73805b57da8Seric MAP *map; 73999f7cf32Seric char *hbuf; 74099f7cf32Seric int hbsize; 74115d084d5Seric char **avp; 74299f7cf32Seric { 74399f7cf32Seric register struct hostent *hp; 7445f78836eSmiriam u_long in_addr; 74505b57da8Seric char *cp; 74638ad259dSeric int i; 747f36ede03Sbostic struct hostent *gethostbyaddr(); 7485f78836eSmiriam 74999b358daSeric /* allow room for null */ 75015d084d5Seric hbsize--; 75115d084d5Seric 752f36ede03Sbostic /* 753f36ede03Sbostic * If first character is a bracket, then it is an address 754f36ede03Sbostic * lookup. Address is copied into a temporary buffer to 755f36ede03Sbostic * strip the brackets and to preserve hbuf if address is 756f36ede03Sbostic * unknown. 757f36ede03Sbostic */ 75815d084d5Seric 759cb452edcSeric if (*hbuf != '[') 76015d084d5Seric { 761d798a1deSeric extern bool getcanonname(); 762d798a1deSeric 7638cb4653dSeric if (tTd(9, 1)) 7649040ec4fSeric printf("maphostname(%s, %d) => ", hbuf, hbsize); 765d5c60ac0Seric if (getcanonname(hbuf, hbsize)) 7669040ec4fSeric { 7679040ec4fSeric if (tTd(9, 1)) 7689040ec4fSeric printf("%s\n", hbuf); 76915d084d5Seric return hbuf; 7709040ec4fSeric } 77115d084d5Seric else 7729040ec4fSeric { 7739040ec4fSeric if (tTd(9, 1)) 7749040ec4fSeric printf("FAIL\n"); 77515d084d5Seric return NULL; 77615d084d5Seric } 7779040ec4fSeric } 77805b57da8Seric if ((cp = strchr(hbuf, ']')) == NULL) 77915d084d5Seric return (NULL); 78034e39927Sbostic *cp = '\0'; 78105b57da8Seric in_addr = inet_addr(&hbuf[1]); 78238ad259dSeric 78338ad259dSeric /* check to see if this is one of our addresses */ 78438ad259dSeric for (i = 0; MyIpAddrs[i].s_addr != 0; i++) 78538ad259dSeric { 78638ad259dSeric if (MyIpAddrs[i].s_addr == in_addr) 78738ad259dSeric { 78838ad259dSeric strncpy(hbuf, MyHostName, hbsize); 78938ad259dSeric hbuf[hbsize] = '\0'; 79038ad259dSeric return hbuf; 79138ad259dSeric } 79238ad259dSeric } 79338ad259dSeric 79438ad259dSeric /* nope -- ask the name server */ 79531601fa7Seric hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 7965f78836eSmiriam if (hp == NULL) 79715d084d5Seric return (NULL); 79815d084d5Seric 79938ad259dSeric /* found a match -- copy out */ 80005b57da8Seric if (strlen(hp->h_name) > hbsize) 80105b57da8Seric hp->h_name[hbsize] = '\0'; 802fefbbe29Seric (void) strcpy(hbuf, hp->h_name); 80315d084d5Seric return hbuf; 80499f7cf32Seric } 805e2f2f828Seric /* 806e2f2f828Seric ** ANYNET_NTOA -- convert a network address to printable form. 807e2f2f828Seric ** 808e2f2f828Seric ** Parameters: 809e2f2f828Seric ** sap -- a pointer to a sockaddr structure. 810e2f2f828Seric ** 811e2f2f828Seric ** Returns: 812e2f2f828Seric ** A printable version of that sockaddr. 813e2f2f828Seric */ 814e2f2f828Seric 815e2f2f828Seric char * 816e2f2f828Seric anynet_ntoa(sap) 817e2f2f828Seric register SOCKADDR *sap; 818e2f2f828Seric { 819e2f2f828Seric register char *bp; 820e2f2f828Seric register char *ap; 821e2f2f828Seric int l; 822e2f2f828Seric static char buf[80]; 823e2f2f828Seric 8248cb4653dSeric /* check for null/zero family */ 8258cb4653dSeric if (sap == NULL) 8268cb4653dSeric return "NULLADDR"; 8278cb4653dSeric if (sap->sa.sa_family == 0) 8288cb4653dSeric return "0"; 8298cb4653dSeric 83083c1f4bcSeric #ifdef NETINET 83183c1f4bcSeric if (sap->sa.sa_family == AF_INET) 832e2f2f828Seric { 833e2f2f828Seric extern char *inet_ntoa(); 834e2f2f828Seric 835e2f2f828Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 836e2f2f828Seric } 83783c1f4bcSeric #endif 838e2f2f828Seric 839e2f2f828Seric /* unknown family -- just dump bytes */ 84083c1f4bcSeric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 841e2f2f828Seric bp = &buf[strlen(buf)]; 84283c1f4bcSeric ap = sap->sa.sa_data; 84383c1f4bcSeric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 844e2f2f828Seric { 845e2f2f828Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 846e2f2f828Seric bp += 3; 847e2f2f828Seric } 848e2f2f828Seric *--bp = '\0'; 849e2f2f828Seric return buf; 850e2f2f828Seric } 851f36ede03Sbostic 8526c2c3107Seric # else /* DAEMON */ 85399f7cf32Seric /* code for systems without sophisticated networking */ 854444eaf03Seric 855444eaf03Seric /* 856444eaf03Seric ** MYHOSTNAME -- stub version for case of no daemon code. 85721e9914dSeric ** 85821e9914dSeric ** Can't convert to upper case here because might be a UUCP name. 859897f1869Seric ** 860897f1869Seric ** Mark, you can change this to be anything you want...... 861444eaf03Seric */ 862444eaf03Seric 863444eaf03Seric char ** 864897f1869Seric myhostname(hostbuf, size) 865444eaf03Seric char hostbuf[]; 866897f1869Seric int size; 867444eaf03Seric { 868444eaf03Seric register FILE *f; 869444eaf03Seric 870444eaf03Seric hostbuf[0] = '\0'; 871444eaf03Seric f = fopen("/usr/include/whoami", "r"); 872444eaf03Seric if (f != NULL) 873444eaf03Seric { 874897f1869Seric (void) fgets(hostbuf, size, f); 875444eaf03Seric fixcrlf(hostbuf, TRUE); 876444eaf03Seric (void) fclose(f); 877444eaf03Seric } 878444eaf03Seric return (NULL); 879444eaf03Seric } 88099f7cf32Seric /* 881320e0d1cSeric ** GETREALHOSTNAME -- get the real host name asociated with a file descriptor 882320e0d1cSeric ** 883320e0d1cSeric ** Parameters: 884320e0d1cSeric ** fd -- the descriptor 885320e0d1cSeric ** 886320e0d1cSeric ** Returns: 887320e0d1cSeric ** The host name associated with this descriptor, if it can 888320e0d1cSeric ** be determined. 889320e0d1cSeric ** NULL otherwise. 890320e0d1cSeric ** 891320e0d1cSeric ** Side Effects: 892320e0d1cSeric ** none 893320e0d1cSeric */ 894320e0d1cSeric 895320e0d1cSeric char * 896320e0d1cSeric getrealhostname(fd) 897320e0d1cSeric int fd; 898320e0d1cSeric { 899320e0d1cSeric return NULL; 900320e0d1cSeric } 901320e0d1cSeric /* 90299f7cf32Seric ** MAPHOSTNAME -- turn a hostname into canonical form 90399f7cf32Seric ** 90499f7cf32Seric ** Parameters: 90505b57da8Seric ** map -- a pointer to the database map. 90699f7cf32Seric ** hbuf -- a buffer containing a hostname. 90715d084d5Seric ** avp -- a pointer to a (cf file defined) argument vector. 90899f7cf32Seric ** 90999f7cf32Seric ** Returns: 91015d084d5Seric ** mapped host name 911cb452edcSeric ** FALSE otherwise. 91299f7cf32Seric ** 91399f7cf32Seric ** Side Effects: 91499f7cf32Seric ** Looks up the host specified in hbuf. If it is not 91599f7cf32Seric ** the canonical name for that host, replace it with 91699f7cf32Seric ** the canonical name. If the name is unknown, or it 91799f7cf32Seric ** is already the canonical name, leave it unchanged. 91899f7cf32Seric */ 91999f7cf32Seric 92099f7cf32Seric /*ARGSUSED*/ 92115d084d5Seric char * 92205b57da8Seric maphostname(map, hbuf, hbsize, avp) 92305b57da8Seric MAP *map; 92499f7cf32Seric char *hbuf; 92599f7cf32Seric int hbsize; 92615d084d5Seric char **avp; 92799f7cf32Seric { 92815d084d5Seric return NULL; 92999f7cf32Seric } 93099f7cf32Seric 9316c2c3107Seric #endif /* DAEMON */ 932