122700Sdist /* 234920Sbostic * Copyright (c) 1983 Eric P. Allman 333780Sbostic * Copyright (c) 1988 Regents of the University of California. 433780Sbostic * All rights reserved. 533780Sbostic * 642825Sbostic * %sccs.include.redist.c% 733780Sbostic */ 822700Sdist 933932Sbostic #include <errno.h> 1058153Seric #include <signal.h> 1140962Sbostic #include "sendmail.h" 124535Seric 1333780Sbostic #ifndef lint 1433780Sbostic #ifdef DAEMON 15*58796Seric static char sccsid[] = "@(#)daemon.c 6.24 (Berkeley) 03/23/93 (with daemon mode)"; 1633780Sbostic #else 17*58796Seric static char sccsid[] = "@(#)daemon.c 6.24 (Berkeley) 03/23/93 (without daemon mode)"; 1833780Sbostic #endif 1933780Sbostic #endif /* not lint */ 204535Seric 2133780Sbostic #ifdef DAEMON 2233780Sbostic 2323120Seric # include <netdb.h> 2423120Seric # include <sys/wait.h> 2523120Seric # include <sys/time.h> 265978Seric 2758755Seric #ifdef NETISO 2858755Seric # include <netiso/iso.h> 2958755Seric #endif 3058755Seric 314535Seric /* 324535Seric ** DAEMON.C -- routines to use when running as a daemon. 337556Seric ** 347556Seric ** This entire file is highly dependent on the 4.2 BSD 357556Seric ** interprocess communication primitives. No attempt has 367556Seric ** been made to make this file portable to Version 7, 377556Seric ** Version 6, MPX files, etc. If you should try such a 387556Seric ** thing yourself, I recommend chucking the entire file 397556Seric ** and starting from scratch. Basic semantics are: 407556Seric ** 417556Seric ** getrequests() 427556Seric ** Opens a port and initiates a connection. 437556Seric ** Returns in a child. Must set InChannel and 447556Seric ** OutChannel appropriately. 4510206Seric ** clrdaemon() 4610206Seric ** Close any open files associated with getting 4710206Seric ** the connection; this is used when running the queue, 4810206Seric ** etc., to avoid having extra file descriptors during 4910206Seric ** the queue run and to avoid confusing the network 5010206Seric ** code (if it cares). 5152106Seric ** makeconnection(host, port, outfile, infile, usesecureport) 527556Seric ** Make a connection to the named host on the given 537556Seric ** port. Set *outfile and *infile to the files 547556Seric ** appropriate for communication. Returns zero on 557556Seric ** success, else an exit status describing the 567556Seric ** error. 5756823Seric ** maphostname(map, hbuf, hbufsiz, avp) 5856823Seric ** Convert the entry in hbuf into a canonical form. 594535Seric */ 6058755Seric 6158755Seric extern char *anynet_ntoa(); 624535Seric /* 634535Seric ** GETREQUESTS -- open mail IPC port and get requests. 644535Seric ** 654535Seric ** Parameters: 664535Seric ** none. 674535Seric ** 684535Seric ** Returns: 694535Seric ** none. 704535Seric ** 714535Seric ** Side Effects: 724535Seric ** Waits until some interesting activity occurs. When 734535Seric ** it does, a child is created to process it, and the 744535Seric ** parent waits for completion. Return from this 759886Seric ** routine is always in the child. The file pointers 769886Seric ** "InChannel" and "OutChannel" should be set to point 779886Seric ** to the communication channel. 784535Seric */ 794535Seric 8016144Seric int DaemonSocket = -1; /* fd describing socket */ 8116144Seric 824535Seric getrequests() 834535Seric { 849610Seric int t; 859610Seric register struct servent *sp; 8625027Seric int on = 1; 8753751Seric bool refusingconnections = TRUE; 8858419Seric FILE *pidf; 8958778Seric SOCKADDR srvraddr; 9046928Sbostic extern void reapchild(); 917117Seric 929610Seric /* 939610Seric ** Set up the address for the mailer. 949610Seric */ 959610Seric 969610Seric sp = getservbyname("smtp", "tcp"); 979610Seric if (sp == NULL) 989610Seric { 9958151Seric syserr("554 server \"smtp\" unknown"); 10010167Seric goto severe; 1019610Seric } 10258778Seric srvraddr.sin.sin_family = AF_INET; 10358778Seric srvraddr.sin.sin_addr.s_addr = INADDR_ANY; 10458778Seric srvraddr.sin.sin_port = sp->s_port; 1059610Seric 1069610Seric /* 1079610Seric ** Try to actually open the connection. 1089610Seric */ 1099610Seric 1109610Seric if (tTd(15, 1)) 11158778Seric printf("getrequests: port 0x%x\n", srvraddr.sin.sin_port); 1129610Seric 1139610Seric /* get a socket for the SMTP connection */ 11423120Seric DaemonSocket = socket(AF_INET, SOCK_STREAM, 0); 11510206Seric if (DaemonSocket < 0) 1169610Seric { 1179610Seric /* probably another daemon already */ 1189610Seric syserr("getrequests: can't create socket"); 1199610Seric severe: 1209610Seric # ifdef LOG 1219610Seric if (LogLevel > 0) 12257663Seric syslog(LOG_ALERT, "problem creating SMTP socket"); 12356795Seric # endif /* LOG */ 1249610Seric finis(); 1259610Seric } 12610347Seric 12710347Seric /* turn on network debugging? */ 12856328Seric if (tTd(15, 101)) 12924945Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 13010347Seric 13125027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 13225027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 13325027Seric 13458778Seric if (bind(DaemonSocket, &srvraddr.sa, sizeof srvraddr) < 0) 1359610Seric { 1369610Seric syserr("getrequests: cannot bind"); 13710206Seric (void) close(DaemonSocket); 1389610Seric goto severe; 1399610Seric } 1409610Seric 14124955Seric (void) signal(SIGCHLD, reapchild); 14224945Seric 14358419Seric /* write the pid to the log file for posterity */ 14458419Seric pidf = fopen(PidFile, "w"); 14558419Seric if (pidf != NULL) 14658419Seric { 14758419Seric fprintf(pidf, "%d\n", getpid()); 14858419Seric fclose(pidf); 14958419Seric } 15058419Seric 15158419Seric 1529610Seric if (tTd(15, 1)) 15310206Seric printf("getrequests: %d\n", DaemonSocket); 1549610Seric 1554631Seric for (;;) 1564631Seric { 15714875Seric register int pid; 15811147Seric auto int lotherend; 15953751Seric extern bool refuseconnections(); 16011147Seric 16114875Seric /* see if we are rejecting connections */ 16253751Seric CurrentLA = getla(); 16353751Seric if (refuseconnections()) 16436584Sbostic { 16553751Seric if (!refusingconnections) 16653751Seric { 16753751Seric /* don't queue so peer will fail quickly */ 16853751Seric (void) listen(DaemonSocket, 0); 16953751Seric refusingconnections = TRUE; 17053751Seric } 17157385Seric setproctitle("rejecting connections: load average: %d", 17257385Seric CurrentLA); 17314875Seric sleep(5); 17453751Seric continue; 17536584Sbostic } 17614875Seric 17753751Seric if (refusingconnections) 17853751Seric { 17953751Seric /* start listening again */ 18053751Seric if (listen(DaemonSocket, 10) < 0) 18153751Seric { 18253751Seric syserr("getrequests: cannot listen"); 18353751Seric (void) close(DaemonSocket); 18453751Seric goto severe; 18553751Seric } 18653751Seric setproctitle("accepting connections"); 18753751Seric refusingconnections = FALSE; 18853751Seric } 18953751Seric 1909610Seric /* wait for a connection */ 1919610Seric do 1929610Seric { 1939610Seric errno = 0; 19436230Skarels lotherend = sizeof RealHostAddr; 19546928Sbostic t = accept(DaemonSocket, 19646928Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 1979610Seric } while (t < 0 && errno == EINTR); 1989610Seric if (t < 0) 1995978Seric { 2009610Seric syserr("getrequests: accept"); 2019610Seric sleep(5); 2029610Seric continue; 2035978Seric } 2044631Seric 2055978Seric /* 2065978Seric ** Create a subprocess to process the mail. 2075978Seric */ 2085978Seric 2097677Seric if (tTd(15, 2)) 2109610Seric printf("getrequests: forking (fd = %d)\n", t); 2115978Seric 2124636Seric pid = fork(); 2134636Seric if (pid < 0) 2144631Seric { 2154636Seric syserr("daemon: cannot fork"); 2164636Seric sleep(10); 2179610Seric (void) close(t); 2184636Seric continue; 2194631Seric } 2204631Seric 2214636Seric if (pid == 0) 2224631Seric { 22311147Seric extern struct hostent *gethostbyaddr(); 22411147Seric register struct hostent *hp; 22511147Seric char buf[MAXNAME]; 22611147Seric 2274636Seric /* 2284636Seric ** CHILD -- return to caller. 22911147Seric ** Collect verified idea of sending host. 2304636Seric ** Verify calling user id if possible here. 2314636Seric */ 2324631Seric 23324955Seric (void) signal(SIGCHLD, SIG_DFL); 23424950Seric 23511147Seric /* determine host name */ 23658778Seric switch (RealHostAddr.sa.sa_family) 23758778Seric { 23858778Seric #ifdef NETINET 23958778Seric case AF_INET: 24058778Seric hp = gethostbyaddr((char *) &RealHostAddr.sin.sin_addr, 24158778Seric sizeof RealHostAddr.sin.sin_addr, 24258778Seric AF_INET); 24358778Seric break; 24458778Seric #endif 24558778Seric 24658778Seric #ifdef NETISO 24758778Seric case AF_ISO: 24858778Seric hp = gethostbyaddr((char *) &RealHostAddr.siso.siso_addr, 24958778Seric sizeof RealHostAddr.siso.siso_addr, 25058778Seric AF_ISO); 25158778Seric break; 25258778Seric #endif 25358778Seric 25458778Seric default: 25558778Seric hp = gethostbyaddr(RealHostAddr.sa.sa_data, 25658778Seric sizeof RealHostAddr.sa.sa_data, 25758778Seric RealHostAddr.sa.sa_family); 25858778Seric break; 25958778Seric } 26058778Seric 26111147Seric if (hp != NULL) 26223104Seric (void) strcpy(buf, hp->h_name); 26311147Seric else 26416884Seric { 26516884Seric /* produce a dotted quad */ 26616884Seric (void) sprintf(buf, "[%s]", 26758755Seric anynet_ntoa(&RealHostAddr)); 26816884Seric } 26916884Seric 27055173Seric #ifdef LOG 27157977Seric if (LogLevel > 10) 27255173Seric { 27355173Seric /* log connection information */ 27455173Seric syslog(LOG_INFO, "connect from %s (%s)", 27558755Seric buf, anynet_ntoa(&RealHostAddr)); 27655173Seric } 27755173Seric #endif 27855173Seric 27916884Seric /* should we check for illegal connection here? XXX */ 28016884Seric 28111147Seric RealHostName = newstr(buf); 28211147Seric 28310206Seric (void) close(DaemonSocket); 2849610Seric InChannel = fdopen(t, "r"); 28521062Seric OutChannel = fdopen(dup(t), "w"); 2867677Seric if (tTd(15, 2)) 2875978Seric printf("getreq: returning\n"); 2884636Seric return; 2894631Seric } 2904631Seric 2917117Seric /* close the port so that others will hang (for a while) */ 2929610Seric (void) close(t); 2934631Seric } 2949886Seric /*NOTREACHED*/ 2954631Seric } 2965978Seric /* 29710206Seric ** CLRDAEMON -- reset the daemon connection 29810206Seric ** 29910206Seric ** Parameters: 30010206Seric ** none. 30110206Seric ** 30210206Seric ** Returns: 30310206Seric ** none. 30410206Seric ** 30510206Seric ** Side Effects: 30610206Seric ** releases any resources used by the passive daemon. 30710206Seric */ 30810206Seric 30910206Seric clrdaemon() 31010206Seric { 31110206Seric if (DaemonSocket >= 0) 31210206Seric (void) close(DaemonSocket); 31310206Seric DaemonSocket = -1; 31410206Seric } 31510206Seric /* 3166039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 3176039Seric ** 3186039Seric ** Parameters: 3196039Seric ** host -- the name of the host. 3206633Seric ** port -- the port number to connect to. 32153739Seric ** mci -- a pointer to the mail connection information 32253739Seric ** structure to be filled in. 32352106Seric ** usesecureport -- if set, use a low numbered (reserved) 32452106Seric ** port to provide some rudimentary authentication. 3256039Seric ** 3266039Seric ** Returns: 3276039Seric ** An exit code telling whether the connection could be 3286039Seric ** made and if not why not. 3296039Seric ** 3306039Seric ** Side Effects: 3316039Seric ** none. 3326039Seric */ 3335978Seric 33458755Seric SOCKADDR CurHostAddr; /* address of current host */ 33558305Seric 33654967Seric int 33753739Seric makeconnection(host, port, mci, usesecureport) 3386039Seric char *host; 3397286Seric u_short port; 34054967Seric register MCI *mci; 34152106Seric bool usesecureport; 3426039Seric { 34329430Sbloom register int i, s; 34429430Sbloom register struct hostent *hp = (struct hostent *)NULL; 34558755Seric SOCKADDR addr; 34652106Seric int sav_errno; 34758755Seric int addrlen; 34835651Seric #ifdef NAMED_BIND 34935651Seric extern int h_errno; 35035651Seric #endif 3516039Seric 3526039Seric /* 3536039Seric ** Set up the address for the mailer. 3549308Seric ** Accept "[a.b.c.d]" syntax for host name. 3556039Seric */ 3566039Seric 35735651Seric #ifdef NAMED_BIND 35825475Smiriam h_errno = 0; 35935651Seric #endif 36025475Smiriam errno = 0; 36125475Smiriam 3629308Seric if (host[0] == '[') 3639308Seric { 36411147Seric long hid; 36556795Seric register char *p = strchr(host, ']'); 3669308Seric 36711147Seric if (p != NULL) 3689308Seric { 36911147Seric *p = '\0'; 37011147Seric hid = inet_addr(&host[1]); 37158360Seric if (hid == -1) 37258360Seric { 37358360Seric /* try it as a host name (avoid MX lookup) */ 37458360Seric hp = gethostbyname(&host[1]); 37558360Seric *p = ']'; 37658360Seric goto gothostent; 37758360Seric } 37811147Seric *p = ']'; 3799308Seric } 38058360Seric if (p == NULL) 3819308Seric { 38258151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 3839308Seric return (EX_NOHOST); 3849308Seric } 38558778Seric addr.sin.sin_family = AF_INET; 38658778Seric addr.sin.sin_addr.s_addr = hid; 3879308Seric } 3889610Seric else 3899610Seric { 39029430Sbloom hp = gethostbyname(host); 39158360Seric gothostent: 39225475Smiriam if (hp == NULL) 39324945Seric { 39435651Seric #ifdef NAMED_BIND 39525475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 39625475Smiriam return (EX_TEMPFAIL); 39725657Seric 39835651Seric /* if name server is specified, assume temp fail */ 39935651Seric if (errno == ECONNREFUSED && UseNameServer) 40035651Seric return (EX_TEMPFAIL); 40135651Seric #endif 40225475Smiriam return (EX_NOHOST); 40324945Seric } 40458778Seric addr.sa.sa_family = hp->h_addrtype; 40558778Seric switch (hp->h_addrtype) 40658778Seric { 40758778Seric #ifdef NETINET 40858778Seric case AF_INET: 40958755Seric bcopy(hp->h_addr, 41058778Seric &addr.sin.sin_addr, 41158755Seric hp->h_length); 41258778Seric break; 41358778Seric #endif 41458778Seric 41558778Seric default: 41658755Seric bcopy(hp->h_addr, 41758778Seric addr.sa.sa_data, 41858755Seric hp->h_length); 41958778Seric break; 42058778Seric } 42129430Sbloom i = 1; 4229610Seric } 4239610Seric 4249610Seric /* 4259610Seric ** Determine the port number. 4269610Seric */ 4279610Seric 42810011Seric if (port != 0) 42958755Seric port = htons(port); 43010011Seric else 4319610Seric { 4329610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 4339610Seric 4349610Seric if (sp == NULL) 4359610Seric { 43658151Seric syserr("554 makeconnection: server \"smtp\" unknown"); 43757977Seric return (EX_OSERR); 4389610Seric } 43958755Seric port = sp->s_port; 4409610Seric } 4416039Seric 44258778Seric switch (addr.sa.sa_family) 44358755Seric { 44458755Seric case AF_INET: 44558778Seric addr.sin.sin_port = port; 44658755Seric addrlen = sizeof (struct sockaddr_in); 44758755Seric break; 44858755Seric 44958755Seric #ifdef NETISO 45058755Seric case AF_ISO: 45158755Seric /* assume two byte transport selector */ 45258755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 45358755Seric addrlen = sizeof (struct sockaddr_iso); 45458755Seric break; 45558755Seric #endif 45658755Seric 45758755Seric default: 45858778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 45958755Seric return (EX_NOHOST); 46058755Seric } 46158755Seric 4626039Seric /* 4636039Seric ** Try to actually open the connection. 4646039Seric */ 4656039Seric 46657736Seric for (;;) 46752106Seric { 46857736Seric if (tTd(16, 1)) 46958755Seric printf("makeconnection (%s [%s])\n", 47058755Seric host, anynet_ntoa(&addr)); 47152106Seric 47258588Seric /* save for logging */ 47358588Seric CurHostAddr = addr; 47458588Seric 47557736Seric if (usesecureport) 47657736Seric { 47757736Seric int rport = IPPORT_RESERVED - 1; 4786039Seric 47957736Seric s = rresvport(&rport); 48057736Seric } 48157736Seric else 48257736Seric { 48357736Seric s = socket(AF_INET, SOCK_STREAM, 0); 48457736Seric } 48557736Seric if (s < 0) 48657736Seric { 48757736Seric sav_errno = errno; 48857736Seric syserr("makeconnection: no socket"); 48957736Seric goto failure; 49057736Seric } 49110347Seric 49257736Seric if (tTd(16, 1)) 49357736Seric printf("makeconnection: fd=%d\n", s); 49457736Seric 49557736Seric /* turn on network debugging? */ 49657736Seric if (tTd(16, 101)) 49757736Seric { 49857736Seric int on = 1; 49957736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 50057736Seric (char *)&on, sizeof on); 50157736Seric } 50257736Seric if (CurEnv->e_xfp != NULL) 50357736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 50457736Seric errno = 0; /* for debugging */ 50558755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 50657736Seric break; 50757736Seric 50857736Seric /* couldn't connect.... figure out why */ 50927744Sbloom sav_errno = errno; 51027744Sbloom (void) close(s); 51129430Sbloom if (hp && hp->h_addr_list[i]) 51229430Sbloom { 51358755Seric extern char *errstring(); 51458755Seric 51557736Seric if (tTd(16, 1)) 51658755Seric printf("Connect failed (%s); trying new address....\n", 51758755Seric errstring(sav_errno)); 51858778Seric switch (addr.sa.sa_family) 51958778Seric { 52058778Seric #ifdef NETINET 52158778Seric case AF_INET: 52258755Seric bcopy(hp->h_addr_list[i++], 52358778Seric &addr.sin.sin_addr, 52458755Seric hp->h_length); 52558778Seric break; 52658778Seric #endif 52758778Seric 52858778Seric default: 52958755Seric bcopy(hp->h_addr_list[i++], 53058778Seric addr.sa.sa_data, 53152106Seric hp->h_length); 53258778Seric break; 53358778Seric } 53457736Seric continue; 53529430Sbloom } 53629430Sbloom 5376039Seric /* failure, decide if temporary or not */ 5386039Seric failure: 53958542Seric if (transienterror(sav_errno)) 54058542Seric return EX_TEMPFAIL; 54158542Seric else 54258542Seric { 54358542Seric extern char *errstring(); 54411147Seric 54558542Seric message("%s", errstring(sav_errno)); 54658542Seric return (EX_UNAVAILABLE); 5476039Seric } 5486039Seric } 5496039Seric 5506039Seric /* connection ok, put it into canonical form */ 55153739Seric mci->mci_out = fdopen(s, "w"); 55253739Seric mci->mci_in = fdopen(dup(s), "r"); 5536039Seric 55410098Seric return (EX_OK); 5556039Seric } 55610758Seric /* 55710758Seric ** MYHOSTNAME -- return the name of this host. 55810758Seric ** 55910758Seric ** Parameters: 56010758Seric ** hostbuf -- a place to return the name of this host. 56112313Seric ** size -- the size of hostbuf. 56210758Seric ** 56310758Seric ** Returns: 56410758Seric ** A list of aliases for this host. 56510758Seric ** 56610758Seric ** Side Effects: 56758110Seric ** Sets the MyIpAddrs buffer to a list of my IP addresses. 56810758Seric */ 5696039Seric 57058110Seric struct in_addr MyIpAddrs[MAXIPADDR + 1]; 57158110Seric 57210758Seric char ** 57312313Seric myhostname(hostbuf, size) 57410758Seric char hostbuf[]; 57512313Seric int size; 57610758Seric { 57758110Seric register struct hostent *hp; 57810758Seric extern struct hostent *gethostbyname(); 57910758Seric 58023120Seric if (gethostname(hostbuf, size) < 0) 58123120Seric { 58223120Seric (void) strcpy(hostbuf, "localhost"); 58323120Seric } 58411147Seric hp = gethostbyname(hostbuf); 58511147Seric if (hp != NULL) 58616877Seric { 58758110Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 58858110Seric hostbuf[size - 1] = '\0'; 58958110Seric 59058110Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 59158110Seric { 59258110Seric register int i; 59358110Seric 59458110Seric for (i = 0; i < MAXIPADDR; i++) 59558110Seric { 59658110Seric if (hp->h_addr_list[i] == NULL) 59758110Seric break; 59858110Seric MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i]; 59958110Seric } 60058110Seric MyIpAddrs[i].s_addr = 0; 60158110Seric } 60258110Seric 60311147Seric return (hp->h_aliases); 60416877Seric } 60510758Seric else 60610758Seric return (NULL); 60710758Seric } 60851315Seric /* 60958308Seric ** GETREALHOSTNAME -- get the real host name asociated with a file descriptor 61058308Seric ** 61158308Seric ** Parameters: 61258308Seric ** fd -- the descriptor 61358308Seric ** 61458308Seric ** Returns: 61558308Seric ** The host name associated with this descriptor, if it can 61658308Seric ** be determined. 61758308Seric ** NULL otherwise. 61858308Seric ** 61958308Seric ** Side Effects: 62058308Seric ** none 62158308Seric */ 62258308Seric 62358308Seric char * 62458308Seric getrealhostname(fd) 62558308Seric int fd; 62658308Seric { 62758308Seric register struct hostent *hp; 62858786Seric SOCKADDR sa; 62958755Seric int salen; 63058308Seric char hbuf[MAXNAME]; 63158308Seric extern struct hostent *gethostbyaddr(); 63258308Seric 63358755Seric salen = sizeof sa; 63458787Seric if (getsockname(fd, &sa.sa, &salen) < 0 || salen <= 0) 63558308Seric return NULL; 63658787Seric hp = gethostbyaddr(sa.sa.sa_data, salen, sa.sa.sa_family); 63758308Seric if (hp != NULL) 63858308Seric (void) strcpy(hbuf, hp->h_name); 63958308Seric else 64058755Seric (void) sprintf(hbuf, "[%s]", anynet_ntoa(&sa)); 64158308Seric return hbuf; 64258308Seric } 64358308Seric /* 64453751Seric ** MAPHOSTNAME -- turn a hostname into canonical form 64553751Seric ** 64653751Seric ** Parameters: 64756823Seric ** map -- a pointer to this map (unused). 64853751Seric ** hbuf -- a buffer containing a hostname. 64953751Seric ** hbsize -- the size of hbuf. 65055019Seric ** avp -- unused -- for compatibility with other mapping 65155019Seric ** functions. 65253751Seric ** 65353751Seric ** Returns: 65453751Seric ** The mapping, if found. 65553751Seric ** NULL if no mapping found. 65653751Seric ** 65753751Seric ** Side Effects: 65853751Seric ** Looks up the host specified in hbuf. If it is not 65953751Seric ** the canonical name for that host, return the canonical 66053751Seric ** name. 66153751Seric */ 66251315Seric 66353751Seric char * 66456823Seric maphostname(map, hbuf, hbsize, avp) 66556823Seric MAP *map; 66616911Seric char *hbuf; 66716911Seric int hbsize; 66853751Seric char **avp; 66916911Seric { 67016911Seric register struct hostent *hp; 67133932Sbostic u_long in_addr; 67256823Seric char *cp; 67358110Seric int i; 67433932Sbostic struct hostent *gethostbyaddr(); 67516911Seric 67656836Seric /* allow room for null */ 67756823Seric hbsize--; 67853751Seric 67925574Smiriam /* 68033932Sbostic * If first character is a bracket, then it is an address 68133932Sbostic * lookup. Address is copied into a temporary buffer to 68233932Sbostic * strip the brackets and to preserve hbuf if address is 68333932Sbostic * unknown. 68433932Sbostic */ 68553751Seric 68651315Seric if (*hbuf != '[') 68753751Seric { 68855019Seric extern bool getcanonname(); 68955019Seric 690*58796Seric printf("maphostname(%s, %d) => ", hbuf, hbsize); 69158674Seric if (getcanonname(hbuf, hbsize)) 692*58796Seric { 693*58796Seric if (tTd(9, 1)) 694*58796Seric printf("%s\n", hbuf); 69553751Seric return hbuf; 696*58796Seric } 69753751Seric else 698*58796Seric { 699*58796Seric if (tTd(9, 1)) 700*58796Seric printf("FAIL\n"); 70153751Seric return NULL; 702*58796Seric } 70353751Seric } 70456823Seric if ((cp = strchr(hbuf, ']')) == NULL) 70553751Seric return (NULL); 70640994Sbostic *cp = '\0'; 70756823Seric in_addr = inet_addr(&hbuf[1]); 70858110Seric 70958110Seric /* check to see if this is one of our addresses */ 71058110Seric for (i = 0; MyIpAddrs[i].s_addr != 0; i++) 71158110Seric { 71258110Seric if (MyIpAddrs[i].s_addr == in_addr) 71358110Seric { 71458110Seric strncpy(hbuf, MyHostName, hbsize); 71558110Seric hbuf[hbsize] = '\0'; 71658110Seric return hbuf; 71758110Seric } 71858110Seric } 71958110Seric 72058110Seric /* nope -- ask the name server */ 72133932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 72233932Sbostic if (hp == NULL) 72353751Seric return (NULL); 72453751Seric 72558110Seric /* found a match -- copy out */ 72656823Seric if (strlen(hp->h_name) > hbsize) 72756823Seric hp->h_name[hbsize] = '\0'; 72853751Seric (void) strcpy(hbuf, hp->h_name); 72953751Seric return hbuf; 73033932Sbostic } 73158755Seric /* 73258755Seric ** ANYNET_NTOA -- convert a network address to printable form. 73358755Seric ** 73458755Seric ** Parameters: 73558755Seric ** sap -- a pointer to a sockaddr structure. 73658755Seric ** 73758755Seric ** Returns: 73858755Seric ** A printable version of that sockaddr. 73958755Seric */ 74016911Seric 74158755Seric char * 74258755Seric anynet_ntoa(sap) 74358755Seric register SOCKADDR *sap; 74458755Seric { 74558755Seric register char *bp; 74658755Seric register char *ap; 74758755Seric int l; 74858755Seric static char buf[80]; 74958755Seric 75058778Seric #ifdef NETINET 75158778Seric if (sap->sa.sa_family == AF_INET) 75258755Seric { 75358755Seric extern char *inet_ntoa(); 75458755Seric 75558755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 75658755Seric } 75758778Seric #endif 75858755Seric 75958755Seric /* unknown family -- just dump bytes */ 76058778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 76158755Seric bp = &buf[strlen(buf)]; 76258778Seric ap = sap->sa.sa_data; 76358778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 76458755Seric { 76558755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 76658755Seric bp += 3; 76758755Seric } 76858755Seric *--bp = '\0'; 76958755Seric return buf; 77058755Seric } 77158755Seric 77256795Seric # else /* DAEMON */ 77316911Seric /* code for systems without sophisticated networking */ 77410758Seric 77510758Seric /* 77610758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 77711297Seric ** 77811297Seric ** Can't convert to upper case here because might be a UUCP name. 77912313Seric ** 78012313Seric ** Mark, you can change this to be anything you want...... 78110758Seric */ 78210758Seric 78310758Seric char ** 78412313Seric myhostname(hostbuf, size) 78510758Seric char hostbuf[]; 78612313Seric int size; 78710758Seric { 78810758Seric register FILE *f; 78910758Seric 79010758Seric hostbuf[0] = '\0'; 79110758Seric f = fopen("/usr/include/whoami", "r"); 79210758Seric if (f != NULL) 79310758Seric { 79412313Seric (void) fgets(hostbuf, size, f); 79510758Seric fixcrlf(hostbuf, TRUE); 79610758Seric (void) fclose(f); 79710758Seric } 79810758Seric return (NULL); 79910758Seric } 80016911Seric /* 80158308Seric ** GETREALHOSTNAME -- get the real host name asociated with a file descriptor 80258308Seric ** 80358308Seric ** Parameters: 80458308Seric ** fd -- the descriptor 80558308Seric ** 80658308Seric ** Returns: 80758308Seric ** The host name associated with this descriptor, if it can 80858308Seric ** be determined. 80958308Seric ** NULL otherwise. 81058308Seric ** 81158308Seric ** Side Effects: 81258308Seric ** none 81358308Seric */ 81458308Seric 81558308Seric char * 81658308Seric getrealhostname(fd) 81758308Seric int fd; 81858308Seric { 81958308Seric return NULL; 82058308Seric } 82158308Seric /* 82216911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 82316911Seric ** 82416911Seric ** Parameters: 82556823Seric ** map -- a pointer to the database map. 82616911Seric ** hbuf -- a buffer containing a hostname. 82753751Seric ** avp -- a pointer to a (cf file defined) argument vector. 82816911Seric ** 82916911Seric ** Returns: 83053751Seric ** mapped host name 83151315Seric ** FALSE otherwise. 83216911Seric ** 83316911Seric ** Side Effects: 83416911Seric ** Looks up the host specified in hbuf. If it is not 83516911Seric ** the canonical name for that host, replace it with 83616911Seric ** the canonical name. If the name is unknown, or it 83716911Seric ** is already the canonical name, leave it unchanged. 83816911Seric */ 83910758Seric 84016911Seric /*ARGSUSED*/ 84153751Seric char * 84256823Seric maphostname(map, hbuf, hbsize, avp) 84356823Seric MAP *map; 84416911Seric char *hbuf; 84516911Seric int hbsize; 84653751Seric char **avp; 84716911Seric { 84853751Seric return NULL; 84916911Seric } 85016911Seric 85156795Seric #endif /* DAEMON */ 852