1939f5b94Sdist /* 2759969d8Seric * Copyright (c) 1983, 1995 Eric P. Allman 3c9d2fa25Sbostic * Copyright (c) 1988, 1993 4c9d2fa25Sbostic * The Regents of the University of California. All rights reserved. 5da1c6175Sbostic * 63bc94712Sbostic * %sccs.include.redist.c% 7939f5b94Sdist */ 8939f5b94Sdist 97aa493c5Seric #include <errno.h> 106c05f684Sbostic #include "sendmail.h" 117fa39d90Seric 12af5e902cSeric #ifndef lint 13da1c6175Sbostic #ifdef DAEMON 14*8868a898Seric static char sccsid[] = "@(#)daemon.c 8.97 (Berkeley) 06/10/95 (with daemon mode)"; 15d0a9e852Seric #else 16*8868a898Seric static char sccsid[] = "@(#)daemon.c 8.97 (Berkeley) 06/10/95 (without daemon mode)"; 17da1c6175Sbostic #endif 18da1c6175Sbostic #endif /* not lint */ 19da1c6175Sbostic 20da1c6175Sbostic #ifdef DAEMON 21d0a9e852Seric 22d8d0a4aeSeric # include <arpa/inet.h> 23d0a9e852Seric 249d4a8008Seric #if NAMED_BIND 253490b9dfSeric # include <resolv.h> 263490b9dfSeric #endif 273490b9dfSeric 2811af795cSeric #if IP_SRCROUTE 2911af795cSeric # include <netinet/in_systm.h> 3011af795cSeric # include <netinet/ip.h> 3111af795cSeric # include <netinet/ip_var.h> 3211af795cSeric #endif 3311af795cSeric 347fa39d90Seric /* 357fa39d90Seric ** DAEMON.C -- routines to use when running as a daemon. 3647b12ae1Seric ** 3747b12ae1Seric ** This entire file is highly dependent on the 4.2 BSD 3847b12ae1Seric ** interprocess communication primitives. No attempt has 3947b12ae1Seric ** been made to make this file portable to Version 7, 4047b12ae1Seric ** Version 6, MPX files, etc. If you should try such a 4147b12ae1Seric ** thing yourself, I recommend chucking the entire file 4247b12ae1Seric ** and starting from scratch. Basic semantics are: 4347b12ae1Seric ** 4447b12ae1Seric ** getrequests() 4547b12ae1Seric ** Opens a port and initiates a connection. 4647b12ae1Seric ** Returns in a child. Must set InChannel and 4747b12ae1Seric ** OutChannel appropriately. 48b7d7afcbSeric ** clrdaemon() 49b7d7afcbSeric ** Close any open files associated with getting 50b7d7afcbSeric ** the connection; this is used when running the queue, 51b7d7afcbSeric ** etc., to avoid having extra file descriptors during 52b7d7afcbSeric ** the queue run and to avoid confusing the network 53b7d7afcbSeric ** code (if it cares). 54914346b1Seric ** makeconnection(host, port, outfile, infile, usesecureport) 5547b12ae1Seric ** Make a connection to the named host on the given 5647b12ae1Seric ** port. Set *outfile and *infile to the files 5747b12ae1Seric ** appropriate for communication. Returns zero on 5847b12ae1Seric ** success, else an exit status describing the 5947b12ae1Seric ** error. 6008de856eSeric ** host_map_lookup(map, hbuf, avp, pstat) 6105b57da8Seric ** Convert the entry in hbuf into a canonical form. 627fa39d90Seric */ 637fa39d90Seric /* 647fa39d90Seric ** GETREQUESTS -- open mail IPC port and get requests. 657fa39d90Seric ** 667fa39d90Seric ** Parameters: 677fa39d90Seric ** none. 687fa39d90Seric ** 697fa39d90Seric ** Returns: 707fa39d90Seric ** none. 717fa39d90Seric ** 727fa39d90Seric ** Side Effects: 737fa39d90Seric ** Waits until some interesting activity occurs. When 747fa39d90Seric ** it does, a child is created to process it, and the 757fa39d90Seric ** parent waits for completion. Return from this 76147303b1Seric ** routine is always in the child. The file pointers 77147303b1Seric ** "InChannel" and "OutChannel" should be set to point 78147303b1Seric ** to the communication channel. 797fa39d90Seric */ 807fa39d90Seric 81b7d7afcbSeric int DaemonSocket = -1; /* fd describing socket */ 82bfb80540Seric SOCKADDR DaemonAddr; /* socket for incoming */ 83bfc1eaf8Seric int ListenQueueSize = 10; /* size of listen queue */ 84b35447dbSeric int TcpRcvBufferSize = 0; /* size of TCP receive buffer */ 85b35447dbSeric int TcpSndBufferSize = 0; /* size of TCP send buffer */ 861c71e510Seric 878b212fe0Seric void 887fa39d90Seric getrequests() 897fa39d90Seric { 901c71e510Seric int t; 9115d084d5Seric bool refusingconnections = TRUE; 920aae1086Seric FILE *pidf; 93dadb8687Seric int socksize; 94dfe840b2Seric #ifdef XDEBUG 95dfe840b2Seric bool j_has_dot; 96dfe840b2Seric #endif 979b100374Sbostic extern void reapchild(); 98eb889047Seric 99a8268164Seric /* 1001c71e510Seric ** Set up the address for the mailer. 101eb889047Seric */ 102eb889047Seric 103bfb80540Seric if (DaemonAddr.sin.sin_family == 0) 104bfb80540Seric DaemonAddr.sin.sin_family = AF_INET; 105bfb80540Seric if (DaemonAddr.sin.sin_addr.s_addr == 0) 106bfb80540Seric DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; 107bfb80540Seric if (DaemonAddr.sin.sin_port == 0) 108bfb80540Seric { 109e5311662Seric register struct servent *sp; 110e5311662Seric 1111c71e510Seric sp = getservbyname("smtp", "tcp"); 1121c71e510Seric if (sp == NULL) 113d0a9e852Seric { 114ad977999Seric syserr("554 service \"smtp\" unknown"); 115e5311662Seric DaemonAddr.sin.sin_port = htons(25); 1161c71e510Seric } 117e5311662Seric else 118bfb80540Seric DaemonAddr.sin.sin_port = sp->s_port; 119bfb80540Seric } 1201c71e510Seric 1211c71e510Seric /* 1221c71e510Seric ** Try to actually open the connection. 1231c71e510Seric */ 1241c71e510Seric 1251c71e510Seric if (tTd(15, 1)) 126bfb80540Seric printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); 1271c71e510Seric 1281c71e510Seric /* get a socket for the SMTP connection */ 12988ea5609Seric socksize = opendaemonsocket(TRUE); 1301c71e510Seric 1312b9178d3Seric (void) setsignal(SIGCHLD, reapchild); 13252308a50Seric 1330aae1086Seric /* write the pid to the log file for posterity */ 1340aae1086Seric pidf = fopen(PidFile, "w"); 1350aae1086Seric if (pidf != NULL) 1360aae1086Seric { 13737950f67Seric extern char *CommandLineArgs; 13837950f67Seric 13937950f67Seric /* write the process id on line 1 */ 1400aae1086Seric fprintf(pidf, "%d\n", getpid()); 14137950f67Seric 14237950f67Seric /* line 2 contains all command line flags */ 14337950f67Seric fprintf(pidf, "%s\n", CommandLineArgs); 14437950f67Seric 14537950f67Seric /* flush and close */ 1460aae1086Seric fclose(pidf); 1470aae1086Seric } 1480aae1086Seric 149dfe840b2Seric #ifdef XDEBUG 150dfe840b2Seric { 15135852b23Seric char jbuf[MAXHOSTNAMELEN]; 152dfe840b2Seric 1538b212fe0Seric expand("\201j", jbuf, sizeof jbuf, CurEnv); 15435852b23Seric j_has_dot = strchr(jbuf, '.') != NULL; 155dfe840b2Seric } 156dfe840b2Seric #endif 1570aae1086Seric 1581c71e510Seric if (tTd(15, 1)) 159b7d7afcbSeric printf("getrequests: %d\n", DaemonSocket); 1601c71e510Seric 1611c71e510Seric for (;;) 1621c71e510Seric { 1633a099713Seric register int pid; 164a44d5a5eSeric auto int lotherend; 16515d084d5Seric extern bool refuseconnections(); 1668b212fe0Seric extern int getla(); 1673a099713Seric 1683a099713Seric /* see if we are rejecting connections */ 16915d084d5Seric CurrentLA = getla(); 17015d084d5Seric if (refuseconnections()) 1716775ec03Sbostic { 1720084e6f6Seric if (DaemonSocket >= 0) 17315d084d5Seric { 1740084e6f6Seric /* close socket so peer will fail quickly */ 1750084e6f6Seric (void) close(DaemonSocket); 1760084e6f6Seric DaemonSocket = -1; 17715d084d5Seric } 1780084e6f6Seric refusingconnections = TRUE; 17971e5e267Seric setproctitle("rejecting connections: load average: %d", 18071e5e267Seric CurrentLA); 1810084e6f6Seric sleep(15); 18215d084d5Seric continue; 18315d084d5Seric } 18415d084d5Seric 1858b212fe0Seric /* arrange to (re)open the socket if necessary */ 18615d084d5Seric if (refusingconnections) 18715d084d5Seric { 1888a0cb579Seric (void) opendaemonsocket(FALSE); 18915d084d5Seric refusingconnections = FALSE; 1906775ec03Sbostic } 191a44d5a5eSeric 192dfe840b2Seric #ifdef XDEBUG 193dfe840b2Seric /* check for disaster */ 194dfe840b2Seric { 19535852b23Seric char jbuf[MAXHOSTNAMELEN]; 196dfe840b2Seric 1978b212fe0Seric expand("\201j", jbuf, sizeof jbuf, CurEnv); 1988b212fe0Seric if (!wordinclass(jbuf, 'w')) 199dfe840b2Seric { 200dfe840b2Seric dumpstate("daemon lost $j"); 201dfe840b2Seric syslog(LOG_ALERT, "daemon process doesn't have $j in $=w; see syslog"); 202dfe840b2Seric abort(); 203dfe840b2Seric } 20435852b23Seric else if (j_has_dot && strchr(jbuf, '.') == NULL) 205dfe840b2Seric { 206dfe840b2Seric dumpstate("daemon $j lost dot"); 207dfe840b2Seric syslog(LOG_ALERT, "daemon process $j lost dot; see syslog"); 208dfe840b2Seric abort(); 209dfe840b2Seric } 210dfe840b2Seric } 211dfe840b2Seric #endif 212dfe840b2Seric 2131c71e510Seric /* wait for a connection */ 214b28779c8Seric setproctitle("accepting connections"); 2151c71e510Seric do 2161c71e510Seric { 2171c71e510Seric errno = 0; 218dadb8687Seric lotherend = socksize; 2199b100374Sbostic t = accept(DaemonSocket, 2209b100374Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 2211c71e510Seric } while (t < 0 && errno == EINTR); 2221c71e510Seric if (t < 0) 2231c71e510Seric { 2241c71e510Seric syserr("getrequests: accept"); 2258b212fe0Seric 2268b212fe0Seric /* arrange to re-open the socket next time around */ 2278b212fe0Seric (void) close(DaemonSocket); 2288b212fe0Seric DaemonSocket = -1; 2291c71e510Seric sleep(5); 2301c71e510Seric continue; 2311c71e510Seric } 232d0a9e852Seric 233d0a9e852Seric /* 234d0a9e852Seric ** Create a subprocess to process the mail. 235d0a9e852Seric */ 236d0a9e852Seric 23761e4310fSeric if (tTd(15, 2)) 2381c71e510Seric printf("getrequests: forking (fd = %d)\n", t); 239eb889047Seric 240a8268164Seric pid = fork(); 241a8268164Seric if (pid < 0) 242a8268164Seric { 243a8268164Seric syserr("daemon: cannot fork"); 244a8268164Seric sleep(10); 2451c71e510Seric (void) close(t); 246a8268164Seric continue; 247a8268164Seric } 248a8268164Seric 249a8268164Seric if (pid == 0) 250a8268164Seric { 251da662164Seric char *p; 2529f8b0eadSeric extern char *hostnamebyanyaddr(); 2538b212fe0Seric extern void intsig(); 254a44d5a5eSeric 255a8268164Seric /* 256a8268164Seric ** CHILD -- return to caller. 257a44d5a5eSeric ** Collect verified idea of sending host. 258a8268164Seric ** Verify calling user id if possible here. 259a8268164Seric */ 260a8268164Seric 2612b9178d3Seric (void) setsignal(SIGCHLD, SIG_DFL); 2628b212fe0Seric (void) setsignal(SIGHUP, intsig); 2638b212fe0Seric (void) close(DaemonSocket); 2649f9b003eSeric DisConnected = FALSE; 265779ac194Seric 2664dd09a90Seric setproctitle("startup with %s", 2674dd09a90Seric anynet_ntoa(&RealHostAddr)); 2684dd09a90Seric 269a44d5a5eSeric /* determine host name */ 270da662164Seric p = hostnamebyanyaddr(&RealHostAddr); 27137b4af40Seric if (strlen(p) > MAXNAME) 27237b4af40Seric p[MAXNAME] = '\0'; 273da662164Seric RealHostName = newstr(p); 2744dd09a90Seric setproctitle("startup with %s", p); 27529dcf4baSeric 276335eae58Seric if ((InChannel = fdopen(t, "r")) == NULL || 277335eae58Seric (t = dup(t)) < 0 || 278335eae58Seric (OutChannel = fdopen(t, "w")) == NULL) 279335eae58Seric { 280335eae58Seric syserr("cannot open SMTP server channel, fd=%d", t); 281335eae58Seric exit(0); 282335eae58Seric } 283244b09d1Seric 28429dcf4baSeric /* should we check for illegal connection here? XXX */ 285e17a3a5aSeric #ifdef XLA 286e17a3a5aSeric if (!xla_host_ok(RealHostName)) 287e17a3a5aSeric { 288244b09d1Seric message("421 Too many SMTP sessions for this host"); 289e17a3a5aSeric exit(0); 290e17a3a5aSeric } 291e17a3a5aSeric #endif 292a44d5a5eSeric 29361e4310fSeric if (tTd(15, 2)) 294d0a9e852Seric printf("getreq: returning\n"); 295a8268164Seric return; 296a8268164Seric } 297a8268164Seric 2983c154354Seric /* close the port so that others will hang (for a while) */ 2993c154354Seric (void) close(t); 3008e3e4b17Seric } 3013c154354Seric /*NOTREACHED*/ 3023c154354Seric } 3038e3e4b17Seric /* 3040084e6f6Seric ** OPENDAEMONSOCKET -- open the SMTP socket 3050084e6f6Seric ** 3060084e6f6Seric ** Deals with setting all appropriate options. DaemonAddr must 3070084e6f6Seric ** be set up in advance. 3080084e6f6Seric ** 3090084e6f6Seric ** Parameters: 31088ea5609Seric ** firsttime -- set if this is the initial open. 3110084e6f6Seric ** 3120084e6f6Seric ** Returns: 3130084e6f6Seric ** Size in bytes of the daemon socket addr. 3140084e6f6Seric ** 3150084e6f6Seric ** Side Effects: 3160084e6f6Seric ** Leaves DaemonSocket set to the open socket. 3170084e6f6Seric ** Exits if the socket cannot be created. 3180084e6f6Seric */ 3190084e6f6Seric 3206173568dSeric #define MAXOPENTRIES 10 /* maximum number of tries to open connection */ 3216173568dSeric 3220084e6f6Seric int 32388ea5609Seric opendaemonsocket(firsttime) 32488ea5609Seric bool firsttime; 3250084e6f6Seric { 3260084e6f6Seric int on = 1; 3278b212fe0Seric int socksize = 0; 3286173568dSeric int ntries = 0; 3296173568dSeric int saveerrno; 3300084e6f6Seric 3310084e6f6Seric if (tTd(15, 2)) 3320084e6f6Seric printf("opendaemonsocket()\n"); 3330084e6f6Seric 3346173568dSeric do 3356173568dSeric { 336254b93c3Seric if (ntries > 0) 337254b93c3Seric sleep(5); 33888ea5609Seric if (firsttime || DaemonSocket < 0) 33988ea5609Seric { 3400084e6f6Seric DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0); 3410084e6f6Seric if (DaemonSocket < 0) 3420084e6f6Seric { 3430084e6f6Seric /* probably another daemon already */ 3446173568dSeric saveerrno = errno; 3450084e6f6Seric syserr("opendaemonsocket: can't create server SMTP socket"); 3460084e6f6Seric severe: 3470084e6f6Seric # ifdef LOG 3480084e6f6Seric if (LogLevel > 0) 3490084e6f6Seric syslog(LOG_ALERT, "problem creating SMTP socket"); 3500084e6f6Seric # endif /* LOG */ 3516173568dSeric DaemonSocket = -1; 3526173568dSeric continue; 3530084e6f6Seric } 3540084e6f6Seric 3550084e6f6Seric /* turn on network debugging? */ 3560084e6f6Seric if (tTd(15, 101)) 3576173568dSeric (void) setsockopt(DaemonSocket, SOL_SOCKET, 3586173568dSeric SO_DEBUG, (char *)&on, 3596173568dSeric sizeof on); 3600084e6f6Seric 3616173568dSeric (void) setsockopt(DaemonSocket, SOL_SOCKET, 3626173568dSeric SO_REUSEADDR, (char *)&on, sizeof on); 3636173568dSeric (void) setsockopt(DaemonSocket, SOL_SOCKET, 3646173568dSeric SO_KEEPALIVE, (char *)&on, sizeof on); 3650084e6f6Seric 3660084e6f6Seric #ifdef SO_RCVBUF 3670084e6f6Seric if (TcpRcvBufferSize > 0) 3680084e6f6Seric { 3696173568dSeric if (setsockopt(DaemonSocket, SOL_SOCKET, 3706173568dSeric SO_RCVBUF, 3710084e6f6Seric (char *) &TcpRcvBufferSize, 3720084e6f6Seric sizeof(TcpRcvBufferSize)) < 0) 3730084e6f6Seric syserr("getrequests: setsockopt(SO_RCVBUF)"); 3740084e6f6Seric } 3750084e6f6Seric #endif 3760084e6f6Seric 3770084e6f6Seric switch (DaemonAddr.sa.sa_family) 3780084e6f6Seric { 3790084e6f6Seric # ifdef NETINET 3800084e6f6Seric case AF_INET: 3810084e6f6Seric socksize = sizeof DaemonAddr.sin; 3820084e6f6Seric break; 3830084e6f6Seric # endif 3840084e6f6Seric 3850084e6f6Seric # ifdef NETISO 3860084e6f6Seric case AF_ISO: 3870084e6f6Seric socksize = sizeof DaemonAddr.siso; 3880084e6f6Seric break; 3890084e6f6Seric # endif 3900084e6f6Seric 3910084e6f6Seric default: 3920084e6f6Seric socksize = sizeof DaemonAddr; 3930084e6f6Seric break; 3940084e6f6Seric } 3950084e6f6Seric 3960084e6f6Seric if (bind(DaemonSocket, &DaemonAddr.sa, socksize) < 0) 3970084e6f6Seric { 3986173568dSeric saveerrno = errno; 3990084e6f6Seric syserr("getrequests: cannot bind"); 4000084e6f6Seric (void) close(DaemonSocket); 4010084e6f6Seric goto severe; 4020084e6f6Seric } 40388ea5609Seric } 40488ea5609Seric if (!firsttime && listen(DaemonSocket, ListenQueueSize) < 0) 4050084e6f6Seric { 4066173568dSeric saveerrno = errno; 4070084e6f6Seric syserr("getrequests: cannot listen"); 4080084e6f6Seric (void) close(DaemonSocket); 4090084e6f6Seric goto severe; 4100084e6f6Seric } 4110084e6f6Seric return socksize; 4126173568dSeric } while (ntries++ < MAXOPENTRIES && transienterror(saveerrno)); 4138b212fe0Seric syserr("!opendaemonsocket: server SMTP socket wedged: exiting"); 4146173568dSeric finis(); 4150084e6f6Seric } 4160084e6f6Seric /* 417b7d7afcbSeric ** CLRDAEMON -- reset the daemon connection 418b7d7afcbSeric ** 419b7d7afcbSeric ** Parameters: 420b7d7afcbSeric ** none. 421b7d7afcbSeric ** 422b7d7afcbSeric ** Returns: 423b7d7afcbSeric ** none. 424b7d7afcbSeric ** 425b7d7afcbSeric ** Side Effects: 426b7d7afcbSeric ** releases any resources used by the passive daemon. 427b7d7afcbSeric */ 428b7d7afcbSeric 4298b212fe0Seric void 430b7d7afcbSeric clrdaemon() 431b7d7afcbSeric { 432b7d7afcbSeric if (DaemonSocket >= 0) 433b7d7afcbSeric (void) close(DaemonSocket); 434b7d7afcbSeric DaemonSocket = -1; 435b7d7afcbSeric } 436b7d7afcbSeric /* 437bfb80540Seric ** SETDAEMONOPTIONS -- set options for running the daemon 438bfb80540Seric ** 439bfb80540Seric ** Parameters: 440bfb80540Seric ** p -- the options line. 441bfb80540Seric ** 442bfb80540Seric ** Returns: 443bfb80540Seric ** none. 444bfb80540Seric */ 445bfb80540Seric 4468b212fe0Seric void 447bfb80540Seric setdaemonoptions(p) 448bfb80540Seric register char *p; 449bfb80540Seric { 450850144caSeric if (DaemonAddr.sa.sa_family == AF_UNSPEC) 451850144caSeric DaemonAddr.sa.sa_family = AF_INET; 452850144caSeric 453bfb80540Seric while (p != NULL) 454bfb80540Seric { 455bfb80540Seric register char *f; 456bfb80540Seric register char *v; 457bfb80540Seric 458bfb80540Seric while (isascii(*p) && isspace(*p)) 459bfb80540Seric p++; 460bfb80540Seric if (*p == '\0') 461bfb80540Seric break; 462bfb80540Seric f = p; 463bfb80540Seric p = strchr(p, ','); 464bfb80540Seric if (p != NULL) 465bfb80540Seric *p++ = '\0'; 466bfb80540Seric v = strchr(f, '='); 467bfb80540Seric if (v == NULL) 468bfb80540Seric continue; 469bfb80540Seric while (isascii(*++v) && isspace(*v)) 470bfb80540Seric continue; 471e7988623Seric if (isascii(*f) && isupper(*f)) 472e7988623Seric *f = tolower(*f); 473bfb80540Seric 474bfb80540Seric switch (*f) 475bfb80540Seric { 476850144caSeric case 'F': /* address family */ 477850144caSeric if (isascii(*v) && isdigit(*v)) 478850144caSeric DaemonAddr.sa.sa_family = atoi(v); 479850144caSeric #ifdef NETINET 480850144caSeric else if (strcasecmp(v, "inet") == 0) 481850144caSeric DaemonAddr.sa.sa_family = AF_INET; 482850144caSeric #endif 483850144caSeric #ifdef NETISO 484850144caSeric else if (strcasecmp(v, "iso") == 0) 485850144caSeric DaemonAddr.sa.sa_family = AF_ISO; 486850144caSeric #endif 487850144caSeric #ifdef NETNS 488850144caSeric else if (strcasecmp(v, "ns") == 0) 489850144caSeric DaemonAddr.sa.sa_family = AF_NS; 490850144caSeric #endif 491850144caSeric #ifdef NETX25 492850144caSeric else if (strcasecmp(v, "x.25") == 0) 493850144caSeric DaemonAddr.sa.sa_family = AF_CCITT; 494850144caSeric #endif 495850144caSeric else 496850144caSeric syserr("554 Unknown address family %s in Family=option", v); 497850144caSeric break; 498850144caSeric 499850144caSeric case 'A': /* address */ 500850144caSeric switch (DaemonAddr.sa.sa_family) 501850144caSeric { 502850144caSeric #ifdef NETINET 503850144caSeric case AF_INET: 504850144caSeric if (isascii(*v) && isdigit(*v)) 5058b212fe0Seric DaemonAddr.sin.sin_addr.s_addr = htonl(inet_network(v)); 506850144caSeric else 507850144caSeric { 508850144caSeric register struct netent *np; 509850144caSeric 510850144caSeric np = getnetbyname(v); 511850144caSeric if (np == NULL) 512850144caSeric syserr("554 network \"%s\" unknown", v); 513850144caSeric else 514850144caSeric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 515850144caSeric } 516850144caSeric break; 517850144caSeric #endif 518850144caSeric 519850144caSeric default: 520850144caSeric syserr("554 Address= option unsupported for family %d", 521850144caSeric DaemonAddr.sa.sa_family); 522850144caSeric break; 523850144caSeric } 524850144caSeric break; 525850144caSeric 526bfb80540Seric case 'P': /* port */ 527850144caSeric switch (DaemonAddr.sa.sa_family) 528850144caSeric { 529850144caSeric short port; 530850144caSeric 531850144caSeric #ifdef NETINET 532850144caSeric case AF_INET: 533bfb80540Seric if (isascii(*v) && isdigit(*v)) 53476b70c58Seric DaemonAddr.sin.sin_port = htons(atoi(v)); 535bfb80540Seric else 536bfb80540Seric { 537bfb80540Seric register struct servent *sp; 538bfb80540Seric 539bfb80540Seric sp = getservbyname(v, "tcp"); 540bfb80540Seric if (sp == NULL) 541ad977999Seric syserr("554 service \"%s\" unknown", v); 542bfb80540Seric else 543bfb80540Seric DaemonAddr.sin.sin_port = sp->s_port; 544bfb80540Seric } 545bfb80540Seric break; 546850144caSeric #endif 547bfb80540Seric 548850144caSeric #ifdef NETISO 549850144caSeric case AF_ISO: 550850144caSeric /* assume two byte transport selector */ 551bfb80540Seric if (isascii(*v) && isdigit(*v)) 55276b70c58Seric port = htons(atoi(v)); 553bfb80540Seric else 554bfb80540Seric { 555850144caSeric register struct servent *sp; 556bfb80540Seric 557850144caSeric sp = getservbyname(v, "tcp"); 558850144caSeric if (sp == NULL) 559ad977999Seric syserr("554 service \"%s\" unknown", v); 560bfb80540Seric else 561850144caSeric port = sp->s_port; 562850144caSeric } 563850144caSeric bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 564850144caSeric break; 565850144caSeric #endif 566850144caSeric 567850144caSeric default: 568850144caSeric syserr("554 Port= option unsupported for family %d", 569850144caSeric DaemonAddr.sa.sa_family); 570850144caSeric break; 571bfb80540Seric } 572bfb80540Seric break; 573bfc1eaf8Seric 574bfc1eaf8Seric case 'L': /* listen queue size */ 575bfc1eaf8Seric ListenQueueSize = atoi(v); 576bfc1eaf8Seric break; 577b35447dbSeric 578b35447dbSeric case 'S': /* send buffer size */ 579b35447dbSeric TcpSndBufferSize = atoi(v); 580b35447dbSeric break; 581b35447dbSeric 582b35447dbSeric case 'R': /* receive buffer size */ 583b35447dbSeric TcpRcvBufferSize = atoi(v); 584b35447dbSeric break; 585e7988623Seric 586e7988623Seric default: 587e7988623Seric syserr("554 DaemonPortOptions parameter \"%s\" unknown", f); 588bfb80540Seric } 589bfb80540Seric } 590bfb80540Seric } 591bfb80540Seric /* 5927aa493c5Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 5937aa493c5Seric ** 5947aa493c5Seric ** Parameters: 5957aa493c5Seric ** host -- the name of the host. 59648ff0a9dSeric ** port -- the port number to connect to. 597655feedbSeric ** mci -- a pointer to the mail connection information 598655feedbSeric ** structure to be filled in. 599914346b1Seric ** usesecureport -- if set, use a low numbered (reserved) 600914346b1Seric ** port to provide some rudimentary authentication. 6017aa493c5Seric ** 6027aa493c5Seric ** Returns: 6037aa493c5Seric ** An exit code telling whether the connection could be 6047aa493c5Seric ** made and if not why not. 6057aa493c5Seric ** 6067aa493c5Seric ** Side Effects: 6077aa493c5Seric ** none. 6087aa493c5Seric */ 6097aa493c5Seric 610e2f2f828Seric SOCKADDR CurHostAddr; /* address of current host */ 61171ff6caaSeric 612b31e7f2bSeric int 613655feedbSeric makeconnection(host, port, mci, usesecureport) 6147aa493c5Seric char *host; 615210215eaSeric u_short port; 616b31e7f2bSeric register MCI *mci; 617914346b1Seric bool usesecureport; 6187aa493c5Seric { 6198b212fe0Seric register int i = 0; 6208b212fe0Seric register int s; 62104344589Sbloom register struct hostent *hp = (struct hostent *)NULL; 622e2f2f828Seric SOCKADDR addr; 6236286bb75Sbloom int sav_errno; 624e2f2f828Seric int addrlen; 6258b212fe0Seric bool firstconnect; 6269d4a8008Seric #if NAMED_BIND 627134746fbSeric extern int h_errno; 628134746fbSeric #endif 6297aa493c5Seric 6307aa493c5Seric /* 6317aa493c5Seric ** Set up the address for the mailer. 63271096d12Seric ** Accept "[a.b.c.d]" syntax for host name. 6337aa493c5Seric */ 6347aa493c5Seric 6359d4a8008Seric #if NAMED_BIND 636794bdbb9Smiriam h_errno = 0; 637134746fbSeric #endif 638794bdbb9Smiriam errno = 0; 639967778e2Seric bzero(&CurHostAddr, sizeof CurHostAddr); 640c931b82bSeric SmtpPhase = mci->mci_phase = "initial connection"; 641d945ebe8Seric CurHostName = host; 642794bdbb9Smiriam 64371096d12Seric if (host[0] == '[') 64471096d12Seric { 645a44d5a5eSeric long hid; 6466c2c3107Seric register char *p = strchr(host, ']'); 64771096d12Seric 648a44d5a5eSeric if (p != NULL) 64971096d12Seric { 650a44d5a5eSeric *p = '\0'; 6514d9c42c2Seric #ifdef NETINET 652a44d5a5eSeric hid = inet_addr(&host[1]); 653a7e21fe6Seric if (hid == -1) 6544d9c42c2Seric #endif 655a7e21fe6Seric { 656a7e21fe6Seric /* try it as a host name (avoid MX lookup) */ 6578b212fe0Seric hp = sm_gethostbyname(&host[1]); 658d8984352Seric if (hp == NULL && p[-1] == '.') 659d8984352Seric { 6608b212fe0Seric #if NAMED_BIND 6618b212fe0Seric int oldopts = _res.options; 6628b212fe0Seric 6638b212fe0Seric _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 6648b212fe0Seric #endif 665d8984352Seric p[-1] = '\0'; 6668b212fe0Seric hp = sm_gethostbyname(&host[1]); 667d8984352Seric p[-1] = '.'; 6688b212fe0Seric #if NAMED_BIND 6698b212fe0Seric _res.options = oldopts; 6708b212fe0Seric #endif 671d8984352Seric } 672a7e21fe6Seric *p = ']'; 673a7e21fe6Seric goto gothostent; 674a7e21fe6Seric } 675a44d5a5eSeric *p = ']'; 67671096d12Seric } 677a7e21fe6Seric if (p == NULL) 67871096d12Seric { 67908b25121Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 6805b068d51Seric mci->mci_status = "5.1.2"; 68171096d12Seric return (EX_NOHOST); 68271096d12Seric } 6834d9c42c2Seric #ifdef NETINET 6844d9c42c2Seric addr.sin.sin_family = AF_INET; /*XXX*/ 68583c1f4bcSeric addr.sin.sin_addr.s_addr = hid; 6864d9c42c2Seric #endif 68771096d12Seric } 6881c71e510Seric else 6891c71e510Seric { 690d8984352Seric register char *p = &host[strlen(host) - 1]; 691d8984352Seric 6928b212fe0Seric hp = sm_gethostbyname(host); 693d8984352Seric if (hp == NULL && *p == '.') 694d8984352Seric { 6958b212fe0Seric #if NAMED_BIND 6968b212fe0Seric int oldopts = _res.options; 6978b212fe0Seric 6988b212fe0Seric _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 6998b212fe0Seric #endif 700d8984352Seric *p = '\0'; 7018b212fe0Seric hp = sm_gethostbyname(host); 702d8984352Seric *p = '.'; 7038b212fe0Seric #if NAMED_BIND 7048b212fe0Seric _res.options = oldopts; 7058b212fe0Seric #endif 706d8984352Seric } 707a7e21fe6Seric gothostent: 708794bdbb9Smiriam if (hp == NULL) 709794bdbb9Smiriam { 7109d4a8008Seric #if NAMED_BIND 7118b212fe0Seric /* check for name server timeouts */ 7128b212fe0Seric if (errno == ETIMEDOUT || h_errno == TRY_AGAIN || 7138b212fe0Seric (errno == ECONNREFUSED && UseNameServer)) 7148b212fe0Seric { 7158b212fe0Seric mci->mci_status = "4.4.3"; 71652308a50Seric return (EX_TEMPFAIL); 7178b212fe0Seric } 718134746fbSeric #endif 7197aa493c5Seric return (EX_NOHOST); 720794bdbb9Smiriam } 72183c1f4bcSeric addr.sa.sa_family = hp->h_addrtype; 72283c1f4bcSeric switch (hp->h_addrtype) 72383c1f4bcSeric { 72483c1f4bcSeric #ifdef NETINET 72583c1f4bcSeric case AF_INET: 726e2f2f828Seric bcopy(hp->h_addr, 72783c1f4bcSeric &addr.sin.sin_addr, 7288b212fe0Seric INADDRSZ); 72983c1f4bcSeric break; 73083c1f4bcSeric #endif 73183c1f4bcSeric 73283c1f4bcSeric default: 733e2f2f828Seric bcopy(hp->h_addr, 73483c1f4bcSeric addr.sa.sa_data, 735e2f2f828Seric hp->h_length); 73683c1f4bcSeric break; 73783c1f4bcSeric } 73804344589Sbloom i = 1; 7391c71e510Seric } 7401c71e510Seric 7411c71e510Seric /* 7421c71e510Seric ** Determine the port number. 7431c71e510Seric */ 7441c71e510Seric 745fd7c0790Seric if (port != 0) 746e2f2f828Seric port = htons(port); 747fd7c0790Seric else 7481c71e510Seric { 7491c71e510Seric register struct servent *sp = getservbyname("smtp", "tcp"); 7501c71e510Seric 7511c71e510Seric if (sp == NULL) 7521c71e510Seric { 7533edb2e00Seric #ifdef LOG 7543edb2e00Seric if (LogLevel > 2) 7553edb2e00Seric syslog(LOG_ERR, "makeconnection: service \"smtp\" unknown"); 7563edb2e00Seric #endif 757e5311662Seric port = htons(25); 7581c71e510Seric } 759e5311662Seric else 760e2f2f828Seric port = sp->s_port; 761e2f2f828Seric } 762e2f2f828Seric 76383c1f4bcSeric switch (addr.sa.sa_family) 764e2f2f828Seric { 7654d9c42c2Seric #ifdef NETINET 766e2f2f828Seric case AF_INET: 76783c1f4bcSeric addr.sin.sin_port = port; 768e2f2f828Seric addrlen = sizeof (struct sockaddr_in); 769e2f2f828Seric break; 7704d9c42c2Seric #endif 771e2f2f828Seric 772e2f2f828Seric #ifdef NETISO 773e2f2f828Seric case AF_ISO: 774e2f2f828Seric /* assume two byte transport selector */ 775e2f2f828Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 776e2f2f828Seric addrlen = sizeof (struct sockaddr_iso); 777e2f2f828Seric break; 778e2f2f828Seric #endif 779e2f2f828Seric 780e2f2f828Seric default: 78183c1f4bcSeric syserr("Can't connect to address family %d", addr.sa.sa_family); 782e2f2f828Seric return (EX_NOHOST); 7831c71e510Seric } 7847aa493c5Seric 7857aa493c5Seric /* 7867aa493c5Seric ** Try to actually open the connection. 7877aa493c5Seric */ 7887aa493c5Seric 789e17a3a5aSeric #ifdef XLA 790e17a3a5aSeric /* if too many connections, don't bother trying */ 791e17a3a5aSeric if (!xla_noqueue_ok(host)) 792e17a3a5aSeric return EX_TEMPFAIL; 793e17a3a5aSeric #endif 794e17a3a5aSeric 7958b212fe0Seric firstconnect = TRUE; 796aea02ca1Seric for (;;) 797aea02ca1Seric { 79861e4310fSeric if (tTd(16, 1)) 799e2f2f828Seric printf("makeconnection (%s [%s])\n", 800e2f2f828Seric host, anynet_ntoa(&addr)); 8017aa493c5Seric 802226e3022Seric /* save for logging */ 803226e3022Seric CurHostAddr = addr; 804226e3022Seric 805914346b1Seric if (usesecureport) 806914346b1Seric { 807914346b1Seric int rport = IPPORT_RESERVED - 1; 808914346b1Seric 809914346b1Seric s = rresvport(&rport); 810914346b1Seric } 811914346b1Seric else 812914346b1Seric { 813af5e902cSeric s = socket(AF_INET, SOCK_STREAM, 0); 814914346b1Seric } 8157aa493c5Seric if (s < 0) 8167aa493c5Seric { 8176286bb75Sbloom sav_errno = errno; 818914346b1Seric syserr("makeconnection: no socket"); 8197aa493c5Seric goto failure; 8207aa493c5Seric } 8217aa493c5Seric 822b35447dbSeric #ifdef SO_SNDBUF 823b35447dbSeric if (TcpSndBufferSize > 0) 824b35447dbSeric { 825b35447dbSeric if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 826bf217a95Seric (char *) &TcpSndBufferSize, 827b35447dbSeric sizeof(TcpSndBufferSize)) < 0) 828b35447dbSeric syserr("makeconnection: setsockopt(SO_SNDBUF)"); 829b35447dbSeric } 830b35447dbSeric #endif 831b35447dbSeric 83261e4310fSeric if (tTd(16, 1)) 833b31e7f2bSeric printf("makeconnection: fd=%d\n", s); 8341b6e4a15Seric 8351b6e4a15Seric /* turn on network debugging? */ 836a2ef5fa4Seric if (tTd(16, 101)) 83752308a50Seric { 83852308a50Seric int on = 1; 8396173568dSeric (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, 840aea02ca1Seric (char *)&on, sizeof on); 84152308a50Seric } 84287d6e633Srick if (CurEnv->e_xfp != NULL) 843877a6142Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 8444bd6a662Seric errno = 0; /* for debugging */ 845e2f2f828Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 846aea02ca1Seric break; 847aea02ca1Seric 8488b212fe0Seric /* if running demand-dialed connection, try again */ 8498b212fe0Seric if (DialDelay > 0 && firstconnect) 8508b212fe0Seric { 8518b212fe0Seric if (tTd(16, 1)) 8528b212fe0Seric printf("Connect failed (%s); trying again...\n", 8538b212fe0Seric errstring(sav_errno)); 8548b212fe0Seric firstconnect = FALSE; 8558b212fe0Seric sleep(DialDelay); 8568b212fe0Seric continue; 8578b212fe0Seric } 8588b212fe0Seric 859aea02ca1Seric /* couldn't connect.... figure out why */ 8606286bb75Sbloom sav_errno = errno; 8616286bb75Sbloom (void) close(s); 8628b212fe0Seric if (hp != NULL && hp->h_addr_list[i]) 86304344589Sbloom { 864aea02ca1Seric if (tTd(16, 1)) 865e2f2f828Seric printf("Connect failed (%s); trying new address....\n", 866e2f2f828Seric errstring(sav_errno)); 86783c1f4bcSeric switch (addr.sa.sa_family) 86883c1f4bcSeric { 86983c1f4bcSeric #ifdef NETINET 87083c1f4bcSeric case AF_INET: 871e2f2f828Seric bcopy(hp->h_addr_list[i++], 87283c1f4bcSeric &addr.sin.sin_addr, 8738b212fe0Seric INADDRSZ); 87483c1f4bcSeric break; 87583c1f4bcSeric #endif 87683c1f4bcSeric 87783c1f4bcSeric default: 878e2f2f828Seric bcopy(hp->h_addr_list[i++], 87983c1f4bcSeric addr.sa.sa_data, 880914346b1Seric hp->h_length); 88183c1f4bcSeric break; 88283c1f4bcSeric } 883aea02ca1Seric continue; 88404344589Sbloom } 88504344589Sbloom 8867aa493c5Seric /* failure, decide if temporary or not */ 8877aa493c5Seric failure: 888244b09d1Seric #ifdef XLA 889244b09d1Seric xla_host_end(host); 890244b09d1Seric #endif 891e2de2524Seric if (transienterror(sav_errno)) 892e2de2524Seric return EX_TEMPFAIL; 893e2de2524Seric else 89487d6e633Srick { 89508b25121Seric message("%s", errstring(sav_errno)); 8967aa493c5Seric return (EX_UNAVAILABLE); 8977aa493c5Seric } 8987aa493c5Seric } 8997aa493c5Seric 9007aa493c5Seric /* connection ok, put it into canonical form */ 901335eae58Seric if ((mci->mci_out = fdopen(s, "w")) == NULL || 902335eae58Seric (s = dup(s)) < 0 || 903ab81ee53Seric (mci->mci_in = fdopen(s, "r")) == NULL) 904335eae58Seric { 905335eae58Seric syserr("cannot open SMTP client channel, fd=%d", s); 906335eae58Seric return EX_TEMPFAIL; 907335eae58Seric } 9087aa493c5Seric 909dca8e1f7Seric return (EX_OK); 9107aa493c5Seric } 911444eaf03Seric /* 912444eaf03Seric ** MYHOSTNAME -- return the name of this host. 913444eaf03Seric ** 914444eaf03Seric ** Parameters: 915444eaf03Seric ** hostbuf -- a place to return the name of this host. 916897f1869Seric ** size -- the size of hostbuf. 917444eaf03Seric ** 918444eaf03Seric ** Returns: 919444eaf03Seric ** A list of aliases for this host. 920444eaf03Seric ** 921444eaf03Seric ** Side Effects: 922d8d0a4aeSeric ** Adds numeric codes to $=w. 923444eaf03Seric */ 924444eaf03Seric 9258b212fe0Seric struct hostent * 926897f1869Seric myhostname(hostbuf, size) 927444eaf03Seric char hostbuf[]; 928897f1869Seric int size; 929444eaf03Seric { 93038ad259dSeric register struct hostent *hp; 9318b212fe0Seric extern bool getcanonname(); 9328b212fe0Seric extern int h_errno; 933444eaf03Seric 934af5e902cSeric if (gethostname(hostbuf, size) < 0) 935af5e902cSeric { 936af5e902cSeric (void) strcpy(hostbuf, "localhost"); 937af5e902cSeric } 9388b212fe0Seric hp = sm_gethostbyname(hostbuf); 9394a5c6430Seric if (hp == NULL) 9408b212fe0Seric return NULL; 9418b212fe0Seric if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL) 942423161fbSeric { 94335852b23Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 94435852b23Seric hostbuf[size - 1] = '\0'; 9458b212fe0Seric } 9464a5c6430Seric 9474a5c6430Seric #if NAMED_BIND 9488b212fe0Seric /* 9498b212fe0Seric ** If still no dot, try DNS directly (i.e., avoid NIS problems). 9508b212fe0Seric ** This ought to be driven from the configuration file, but 9518b212fe0Seric ** we are called before the configuration is read. We could 9528b212fe0Seric ** check for an /etc/resolv.conf file, but that isn't required. 9538b212fe0Seric ** All in all, a bit of a mess. 9548b212fe0Seric */ 95523668637Seric 956*8868a898Seric if (strchr(hostbuf, '.') == NULL) 957*8868a898Seric { 958*8868a898Seric int nmaps; 959*8868a898Seric int i; 960*8868a898Seric char *maptype[MAXMAPSTACK]; 961*8868a898Seric short mapreturn[MAXMAPACTIONS]; 962*8868a898Seric 963*8868a898Seric nmaps = switch_map_find("hosts", maptype, mapreturn); 964*8868a898Seric for (i = 0; i < nmaps; i++) 965*8868a898Seric if (strcmp(maptype[i], "dns") == 0) 966*8868a898Seric break; 967*8868a898Seric if (i < nmaps && 968*8868a898Seric !dns_getcanonname(hostbuf, size, TRUE) && 9698b212fe0Seric h_errno == TRY_AGAIN) 97023668637Seric { 9718b212fe0Seric /* try twice in case name server not yet started up */ 9728b212fe0Seric message("My unqualifed host name (%s) unknown to DNS; sleeping for retry", 97323668637Seric hostbuf); 9748b212fe0Seric sleep(60); 975*8868a898Seric if (!dns_getcanonname(hostbuf, size, TRUE)) 9768b212fe0Seric errno = h_errno + E_DNSBASE; 977747df804Seric } 978*8868a898Seric } 979747df804Seric #endif 9808b212fe0Seric return (hp); 9817364df9fSeric } 982cb452edcSeric /* 9839f8b0eadSeric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 9849f8b0eadSeric ** 9859f8b0eadSeric ** Uses RFC1413 protocol to try to get info from the other end. 986320e0d1cSeric ** 987320e0d1cSeric ** Parameters: 988320e0d1cSeric ** fd -- the descriptor 989320e0d1cSeric ** 990320e0d1cSeric ** Returns: 9919f8b0eadSeric ** The user@host information associated with this descriptor. 992320e0d1cSeric */ 993320e0d1cSeric 9949f8b0eadSeric static jmp_buf CtxAuthTimeout; 9959f8b0eadSeric 9968b212fe0Seric static void 9979f8b0eadSeric authtimeout() 9989f8b0eadSeric { 9999f8b0eadSeric longjmp(CtxAuthTimeout, 1); 10009f8b0eadSeric } 10019f8b0eadSeric 1002320e0d1cSeric char * 10039f8b0eadSeric getauthinfo(fd) 1004320e0d1cSeric int fd; 1005320e0d1cSeric { 10069f8b0eadSeric int falen; 1007a5546e24Seric register char *p; 10089f8b0eadSeric SOCKADDR la; 10099f8b0eadSeric int lalen; 10109f8b0eadSeric register struct servent *sp; 10119f8b0eadSeric int s; 10129f8b0eadSeric int i; 10139f8b0eadSeric EVENT *ev; 1014579270a3Seric int nleft; 1015f036c8d7Seric char ibuf[MAXNAME + 1]; 10169f8b0eadSeric static char hbuf[MAXNAME * 2 + 2]; 10179f8b0eadSeric extern char *hostnamebyanyaddr(); 1018320e0d1cSeric 1019e29a76d1Seric falen = sizeof RealHostAddr; 10208b212fe0Seric if (isatty(fd) || getpeername(fd, &RealHostAddr.sa, &falen) < 0 || 10218b212fe0Seric falen <= 0 || RealHostAddr.sa.sa_family == 0) 10229f8b0eadSeric { 10239f8b0eadSeric (void) sprintf(hbuf, "%s@localhost", RealUserName); 102453853673Seric if (tTd(9, 1)) 10259f8b0eadSeric printf("getauthinfo: %s\n", hbuf); 1026320e0d1cSeric return hbuf; 1027320e0d1cSeric } 10289f8b0eadSeric 1029e29a76d1Seric if (RealHostName == NULL) 1030e29a76d1Seric { 1031e29a76d1Seric /* translate that to a host name */ 1032e29a76d1Seric RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 1033e29a76d1Seric } 1034e29a76d1Seric 103593b3215bSeric if (TimeOuts.to_ident == 0) 103693b3215bSeric goto noident; 103793b3215bSeric 10389f8b0eadSeric lalen = sizeof la; 1039e29a76d1Seric if (RealHostAddr.sa.sa_family != AF_INET || 10409f8b0eadSeric getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || 10419f8b0eadSeric la.sa.sa_family != AF_INET) 10429f8b0eadSeric { 10439f8b0eadSeric /* no ident info */ 10449f8b0eadSeric goto noident; 10459f8b0eadSeric } 10469f8b0eadSeric 10479f8b0eadSeric /* create ident query */ 104881d2944fSeric (void) sprintf(ibuf, "%d,%d\r\n", 1049e29a76d1Seric ntohs(RealHostAddr.sin.sin_port), ntohs(la.sin.sin_port)); 10509f8b0eadSeric 10519f8b0eadSeric /* create local address */ 1052d6af7dadSeric la.sin.sin_port = 0; 10539f8b0eadSeric 10549f8b0eadSeric /* create foreign address */ 10559f8b0eadSeric sp = getservbyname("auth", "tcp"); 10569f8b0eadSeric if (sp != NULL) 1057e29a76d1Seric RealHostAddr.sin.sin_port = sp->s_port; 10589f8b0eadSeric else 1059e29a76d1Seric RealHostAddr.sin.sin_port = htons(113); 10609f8b0eadSeric 10619f8b0eadSeric s = -1; 10629f8b0eadSeric if (setjmp(CtxAuthTimeout) != 0) 10639f8b0eadSeric { 10649f8b0eadSeric if (s >= 0) 10659f8b0eadSeric (void) close(s); 10669f8b0eadSeric goto noident; 10679f8b0eadSeric } 10689f8b0eadSeric 10699f8b0eadSeric /* put a timeout around the whole thing */ 1070a0f780efSeric ev = setevent(TimeOuts.to_ident, authtimeout, 0); 10719f8b0eadSeric 1072d6af7dadSeric /* connect to foreign IDENT server using same address as SMTP socket */ 10739f8b0eadSeric s = socket(AF_INET, SOCK_STREAM, 0); 10749f8b0eadSeric if (s < 0) 10759f8b0eadSeric { 10769f8b0eadSeric clrevent(ev); 10779f8b0eadSeric goto noident; 10789f8b0eadSeric } 1079d6af7dadSeric if (bind(s, &la.sa, sizeof la.sin) < 0 || 1080e29a76d1Seric connect(s, &RealHostAddr.sa, sizeof RealHostAddr.sin) < 0) 10819f8b0eadSeric { 10827c201575Seric goto closeident; 10839f8b0eadSeric } 10849f8b0eadSeric 108553853673Seric if (tTd(9, 10)) 108681d2944fSeric printf("getauthinfo: sent %s", ibuf); 10879f8b0eadSeric 10889f8b0eadSeric /* send query */ 108981d2944fSeric if (write(s, ibuf, strlen(ibuf)) < 0) 10909f8b0eadSeric goto closeident; 10919f8b0eadSeric 10929f8b0eadSeric /* get result */ 109381d2944fSeric p = &ibuf[0]; 1094b26156f6Seric nleft = sizeof ibuf - 1; 1095579270a3Seric while ((i = read(s, p, nleft)) > 0) 1096579270a3Seric { 1097579270a3Seric p += i; 1098579270a3Seric nleft -= i; 1099579270a3Seric } 11009f8b0eadSeric (void) close(s); 11019f8b0eadSeric clrevent(ev); 110281d2944fSeric if (i < 0 || p == &ibuf[0]) 11039f8b0eadSeric goto noident; 1104579270a3Seric 1105579270a3Seric if (*--p == '\n' && *--p == '\r') 1106579270a3Seric p--; 1107579270a3Seric *++p = '\0'; 11089f8b0eadSeric 110953853673Seric if (tTd(9, 3)) 111081d2944fSeric printf("getauthinfo: got %s\n", ibuf); 11119f8b0eadSeric 11129f8b0eadSeric /* parse result */ 111381d2944fSeric p = strchr(ibuf, ':'); 11149f8b0eadSeric if (p == NULL) 11159f8b0eadSeric { 11169f8b0eadSeric /* malformed response */ 11179f8b0eadSeric goto noident; 11189f8b0eadSeric } 11199f8b0eadSeric while (isascii(*++p) && isspace(*p)) 11209f8b0eadSeric continue; 11219f8b0eadSeric if (strncasecmp(p, "userid", 6) != 0) 11229f8b0eadSeric { 11239f8b0eadSeric /* presumably an error string */ 11249f8b0eadSeric goto noident; 11259f8b0eadSeric } 11269f8b0eadSeric p += 6; 11279f8b0eadSeric while (isascii(*p) && isspace(*p)) 11289f8b0eadSeric p++; 11299f8b0eadSeric if (*p++ != ':') 11309f8b0eadSeric { 11319f8b0eadSeric /* either useridxx or malformed response */ 11329f8b0eadSeric goto noident; 11339f8b0eadSeric } 11349f8b0eadSeric 11359f8b0eadSeric /* p now points to the OSTYPE field */ 11368b212fe0Seric while (isascii(*p) && isspace(*p)) 11378b212fe0Seric p++; 11388b212fe0Seric if (strncasecmp(p, "other", 5) == 0 && 11398b212fe0Seric (p[5] == ':' || p[5] == ' ' || p[5] == ',' || p[5] == '\0')) 11408b212fe0Seric { 11418b212fe0Seric /* not useful information */ 11428b212fe0Seric goto noident; 11438b212fe0Seric } 11449f8b0eadSeric p = strchr(p, ':'); 11459f8b0eadSeric if (p == NULL) 11469f8b0eadSeric { 11479f8b0eadSeric /* malformed response */ 11489f8b0eadSeric goto noident; 11499f8b0eadSeric } 115053853673Seric 115153853673Seric /* 1413 says don't do this -- but it's broken otherwise */ 115253853673Seric while (isascii(*++p) && isspace(*p)) 115353853673Seric continue; 11549f8b0eadSeric 1155a7763879Seric /* p now points to the authenticated name -- copy carefully */ 115681d2944fSeric cleanstrcpy(hbuf, p, MAXNAME); 115793433f31Seric i = strlen(hbuf); 1158a7763879Seric hbuf[i++] = '@'; 1159a7763879Seric strcpy(&hbuf[i], RealHostName == NULL ? "localhost" : RealHostName); 116011af795cSeric goto postident; 116153853673Seric 11627c201575Seric closeident: 11637c201575Seric (void) close(s); 11647c201575Seric clrevent(ev); 11657c201575Seric 116653853673Seric noident: 1167f7869e68Seric if (RealHostName == NULL) 1168f7869e68Seric { 1169f7869e68Seric if (tTd(9, 1)) 1170f7869e68Seric printf("getauthinfo: NULL\n"); 1171f7869e68Seric return NULL; 1172f7869e68Seric } 117353853673Seric (void) strcpy(hbuf, RealHostName); 117453853673Seric 117511af795cSeric postident: 117611af795cSeric #if IP_SRCROUTE 117711af795cSeric /* 117811af795cSeric ** Extract IP source routing information. 117911af795cSeric ** 118011af795cSeric ** Format of output for a connection from site a through b 118111af795cSeric ** through c to d: 118211af795cSeric ** loose: @site-c@site-b:site-a 118311af795cSeric ** strict: !@site-c@site-b:site-a 118411af795cSeric ** 118511af795cSeric ** o - pointer within ipopt_list structure. 118611af795cSeric ** q - pointer within ls/ss rr route data 118711af795cSeric ** p - pointer to hbuf 118811af795cSeric */ 118911af795cSeric 119011af795cSeric if (RealHostAddr.sa.sa_family == AF_INET) 119111af795cSeric { 119211af795cSeric int ipoptlen, j; 11934d6b8580Seric u_char *q; 119411af795cSeric u_char *o; 119511af795cSeric struct in_addr addr; 119611af795cSeric struct ipoption ipopt; 119711af795cSeric 119811af795cSeric ipoptlen = sizeof ipopt; 119911af795cSeric if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS, 120011af795cSeric (char *) &ipopt, &ipoptlen) < 0) 120111af795cSeric goto noipsr; 120211af795cSeric if (ipoptlen == 0) 120311af795cSeric goto noipsr; 12044d6b8580Seric o = (u_char *) ipopt.ipopt_list; 12055db00695Seric while (o != NULL && o < (u_char *) &ipopt + ipoptlen) 120611af795cSeric { 120711af795cSeric switch (*o) 120811af795cSeric { 120911af795cSeric case IPOPT_EOL: 121011af795cSeric o = NULL; 121111af795cSeric break; 121211af795cSeric 121311af795cSeric case IPOPT_NOP: 121411af795cSeric o++; 121511af795cSeric break; 121611af795cSeric 121711af795cSeric case IPOPT_SSRR: 121811af795cSeric case IPOPT_LSRR: 121911af795cSeric p = &hbuf[strlen(hbuf)]; 122011af795cSeric sprintf(p, " [%s@%s", 122111af795cSeric *o == IPOPT_SSRR ? "!" : "", 122211af795cSeric inet_ntoa(ipopt.ipopt_dst)); 122311af795cSeric p += strlen(p); 122411af795cSeric 122511af795cSeric /* o[1] is option length */ 122611af795cSeric j = *++o / sizeof(struct in_addr) - 1; 122711af795cSeric 122811af795cSeric /* q skips length and router pointer to data */ 122911af795cSeric q = o + 2; 123011af795cSeric for ( ; j >= 0; j--) 123111af795cSeric { 123211af795cSeric memcpy(&addr, q, sizeof(addr)); 12334d6b8580Seric sprintf(p, "%c%s", 123411af795cSeric j ? '@' : ':', 123511af795cSeric inet_ntoa(addr)); 12364d6b8580Seric p += strlen(p); 123711af795cSeric q += sizeof(struct in_addr); 123811af795cSeric } 123911af795cSeric o += *o; 124011af795cSeric break; 124111af795cSeric 124211af795cSeric default: 124311af795cSeric /* Skip over option */ 124411af795cSeric o += o[1]; 124511af795cSeric break; 124611af795cSeric } 124711af795cSeric } 124811af795cSeric strcat(hbuf,"]"); 124911af795cSeric goto postipsr; 125011af795cSeric } 125111af795cSeric #endif 125211af795cSeric 125311af795cSeric noipsr: 1254f7869e68Seric if (RealHostName != NULL && RealHostName[0] != '[') 12559f8b0eadSeric { 12569f8b0eadSeric p = &hbuf[strlen(hbuf)]; 12579f8b0eadSeric (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); 12589f8b0eadSeric } 125911af795cSeric 126011af795cSeric postipsr: 126153853673Seric if (tTd(9, 1)) 12629f8b0eadSeric printf("getauthinfo: %s\n", hbuf); 12639f8b0eadSeric return hbuf; 12649f8b0eadSeric } 1265320e0d1cSeric /* 126608de856eSeric ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 126715d084d5Seric ** 126815d084d5Seric ** Parameters: 126905b57da8Seric ** map -- a pointer to this map (unused). 127008de856eSeric ** name -- the (presumably unqualified) hostname. 127100b385a9Seric ** av -- unused -- for compatibility with other mapping 1272d798a1deSeric ** functions. 12732d29d43aSeric ** statp -- an exit status (out parameter) -- set to 12742d29d43aSeric ** EX_TEMPFAIL if the name server is unavailable. 127515d084d5Seric ** 127615d084d5Seric ** Returns: 127715d084d5Seric ** The mapping, if found. 127815d084d5Seric ** NULL if no mapping found. 127915d084d5Seric ** 128015d084d5Seric ** Side Effects: 128115d084d5Seric ** Looks up the host specified in hbuf. If it is not 128215d084d5Seric ** the canonical name for that host, return the canonical 128315d084d5Seric ** name. 1284f36ede03Sbostic */ 1285cb452edcSeric 128615d084d5Seric char * 128700b385a9Seric host_map_lookup(map, name, av, statp) 128805b57da8Seric MAP *map; 128908de856eSeric char *name; 129000b385a9Seric char **av; 12912d29d43aSeric int *statp; 129299f7cf32Seric { 129399f7cf32Seric register struct hostent *hp; 12948b212fe0Seric struct in_addr in_addr; 129505b57da8Seric char *cp; 1296eea91d78Seric register STAB *s; 12978b212fe0Seric char hbuf[MAXNAME + 1]; 12989d4a8008Seric #if NAMED_BIND 1299eea91d78Seric extern int h_errno; 1300c304a798Seric #endif 13015f78836eSmiriam 1302f36ede03Sbostic /* 1303eea91d78Seric ** See if we have already looked up this name. If so, just 1304eea91d78Seric ** return it. 1305eea91d78Seric */ 1306eea91d78Seric 130708de856eSeric s = stab(name, ST_NAMECANON, ST_ENTER); 1308eea91d78Seric if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 1309eea91d78Seric { 1310f92c3297Seric if (tTd(9, 1)) 131108de856eSeric printf("host_map_lookup(%s) => CACHE %s\n", 131298826a83Seric name, 131398826a83Seric s->s_namecanon.nc_cname == NULL 131498826a83Seric ? "NULL" 13155f08d413Seric : s->s_namecanon.nc_cname); 1316eea91d78Seric errno = s->s_namecanon.nc_errno; 13179d4a8008Seric #if NAMED_BIND 1318eea91d78Seric h_errno = s->s_namecanon.nc_herrno; 1319c304a798Seric #endif 1320eea91d78Seric *statp = s->s_namecanon.nc_stat; 1321fcfb36d9Seric if (*statp == EX_TEMPFAIL) 1322ed63aae0Seric { 13235b068d51Seric CurEnv->e_status = "4.4.3"; 1324fcfb36d9Seric usrerr("451 %s: Name server timeout", 1325ed63aae0Seric shortenstring(name, 33)); 1326ed63aae0Seric } 1327eea91d78Seric return s->s_namecanon.nc_cname; 1328eea91d78Seric } 1329eea91d78Seric 1330eea91d78Seric /* 1331eea91d78Seric ** If first character is a bracket, then it is an address 1332eea91d78Seric ** lookup. Address is copied into a temporary buffer to 133308de856eSeric ** strip the brackets and to preserve name if address is 1334eea91d78Seric ** unknown. 1335f36ede03Sbostic */ 133615d084d5Seric 133708de856eSeric if (*name != '[') 133815d084d5Seric { 1339d798a1deSeric extern bool getcanonname(); 1340d798a1deSeric 13418cb4653dSeric if (tTd(9, 1)) 134208de856eSeric printf("host_map_lookup(%s) => ", name); 1343eea91d78Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 13448b212fe0Seric if (strlen(name) < sizeof hbuf) 134508de856eSeric (void) strcpy(hbuf, name); 13468b212fe0Seric else 13478b212fe0Seric { 13488b212fe0Seric bcopy(name, hbuf, sizeof hbuf - 1); 13498b212fe0Seric hbuf[sizeof hbuf - 1] = '\0'; 13508b212fe0Seric } 13510183c3f6Seric if (getcanonname(hbuf, sizeof hbuf - 1, !NoMXforCanon)) 13529040ec4fSeric { 13539040ec4fSeric if (tTd(9, 1)) 13549040ec4fSeric printf("%s\n", hbuf); 135500b385a9Seric cp = map_rewrite(map, hbuf, strlen(hbuf), av); 135600b385a9Seric s->s_namecanon.nc_cname = newstr(cp); 135700b385a9Seric return cp; 13589040ec4fSeric } 135915d084d5Seric else 13609040ec4fSeric { 13612d29d43aSeric register struct hostent *hp; 13622d29d43aSeric 1363c304a798Seric s->s_namecanon.nc_errno = errno; 13649d4a8008Seric #if NAMED_BIND 1365c304a798Seric s->s_namecanon.nc_herrno = h_errno; 13669040ec4fSeric if (tTd(9, 1)) 13672d29d43aSeric printf("FAIL (%d)\n", h_errno); 13682d29d43aSeric switch (h_errno) 13692d29d43aSeric { 13702d29d43aSeric case TRY_AGAIN: 137189cb2793Seric if (UseNameServer) 13728820d51bSeric { 13735b068d51Seric CurEnv->e_status = "4.4.3"; 1374fcfb36d9Seric usrerr("451 %s: Name server timeout", 1375ed63aae0Seric shortenstring(name, 33)); 13768820d51bSeric } 13772d29d43aSeric *statp = EX_TEMPFAIL; 13782d29d43aSeric break; 13792d29d43aSeric 13802d29d43aSeric case HOST_NOT_FOUND: 138180027ae6Seric case NO_DATA: 13822d29d43aSeric *statp = EX_NOHOST; 13832d29d43aSeric break; 13842d29d43aSeric 13852d29d43aSeric case NO_RECOVERY: 13862d29d43aSeric *statp = EX_SOFTWARE; 13872d29d43aSeric break; 13882d29d43aSeric 13892d29d43aSeric default: 13902d29d43aSeric *statp = EX_UNAVAILABLE; 13912d29d43aSeric break; 13922d29d43aSeric } 1393c304a798Seric #else 1394c304a798Seric if (tTd(9, 1)) 1395c304a798Seric printf("FAIL\n"); 1396c304a798Seric *statp = EX_NOHOST; 1397c304a798Seric #endif 1398eea91d78Seric s->s_namecanon.nc_stat = *statp; 13998b212fe0Seric if ((*statp != EX_TEMPFAIL && *statp != EX_NOHOST) || 14008b212fe0Seric UseNameServer) 140115d084d5Seric return NULL; 14022d29d43aSeric 14032d29d43aSeric /* 14042d29d43aSeric ** Try to look it up in /etc/hosts 14052d29d43aSeric */ 14062d29d43aSeric 14078b212fe0Seric hp = sm_gethostbyname(name); 14082d29d43aSeric if (hp == NULL) 14092d29d43aSeric { 14102d29d43aSeric /* no dice there either */ 1411eea91d78Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 14122d29d43aSeric return NULL; 14132d29d43aSeric } 14142d29d43aSeric 1415eea91d78Seric s->s_namecanon.nc_stat = *statp = EX_OK; 141600b385a9Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 141700b385a9Seric s->s_namecanon.nc_cname = newstr(cp); 141800b385a9Seric return cp; 141915d084d5Seric } 14209040ec4fSeric } 142108de856eSeric if ((cp = strchr(name, ']')) == NULL) 142215d084d5Seric return (NULL); 142334e39927Sbostic *cp = '\0'; 14248b212fe0Seric in_addr.s_addr = inet_addr(&name[1]); 142538ad259dSeric 142638ad259dSeric /* nope -- ask the name server */ 14278b212fe0Seric hp = sm_gethostbyaddr((char *)&in_addr, INADDRSZ, AF_INET); 1428eea91d78Seric s->s_namecanon.nc_errno = errno; 14299d4a8008Seric #if NAMED_BIND 1430eea91d78Seric s->s_namecanon.nc_herrno = h_errno; 1431c304a798Seric #endif 1432eea91d78Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 14335f78836eSmiriam if (hp == NULL) 1434eea91d78Seric { 1435eea91d78Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 143615d084d5Seric return (NULL); 1437eea91d78Seric } 143815d084d5Seric 143938ad259dSeric /* found a match -- copy out */ 144000b385a9Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 1441eea91d78Seric s->s_namecanon.nc_stat = *statp = EX_OK; 144200b385a9Seric s->s_namecanon.nc_cname = newstr(cp); 144300b385a9Seric return cp; 144499f7cf32Seric } 1445e2f2f828Seric /* 1446e2f2f828Seric ** ANYNET_NTOA -- convert a network address to printable form. 1447e2f2f828Seric ** 1448e2f2f828Seric ** Parameters: 1449e2f2f828Seric ** sap -- a pointer to a sockaddr structure. 1450e2f2f828Seric ** 1451e2f2f828Seric ** Returns: 1452e2f2f828Seric ** A printable version of that sockaddr. 1453e2f2f828Seric */ 1454e2f2f828Seric 1455543d9d93Seric #ifdef NETLINK 145606cc5485Seric # include <net/if_dl.h> 145706cc5485Seric #endif 145806cc5485Seric 1459e2f2f828Seric char * 1460e2f2f828Seric anynet_ntoa(sap) 1461e2f2f828Seric register SOCKADDR *sap; 1462e2f2f828Seric { 1463e2f2f828Seric register char *bp; 1464e2f2f828Seric register char *ap; 1465e2f2f828Seric int l; 1466e387851eSeric static char buf[100]; 1467e2f2f828Seric 14688cb4653dSeric /* check for null/zero family */ 14698cb4653dSeric if (sap == NULL) 14708cb4653dSeric return "NULLADDR"; 14718cb4653dSeric if (sap->sa.sa_family == 0) 14728cb4653dSeric return "0"; 14738cb4653dSeric 1474e387851eSeric switch (sap->sa.sa_family) 1475e387851eSeric { 1476139b52c8Seric #ifdef NETUNIX 1477e387851eSeric case AF_UNIX: 1478c24cf5a4Seric if (sap->sunix.sun_path[0] != '\0') 1479c24cf5a4Seric sprintf(buf, "[UNIX: %.64s]", sap->sunix.sun_path); 1480e387851eSeric else 1481e387851eSeric sprintf(buf, "[UNIX: localhost]"); 1482e387851eSeric return buf; 1483e387851eSeric #endif 1484e387851eSeric 148583c1f4bcSeric #ifdef NETINET 1486e387851eSeric case AF_INET: 1487482e28bcSeric return inet_ntoa(sap->sin.sin_addr); 148883c1f4bcSeric #endif 1489e2f2f828Seric 1490543d9d93Seric #ifdef NETLINK 149106cc5485Seric case AF_LINK: 149206cc5485Seric sprintf(buf, "[LINK: %s]", 149306cc5485Seric link_ntoa((struct sockaddr_dl *) &sap->sa)); 149406cc5485Seric return buf; 149506cc5485Seric #endif 1496e387851eSeric default: 149706cc5485Seric /* this case is needed when nothing is #defined */ 149806cc5485Seric /* in order to keep the switch syntactically correct */ 1499e387851eSeric break; 1500e387851eSeric } 1501e387851eSeric 1502e2f2f828Seric /* unknown family -- just dump bytes */ 150383c1f4bcSeric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 1504e2f2f828Seric bp = &buf[strlen(buf)]; 150583c1f4bcSeric ap = sap->sa.sa_data; 150683c1f4bcSeric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 1507e2f2f828Seric { 1508e2f2f828Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 1509e2f2f828Seric bp += 3; 1510e2f2f828Seric } 1511e2f2f828Seric *--bp = '\0'; 1512e2f2f828Seric return buf; 1513e2f2f828Seric } 15149f8b0eadSeric /* 15159f8b0eadSeric ** HOSTNAMEBYANYADDR -- return name of host based on address 15169f8b0eadSeric ** 15179f8b0eadSeric ** Parameters: 15189f8b0eadSeric ** sap -- SOCKADDR pointer 15199f8b0eadSeric ** 15209f8b0eadSeric ** Returns: 15219f8b0eadSeric ** text representation of host name. 15229f8b0eadSeric ** 15239f8b0eadSeric ** Side Effects: 15249f8b0eadSeric ** none. 15259f8b0eadSeric */ 15269f8b0eadSeric 15279f8b0eadSeric char * 15289f8b0eadSeric hostnamebyanyaddr(sap) 15299f8b0eadSeric register SOCKADDR *sap; 15309f8b0eadSeric { 15319f8b0eadSeric register struct hostent *hp; 15323490b9dfSeric int saveretry; 15333490b9dfSeric 15349d4a8008Seric #if NAMED_BIND 15353490b9dfSeric /* shorten name server timeout to avoid higher level timeouts */ 15363490b9dfSeric saveretry = _res.retry; 15373490b9dfSeric _res.retry = 3; 15383490b9dfSeric #endif /* NAMED_BIND */ 15393490b9dfSeric 15409f8b0eadSeric switch (sap->sa.sa_family) 15419f8b0eadSeric { 15429f8b0eadSeric #ifdef NETINET 15439f8b0eadSeric case AF_INET: 15448b212fe0Seric hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr, 15458b212fe0Seric INADDRSZ, 15469f8b0eadSeric AF_INET); 15479f8b0eadSeric break; 15489f8b0eadSeric #endif 15499f8b0eadSeric 15509f8b0eadSeric #ifdef NETISO 15519f8b0eadSeric case AF_ISO: 15528b212fe0Seric hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr, 15539f8b0eadSeric sizeof sap->siso.siso_addr, 15549f8b0eadSeric AF_ISO); 15559f8b0eadSeric break; 15569f8b0eadSeric #endif 15579f8b0eadSeric 1558e387851eSeric case AF_UNIX: 1559e387851eSeric hp = NULL; 1560e387851eSeric break; 1561e387851eSeric 15629f8b0eadSeric default: 15638b212fe0Seric hp = sm_gethostbyaddr(sap->sa.sa_data, 15649f8b0eadSeric sizeof sap->sa.sa_data, 15659f8b0eadSeric sap->sa.sa_family); 15669f8b0eadSeric break; 15679f8b0eadSeric } 15689f8b0eadSeric 15699d4a8008Seric #if NAMED_BIND 15703490b9dfSeric _res.retry = saveretry; 15713490b9dfSeric #endif /* NAMED_BIND */ 15723490b9dfSeric 15739f8b0eadSeric if (hp != NULL) 15749f8b0eadSeric return hp->h_name; 15759f8b0eadSeric else 15769f8b0eadSeric { 15779f8b0eadSeric /* produce a dotted quad */ 15789f8b0eadSeric static char buf[512]; 15799f8b0eadSeric 15809f8b0eadSeric (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); 15819f8b0eadSeric return buf; 15829f8b0eadSeric } 15839f8b0eadSeric } 1584f36ede03Sbostic 15856c2c3107Seric # else /* DAEMON */ 158699f7cf32Seric /* code for systems without sophisticated networking */ 1587444eaf03Seric 1588444eaf03Seric /* 1589444eaf03Seric ** MYHOSTNAME -- stub version for case of no daemon code. 159021e9914dSeric ** 159121e9914dSeric ** Can't convert to upper case here because might be a UUCP name. 1592897f1869Seric ** 1593897f1869Seric ** Mark, you can change this to be anything you want...... 1594444eaf03Seric */ 1595444eaf03Seric 1596444eaf03Seric char ** 1597897f1869Seric myhostname(hostbuf, size) 1598444eaf03Seric char hostbuf[]; 1599897f1869Seric int size; 1600444eaf03Seric { 1601444eaf03Seric register FILE *f; 1602444eaf03Seric 1603444eaf03Seric hostbuf[0] = '\0'; 1604444eaf03Seric f = fopen("/usr/include/whoami", "r"); 1605444eaf03Seric if (f != NULL) 1606444eaf03Seric { 1607897f1869Seric (void) fgets(hostbuf, size, f); 1608444eaf03Seric fixcrlf(hostbuf, TRUE); 1609444eaf03Seric (void) fclose(f); 1610444eaf03Seric } 1611444eaf03Seric return (NULL); 1612444eaf03Seric } 161399f7cf32Seric /* 16149f8b0eadSeric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 1615320e0d1cSeric ** 1616320e0d1cSeric ** Parameters: 1617320e0d1cSeric ** fd -- the descriptor 1618320e0d1cSeric ** 1619320e0d1cSeric ** Returns: 1620320e0d1cSeric ** The host name associated with this descriptor, if it can 1621320e0d1cSeric ** be determined. 1622320e0d1cSeric ** NULL otherwise. 1623320e0d1cSeric ** 1624320e0d1cSeric ** Side Effects: 1625320e0d1cSeric ** none 1626320e0d1cSeric */ 1627320e0d1cSeric 1628320e0d1cSeric char * 16299f8b0eadSeric getauthinfo(fd) 1630320e0d1cSeric int fd; 1631320e0d1cSeric { 1632320e0d1cSeric return NULL; 1633320e0d1cSeric } 1634320e0d1cSeric /* 163599f7cf32Seric ** MAPHOSTNAME -- turn a hostname into canonical form 163699f7cf32Seric ** 163799f7cf32Seric ** Parameters: 163805b57da8Seric ** map -- a pointer to the database map. 163908de856eSeric ** name -- a buffer containing a hostname. 164015d084d5Seric ** avp -- a pointer to a (cf file defined) argument vector. 16412d29d43aSeric ** statp -- an exit status (out parameter). 164299f7cf32Seric ** 164399f7cf32Seric ** Returns: 164415d084d5Seric ** mapped host name 1645cb452edcSeric ** FALSE otherwise. 164699f7cf32Seric ** 164799f7cf32Seric ** Side Effects: 164808de856eSeric ** Looks up the host specified in name. If it is not 164999f7cf32Seric ** the canonical name for that host, replace it with 165099f7cf32Seric ** the canonical name. If the name is unknown, or it 165199f7cf32Seric ** is already the canonical name, leave it unchanged. 165299f7cf32Seric */ 165399f7cf32Seric 165499f7cf32Seric /*ARGSUSED*/ 165515d084d5Seric char * 165608de856eSeric host_map_lookup(map, name, avp, statp) 165705b57da8Seric MAP *map; 165808de856eSeric char *name; 165915d084d5Seric char **avp; 16602d29d43aSeric char *statp; 166199f7cf32Seric { 16622d29d43aSeric register struct hostent *hp; 16632d29d43aSeric 16648b212fe0Seric hp = sm_gethostbyname(name); 16652d29d43aSeric if (hp != NULL) 16662d29d43aSeric return hp->h_name; 16672d29d43aSeric *statp = EX_NOHOST; 166815d084d5Seric return NULL; 166999f7cf32Seric } 167099f7cf32Seric 16716c2c3107Seric #endif /* DAEMON */ 1672