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*58755Seric static char sccsid[] = "@(#)daemon.c 6.20 (Berkeley) 03/19/93 (with daemon mode)"; 1633780Sbostic #else 17*58755Seric static char sccsid[] = "@(#)daemon.c 6.20 (Berkeley) 03/19/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 27*58755Seric #ifdef NETISO 28*58755Seric # include <netiso/iso.h> 29*58755Seric #endif 30*58755Seric 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 */ 60*58755Seric 61*58755Seric 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; 8952106Seric struct sockaddr_in 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 } 10252106Seric srvraddr.sin_family = AF_INET; 10352106Seric srvraddr.sin_addr.s_addr = INADDR_ANY; 10452106Seric srvraddr.sin_port = sp->s_port; 1059610Seric 1069610Seric /* 1079610Seric ** Try to actually open the connection. 1089610Seric */ 1099610Seric 1109610Seric if (tTd(15, 1)) 11152106Seric printf("getrequests: port 0x%x\n", srvraddr.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 13452106Seric if (bind(DaemonSocket, (struct sockaddr *)&srvraddr, 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 */ 236*58755Seric hp = gethostbyaddr(RealHostAddr.sa_u.sa_data, 237*58755Seric sizeof RealHostAddr.sa_u.sa_data, 238*58755Seric RealHostAddr.sa_family); 23911147Seric if (hp != NULL) 24023104Seric (void) strcpy(buf, hp->h_name); 24111147Seric else 24216884Seric { 24316884Seric /* produce a dotted quad */ 24416884Seric (void) sprintf(buf, "[%s]", 245*58755Seric anynet_ntoa(&RealHostAddr)); 24616884Seric } 24716884Seric 24855173Seric #ifdef LOG 24957977Seric if (LogLevel > 10) 25055173Seric { 25155173Seric /* log connection information */ 25255173Seric syslog(LOG_INFO, "connect from %s (%s)", 253*58755Seric buf, anynet_ntoa(&RealHostAddr)); 25455173Seric } 25555173Seric #endif 25655173Seric 25716884Seric /* should we check for illegal connection here? XXX */ 25816884Seric 25911147Seric RealHostName = newstr(buf); 26011147Seric 26110206Seric (void) close(DaemonSocket); 2629610Seric InChannel = fdopen(t, "r"); 26321062Seric OutChannel = fdopen(dup(t), "w"); 2647677Seric if (tTd(15, 2)) 2655978Seric printf("getreq: returning\n"); 2664636Seric return; 2674631Seric } 2684631Seric 2697117Seric /* close the port so that others will hang (for a while) */ 2709610Seric (void) close(t); 2714631Seric } 2729886Seric /*NOTREACHED*/ 2734631Seric } 2745978Seric /* 27510206Seric ** CLRDAEMON -- reset the daemon connection 27610206Seric ** 27710206Seric ** Parameters: 27810206Seric ** none. 27910206Seric ** 28010206Seric ** Returns: 28110206Seric ** none. 28210206Seric ** 28310206Seric ** Side Effects: 28410206Seric ** releases any resources used by the passive daemon. 28510206Seric */ 28610206Seric 28710206Seric clrdaemon() 28810206Seric { 28910206Seric if (DaemonSocket >= 0) 29010206Seric (void) close(DaemonSocket); 29110206Seric DaemonSocket = -1; 29210206Seric } 29310206Seric /* 2946039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 2956039Seric ** 2966039Seric ** Parameters: 2976039Seric ** host -- the name of the host. 2986633Seric ** port -- the port number to connect to. 29953739Seric ** mci -- a pointer to the mail connection information 30053739Seric ** structure to be filled in. 30152106Seric ** usesecureport -- if set, use a low numbered (reserved) 30252106Seric ** port to provide some rudimentary authentication. 3036039Seric ** 3046039Seric ** Returns: 3056039Seric ** An exit code telling whether the connection could be 3066039Seric ** made and if not why not. 3076039Seric ** 3086039Seric ** Side Effects: 3096039Seric ** none. 3106039Seric */ 3115978Seric 312*58755Seric SOCKADDR CurHostAddr; /* address of current host */ 31358305Seric 31454967Seric int 31553739Seric makeconnection(host, port, mci, usesecureport) 3166039Seric char *host; 3177286Seric u_short port; 31854967Seric register MCI *mci; 31952106Seric bool usesecureport; 3206039Seric { 32129430Sbloom register int i, s; 32229430Sbloom register struct hostent *hp = (struct hostent *)NULL; 323*58755Seric SOCKADDR addr; 32452106Seric int sav_errno; 325*58755Seric int addrlen; 32635651Seric #ifdef NAMED_BIND 32735651Seric extern int h_errno; 32835651Seric #endif 3296039Seric 3306039Seric /* 3316039Seric ** Set up the address for the mailer. 3329308Seric ** Accept "[a.b.c.d]" syntax for host name. 3336039Seric */ 3346039Seric 33535651Seric #ifdef NAMED_BIND 33625475Smiriam h_errno = 0; 33735651Seric #endif 33825475Smiriam errno = 0; 33925475Smiriam 3409308Seric if (host[0] == '[') 3419308Seric { 34211147Seric long hid; 34356795Seric register char *p = strchr(host, ']'); 3449308Seric 34511147Seric if (p != NULL) 3469308Seric { 34711147Seric *p = '\0'; 34811147Seric hid = inet_addr(&host[1]); 34958360Seric if (hid == -1) 35058360Seric { 35158360Seric /* try it as a host name (avoid MX lookup) */ 35258360Seric hp = gethostbyname(&host[1]); 35358360Seric *p = ']'; 35458360Seric goto gothostent; 35558360Seric } 35611147Seric *p = ']'; 3579308Seric } 35858360Seric if (p == NULL) 3599308Seric { 36058151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 3619308Seric return (EX_NOHOST); 3629308Seric } 363*58755Seric addr.sa_family = AF_INET; 364*58755Seric addr.sa_len = sizeof hid; 365*58755Seric addr.sa_u.sa_inet.sin_addr.s_addr = hid; 3669308Seric } 3679610Seric else 3689610Seric { 36929430Sbloom hp = gethostbyname(host); 37058360Seric gothostent: 37125475Smiriam if (hp == NULL) 37224945Seric { 37335651Seric #ifdef NAMED_BIND 37425475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 37525475Smiriam return (EX_TEMPFAIL); 37625657Seric 37735651Seric /* if name server is specified, assume temp fail */ 37835651Seric if (errno == ECONNREFUSED && UseNameServer) 37935651Seric return (EX_TEMPFAIL); 38035651Seric #endif 38125475Smiriam return (EX_NOHOST); 38224945Seric } 383*58755Seric addr.sa_family = hp->h_addrtype; 384*58755Seric addr.sa_len = hp->h_length; 385*58755Seric if (addr.sa_family == AF_INET) 386*58755Seric bcopy(hp->h_addr, 387*58755Seric &addr.sa_u.sa_inet.sin_addr, 388*58755Seric hp->h_length); 389*58755Seric else 390*58755Seric bcopy(hp->h_addr, 391*58755Seric addr.sa_u.sa_data, 392*58755Seric hp->h_length); 39329430Sbloom i = 1; 3949610Seric } 3959610Seric 3969610Seric /* 3979610Seric ** Determine the port number. 3989610Seric */ 3999610Seric 40010011Seric if (port != 0) 401*58755Seric port = htons(port); 40210011Seric else 4039610Seric { 4049610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 4059610Seric 4069610Seric if (sp == NULL) 4079610Seric { 40858151Seric syserr("554 makeconnection: server \"smtp\" unknown"); 40957977Seric return (EX_OSERR); 4109610Seric } 411*58755Seric port = sp->s_port; 4129610Seric } 4136039Seric 414*58755Seric switch (addr.sa_family) 415*58755Seric { 416*58755Seric case AF_INET: 417*58755Seric addr.sa_u.sa_inet.sin_port = port; 418*58755Seric addrlen = sizeof (struct sockaddr_in); 419*58755Seric break; 420*58755Seric 421*58755Seric #ifdef NETISO 422*58755Seric case AF_ISO: 423*58755Seric /* assume two byte transport selector */ 424*58755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 425*58755Seric addrlen = sizeof (struct sockaddr_iso); 426*58755Seric break; 427*58755Seric #endif 428*58755Seric 429*58755Seric default: 430*58755Seric syserr("Can't connect to address family %d", addr.sa_family); 431*58755Seric return (EX_NOHOST); 432*58755Seric } 433*58755Seric 4346039Seric /* 4356039Seric ** Try to actually open the connection. 4366039Seric */ 4376039Seric 43857736Seric for (;;) 43952106Seric { 44057736Seric if (tTd(16, 1)) 441*58755Seric printf("makeconnection (%s [%s])\n", 442*58755Seric host, anynet_ntoa(&addr)); 44352106Seric 44458588Seric /* save for logging */ 44558588Seric CurHostAddr = addr; 44658588Seric 44757736Seric if (usesecureport) 44857736Seric { 44957736Seric int rport = IPPORT_RESERVED - 1; 4506039Seric 45157736Seric s = rresvport(&rport); 45257736Seric } 45357736Seric else 45457736Seric { 45557736Seric s = socket(AF_INET, SOCK_STREAM, 0); 45657736Seric } 45757736Seric if (s < 0) 45857736Seric { 45957736Seric sav_errno = errno; 46057736Seric syserr("makeconnection: no socket"); 46157736Seric goto failure; 46257736Seric } 46310347Seric 46457736Seric if (tTd(16, 1)) 46557736Seric printf("makeconnection: fd=%d\n", s); 46657736Seric 46757736Seric /* turn on network debugging? */ 46857736Seric if (tTd(16, 101)) 46957736Seric { 47057736Seric int on = 1; 47157736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 47257736Seric (char *)&on, sizeof on); 47357736Seric } 47457736Seric if (CurEnv->e_xfp != NULL) 47557736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 47657736Seric errno = 0; /* for debugging */ 477*58755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 47857736Seric break; 47957736Seric 48057736Seric /* couldn't connect.... figure out why */ 48127744Sbloom sav_errno = errno; 48227744Sbloom (void) close(s); 48329430Sbloom if (hp && hp->h_addr_list[i]) 48429430Sbloom { 485*58755Seric extern char *errstring(); 486*58755Seric 48757736Seric if (tTd(16, 1)) 488*58755Seric printf("Connect failed (%s); trying new address....\n", 489*58755Seric errstring(sav_errno)); 490*58755Seric if (addr.sa_family == AF_INET) 491*58755Seric bcopy(hp->h_addr_list[i++], 492*58755Seric &addr.sa_u.sa_inet.sin_addr, 493*58755Seric hp->h_length); 494*58755Seric else 495*58755Seric bcopy(hp->h_addr_list[i++], 496*58755Seric addr.sa_u.sa_data, 49752106Seric hp->h_length); 49857736Seric continue; 49929430Sbloom } 50029430Sbloom 5016039Seric /* failure, decide if temporary or not */ 5026039Seric failure: 50358542Seric if (transienterror(sav_errno)) 50458542Seric return EX_TEMPFAIL; 50558542Seric else 50658542Seric { 50758542Seric extern char *errstring(); 50811147Seric 50958542Seric message("%s", errstring(sav_errno)); 51058542Seric return (EX_UNAVAILABLE); 5116039Seric } 5126039Seric } 5136039Seric 5146039Seric /* connection ok, put it into canonical form */ 51553739Seric mci->mci_out = fdopen(s, "w"); 51653739Seric mci->mci_in = fdopen(dup(s), "r"); 5176039Seric 51810098Seric return (EX_OK); 5196039Seric } 52010758Seric /* 52110758Seric ** MYHOSTNAME -- return the name of this host. 52210758Seric ** 52310758Seric ** Parameters: 52410758Seric ** hostbuf -- a place to return the name of this host. 52512313Seric ** size -- the size of hostbuf. 52610758Seric ** 52710758Seric ** Returns: 52810758Seric ** A list of aliases for this host. 52910758Seric ** 53010758Seric ** Side Effects: 53158110Seric ** Sets the MyIpAddrs buffer to a list of my IP addresses. 53210758Seric */ 5336039Seric 53458110Seric struct in_addr MyIpAddrs[MAXIPADDR + 1]; 53558110Seric 53610758Seric char ** 53712313Seric myhostname(hostbuf, size) 53810758Seric char hostbuf[]; 53912313Seric int size; 54010758Seric { 54158110Seric register struct hostent *hp; 54210758Seric extern struct hostent *gethostbyname(); 54310758Seric 54423120Seric if (gethostname(hostbuf, size) < 0) 54523120Seric { 54623120Seric (void) strcpy(hostbuf, "localhost"); 54723120Seric } 54811147Seric hp = gethostbyname(hostbuf); 54911147Seric if (hp != NULL) 55016877Seric { 55158110Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 55258110Seric hostbuf[size - 1] = '\0'; 55358110Seric 55458110Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 55558110Seric { 55658110Seric register int i; 55758110Seric 55858110Seric for (i = 0; i < MAXIPADDR; i++) 55958110Seric { 56058110Seric if (hp->h_addr_list[i] == NULL) 56158110Seric break; 56258110Seric MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i]; 56358110Seric } 56458110Seric MyIpAddrs[i].s_addr = 0; 56558110Seric } 56658110Seric 56711147Seric return (hp->h_aliases); 56816877Seric } 56910758Seric else 57010758Seric return (NULL); 57110758Seric } 57251315Seric /* 57358308Seric ** GETREALHOSTNAME -- get the real host name asociated with a file descriptor 57458308Seric ** 57558308Seric ** Parameters: 57658308Seric ** fd -- the descriptor 57758308Seric ** 57858308Seric ** Returns: 57958308Seric ** The host name associated with this descriptor, if it can 58058308Seric ** be determined. 58158308Seric ** NULL otherwise. 58258308Seric ** 58358308Seric ** Side Effects: 58458308Seric ** none 58558308Seric */ 58658308Seric 58758308Seric char * 58858308Seric getrealhostname(fd) 58958308Seric int fd; 59058308Seric { 59158308Seric register struct hostent *hp; 592*58755Seric struct sockaddr sa; 593*58755Seric int salen; 59458308Seric char hbuf[MAXNAME]; 59558308Seric extern struct hostent *gethostbyaddr(); 59658308Seric 597*58755Seric salen = sizeof sa; 598*58755Seric if (getsockname(fd, &sa, &salen) < 0 || salen <= 0) 59958308Seric return NULL; 600*58755Seric hp = gethostbyaddr(sa.sa_data, sa.sa_len, 601*58755Seric sa.sa_family); 60258308Seric if (hp != NULL) 60358308Seric (void) strcpy(hbuf, hp->h_name); 60458308Seric else 605*58755Seric (void) sprintf(hbuf, "[%s]", anynet_ntoa(&sa)); 60658308Seric return hbuf; 60758308Seric } 60858308Seric /* 60953751Seric ** MAPHOSTNAME -- turn a hostname into canonical form 61053751Seric ** 61153751Seric ** Parameters: 61256823Seric ** map -- a pointer to this map (unused). 61353751Seric ** hbuf -- a buffer containing a hostname. 61453751Seric ** hbsize -- the size of hbuf. 61555019Seric ** avp -- unused -- for compatibility with other mapping 61655019Seric ** functions. 61753751Seric ** 61853751Seric ** Returns: 61953751Seric ** The mapping, if found. 62053751Seric ** NULL if no mapping found. 62153751Seric ** 62253751Seric ** Side Effects: 62353751Seric ** Looks up the host specified in hbuf. If it is not 62453751Seric ** the canonical name for that host, return the canonical 62553751Seric ** name. 62653751Seric */ 62751315Seric 62853751Seric char * 62956823Seric maphostname(map, hbuf, hbsize, avp) 63056823Seric MAP *map; 63116911Seric char *hbuf; 63216911Seric int hbsize; 63353751Seric char **avp; 63416911Seric { 63516911Seric register struct hostent *hp; 63633932Sbostic u_long in_addr; 63756823Seric char *cp; 63858110Seric int i; 63933932Sbostic struct hostent *gethostbyaddr(); 64016911Seric 64156836Seric /* allow room for null */ 64256823Seric hbsize--; 64353751Seric 64425574Smiriam /* 64533932Sbostic * If first character is a bracket, then it is an address 64633932Sbostic * lookup. Address is copied into a temporary buffer to 64733932Sbostic * strip the brackets and to preserve hbuf if address is 64833932Sbostic * unknown. 64933932Sbostic */ 65053751Seric 65151315Seric if (*hbuf != '[') 65253751Seric { 65355019Seric extern bool getcanonname(); 65455019Seric 65558674Seric if (getcanonname(hbuf, hbsize)) 65653751Seric return hbuf; 65753751Seric else 65853751Seric return NULL; 65953751Seric } 66056823Seric if ((cp = strchr(hbuf, ']')) == NULL) 66153751Seric return (NULL); 66240994Sbostic *cp = '\0'; 66356823Seric in_addr = inet_addr(&hbuf[1]); 66458110Seric 66558110Seric /* check to see if this is one of our addresses */ 66658110Seric for (i = 0; MyIpAddrs[i].s_addr != 0; i++) 66758110Seric { 66858110Seric if (MyIpAddrs[i].s_addr == in_addr) 66958110Seric { 67058110Seric strncpy(hbuf, MyHostName, hbsize); 67158110Seric hbuf[hbsize] = '\0'; 67258110Seric return hbuf; 67358110Seric } 67458110Seric } 67558110Seric 67658110Seric /* nope -- ask the name server */ 67733932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 67833932Sbostic if (hp == NULL) 67953751Seric return (NULL); 68053751Seric 68158110Seric /* found a match -- copy out */ 68256823Seric if (strlen(hp->h_name) > hbsize) 68356823Seric hp->h_name[hbsize] = '\0'; 68453751Seric (void) strcpy(hbuf, hp->h_name); 68553751Seric return hbuf; 68633932Sbostic } 687*58755Seric /* 688*58755Seric ** ANYNET_NTOA -- convert a network address to printable form. 689*58755Seric ** 690*58755Seric ** Parameters: 691*58755Seric ** sap -- a pointer to a sockaddr structure. 692*58755Seric ** 693*58755Seric ** Returns: 694*58755Seric ** A printable version of that sockaddr. 695*58755Seric */ 69616911Seric 697*58755Seric char * 698*58755Seric anynet_ntoa(sap) 699*58755Seric register SOCKADDR *sap; 700*58755Seric { 701*58755Seric register char *bp; 702*58755Seric register char *ap; 703*58755Seric int l; 704*58755Seric static char buf[80]; 705*58755Seric 706*58755Seric if (sap->sa_family == AF_INET) 707*58755Seric { 708*58755Seric extern char *inet_ntoa(); 709*58755Seric 710*58755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 711*58755Seric } 712*58755Seric 713*58755Seric /* unknown family -- just dump bytes */ 714*58755Seric (void) sprintf(buf, "Family %d: ", sap->sa_family); 715*58755Seric bp = &buf[strlen(buf)]; 716*58755Seric ap = sap->sa_u.sa_data; 717*58755Seric for (l = sap->sa_len; --l >= 0; ) 718*58755Seric { 719*58755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 720*58755Seric bp += 3; 721*58755Seric } 722*58755Seric *--bp = '\0'; 723*58755Seric return buf; 724*58755Seric } 725*58755Seric 72656795Seric # else /* DAEMON */ 72716911Seric /* code for systems without sophisticated networking */ 72810758Seric 72910758Seric /* 73010758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 73111297Seric ** 73211297Seric ** Can't convert to upper case here because might be a UUCP name. 73312313Seric ** 73412313Seric ** Mark, you can change this to be anything you want...... 73510758Seric */ 73610758Seric 73710758Seric char ** 73812313Seric myhostname(hostbuf, size) 73910758Seric char hostbuf[]; 74012313Seric int size; 74110758Seric { 74210758Seric register FILE *f; 74310758Seric 74410758Seric hostbuf[0] = '\0'; 74510758Seric f = fopen("/usr/include/whoami", "r"); 74610758Seric if (f != NULL) 74710758Seric { 74812313Seric (void) fgets(hostbuf, size, f); 74910758Seric fixcrlf(hostbuf, TRUE); 75010758Seric (void) fclose(f); 75110758Seric } 75210758Seric return (NULL); 75310758Seric } 75416911Seric /* 75558308Seric ** GETREALHOSTNAME -- get the real host name asociated with a file descriptor 75658308Seric ** 75758308Seric ** Parameters: 75858308Seric ** fd -- the descriptor 75958308Seric ** 76058308Seric ** Returns: 76158308Seric ** The host name associated with this descriptor, if it can 76258308Seric ** be determined. 76358308Seric ** NULL otherwise. 76458308Seric ** 76558308Seric ** Side Effects: 76658308Seric ** none 76758308Seric */ 76858308Seric 76958308Seric char * 77058308Seric getrealhostname(fd) 77158308Seric int fd; 77258308Seric { 77358308Seric return NULL; 77458308Seric } 77558308Seric /* 77616911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 77716911Seric ** 77816911Seric ** Parameters: 77956823Seric ** map -- a pointer to the database map. 78016911Seric ** hbuf -- a buffer containing a hostname. 78153751Seric ** avp -- a pointer to a (cf file defined) argument vector. 78216911Seric ** 78316911Seric ** Returns: 78453751Seric ** mapped host name 78551315Seric ** FALSE otherwise. 78616911Seric ** 78716911Seric ** Side Effects: 78816911Seric ** Looks up the host specified in hbuf. If it is not 78916911Seric ** the canonical name for that host, replace it with 79016911Seric ** the canonical name. If the name is unknown, or it 79116911Seric ** is already the canonical name, leave it unchanged. 79216911Seric */ 79310758Seric 79416911Seric /*ARGSUSED*/ 79553751Seric char * 79656823Seric maphostname(map, hbuf, hbsize, avp) 79756823Seric MAP *map; 79816911Seric char *hbuf; 79916911Seric int hbsize; 80053751Seric char **avp; 80116911Seric { 80253751Seric return NULL; 80316911Seric } 80416911Seric 80556795Seric #endif /* DAEMON */ 806