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*5f08d413Seric static char sccsid[] = "@(#)daemon.c 8.88 (Berkeley) 05/16/95 (with daemon mode)"; 15d0a9e852Seric #else 16*5f08d413Seric static char sccsid[] = "@(#)daemon.c 8.88 (Berkeley) 05/16/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 287fa39d90Seric /* 297fa39d90Seric ** DAEMON.C -- routines to use when running as a daemon. 3047b12ae1Seric ** 3147b12ae1Seric ** This entire file is highly dependent on the 4.2 BSD 3247b12ae1Seric ** interprocess communication primitives. No attempt has 3347b12ae1Seric ** been made to make this file portable to Version 7, 3447b12ae1Seric ** Version 6, MPX files, etc. If you should try such a 3547b12ae1Seric ** thing yourself, I recommend chucking the entire file 3647b12ae1Seric ** and starting from scratch. Basic semantics are: 3747b12ae1Seric ** 3847b12ae1Seric ** getrequests() 3947b12ae1Seric ** Opens a port and initiates a connection. 4047b12ae1Seric ** Returns in a child. Must set InChannel and 4147b12ae1Seric ** OutChannel appropriately. 42b7d7afcbSeric ** clrdaemon() 43b7d7afcbSeric ** Close any open files associated with getting 44b7d7afcbSeric ** the connection; this is used when running the queue, 45b7d7afcbSeric ** etc., to avoid having extra file descriptors during 46b7d7afcbSeric ** the queue run and to avoid confusing the network 47b7d7afcbSeric ** code (if it cares). 48914346b1Seric ** makeconnection(host, port, outfile, infile, usesecureport) 4947b12ae1Seric ** Make a connection to the named host on the given 5047b12ae1Seric ** port. Set *outfile and *infile to the files 5147b12ae1Seric ** appropriate for communication. Returns zero on 5247b12ae1Seric ** success, else an exit status describing the 5347b12ae1Seric ** error. 5408de856eSeric ** host_map_lookup(map, hbuf, avp, pstat) 5505b57da8Seric ** Convert the entry in hbuf into a canonical form. 567fa39d90Seric */ 577fa39d90Seric /* 587fa39d90Seric ** GETREQUESTS -- open mail IPC port and get requests. 597fa39d90Seric ** 607fa39d90Seric ** Parameters: 617fa39d90Seric ** none. 627fa39d90Seric ** 637fa39d90Seric ** Returns: 647fa39d90Seric ** none. 657fa39d90Seric ** 667fa39d90Seric ** Side Effects: 677fa39d90Seric ** Waits until some interesting activity occurs. When 687fa39d90Seric ** it does, a child is created to process it, and the 697fa39d90Seric ** parent waits for completion. Return from this 70147303b1Seric ** routine is always in the child. The file pointers 71147303b1Seric ** "InChannel" and "OutChannel" should be set to point 72147303b1Seric ** to the communication channel. 737fa39d90Seric */ 747fa39d90Seric 75b7d7afcbSeric int DaemonSocket = -1; /* fd describing socket */ 76bfb80540Seric SOCKADDR DaemonAddr; /* socket for incoming */ 77bfc1eaf8Seric int ListenQueueSize = 10; /* size of listen queue */ 78b35447dbSeric int TcpRcvBufferSize = 0; /* size of TCP receive buffer */ 79b35447dbSeric int TcpSndBufferSize = 0; /* size of TCP send buffer */ 801c71e510Seric 818b212fe0Seric void 827fa39d90Seric getrequests() 837fa39d90Seric { 841c71e510Seric int t; 8515d084d5Seric bool refusingconnections = TRUE; 860aae1086Seric FILE *pidf; 87dadb8687Seric int socksize; 88dfe840b2Seric #ifdef XDEBUG 89dfe840b2Seric bool j_has_dot; 90dfe840b2Seric #endif 919b100374Sbostic extern void reapchild(); 92eb889047Seric 93a8268164Seric /* 941c71e510Seric ** Set up the address for the mailer. 95eb889047Seric */ 96eb889047Seric 97bfb80540Seric if (DaemonAddr.sin.sin_family == 0) 98bfb80540Seric DaemonAddr.sin.sin_family = AF_INET; 99bfb80540Seric if (DaemonAddr.sin.sin_addr.s_addr == 0) 100bfb80540Seric DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; 101bfb80540Seric if (DaemonAddr.sin.sin_port == 0) 102bfb80540Seric { 103e5311662Seric register struct servent *sp; 104e5311662Seric 1051c71e510Seric sp = getservbyname("smtp", "tcp"); 1061c71e510Seric if (sp == NULL) 107d0a9e852Seric { 108ad977999Seric syserr("554 service \"smtp\" unknown"); 109e5311662Seric DaemonAddr.sin.sin_port = htons(25); 1101c71e510Seric } 111e5311662Seric else 112bfb80540Seric DaemonAddr.sin.sin_port = sp->s_port; 113bfb80540Seric } 1141c71e510Seric 1151c71e510Seric /* 1161c71e510Seric ** Try to actually open the connection. 1171c71e510Seric */ 1181c71e510Seric 1191c71e510Seric if (tTd(15, 1)) 120bfb80540Seric printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); 1211c71e510Seric 1221c71e510Seric /* get a socket for the SMTP connection */ 12388ea5609Seric socksize = opendaemonsocket(TRUE); 1241c71e510Seric 1252b9178d3Seric (void) setsignal(SIGCHLD, reapchild); 12652308a50Seric 1270aae1086Seric /* write the pid to the log file for posterity */ 1280aae1086Seric pidf = fopen(PidFile, "w"); 1290aae1086Seric if (pidf != NULL) 1300aae1086Seric { 13137950f67Seric extern char *CommandLineArgs; 13237950f67Seric 13337950f67Seric /* write the process id on line 1 */ 1340aae1086Seric fprintf(pidf, "%d\n", getpid()); 13537950f67Seric 13637950f67Seric /* line 2 contains all command line flags */ 13737950f67Seric fprintf(pidf, "%s\n", CommandLineArgs); 13837950f67Seric 13937950f67Seric /* flush and close */ 1400aae1086Seric fclose(pidf); 1410aae1086Seric } 1420aae1086Seric 143dfe840b2Seric #ifdef XDEBUG 144dfe840b2Seric { 14535852b23Seric char jbuf[MAXHOSTNAMELEN]; 146dfe840b2Seric 1478b212fe0Seric expand("\201j", jbuf, sizeof jbuf, CurEnv); 14835852b23Seric j_has_dot = strchr(jbuf, '.') != NULL; 149dfe840b2Seric } 150dfe840b2Seric #endif 1510aae1086Seric 1521c71e510Seric if (tTd(15, 1)) 153b7d7afcbSeric printf("getrequests: %d\n", DaemonSocket); 1541c71e510Seric 1551c71e510Seric for (;;) 1561c71e510Seric { 1573a099713Seric register int pid; 158a44d5a5eSeric auto int lotherend; 15915d084d5Seric extern bool refuseconnections(); 1608b212fe0Seric extern int getla(); 1613a099713Seric 1623a099713Seric /* see if we are rejecting connections */ 16315d084d5Seric CurrentLA = getla(); 16415d084d5Seric if (refuseconnections()) 1656775ec03Sbostic { 1660084e6f6Seric if (DaemonSocket >= 0) 16715d084d5Seric { 1680084e6f6Seric /* close socket so peer will fail quickly */ 1690084e6f6Seric (void) close(DaemonSocket); 1700084e6f6Seric DaemonSocket = -1; 17115d084d5Seric } 1720084e6f6Seric refusingconnections = TRUE; 17371e5e267Seric setproctitle("rejecting connections: load average: %d", 17471e5e267Seric CurrentLA); 1750084e6f6Seric sleep(15); 17615d084d5Seric continue; 17715d084d5Seric } 17815d084d5Seric 1798b212fe0Seric /* arrange to (re)open the socket if necessary */ 18015d084d5Seric if (refusingconnections) 18115d084d5Seric { 1828a0cb579Seric (void) opendaemonsocket(FALSE); 18315d084d5Seric setproctitle("accepting connections"); 18415d084d5Seric refusingconnections = FALSE; 1856775ec03Sbostic } 186a44d5a5eSeric 187dfe840b2Seric #ifdef XDEBUG 188dfe840b2Seric /* check for disaster */ 189dfe840b2Seric { 19035852b23Seric char jbuf[MAXHOSTNAMELEN]; 191dfe840b2Seric 1928b212fe0Seric expand("\201j", jbuf, sizeof jbuf, CurEnv); 1938b212fe0Seric if (!wordinclass(jbuf, 'w')) 194dfe840b2Seric { 195dfe840b2Seric dumpstate("daemon lost $j"); 196dfe840b2Seric syslog(LOG_ALERT, "daemon process doesn't have $j in $=w; see syslog"); 197dfe840b2Seric abort(); 198dfe840b2Seric } 19935852b23Seric else if (j_has_dot && strchr(jbuf, '.') == NULL) 200dfe840b2Seric { 201dfe840b2Seric dumpstate("daemon $j lost dot"); 202dfe840b2Seric syslog(LOG_ALERT, "daemon process $j lost dot; see syslog"); 203dfe840b2Seric abort(); 204dfe840b2Seric } 205dfe840b2Seric } 206dfe840b2Seric #endif 207dfe840b2Seric 2081c71e510Seric /* wait for a connection */ 2091c71e510Seric do 2101c71e510Seric { 2111c71e510Seric errno = 0; 212dadb8687Seric lotherend = socksize; 2139b100374Sbostic t = accept(DaemonSocket, 2149b100374Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 2151c71e510Seric } while (t < 0 && errno == EINTR); 2161c71e510Seric if (t < 0) 2171c71e510Seric { 2181c71e510Seric syserr("getrequests: accept"); 2198b212fe0Seric 2208b212fe0Seric /* arrange to re-open the socket next time around */ 2218b212fe0Seric (void) close(DaemonSocket); 2228b212fe0Seric DaemonSocket = -1; 2231c71e510Seric sleep(5); 2241c71e510Seric continue; 2251c71e510Seric } 226d0a9e852Seric 227d0a9e852Seric /* 228d0a9e852Seric ** Create a subprocess to process the mail. 229d0a9e852Seric */ 230d0a9e852Seric 23161e4310fSeric if (tTd(15, 2)) 2321c71e510Seric printf("getrequests: forking (fd = %d)\n", t); 233eb889047Seric 234a8268164Seric pid = fork(); 235a8268164Seric if (pid < 0) 236a8268164Seric { 237a8268164Seric syserr("daemon: cannot fork"); 238a8268164Seric sleep(10); 2391c71e510Seric (void) close(t); 240a8268164Seric continue; 241a8268164Seric } 242a8268164Seric 243a8268164Seric if (pid == 0) 244a8268164Seric { 245da662164Seric char *p; 2469f8b0eadSeric extern char *hostnamebyanyaddr(); 2478b212fe0Seric extern void intsig(); 248a44d5a5eSeric 249a8268164Seric /* 250a8268164Seric ** CHILD -- return to caller. 251a44d5a5eSeric ** Collect verified idea of sending host. 252a8268164Seric ** Verify calling user id if possible here. 253a8268164Seric */ 254a8268164Seric 2552b9178d3Seric (void) setsignal(SIGCHLD, SIG_DFL); 2568b212fe0Seric (void) setsignal(SIGHUP, intsig); 2578b212fe0Seric (void) close(DaemonSocket); 2589f9b003eSeric DisConnected = FALSE; 259779ac194Seric 2604dd09a90Seric setproctitle("startup with %s", 2614dd09a90Seric anynet_ntoa(&RealHostAddr)); 2624dd09a90Seric 263a44d5a5eSeric /* determine host name */ 264da662164Seric p = hostnamebyanyaddr(&RealHostAddr); 26537b4af40Seric if (strlen(p) > MAXNAME) 26637b4af40Seric p[MAXNAME] = '\0'; 267da662164Seric RealHostName = newstr(p); 2684dd09a90Seric setproctitle("startup with %s", p); 26929dcf4baSeric 2702a6bc25bSeric #ifdef LOG 2711f2ff1a4Seric if (LogLevel > 11) 2722a6bc25bSeric { 2732a6bc25bSeric /* log connection information */ 2742a6bc25bSeric syslog(LOG_INFO, "connect from %s (%s)", 2759f8b0eadSeric RealHostName, anynet_ntoa(&RealHostAddr)); 2762a6bc25bSeric } 2772a6bc25bSeric #endif 2782a6bc25bSeric 279335eae58Seric if ((InChannel = fdopen(t, "r")) == NULL || 280335eae58Seric (t = dup(t)) < 0 || 281335eae58Seric (OutChannel = fdopen(t, "w")) == NULL) 282335eae58Seric { 283335eae58Seric syserr("cannot open SMTP server channel, fd=%d", t); 284335eae58Seric exit(0); 285335eae58Seric } 286244b09d1Seric 28729dcf4baSeric /* should we check for illegal connection here? XXX */ 288e17a3a5aSeric #ifdef XLA 289e17a3a5aSeric if (!xla_host_ok(RealHostName)) 290e17a3a5aSeric { 291244b09d1Seric message("421 Too many SMTP sessions for this host"); 292e17a3a5aSeric exit(0); 293e17a3a5aSeric } 294e17a3a5aSeric #endif 295a44d5a5eSeric 29661e4310fSeric if (tTd(15, 2)) 297d0a9e852Seric printf("getreq: returning\n"); 298a8268164Seric return; 299a8268164Seric } 300a8268164Seric 3013c154354Seric /* close the port so that others will hang (for a while) */ 3023c154354Seric (void) close(t); 3038e3e4b17Seric } 3043c154354Seric /*NOTREACHED*/ 3053c154354Seric } 3068e3e4b17Seric /* 3070084e6f6Seric ** OPENDAEMONSOCKET -- open the SMTP socket 3080084e6f6Seric ** 3090084e6f6Seric ** Deals with setting all appropriate options. DaemonAddr must 3100084e6f6Seric ** be set up in advance. 3110084e6f6Seric ** 3120084e6f6Seric ** Parameters: 31388ea5609Seric ** firsttime -- set if this is the initial open. 3140084e6f6Seric ** 3150084e6f6Seric ** Returns: 3160084e6f6Seric ** Size in bytes of the daemon socket addr. 3170084e6f6Seric ** 3180084e6f6Seric ** Side Effects: 3190084e6f6Seric ** Leaves DaemonSocket set to the open socket. 3200084e6f6Seric ** Exits if the socket cannot be created. 3210084e6f6Seric */ 3220084e6f6Seric 3236173568dSeric #define MAXOPENTRIES 10 /* maximum number of tries to open connection */ 3246173568dSeric 3250084e6f6Seric int 32688ea5609Seric opendaemonsocket(firsttime) 32788ea5609Seric bool firsttime; 3280084e6f6Seric { 3290084e6f6Seric int on = 1; 3308b212fe0Seric int socksize = 0; 3316173568dSeric int ntries = 0; 3326173568dSeric int saveerrno; 3330084e6f6Seric 3340084e6f6Seric if (tTd(15, 2)) 3350084e6f6Seric printf("opendaemonsocket()\n"); 3360084e6f6Seric 3376173568dSeric do 3386173568dSeric { 339254b93c3Seric if (ntries > 0) 340254b93c3Seric sleep(5); 34188ea5609Seric if (firsttime || DaemonSocket < 0) 34288ea5609Seric { 3430084e6f6Seric DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0); 3440084e6f6Seric if (DaemonSocket < 0) 3450084e6f6Seric { 3460084e6f6Seric /* probably another daemon already */ 3476173568dSeric saveerrno = errno; 3480084e6f6Seric syserr("opendaemonsocket: can't create server SMTP socket"); 3490084e6f6Seric severe: 3500084e6f6Seric # ifdef LOG 3510084e6f6Seric if (LogLevel > 0) 3520084e6f6Seric syslog(LOG_ALERT, "problem creating SMTP socket"); 3530084e6f6Seric # endif /* LOG */ 3546173568dSeric DaemonSocket = -1; 3556173568dSeric continue; 3560084e6f6Seric } 3570084e6f6Seric 3580084e6f6Seric /* turn on network debugging? */ 3590084e6f6Seric if (tTd(15, 101)) 3606173568dSeric (void) setsockopt(DaemonSocket, SOL_SOCKET, 3616173568dSeric SO_DEBUG, (char *)&on, 3626173568dSeric sizeof on); 3630084e6f6Seric 3646173568dSeric (void) setsockopt(DaemonSocket, SOL_SOCKET, 3656173568dSeric SO_REUSEADDR, (char *)&on, sizeof on); 3666173568dSeric (void) setsockopt(DaemonSocket, SOL_SOCKET, 3676173568dSeric SO_KEEPALIVE, (char *)&on, sizeof on); 3680084e6f6Seric 3690084e6f6Seric #ifdef SO_RCVBUF 3700084e6f6Seric if (TcpRcvBufferSize > 0) 3710084e6f6Seric { 3726173568dSeric if (setsockopt(DaemonSocket, SOL_SOCKET, 3736173568dSeric SO_RCVBUF, 3740084e6f6Seric (char *) &TcpRcvBufferSize, 3750084e6f6Seric sizeof(TcpRcvBufferSize)) < 0) 3760084e6f6Seric syserr("getrequests: setsockopt(SO_RCVBUF)"); 3770084e6f6Seric } 3780084e6f6Seric #endif 3790084e6f6Seric 3800084e6f6Seric switch (DaemonAddr.sa.sa_family) 3810084e6f6Seric { 3820084e6f6Seric # ifdef NETINET 3830084e6f6Seric case AF_INET: 3840084e6f6Seric socksize = sizeof DaemonAddr.sin; 3850084e6f6Seric break; 3860084e6f6Seric # endif 3870084e6f6Seric 3880084e6f6Seric # ifdef NETISO 3890084e6f6Seric case AF_ISO: 3900084e6f6Seric socksize = sizeof DaemonAddr.siso; 3910084e6f6Seric break; 3920084e6f6Seric # endif 3930084e6f6Seric 3940084e6f6Seric default: 3950084e6f6Seric socksize = sizeof DaemonAddr; 3960084e6f6Seric break; 3970084e6f6Seric } 3980084e6f6Seric 3990084e6f6Seric if (bind(DaemonSocket, &DaemonAddr.sa, socksize) < 0) 4000084e6f6Seric { 4016173568dSeric saveerrno = errno; 4020084e6f6Seric syserr("getrequests: cannot bind"); 4030084e6f6Seric (void) close(DaemonSocket); 4040084e6f6Seric goto severe; 4050084e6f6Seric } 40688ea5609Seric } 40788ea5609Seric if (!firsttime && listen(DaemonSocket, ListenQueueSize) < 0) 4080084e6f6Seric { 4096173568dSeric saveerrno = errno; 4100084e6f6Seric syserr("getrequests: cannot listen"); 4110084e6f6Seric (void) close(DaemonSocket); 4120084e6f6Seric goto severe; 4130084e6f6Seric } 4140084e6f6Seric return socksize; 4156173568dSeric } while (ntries++ < MAXOPENTRIES && transienterror(saveerrno)); 4168b212fe0Seric syserr("!opendaemonsocket: server SMTP socket wedged: exiting"); 4176173568dSeric finis(); 4180084e6f6Seric } 4190084e6f6Seric /* 420b7d7afcbSeric ** CLRDAEMON -- reset the daemon connection 421b7d7afcbSeric ** 422b7d7afcbSeric ** Parameters: 423b7d7afcbSeric ** none. 424b7d7afcbSeric ** 425b7d7afcbSeric ** Returns: 426b7d7afcbSeric ** none. 427b7d7afcbSeric ** 428b7d7afcbSeric ** Side Effects: 429b7d7afcbSeric ** releases any resources used by the passive daemon. 430b7d7afcbSeric */ 431b7d7afcbSeric 4328b212fe0Seric void 433b7d7afcbSeric clrdaemon() 434b7d7afcbSeric { 435b7d7afcbSeric if (DaemonSocket >= 0) 436b7d7afcbSeric (void) close(DaemonSocket); 437b7d7afcbSeric DaemonSocket = -1; 438b7d7afcbSeric } 439b7d7afcbSeric /* 440bfb80540Seric ** SETDAEMONOPTIONS -- set options for running the daemon 441bfb80540Seric ** 442bfb80540Seric ** Parameters: 443bfb80540Seric ** p -- the options line. 444bfb80540Seric ** 445bfb80540Seric ** Returns: 446bfb80540Seric ** none. 447bfb80540Seric */ 448bfb80540Seric 4498b212fe0Seric void 450bfb80540Seric setdaemonoptions(p) 451bfb80540Seric register char *p; 452bfb80540Seric { 453850144caSeric if (DaemonAddr.sa.sa_family == AF_UNSPEC) 454850144caSeric DaemonAddr.sa.sa_family = AF_INET; 455850144caSeric 456bfb80540Seric while (p != NULL) 457bfb80540Seric { 458bfb80540Seric register char *f; 459bfb80540Seric register char *v; 460bfb80540Seric 461bfb80540Seric while (isascii(*p) && isspace(*p)) 462bfb80540Seric p++; 463bfb80540Seric if (*p == '\0') 464bfb80540Seric break; 465bfb80540Seric f = p; 466bfb80540Seric p = strchr(p, ','); 467bfb80540Seric if (p != NULL) 468bfb80540Seric *p++ = '\0'; 469bfb80540Seric v = strchr(f, '='); 470bfb80540Seric if (v == NULL) 471bfb80540Seric continue; 472bfb80540Seric while (isascii(*++v) && isspace(*v)) 473bfb80540Seric continue; 474e7988623Seric if (isascii(*f) && isupper(*f)) 475e7988623Seric *f = tolower(*f); 476bfb80540Seric 477bfb80540Seric switch (*f) 478bfb80540Seric { 479850144caSeric case 'F': /* address family */ 480850144caSeric if (isascii(*v) && isdigit(*v)) 481850144caSeric DaemonAddr.sa.sa_family = atoi(v); 482850144caSeric #ifdef NETINET 483850144caSeric else if (strcasecmp(v, "inet") == 0) 484850144caSeric DaemonAddr.sa.sa_family = AF_INET; 485850144caSeric #endif 486850144caSeric #ifdef NETISO 487850144caSeric else if (strcasecmp(v, "iso") == 0) 488850144caSeric DaemonAddr.sa.sa_family = AF_ISO; 489850144caSeric #endif 490850144caSeric #ifdef NETNS 491850144caSeric else if (strcasecmp(v, "ns") == 0) 492850144caSeric DaemonAddr.sa.sa_family = AF_NS; 493850144caSeric #endif 494850144caSeric #ifdef NETX25 495850144caSeric else if (strcasecmp(v, "x.25") == 0) 496850144caSeric DaemonAddr.sa.sa_family = AF_CCITT; 497850144caSeric #endif 498850144caSeric else 499850144caSeric syserr("554 Unknown address family %s in Family=option", v); 500850144caSeric break; 501850144caSeric 502850144caSeric case 'A': /* address */ 503850144caSeric switch (DaemonAddr.sa.sa_family) 504850144caSeric { 505850144caSeric #ifdef NETINET 506850144caSeric case AF_INET: 507850144caSeric if (isascii(*v) && isdigit(*v)) 5088b212fe0Seric DaemonAddr.sin.sin_addr.s_addr = htonl(inet_network(v)); 509850144caSeric else 510850144caSeric { 511850144caSeric register struct netent *np; 512850144caSeric 513850144caSeric np = getnetbyname(v); 514850144caSeric if (np == NULL) 515850144caSeric syserr("554 network \"%s\" unknown", v); 516850144caSeric else 517850144caSeric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 518850144caSeric } 519850144caSeric break; 520850144caSeric #endif 521850144caSeric 522850144caSeric default: 523850144caSeric syserr("554 Address= option unsupported for family %d", 524850144caSeric DaemonAddr.sa.sa_family); 525850144caSeric break; 526850144caSeric } 527850144caSeric break; 528850144caSeric 529bfb80540Seric case 'P': /* port */ 530850144caSeric switch (DaemonAddr.sa.sa_family) 531850144caSeric { 532850144caSeric short port; 533850144caSeric 534850144caSeric #ifdef NETINET 535850144caSeric case AF_INET: 536bfb80540Seric if (isascii(*v) && isdigit(*v)) 53776b70c58Seric DaemonAddr.sin.sin_port = htons(atoi(v)); 538bfb80540Seric else 539bfb80540Seric { 540bfb80540Seric register struct servent *sp; 541bfb80540Seric 542bfb80540Seric sp = getservbyname(v, "tcp"); 543bfb80540Seric if (sp == NULL) 544ad977999Seric syserr("554 service \"%s\" unknown", v); 545bfb80540Seric else 546bfb80540Seric DaemonAddr.sin.sin_port = sp->s_port; 547bfb80540Seric } 548bfb80540Seric break; 549850144caSeric #endif 550bfb80540Seric 551850144caSeric #ifdef NETISO 552850144caSeric case AF_ISO: 553850144caSeric /* assume two byte transport selector */ 554bfb80540Seric if (isascii(*v) && isdigit(*v)) 55576b70c58Seric port = htons(atoi(v)); 556bfb80540Seric else 557bfb80540Seric { 558850144caSeric register struct servent *sp; 559bfb80540Seric 560850144caSeric sp = getservbyname(v, "tcp"); 561850144caSeric if (sp == NULL) 562ad977999Seric syserr("554 service \"%s\" unknown", v); 563bfb80540Seric else 564850144caSeric port = sp->s_port; 565850144caSeric } 566850144caSeric bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 567850144caSeric break; 568850144caSeric #endif 569850144caSeric 570850144caSeric default: 571850144caSeric syserr("554 Port= option unsupported for family %d", 572850144caSeric DaemonAddr.sa.sa_family); 573850144caSeric break; 574bfb80540Seric } 575bfb80540Seric break; 576bfc1eaf8Seric 577bfc1eaf8Seric case 'L': /* listen queue size */ 578bfc1eaf8Seric ListenQueueSize = atoi(v); 579bfc1eaf8Seric break; 580b35447dbSeric 581b35447dbSeric case 'S': /* send buffer size */ 582b35447dbSeric TcpSndBufferSize = atoi(v); 583b35447dbSeric break; 584b35447dbSeric 585b35447dbSeric case 'R': /* receive buffer size */ 586b35447dbSeric TcpRcvBufferSize = atoi(v); 587b35447dbSeric break; 588e7988623Seric 589e7988623Seric default: 590e7988623Seric syserr("554 DaemonPortOptions parameter \"%s\" unknown", f); 591bfb80540Seric } 592bfb80540Seric } 593bfb80540Seric } 594bfb80540Seric /* 5957aa493c5Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 5967aa493c5Seric ** 5977aa493c5Seric ** Parameters: 5987aa493c5Seric ** host -- the name of the host. 59948ff0a9dSeric ** port -- the port number to connect to. 600655feedbSeric ** mci -- a pointer to the mail connection information 601655feedbSeric ** structure to be filled in. 602914346b1Seric ** usesecureport -- if set, use a low numbered (reserved) 603914346b1Seric ** port to provide some rudimentary authentication. 6047aa493c5Seric ** 6057aa493c5Seric ** Returns: 6067aa493c5Seric ** An exit code telling whether the connection could be 6077aa493c5Seric ** made and if not why not. 6087aa493c5Seric ** 6097aa493c5Seric ** Side Effects: 6107aa493c5Seric ** none. 6117aa493c5Seric */ 6127aa493c5Seric 613e2f2f828Seric SOCKADDR CurHostAddr; /* address of current host */ 61471ff6caaSeric 615b31e7f2bSeric int 616655feedbSeric makeconnection(host, port, mci, usesecureport) 6177aa493c5Seric char *host; 618210215eaSeric u_short port; 619b31e7f2bSeric register MCI *mci; 620914346b1Seric bool usesecureport; 6217aa493c5Seric { 6228b212fe0Seric register int i = 0; 6238b212fe0Seric register int s; 62404344589Sbloom register struct hostent *hp = (struct hostent *)NULL; 625e2f2f828Seric SOCKADDR addr; 6266286bb75Sbloom int sav_errno; 627e2f2f828Seric int addrlen; 6288b212fe0Seric bool firstconnect; 6299d4a8008Seric #if NAMED_BIND 630134746fbSeric extern int h_errno; 631134746fbSeric #endif 6327aa493c5Seric 6337aa493c5Seric /* 6347aa493c5Seric ** Set up the address for the mailer. 63571096d12Seric ** Accept "[a.b.c.d]" syntax for host name. 6367aa493c5Seric */ 6377aa493c5Seric 6389d4a8008Seric #if NAMED_BIND 639794bdbb9Smiriam h_errno = 0; 640134746fbSeric #endif 641794bdbb9Smiriam errno = 0; 642967778e2Seric bzero(&CurHostAddr, sizeof CurHostAddr); 643c931b82bSeric SmtpPhase = mci->mci_phase = "initial connection"; 644d945ebe8Seric CurHostName = host; 645794bdbb9Smiriam 64671096d12Seric if (host[0] == '[') 64771096d12Seric { 648a44d5a5eSeric long hid; 6496c2c3107Seric register char *p = strchr(host, ']'); 65071096d12Seric 651a44d5a5eSeric if (p != NULL) 65271096d12Seric { 653a44d5a5eSeric *p = '\0'; 6544d9c42c2Seric #ifdef NETINET 655a44d5a5eSeric hid = inet_addr(&host[1]); 656a7e21fe6Seric if (hid == -1) 6574d9c42c2Seric #endif 658a7e21fe6Seric { 659a7e21fe6Seric /* try it as a host name (avoid MX lookup) */ 6608b212fe0Seric hp = sm_gethostbyname(&host[1]); 661d8984352Seric if (hp == NULL && p[-1] == '.') 662d8984352Seric { 6638b212fe0Seric #if NAMED_BIND 6648b212fe0Seric int oldopts = _res.options; 6658b212fe0Seric 6668b212fe0Seric _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 6678b212fe0Seric #endif 668d8984352Seric p[-1] = '\0'; 6698b212fe0Seric hp = sm_gethostbyname(&host[1]); 670d8984352Seric p[-1] = '.'; 6718b212fe0Seric #if NAMED_BIND 6728b212fe0Seric _res.options = oldopts; 6738b212fe0Seric #endif 674d8984352Seric } 675a7e21fe6Seric *p = ']'; 676a7e21fe6Seric goto gothostent; 677a7e21fe6Seric } 678a44d5a5eSeric *p = ']'; 67971096d12Seric } 680a7e21fe6Seric if (p == NULL) 68171096d12Seric { 68208b25121Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 6835b068d51Seric mci->mci_status = "5.1.2"; 68471096d12Seric return (EX_NOHOST); 68571096d12Seric } 6864d9c42c2Seric #ifdef NETINET 6874d9c42c2Seric addr.sin.sin_family = AF_INET; /*XXX*/ 68883c1f4bcSeric addr.sin.sin_addr.s_addr = hid; 6894d9c42c2Seric #endif 69071096d12Seric } 6911c71e510Seric else 6921c71e510Seric { 693d8984352Seric register char *p = &host[strlen(host) - 1]; 694d8984352Seric 6958b212fe0Seric hp = sm_gethostbyname(host); 696d8984352Seric if (hp == NULL && *p == '.') 697d8984352Seric { 6988b212fe0Seric #if NAMED_BIND 6998b212fe0Seric int oldopts = _res.options; 7008b212fe0Seric 7018b212fe0Seric _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 7028b212fe0Seric #endif 703d8984352Seric *p = '\0'; 7048b212fe0Seric hp = sm_gethostbyname(host); 705d8984352Seric *p = '.'; 7068b212fe0Seric #if NAMED_BIND 7078b212fe0Seric _res.options = oldopts; 7088b212fe0Seric #endif 709d8984352Seric } 710a7e21fe6Seric gothostent: 711794bdbb9Smiriam if (hp == NULL) 712794bdbb9Smiriam { 7139d4a8008Seric #if NAMED_BIND 7148b212fe0Seric /* check for name server timeouts */ 7158b212fe0Seric if (errno == ETIMEDOUT || h_errno == TRY_AGAIN || 7168b212fe0Seric (errno == ECONNREFUSED && UseNameServer)) 7178b212fe0Seric { 7188b212fe0Seric mci->mci_status = "4.4.3"; 71952308a50Seric return (EX_TEMPFAIL); 7208b212fe0Seric } 721134746fbSeric #endif 7227aa493c5Seric return (EX_NOHOST); 723794bdbb9Smiriam } 72483c1f4bcSeric addr.sa.sa_family = hp->h_addrtype; 72583c1f4bcSeric switch (hp->h_addrtype) 72683c1f4bcSeric { 72783c1f4bcSeric #ifdef NETINET 72883c1f4bcSeric case AF_INET: 729e2f2f828Seric bcopy(hp->h_addr, 73083c1f4bcSeric &addr.sin.sin_addr, 7318b212fe0Seric INADDRSZ); 73283c1f4bcSeric break; 73383c1f4bcSeric #endif 73483c1f4bcSeric 73583c1f4bcSeric default: 736e2f2f828Seric bcopy(hp->h_addr, 73783c1f4bcSeric addr.sa.sa_data, 738e2f2f828Seric hp->h_length); 73983c1f4bcSeric break; 74083c1f4bcSeric } 74104344589Sbloom i = 1; 7421c71e510Seric } 7431c71e510Seric 7441c71e510Seric /* 7451c71e510Seric ** Determine the port number. 7461c71e510Seric */ 7471c71e510Seric 748fd7c0790Seric if (port != 0) 749e2f2f828Seric port = htons(port); 750fd7c0790Seric else 7511c71e510Seric { 7521c71e510Seric register struct servent *sp = getservbyname("smtp", "tcp"); 7531c71e510Seric 7541c71e510Seric if (sp == NULL) 7551c71e510Seric { 7563edb2e00Seric #ifdef LOG 7573edb2e00Seric if (LogLevel > 2) 7583edb2e00Seric syslog(LOG_ERR, "makeconnection: service \"smtp\" unknown"); 7593edb2e00Seric #endif 760e5311662Seric port = htons(25); 7611c71e510Seric } 762e5311662Seric else 763e2f2f828Seric port = sp->s_port; 764e2f2f828Seric } 765e2f2f828Seric 76683c1f4bcSeric switch (addr.sa.sa_family) 767e2f2f828Seric { 7684d9c42c2Seric #ifdef NETINET 769e2f2f828Seric case AF_INET: 77083c1f4bcSeric addr.sin.sin_port = port; 771e2f2f828Seric addrlen = sizeof (struct sockaddr_in); 772e2f2f828Seric break; 7734d9c42c2Seric #endif 774e2f2f828Seric 775e2f2f828Seric #ifdef NETISO 776e2f2f828Seric case AF_ISO: 777e2f2f828Seric /* assume two byte transport selector */ 778e2f2f828Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 779e2f2f828Seric addrlen = sizeof (struct sockaddr_iso); 780e2f2f828Seric break; 781e2f2f828Seric #endif 782e2f2f828Seric 783e2f2f828Seric default: 78483c1f4bcSeric syserr("Can't connect to address family %d", addr.sa.sa_family); 785e2f2f828Seric return (EX_NOHOST); 7861c71e510Seric } 7877aa493c5Seric 7887aa493c5Seric /* 7897aa493c5Seric ** Try to actually open the connection. 7907aa493c5Seric */ 7917aa493c5Seric 792e17a3a5aSeric #ifdef XLA 793e17a3a5aSeric /* if too many connections, don't bother trying */ 794e17a3a5aSeric if (!xla_noqueue_ok(host)) 795e17a3a5aSeric return EX_TEMPFAIL; 796e17a3a5aSeric #endif 797e17a3a5aSeric 7988b212fe0Seric firstconnect = TRUE; 799aea02ca1Seric for (;;) 800aea02ca1Seric { 80161e4310fSeric if (tTd(16, 1)) 802e2f2f828Seric printf("makeconnection (%s [%s])\n", 803e2f2f828Seric host, anynet_ntoa(&addr)); 8047aa493c5Seric 805226e3022Seric /* save for logging */ 806226e3022Seric CurHostAddr = addr; 807226e3022Seric 808914346b1Seric if (usesecureport) 809914346b1Seric { 810914346b1Seric int rport = IPPORT_RESERVED - 1; 811914346b1Seric 812914346b1Seric s = rresvport(&rport); 813914346b1Seric } 814914346b1Seric else 815914346b1Seric { 816af5e902cSeric s = socket(AF_INET, SOCK_STREAM, 0); 817914346b1Seric } 8187aa493c5Seric if (s < 0) 8197aa493c5Seric { 8206286bb75Sbloom sav_errno = errno; 821914346b1Seric syserr("makeconnection: no socket"); 8227aa493c5Seric goto failure; 8237aa493c5Seric } 8247aa493c5Seric 825b35447dbSeric #ifdef SO_SNDBUF 826b35447dbSeric if (TcpSndBufferSize > 0) 827b35447dbSeric { 828b35447dbSeric if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 829bf217a95Seric (char *) &TcpSndBufferSize, 830b35447dbSeric sizeof(TcpSndBufferSize)) < 0) 831b35447dbSeric syserr("makeconnection: setsockopt(SO_SNDBUF)"); 832b35447dbSeric } 833b35447dbSeric #endif 834b35447dbSeric 83561e4310fSeric if (tTd(16, 1)) 836b31e7f2bSeric printf("makeconnection: fd=%d\n", s); 8371b6e4a15Seric 8381b6e4a15Seric /* turn on network debugging? */ 839a2ef5fa4Seric if (tTd(16, 101)) 84052308a50Seric { 84152308a50Seric int on = 1; 8426173568dSeric (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, 843aea02ca1Seric (char *)&on, sizeof on); 84452308a50Seric } 84587d6e633Srick if (CurEnv->e_xfp != NULL) 846877a6142Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 8474bd6a662Seric errno = 0; /* for debugging */ 848e2f2f828Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 849aea02ca1Seric break; 850aea02ca1Seric 8518b212fe0Seric /* if running demand-dialed connection, try again */ 8528b212fe0Seric if (DialDelay > 0 && firstconnect) 8538b212fe0Seric { 8548b212fe0Seric if (tTd(16, 1)) 8558b212fe0Seric printf("Connect failed (%s); trying again...\n", 8568b212fe0Seric errstring(sav_errno)); 8578b212fe0Seric firstconnect = FALSE; 8588b212fe0Seric sleep(DialDelay); 8598b212fe0Seric continue; 8608b212fe0Seric } 8618b212fe0Seric 862aea02ca1Seric /* couldn't connect.... figure out why */ 8636286bb75Sbloom sav_errno = errno; 8646286bb75Sbloom (void) close(s); 8658b212fe0Seric if (hp != NULL && hp->h_addr_list[i]) 86604344589Sbloom { 867aea02ca1Seric if (tTd(16, 1)) 868e2f2f828Seric printf("Connect failed (%s); trying new address....\n", 869e2f2f828Seric errstring(sav_errno)); 87083c1f4bcSeric switch (addr.sa.sa_family) 87183c1f4bcSeric { 87283c1f4bcSeric #ifdef NETINET 87383c1f4bcSeric case AF_INET: 874e2f2f828Seric bcopy(hp->h_addr_list[i++], 87583c1f4bcSeric &addr.sin.sin_addr, 8768b212fe0Seric INADDRSZ); 87783c1f4bcSeric break; 87883c1f4bcSeric #endif 87983c1f4bcSeric 88083c1f4bcSeric default: 881e2f2f828Seric bcopy(hp->h_addr_list[i++], 88283c1f4bcSeric addr.sa.sa_data, 883914346b1Seric hp->h_length); 88483c1f4bcSeric break; 88583c1f4bcSeric } 886aea02ca1Seric continue; 88704344589Sbloom } 88804344589Sbloom 8897aa493c5Seric /* failure, decide if temporary or not */ 8907aa493c5Seric failure: 891244b09d1Seric #ifdef XLA 892244b09d1Seric xla_host_end(host); 893244b09d1Seric #endif 894e2de2524Seric if (transienterror(sav_errno)) 895e2de2524Seric return EX_TEMPFAIL; 896e2de2524Seric else 89787d6e633Srick { 89808b25121Seric message("%s", errstring(sav_errno)); 8997aa493c5Seric return (EX_UNAVAILABLE); 9007aa493c5Seric } 9017aa493c5Seric } 9027aa493c5Seric 9037aa493c5Seric /* connection ok, put it into canonical form */ 904335eae58Seric if ((mci->mci_out = fdopen(s, "w")) == NULL || 905335eae58Seric (s = dup(s)) < 0 || 906ab81ee53Seric (mci->mci_in = fdopen(s, "r")) == NULL) 907335eae58Seric { 908335eae58Seric syserr("cannot open SMTP client channel, fd=%d", s); 909335eae58Seric return EX_TEMPFAIL; 910335eae58Seric } 9117aa493c5Seric 912dca8e1f7Seric return (EX_OK); 9137aa493c5Seric } 914444eaf03Seric /* 915444eaf03Seric ** MYHOSTNAME -- return the name of this host. 916444eaf03Seric ** 917444eaf03Seric ** Parameters: 918444eaf03Seric ** hostbuf -- a place to return the name of this host. 919897f1869Seric ** size -- the size of hostbuf. 920444eaf03Seric ** 921444eaf03Seric ** Returns: 922444eaf03Seric ** A list of aliases for this host. 923444eaf03Seric ** 924444eaf03Seric ** Side Effects: 925d8d0a4aeSeric ** Adds numeric codes to $=w. 926444eaf03Seric */ 927444eaf03Seric 9288b212fe0Seric struct hostent * 929897f1869Seric myhostname(hostbuf, size) 930444eaf03Seric char hostbuf[]; 931897f1869Seric int size; 932444eaf03Seric { 93338ad259dSeric register struct hostent *hp; 9348b212fe0Seric extern bool getcanonname(); 9358b212fe0Seric extern int h_errno; 936444eaf03Seric 937af5e902cSeric if (gethostname(hostbuf, size) < 0) 938af5e902cSeric { 939af5e902cSeric (void) strcpy(hostbuf, "localhost"); 940af5e902cSeric } 9418b212fe0Seric hp = sm_gethostbyname(hostbuf); 9424a5c6430Seric if (hp == NULL) 9438b212fe0Seric return NULL; 9448b212fe0Seric if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL) 945423161fbSeric { 94635852b23Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 94735852b23Seric hostbuf[size - 1] = '\0'; 9488b212fe0Seric } 9494a5c6430Seric 9504a5c6430Seric #if NAMED_BIND 9518b212fe0Seric /* 9528b212fe0Seric ** If still no dot, try DNS directly (i.e., avoid NIS problems). 9538b212fe0Seric ** This ought to be driven from the configuration file, but 9548b212fe0Seric ** we are called before the configuration is read. We could 9558b212fe0Seric ** check for an /etc/resolv.conf file, but that isn't required. 9568b212fe0Seric ** All in all, a bit of a mess. 9578b212fe0Seric */ 95823668637Seric 9598b212fe0Seric if (strchr(hostbuf, '.') == NULL && 9608b212fe0Seric !getcanonname(hostbuf, size, TRUE) && 9618b212fe0Seric h_errno == TRY_AGAIN) 96223668637Seric { 9638b212fe0Seric /* try twice in case name server not yet started up */ 9648b212fe0Seric message("My unqualifed host name (%s) unknown to DNS; sleeping for retry", 96523668637Seric hostbuf); 9668b212fe0Seric sleep(60); 9678b212fe0Seric if (!getcanonname(hostbuf, size, TRUE)) 9688b212fe0Seric errno = h_errno + E_DNSBASE; 969747df804Seric } 970747df804Seric #endif 9718b212fe0Seric return (hp); 9727364df9fSeric } 973cb452edcSeric /* 9749f8b0eadSeric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 9759f8b0eadSeric ** 9769f8b0eadSeric ** Uses RFC1413 protocol to try to get info from the other end. 977320e0d1cSeric ** 978320e0d1cSeric ** Parameters: 979320e0d1cSeric ** fd -- the descriptor 980320e0d1cSeric ** 981320e0d1cSeric ** Returns: 9829f8b0eadSeric ** The user@host information associated with this descriptor. 983320e0d1cSeric */ 984320e0d1cSeric 9859f8b0eadSeric static jmp_buf CtxAuthTimeout; 9869f8b0eadSeric 9878b212fe0Seric static void 9889f8b0eadSeric authtimeout() 9899f8b0eadSeric { 9909f8b0eadSeric longjmp(CtxAuthTimeout, 1); 9919f8b0eadSeric } 9929f8b0eadSeric 993320e0d1cSeric char * 9949f8b0eadSeric getauthinfo(fd) 995320e0d1cSeric int fd; 996320e0d1cSeric { 9979f8b0eadSeric int falen; 998a5546e24Seric register char *p; 9999f8b0eadSeric SOCKADDR la; 10009f8b0eadSeric int lalen; 10019f8b0eadSeric register struct servent *sp; 10029f8b0eadSeric int s; 10039f8b0eadSeric int i; 10049f8b0eadSeric EVENT *ev; 1005579270a3Seric int nleft; 1006f036c8d7Seric char ibuf[MAXNAME + 1]; 10079f8b0eadSeric static char hbuf[MAXNAME * 2 + 2]; 10089f8b0eadSeric extern char *hostnamebyanyaddr(); 10099f8b0eadSeric extern char RealUserName[]; /* main.c */ 1010320e0d1cSeric 1011e29a76d1Seric falen = sizeof RealHostAddr; 10128b212fe0Seric if (isatty(fd) || getpeername(fd, &RealHostAddr.sa, &falen) < 0 || 10138b212fe0Seric falen <= 0 || RealHostAddr.sa.sa_family == 0) 10149f8b0eadSeric { 10159f8b0eadSeric (void) sprintf(hbuf, "%s@localhost", RealUserName); 101653853673Seric if (tTd(9, 1)) 10179f8b0eadSeric printf("getauthinfo: %s\n", hbuf); 1018320e0d1cSeric return hbuf; 1019320e0d1cSeric } 10209f8b0eadSeric 1021e29a76d1Seric if (RealHostName == NULL) 1022e29a76d1Seric { 1023e29a76d1Seric /* translate that to a host name */ 1024e29a76d1Seric RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 1025e29a76d1Seric } 1026e29a76d1Seric 102793b3215bSeric if (TimeOuts.to_ident == 0) 102893b3215bSeric goto noident; 102993b3215bSeric 10309f8b0eadSeric lalen = sizeof la; 1031e29a76d1Seric if (RealHostAddr.sa.sa_family != AF_INET || 10329f8b0eadSeric getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || 10339f8b0eadSeric la.sa.sa_family != AF_INET) 10349f8b0eadSeric { 10359f8b0eadSeric /* no ident info */ 10369f8b0eadSeric goto noident; 10379f8b0eadSeric } 10389f8b0eadSeric 10399f8b0eadSeric /* create ident query */ 104081d2944fSeric (void) sprintf(ibuf, "%d,%d\r\n", 1041e29a76d1Seric ntohs(RealHostAddr.sin.sin_port), ntohs(la.sin.sin_port)); 10429f8b0eadSeric 10439f8b0eadSeric /* create local address */ 1044d6af7dadSeric la.sin.sin_port = 0; 10459f8b0eadSeric 10469f8b0eadSeric /* create foreign address */ 10479f8b0eadSeric sp = getservbyname("auth", "tcp"); 10489f8b0eadSeric if (sp != NULL) 1049e29a76d1Seric RealHostAddr.sin.sin_port = sp->s_port; 10509f8b0eadSeric else 1051e29a76d1Seric RealHostAddr.sin.sin_port = htons(113); 10529f8b0eadSeric 10539f8b0eadSeric s = -1; 10549f8b0eadSeric if (setjmp(CtxAuthTimeout) != 0) 10559f8b0eadSeric { 10569f8b0eadSeric if (s >= 0) 10579f8b0eadSeric (void) close(s); 10589f8b0eadSeric goto noident; 10599f8b0eadSeric } 10609f8b0eadSeric 10619f8b0eadSeric /* put a timeout around the whole thing */ 1062a0f780efSeric ev = setevent(TimeOuts.to_ident, authtimeout, 0); 10639f8b0eadSeric 1064d6af7dadSeric /* connect to foreign IDENT server using same address as SMTP socket */ 10659f8b0eadSeric s = socket(AF_INET, SOCK_STREAM, 0); 10669f8b0eadSeric if (s < 0) 10679f8b0eadSeric { 10689f8b0eadSeric clrevent(ev); 10699f8b0eadSeric goto noident; 10709f8b0eadSeric } 1071d6af7dadSeric if (bind(s, &la.sa, sizeof la.sin) < 0 || 1072e29a76d1Seric connect(s, &RealHostAddr.sa, sizeof RealHostAddr.sin) < 0) 10739f8b0eadSeric { 10747c201575Seric goto closeident; 10759f8b0eadSeric } 10769f8b0eadSeric 107753853673Seric if (tTd(9, 10)) 107881d2944fSeric printf("getauthinfo: sent %s", ibuf); 10799f8b0eadSeric 10809f8b0eadSeric /* send query */ 108181d2944fSeric if (write(s, ibuf, strlen(ibuf)) < 0) 10829f8b0eadSeric goto closeident; 10839f8b0eadSeric 10849f8b0eadSeric /* get result */ 108581d2944fSeric p = &ibuf[0]; 1086b26156f6Seric nleft = sizeof ibuf - 1; 1087579270a3Seric while ((i = read(s, p, nleft)) > 0) 1088579270a3Seric { 1089579270a3Seric p += i; 1090579270a3Seric nleft -= i; 1091579270a3Seric } 10929f8b0eadSeric (void) close(s); 10939f8b0eadSeric clrevent(ev); 109481d2944fSeric if (i < 0 || p == &ibuf[0]) 10959f8b0eadSeric goto noident; 1096579270a3Seric 1097579270a3Seric if (*--p == '\n' && *--p == '\r') 1098579270a3Seric p--; 1099579270a3Seric *++p = '\0'; 11009f8b0eadSeric 110153853673Seric if (tTd(9, 3)) 110281d2944fSeric printf("getauthinfo: got %s\n", ibuf); 11039f8b0eadSeric 11049f8b0eadSeric /* parse result */ 110581d2944fSeric p = strchr(ibuf, ':'); 11069f8b0eadSeric if (p == NULL) 11079f8b0eadSeric { 11089f8b0eadSeric /* malformed response */ 11099f8b0eadSeric goto noident; 11109f8b0eadSeric } 11119f8b0eadSeric while (isascii(*++p) && isspace(*p)) 11129f8b0eadSeric continue; 11139f8b0eadSeric if (strncasecmp(p, "userid", 6) != 0) 11149f8b0eadSeric { 11159f8b0eadSeric /* presumably an error string */ 11169f8b0eadSeric goto noident; 11179f8b0eadSeric } 11189f8b0eadSeric p += 6; 11199f8b0eadSeric while (isascii(*p) && isspace(*p)) 11209f8b0eadSeric p++; 11219f8b0eadSeric if (*p++ != ':') 11229f8b0eadSeric { 11239f8b0eadSeric /* either useridxx or malformed response */ 11249f8b0eadSeric goto noident; 11259f8b0eadSeric } 11269f8b0eadSeric 11279f8b0eadSeric /* p now points to the OSTYPE field */ 11288b212fe0Seric while (isascii(*p) && isspace(*p)) 11298b212fe0Seric p++; 11308b212fe0Seric if (strncasecmp(p, "other", 5) == 0 && 11318b212fe0Seric (p[5] == ':' || p[5] == ' ' || p[5] == ',' || p[5] == '\0')) 11328b212fe0Seric { 11338b212fe0Seric /* not useful information */ 11348b212fe0Seric goto noident; 11358b212fe0Seric } 11369f8b0eadSeric p = strchr(p, ':'); 11379f8b0eadSeric if (p == NULL) 11389f8b0eadSeric { 11399f8b0eadSeric /* malformed response */ 11409f8b0eadSeric goto noident; 11419f8b0eadSeric } 114253853673Seric 114353853673Seric /* 1413 says don't do this -- but it's broken otherwise */ 114453853673Seric while (isascii(*++p) && isspace(*p)) 114553853673Seric continue; 11469f8b0eadSeric 1147a7763879Seric /* p now points to the authenticated name -- copy carefully */ 114881d2944fSeric cleanstrcpy(hbuf, p, MAXNAME); 114993433f31Seric i = strlen(hbuf); 1150a7763879Seric hbuf[i++] = '@'; 1151a7763879Seric strcpy(&hbuf[i], RealHostName == NULL ? "localhost" : RealHostName); 115253853673Seric goto finish; 115353853673Seric 11547c201575Seric closeident: 11557c201575Seric (void) close(s); 11567c201575Seric clrevent(ev); 11577c201575Seric 115853853673Seric noident: 1159f7869e68Seric if (RealHostName == NULL) 1160f7869e68Seric { 1161f7869e68Seric if (tTd(9, 1)) 1162f7869e68Seric printf("getauthinfo: NULL\n"); 1163f7869e68Seric return NULL; 1164f7869e68Seric } 116553853673Seric (void) strcpy(hbuf, RealHostName); 116653853673Seric 116753853673Seric finish: 1168f7869e68Seric if (RealHostName != NULL && RealHostName[0] != '[') 11699f8b0eadSeric { 11709f8b0eadSeric p = &hbuf[strlen(hbuf)]; 11719f8b0eadSeric (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); 11729f8b0eadSeric } 117353853673Seric if (tTd(9, 1)) 11749f8b0eadSeric printf("getauthinfo: %s\n", hbuf); 11759f8b0eadSeric return hbuf; 11769f8b0eadSeric } 1177320e0d1cSeric /* 117808de856eSeric ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 117915d084d5Seric ** 118015d084d5Seric ** Parameters: 118105b57da8Seric ** map -- a pointer to this map (unused). 118208de856eSeric ** name -- the (presumably unqualified) hostname. 118300b385a9Seric ** av -- unused -- for compatibility with other mapping 1184d798a1deSeric ** functions. 11852d29d43aSeric ** statp -- an exit status (out parameter) -- set to 11862d29d43aSeric ** EX_TEMPFAIL if the name server is unavailable. 118715d084d5Seric ** 118815d084d5Seric ** Returns: 118915d084d5Seric ** The mapping, if found. 119015d084d5Seric ** NULL if no mapping found. 119115d084d5Seric ** 119215d084d5Seric ** Side Effects: 119315d084d5Seric ** Looks up the host specified in hbuf. If it is not 119415d084d5Seric ** the canonical name for that host, return the canonical 119515d084d5Seric ** name. 1196f36ede03Sbostic */ 1197cb452edcSeric 119815d084d5Seric char * 119900b385a9Seric host_map_lookup(map, name, av, statp) 120005b57da8Seric MAP *map; 120108de856eSeric char *name; 120200b385a9Seric char **av; 12032d29d43aSeric int *statp; 120499f7cf32Seric { 120599f7cf32Seric register struct hostent *hp; 12068b212fe0Seric struct in_addr in_addr; 120705b57da8Seric char *cp; 1208eea91d78Seric register STAB *s; 12098b212fe0Seric char hbuf[MAXNAME + 1]; 12109d4a8008Seric #if NAMED_BIND 1211eea91d78Seric extern int h_errno; 1212c304a798Seric #endif 12135f78836eSmiriam 1214f36ede03Sbostic /* 1215eea91d78Seric ** See if we have already looked up this name. If so, just 1216eea91d78Seric ** return it. 1217eea91d78Seric */ 1218eea91d78Seric 121908de856eSeric s = stab(name, ST_NAMECANON, ST_ENTER); 1220eea91d78Seric if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 1221eea91d78Seric { 1222f92c3297Seric if (tTd(9, 1)) 122308de856eSeric printf("host_map_lookup(%s) => CACHE %s\n", 122498826a83Seric name, 122598826a83Seric s->s_namecanon.nc_cname == NULL 122698826a83Seric ? "NULL" 1227*5f08d413Seric : s->s_namecanon.nc_cname); 1228eea91d78Seric errno = s->s_namecanon.nc_errno; 12299d4a8008Seric #if NAMED_BIND 1230eea91d78Seric h_errno = s->s_namecanon.nc_herrno; 1231c304a798Seric #endif 1232eea91d78Seric *statp = s->s_namecanon.nc_stat; 1233fcfb36d9Seric if (*statp == EX_TEMPFAIL) 1234ed63aae0Seric { 12355b068d51Seric CurEnv->e_status = "4.4.3"; 1236fcfb36d9Seric usrerr("451 %s: Name server timeout", 1237ed63aae0Seric shortenstring(name, 33)); 1238ed63aae0Seric } 1239eea91d78Seric return s->s_namecanon.nc_cname; 1240eea91d78Seric } 1241eea91d78Seric 1242eea91d78Seric /* 1243eea91d78Seric ** If first character is a bracket, then it is an address 1244eea91d78Seric ** lookup. Address is copied into a temporary buffer to 124508de856eSeric ** strip the brackets and to preserve name if address is 1246eea91d78Seric ** unknown. 1247f36ede03Sbostic */ 124815d084d5Seric 124908de856eSeric if (*name != '[') 125015d084d5Seric { 1251d798a1deSeric extern bool getcanonname(); 1252d798a1deSeric 12538cb4653dSeric if (tTd(9, 1)) 125408de856eSeric printf("host_map_lookup(%s) => ", name); 1255eea91d78Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 12568b212fe0Seric if (strlen(name) < sizeof hbuf) 125708de856eSeric (void) strcpy(hbuf, name); 12588b212fe0Seric else 12598b212fe0Seric { 12608b212fe0Seric bcopy(name, hbuf, sizeof hbuf - 1); 12618b212fe0Seric hbuf[sizeof hbuf - 1] = '\0'; 12628b212fe0Seric } 12630183c3f6Seric if (getcanonname(hbuf, sizeof hbuf - 1, !NoMXforCanon)) 12649040ec4fSeric { 12659040ec4fSeric if (tTd(9, 1)) 12669040ec4fSeric printf("%s\n", hbuf); 126700b385a9Seric cp = map_rewrite(map, hbuf, strlen(hbuf), av); 126800b385a9Seric s->s_namecanon.nc_cname = newstr(cp); 126900b385a9Seric return cp; 12709040ec4fSeric } 127115d084d5Seric else 12729040ec4fSeric { 12732d29d43aSeric register struct hostent *hp; 12742d29d43aSeric 1275c304a798Seric s->s_namecanon.nc_errno = errno; 12769d4a8008Seric #if NAMED_BIND 1277c304a798Seric s->s_namecanon.nc_herrno = h_errno; 12789040ec4fSeric if (tTd(9, 1)) 12792d29d43aSeric printf("FAIL (%d)\n", h_errno); 12802d29d43aSeric switch (h_errno) 12812d29d43aSeric { 12822d29d43aSeric case TRY_AGAIN: 128389cb2793Seric if (UseNameServer) 12848820d51bSeric { 12855b068d51Seric CurEnv->e_status = "4.4.3"; 1286fcfb36d9Seric usrerr("451 %s: Name server timeout", 1287ed63aae0Seric shortenstring(name, 33)); 12888820d51bSeric } 12892d29d43aSeric *statp = EX_TEMPFAIL; 12902d29d43aSeric break; 12912d29d43aSeric 12922d29d43aSeric case HOST_NOT_FOUND: 129380027ae6Seric case NO_DATA: 12942d29d43aSeric *statp = EX_NOHOST; 12952d29d43aSeric break; 12962d29d43aSeric 12972d29d43aSeric case NO_RECOVERY: 12982d29d43aSeric *statp = EX_SOFTWARE; 12992d29d43aSeric break; 13002d29d43aSeric 13012d29d43aSeric default: 13022d29d43aSeric *statp = EX_UNAVAILABLE; 13032d29d43aSeric break; 13042d29d43aSeric } 1305c304a798Seric #else 1306c304a798Seric if (tTd(9, 1)) 1307c304a798Seric printf("FAIL\n"); 1308c304a798Seric *statp = EX_NOHOST; 1309c304a798Seric #endif 1310eea91d78Seric s->s_namecanon.nc_stat = *statp; 13118b212fe0Seric if ((*statp != EX_TEMPFAIL && *statp != EX_NOHOST) || 13128b212fe0Seric UseNameServer) 131315d084d5Seric return NULL; 13142d29d43aSeric 13152d29d43aSeric /* 13162d29d43aSeric ** Try to look it up in /etc/hosts 13172d29d43aSeric */ 13182d29d43aSeric 13198b212fe0Seric hp = sm_gethostbyname(name); 13202d29d43aSeric if (hp == NULL) 13212d29d43aSeric { 13222d29d43aSeric /* no dice there either */ 1323eea91d78Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 13242d29d43aSeric return NULL; 13252d29d43aSeric } 13262d29d43aSeric 1327eea91d78Seric s->s_namecanon.nc_stat = *statp = EX_OK; 132800b385a9Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 132900b385a9Seric s->s_namecanon.nc_cname = newstr(cp); 133000b385a9Seric return cp; 133115d084d5Seric } 13329040ec4fSeric } 133308de856eSeric if ((cp = strchr(name, ']')) == NULL) 133415d084d5Seric return (NULL); 133534e39927Sbostic *cp = '\0'; 13368b212fe0Seric in_addr.s_addr = inet_addr(&name[1]); 133738ad259dSeric 133838ad259dSeric /* nope -- ask the name server */ 13398b212fe0Seric hp = sm_gethostbyaddr((char *)&in_addr, INADDRSZ, AF_INET); 1340eea91d78Seric s->s_namecanon.nc_errno = errno; 13419d4a8008Seric #if NAMED_BIND 1342eea91d78Seric s->s_namecanon.nc_herrno = h_errno; 1343c304a798Seric #endif 1344eea91d78Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 13455f78836eSmiriam if (hp == NULL) 1346eea91d78Seric { 1347eea91d78Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 134815d084d5Seric return (NULL); 1349eea91d78Seric } 135015d084d5Seric 135138ad259dSeric /* found a match -- copy out */ 135200b385a9Seric cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 1353eea91d78Seric s->s_namecanon.nc_stat = *statp = EX_OK; 135400b385a9Seric s->s_namecanon.nc_cname = newstr(cp); 135500b385a9Seric return cp; 135699f7cf32Seric } 1357e2f2f828Seric /* 1358e2f2f828Seric ** ANYNET_NTOA -- convert a network address to printable form. 1359e2f2f828Seric ** 1360e2f2f828Seric ** Parameters: 1361e2f2f828Seric ** sap -- a pointer to a sockaddr structure. 1362e2f2f828Seric ** 1363e2f2f828Seric ** Returns: 1364e2f2f828Seric ** A printable version of that sockaddr. 1365e2f2f828Seric */ 1366e2f2f828Seric 1367e2f2f828Seric char * 1368e2f2f828Seric anynet_ntoa(sap) 1369e2f2f828Seric register SOCKADDR *sap; 1370e2f2f828Seric { 1371e2f2f828Seric register char *bp; 1372e2f2f828Seric register char *ap; 1373e2f2f828Seric int l; 1374e387851eSeric static char buf[100]; 1375e2f2f828Seric 13768cb4653dSeric /* check for null/zero family */ 13778cb4653dSeric if (sap == NULL) 13788cb4653dSeric return "NULLADDR"; 13798cb4653dSeric if (sap->sa.sa_family == 0) 13808cb4653dSeric return "0"; 13818cb4653dSeric 1382e387851eSeric switch (sap->sa.sa_family) 1383e387851eSeric { 1384139b52c8Seric #ifdef NETUNIX 1385e387851eSeric case AF_UNIX: 1386c24cf5a4Seric if (sap->sunix.sun_path[0] != '\0') 1387c24cf5a4Seric sprintf(buf, "[UNIX: %.64s]", sap->sunix.sun_path); 1388e387851eSeric else 1389e387851eSeric sprintf(buf, "[UNIX: localhost]"); 1390e387851eSeric return buf; 1391e387851eSeric #endif 1392e387851eSeric 139383c1f4bcSeric #ifdef NETINET 1394e387851eSeric case AF_INET: 1395482e28bcSeric return inet_ntoa(sap->sin.sin_addr); 139683c1f4bcSeric #endif 1397e2f2f828Seric 1398e387851eSeric default: 1399e387851eSeric /* this case is only to ensure syntactic correctness */ 1400e387851eSeric break; 1401e387851eSeric } 1402e387851eSeric 1403e2f2f828Seric /* unknown family -- just dump bytes */ 140483c1f4bcSeric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 1405e2f2f828Seric bp = &buf[strlen(buf)]; 140683c1f4bcSeric ap = sap->sa.sa_data; 140783c1f4bcSeric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 1408e2f2f828Seric { 1409e2f2f828Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 1410e2f2f828Seric bp += 3; 1411e2f2f828Seric } 1412e2f2f828Seric *--bp = '\0'; 1413e2f2f828Seric return buf; 1414e2f2f828Seric } 14159f8b0eadSeric /* 14169f8b0eadSeric ** HOSTNAMEBYANYADDR -- return name of host based on address 14179f8b0eadSeric ** 14189f8b0eadSeric ** Parameters: 14199f8b0eadSeric ** sap -- SOCKADDR pointer 14209f8b0eadSeric ** 14219f8b0eadSeric ** Returns: 14229f8b0eadSeric ** text representation of host name. 14239f8b0eadSeric ** 14249f8b0eadSeric ** Side Effects: 14259f8b0eadSeric ** none. 14269f8b0eadSeric */ 14279f8b0eadSeric 14289f8b0eadSeric char * 14299f8b0eadSeric hostnamebyanyaddr(sap) 14309f8b0eadSeric register SOCKADDR *sap; 14319f8b0eadSeric { 14329f8b0eadSeric register struct hostent *hp; 14333490b9dfSeric int saveretry; 14343490b9dfSeric 14359d4a8008Seric #if NAMED_BIND 14363490b9dfSeric /* shorten name server timeout to avoid higher level timeouts */ 14373490b9dfSeric saveretry = _res.retry; 14383490b9dfSeric _res.retry = 3; 14393490b9dfSeric #endif /* NAMED_BIND */ 14403490b9dfSeric 14419f8b0eadSeric switch (sap->sa.sa_family) 14429f8b0eadSeric { 14439f8b0eadSeric #ifdef NETINET 14449f8b0eadSeric case AF_INET: 14458b212fe0Seric hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr, 14468b212fe0Seric INADDRSZ, 14479f8b0eadSeric AF_INET); 14489f8b0eadSeric break; 14499f8b0eadSeric #endif 14509f8b0eadSeric 14519f8b0eadSeric #ifdef NETISO 14529f8b0eadSeric case AF_ISO: 14538b212fe0Seric hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr, 14549f8b0eadSeric sizeof sap->siso.siso_addr, 14559f8b0eadSeric AF_ISO); 14569f8b0eadSeric break; 14579f8b0eadSeric #endif 14589f8b0eadSeric 1459e387851eSeric case AF_UNIX: 1460e387851eSeric hp = NULL; 1461e387851eSeric break; 1462e387851eSeric 14639f8b0eadSeric default: 14648b212fe0Seric hp = sm_gethostbyaddr(sap->sa.sa_data, 14659f8b0eadSeric sizeof sap->sa.sa_data, 14669f8b0eadSeric sap->sa.sa_family); 14679f8b0eadSeric break; 14689f8b0eadSeric } 14699f8b0eadSeric 14709d4a8008Seric #if NAMED_BIND 14713490b9dfSeric _res.retry = saveretry; 14723490b9dfSeric #endif /* NAMED_BIND */ 14733490b9dfSeric 14749f8b0eadSeric if (hp != NULL) 14759f8b0eadSeric return hp->h_name; 14769f8b0eadSeric else 14779f8b0eadSeric { 14789f8b0eadSeric /* produce a dotted quad */ 14799f8b0eadSeric static char buf[512]; 14809f8b0eadSeric 14819f8b0eadSeric (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); 14829f8b0eadSeric return buf; 14839f8b0eadSeric } 14849f8b0eadSeric } 1485f36ede03Sbostic 14866c2c3107Seric # else /* DAEMON */ 148799f7cf32Seric /* code for systems without sophisticated networking */ 1488444eaf03Seric 1489444eaf03Seric /* 1490444eaf03Seric ** MYHOSTNAME -- stub version for case of no daemon code. 149121e9914dSeric ** 149221e9914dSeric ** Can't convert to upper case here because might be a UUCP name. 1493897f1869Seric ** 1494897f1869Seric ** Mark, you can change this to be anything you want...... 1495444eaf03Seric */ 1496444eaf03Seric 1497444eaf03Seric char ** 1498897f1869Seric myhostname(hostbuf, size) 1499444eaf03Seric char hostbuf[]; 1500897f1869Seric int size; 1501444eaf03Seric { 1502444eaf03Seric register FILE *f; 1503444eaf03Seric 1504444eaf03Seric hostbuf[0] = '\0'; 1505444eaf03Seric f = fopen("/usr/include/whoami", "r"); 1506444eaf03Seric if (f != NULL) 1507444eaf03Seric { 1508897f1869Seric (void) fgets(hostbuf, size, f); 1509444eaf03Seric fixcrlf(hostbuf, TRUE); 1510444eaf03Seric (void) fclose(f); 1511444eaf03Seric } 1512444eaf03Seric return (NULL); 1513444eaf03Seric } 151499f7cf32Seric /* 15159f8b0eadSeric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 1516320e0d1cSeric ** 1517320e0d1cSeric ** Parameters: 1518320e0d1cSeric ** fd -- the descriptor 1519320e0d1cSeric ** 1520320e0d1cSeric ** Returns: 1521320e0d1cSeric ** The host name associated with this descriptor, if it can 1522320e0d1cSeric ** be determined. 1523320e0d1cSeric ** NULL otherwise. 1524320e0d1cSeric ** 1525320e0d1cSeric ** Side Effects: 1526320e0d1cSeric ** none 1527320e0d1cSeric */ 1528320e0d1cSeric 1529320e0d1cSeric char * 15309f8b0eadSeric getauthinfo(fd) 1531320e0d1cSeric int fd; 1532320e0d1cSeric { 1533320e0d1cSeric return NULL; 1534320e0d1cSeric } 1535320e0d1cSeric /* 153699f7cf32Seric ** MAPHOSTNAME -- turn a hostname into canonical form 153799f7cf32Seric ** 153899f7cf32Seric ** Parameters: 153905b57da8Seric ** map -- a pointer to the database map. 154008de856eSeric ** name -- a buffer containing a hostname. 154115d084d5Seric ** avp -- a pointer to a (cf file defined) argument vector. 15422d29d43aSeric ** statp -- an exit status (out parameter). 154399f7cf32Seric ** 154499f7cf32Seric ** Returns: 154515d084d5Seric ** mapped host name 1546cb452edcSeric ** FALSE otherwise. 154799f7cf32Seric ** 154899f7cf32Seric ** Side Effects: 154908de856eSeric ** Looks up the host specified in name. If it is not 155099f7cf32Seric ** the canonical name for that host, replace it with 155199f7cf32Seric ** the canonical name. If the name is unknown, or it 155299f7cf32Seric ** is already the canonical name, leave it unchanged. 155399f7cf32Seric */ 155499f7cf32Seric 155599f7cf32Seric /*ARGSUSED*/ 155615d084d5Seric char * 155708de856eSeric host_map_lookup(map, name, avp, statp) 155805b57da8Seric MAP *map; 155908de856eSeric char *name; 156015d084d5Seric char **avp; 15612d29d43aSeric char *statp; 156299f7cf32Seric { 15632d29d43aSeric register struct hostent *hp; 15642d29d43aSeric 15658b212fe0Seric hp = sm_gethostbyname(name); 15662d29d43aSeric if (hp != NULL) 15672d29d43aSeric return hp->h_name; 15682d29d43aSeric *statp = EX_NOHOST; 156915d084d5Seric return NULL; 157099f7cf32Seric } 157199f7cf32Seric 15726c2c3107Seric #endif /* DAEMON */ 1573