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*58864Seric static char sccsid[] = "@(#)daemon.c 6.28 (Berkeley) 03/30/93 (with daemon mode)"; 1633780Sbostic #else 17*58864Seric static char sccsid[] = "@(#)daemon.c 6.28 (Berkeley) 03/30/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 8058849Seric int DaemonSocket = -1; /* fd describing socket */ 8158849Seric SOCKADDR DaemonAddr; /* socket for incoming */ 8216144Seric 834535Seric getrequests() 844535Seric { 859610Seric int t; 869610Seric register struct servent *sp; 8725027Seric int on = 1; 8853751Seric bool refusingconnections = TRUE; 8958419Seric FILE *pidf; 9046928Sbostic extern void reapchild(); 917117Seric 929610Seric /* 939610Seric ** Set up the address for the mailer. 949610Seric */ 959610Seric 9658849Seric if (DaemonAddr.sin.sin_family == 0) 9758849Seric DaemonAddr.sin.sin_family = AF_INET; 9858849Seric if (DaemonAddr.sin.sin_addr.s_addr == 0) 9958849Seric DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; 10058849Seric if (DaemonAddr.sin.sin_port == 0) 1019610Seric { 10258849Seric sp = getservbyname("smtp", "tcp"); 10358849Seric if (sp == NULL) 10458849Seric { 10558849Seric syserr("554 server \"smtp\" unknown"); 10658849Seric goto severe; 10758849Seric } 10858849Seric DaemonAddr.sin.sin_port = sp->s_port; 1099610Seric } 1109610Seric 1119610Seric /* 1129610Seric ** Try to actually open the connection. 1139610Seric */ 1149610Seric 1159610Seric if (tTd(15, 1)) 11658849Seric printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); 1179610Seric 1189610Seric /* get a socket for the SMTP connection */ 11923120Seric DaemonSocket = socket(AF_INET, SOCK_STREAM, 0); 12010206Seric if (DaemonSocket < 0) 1219610Seric { 1229610Seric /* probably another daemon already */ 1239610Seric syserr("getrequests: can't create socket"); 1249610Seric severe: 1259610Seric # ifdef LOG 1269610Seric if (LogLevel > 0) 12757663Seric syslog(LOG_ALERT, "problem creating SMTP socket"); 12856795Seric # endif /* LOG */ 1299610Seric finis(); 1309610Seric } 13110347Seric 13210347Seric /* turn on network debugging? */ 13356328Seric if (tTd(15, 101)) 13424945Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 13510347Seric 13625027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 13725027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 13825027Seric 13958849Seric if (bind(DaemonSocket, &DaemonAddr.sa, sizeof DaemonAddr) < 0) 1409610Seric { 1419610Seric syserr("getrequests: cannot bind"); 14210206Seric (void) close(DaemonSocket); 1439610Seric goto severe; 1449610Seric } 1459610Seric 14624955Seric (void) signal(SIGCHLD, reapchild); 14724945Seric 14858419Seric /* write the pid to the log file for posterity */ 14958419Seric pidf = fopen(PidFile, "w"); 15058419Seric if (pidf != NULL) 15158419Seric { 15258419Seric fprintf(pidf, "%d\n", getpid()); 15358419Seric fclose(pidf); 15458419Seric } 15558419Seric 15658419Seric 1579610Seric if (tTd(15, 1)) 15810206Seric printf("getrequests: %d\n", DaemonSocket); 1599610Seric 1604631Seric for (;;) 1614631Seric { 16214875Seric register int pid; 16311147Seric auto int lotherend; 16453751Seric extern bool refuseconnections(); 16511147Seric 16614875Seric /* see if we are rejecting connections */ 16753751Seric CurrentLA = getla(); 16853751Seric if (refuseconnections()) 16936584Sbostic { 17053751Seric if (!refusingconnections) 17153751Seric { 17253751Seric /* don't queue so peer will fail quickly */ 17353751Seric (void) listen(DaemonSocket, 0); 17453751Seric refusingconnections = TRUE; 17553751Seric } 17657385Seric setproctitle("rejecting connections: load average: %d", 17757385Seric CurrentLA); 17814875Seric sleep(5); 17953751Seric continue; 18036584Sbostic } 18114875Seric 18253751Seric if (refusingconnections) 18353751Seric { 18453751Seric /* start listening again */ 18553751Seric if (listen(DaemonSocket, 10) < 0) 18653751Seric { 18753751Seric syserr("getrequests: cannot listen"); 18853751Seric (void) close(DaemonSocket); 18953751Seric goto severe; 19053751Seric } 19153751Seric setproctitle("accepting connections"); 19253751Seric refusingconnections = FALSE; 19353751Seric } 19453751Seric 1959610Seric /* wait for a connection */ 1969610Seric do 1979610Seric { 1989610Seric errno = 0; 19936230Skarels lotherend = sizeof RealHostAddr; 20046928Sbostic t = accept(DaemonSocket, 20146928Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 2029610Seric } while (t < 0 && errno == EINTR); 2039610Seric if (t < 0) 2045978Seric { 2059610Seric syserr("getrequests: accept"); 2069610Seric sleep(5); 2079610Seric continue; 2085978Seric } 2094631Seric 2105978Seric /* 2115978Seric ** Create a subprocess to process the mail. 2125978Seric */ 2135978Seric 2147677Seric if (tTd(15, 2)) 2159610Seric printf("getrequests: forking (fd = %d)\n", t); 2165978Seric 2174636Seric pid = fork(); 2184636Seric if (pid < 0) 2194631Seric { 2204636Seric syserr("daemon: cannot fork"); 2214636Seric sleep(10); 2229610Seric (void) close(t); 2234636Seric continue; 2244631Seric } 2254631Seric 2264636Seric if (pid == 0) 2274631Seric { 22811147Seric extern struct hostent *gethostbyaddr(); 22911147Seric register struct hostent *hp; 23011147Seric char buf[MAXNAME]; 23111147Seric 2324636Seric /* 2334636Seric ** CHILD -- return to caller. 23411147Seric ** Collect verified idea of sending host. 2354636Seric ** Verify calling user id if possible here. 2364636Seric */ 2374631Seric 23824955Seric (void) signal(SIGCHLD, SIG_DFL); 23924950Seric 24011147Seric /* determine host name */ 24158778Seric switch (RealHostAddr.sa.sa_family) 24258778Seric { 24358778Seric #ifdef NETINET 24458778Seric case AF_INET: 24558778Seric hp = gethostbyaddr((char *) &RealHostAddr.sin.sin_addr, 24658778Seric sizeof RealHostAddr.sin.sin_addr, 24758778Seric AF_INET); 24858778Seric break; 24958778Seric #endif 25058778Seric 25158778Seric #ifdef NETISO 25258778Seric case AF_ISO: 25358778Seric hp = gethostbyaddr((char *) &RealHostAddr.siso.siso_addr, 25458778Seric sizeof RealHostAddr.siso.siso_addr, 25558778Seric AF_ISO); 25658778Seric break; 25758778Seric #endif 25858778Seric 25958778Seric default: 26058778Seric hp = gethostbyaddr(RealHostAddr.sa.sa_data, 26158778Seric sizeof RealHostAddr.sa.sa_data, 26258778Seric RealHostAddr.sa.sa_family); 26358778Seric break; 26458778Seric } 26558778Seric 26611147Seric if (hp != NULL) 26723104Seric (void) strcpy(buf, hp->h_name); 26811147Seric else 26916884Seric { 27016884Seric /* produce a dotted quad */ 27116884Seric (void) sprintf(buf, "[%s]", 27258755Seric anynet_ntoa(&RealHostAddr)); 27316884Seric } 27416884Seric 27555173Seric #ifdef LOG 27657977Seric if (LogLevel > 10) 27755173Seric { 27855173Seric /* log connection information */ 27955173Seric syslog(LOG_INFO, "connect from %s (%s)", 28058755Seric buf, anynet_ntoa(&RealHostAddr)); 28155173Seric } 28255173Seric #endif 28355173Seric 28416884Seric /* should we check for illegal connection here? XXX */ 28516884Seric 28611147Seric RealHostName = newstr(buf); 28711147Seric 28810206Seric (void) close(DaemonSocket); 2899610Seric InChannel = fdopen(t, "r"); 29021062Seric OutChannel = fdopen(dup(t), "w"); 2917677Seric if (tTd(15, 2)) 2925978Seric printf("getreq: returning\n"); 2934636Seric return; 2944631Seric } 2954631Seric 2967117Seric /* close the port so that others will hang (for a while) */ 2979610Seric (void) close(t); 2984631Seric } 2999886Seric /*NOTREACHED*/ 3004631Seric } 3015978Seric /* 30210206Seric ** CLRDAEMON -- reset the daemon connection 30310206Seric ** 30410206Seric ** Parameters: 30510206Seric ** none. 30610206Seric ** 30710206Seric ** Returns: 30810206Seric ** none. 30910206Seric ** 31010206Seric ** Side Effects: 31110206Seric ** releases any resources used by the passive daemon. 31210206Seric */ 31310206Seric 31410206Seric clrdaemon() 31510206Seric { 31610206Seric if (DaemonSocket >= 0) 31710206Seric (void) close(DaemonSocket); 31810206Seric DaemonSocket = -1; 31910206Seric } 32010206Seric /* 32158849Seric ** SETDAEMONOPTIONS -- set options for running the daemon 32258849Seric ** 32358849Seric ** Parameters: 32458849Seric ** p -- the options line. 32558849Seric ** 32658849Seric ** Returns: 32758849Seric ** none. 32858849Seric */ 32958849Seric 33058849Seric setdaemonoptions(p) 33158849Seric register char *p; 33258849Seric { 33358849Seric while (p != NULL) 33458849Seric { 33558849Seric register char *f; 33658849Seric register char *v; 33758849Seric 33858849Seric while (isascii(*p) && isspace(*p)) 33958849Seric p++; 34058849Seric if (*p == '\0') 34158849Seric break; 34258849Seric f = p; 34358849Seric p = strchr(p, ','); 34458849Seric if (p != NULL) 34558849Seric *p++ = '\0'; 34658849Seric v = strchr(f, '='); 34758849Seric if (v == NULL) 34858849Seric continue; 34958849Seric while (isascii(*++v) && isspace(*v)) 35058849Seric continue; 35158849Seric 35258849Seric switch (*f) 35358849Seric { 35458849Seric case 'P': /* port */ 35558849Seric case 'p': 35658849Seric if (isascii(*v) && isdigit(*v)) 35758849Seric DaemonAddr.sin.sin_port = atoi(v); 35858849Seric else 35958849Seric { 36058849Seric register struct servent *sp; 36158849Seric 36258849Seric sp = getservbyname(v, "tcp"); 36358849Seric if (sp == NULL) 36458849Seric syserr("554 server \"%s\" unknown", v); 36558849Seric else 36658849Seric DaemonAddr.sin.sin_port = sp->s_port; 36758849Seric } 36858849Seric break; 36958849Seric 37058849Seric case 'A': /* address */ 37158849Seric case 'a': 37258849Seric if (isascii(*v) && isdigit(*v)) 37358863Seric DaemonAddr.sin.sin_addr.s_addr = inet_network(v); 37458849Seric else 37558849Seric { 37658849Seric register struct netent *np; 37758849Seric 37858849Seric np = getnetbyname(v); 37958849Seric if (np == NULL) 38058849Seric syserr("554 network \"%s\" unknown", v); 38158849Seric else 38258849Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 38358849Seric } 38458849Seric break; 38558849Seric } 38658849Seric } 38758849Seric } 38858849Seric /* 3896039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 3906039Seric ** 3916039Seric ** Parameters: 3926039Seric ** host -- the name of the host. 3936633Seric ** port -- the port number to connect to. 39453739Seric ** mci -- a pointer to the mail connection information 39553739Seric ** structure to be filled in. 39652106Seric ** usesecureport -- if set, use a low numbered (reserved) 39752106Seric ** port to provide some rudimentary authentication. 3986039Seric ** 3996039Seric ** Returns: 4006039Seric ** An exit code telling whether the connection could be 4016039Seric ** made and if not why not. 4026039Seric ** 4036039Seric ** Side Effects: 4046039Seric ** none. 4056039Seric */ 4065978Seric 40758755Seric SOCKADDR CurHostAddr; /* address of current host */ 40858305Seric 40954967Seric int 41053739Seric makeconnection(host, port, mci, usesecureport) 4116039Seric char *host; 4127286Seric u_short port; 41354967Seric register MCI *mci; 41452106Seric bool usesecureport; 4156039Seric { 41629430Sbloom register int i, s; 41729430Sbloom register struct hostent *hp = (struct hostent *)NULL; 41858755Seric SOCKADDR addr; 41952106Seric int sav_errno; 42058755Seric int addrlen; 42135651Seric #ifdef NAMED_BIND 42235651Seric extern int h_errno; 42335651Seric #endif 4246039Seric 4256039Seric /* 4266039Seric ** Set up the address for the mailer. 4279308Seric ** Accept "[a.b.c.d]" syntax for host name. 4286039Seric */ 4296039Seric 43035651Seric #ifdef NAMED_BIND 43125475Smiriam h_errno = 0; 43235651Seric #endif 43325475Smiriam errno = 0; 434*58864Seric bzero(&CurHostAddr, sizeof CurHostAddr); 43525475Smiriam 4369308Seric if (host[0] == '[') 4379308Seric { 43811147Seric long hid; 43956795Seric register char *p = strchr(host, ']'); 4409308Seric 44111147Seric if (p != NULL) 4429308Seric { 44311147Seric *p = '\0'; 44411147Seric hid = inet_addr(&host[1]); 44558360Seric if (hid == -1) 44658360Seric { 44758360Seric /* try it as a host name (avoid MX lookup) */ 44858360Seric hp = gethostbyname(&host[1]); 44958360Seric *p = ']'; 45058360Seric goto gothostent; 45158360Seric } 45211147Seric *p = ']'; 4539308Seric } 45458360Seric if (p == NULL) 4559308Seric { 45658151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 4579308Seric return (EX_NOHOST); 4589308Seric } 45958778Seric addr.sin.sin_family = AF_INET; 46058778Seric addr.sin.sin_addr.s_addr = hid; 4619308Seric } 4629610Seric else 4639610Seric { 46429430Sbloom hp = gethostbyname(host); 46558360Seric gothostent: 46625475Smiriam if (hp == NULL) 46724945Seric { 46835651Seric #ifdef NAMED_BIND 46925475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 47025475Smiriam return (EX_TEMPFAIL); 47125657Seric 47235651Seric /* if name server is specified, assume temp fail */ 47335651Seric if (errno == ECONNREFUSED && UseNameServer) 47435651Seric return (EX_TEMPFAIL); 47535651Seric #endif 47625475Smiriam return (EX_NOHOST); 47724945Seric } 47858778Seric addr.sa.sa_family = hp->h_addrtype; 47958778Seric switch (hp->h_addrtype) 48058778Seric { 48158778Seric #ifdef NETINET 48258778Seric case AF_INET: 48358755Seric bcopy(hp->h_addr, 48458778Seric &addr.sin.sin_addr, 48558755Seric hp->h_length); 48658778Seric break; 48758778Seric #endif 48858778Seric 48958778Seric default: 49058755Seric bcopy(hp->h_addr, 49158778Seric addr.sa.sa_data, 49258755Seric hp->h_length); 49358778Seric break; 49458778Seric } 49529430Sbloom i = 1; 4969610Seric } 4979610Seric 4989610Seric /* 4999610Seric ** Determine the port number. 5009610Seric */ 5019610Seric 50210011Seric if (port != 0) 50358755Seric port = htons(port); 50410011Seric else 5059610Seric { 5069610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 5079610Seric 5089610Seric if (sp == NULL) 5099610Seric { 51058151Seric syserr("554 makeconnection: server \"smtp\" unknown"); 51157977Seric return (EX_OSERR); 5129610Seric } 51358755Seric port = sp->s_port; 5149610Seric } 5156039Seric 51658778Seric switch (addr.sa.sa_family) 51758755Seric { 51858755Seric case AF_INET: 51958778Seric addr.sin.sin_port = port; 52058755Seric addrlen = sizeof (struct sockaddr_in); 52158755Seric break; 52258755Seric 52358755Seric #ifdef NETISO 52458755Seric case AF_ISO: 52558755Seric /* assume two byte transport selector */ 52658755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 52758755Seric addrlen = sizeof (struct sockaddr_iso); 52858755Seric break; 52958755Seric #endif 53058755Seric 53158755Seric default: 53258778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 53358755Seric return (EX_NOHOST); 53458755Seric } 53558755Seric 5366039Seric /* 5376039Seric ** Try to actually open the connection. 5386039Seric */ 5396039Seric 54057736Seric for (;;) 54152106Seric { 54257736Seric if (tTd(16, 1)) 54358755Seric printf("makeconnection (%s [%s])\n", 54458755Seric host, anynet_ntoa(&addr)); 54552106Seric 54658588Seric /* save for logging */ 54758588Seric CurHostAddr = addr; 54858588Seric 54957736Seric if (usesecureport) 55057736Seric { 55157736Seric int rport = IPPORT_RESERVED - 1; 5526039Seric 55357736Seric s = rresvport(&rport); 55457736Seric } 55557736Seric else 55657736Seric { 55757736Seric s = socket(AF_INET, SOCK_STREAM, 0); 55857736Seric } 55957736Seric if (s < 0) 56057736Seric { 56157736Seric sav_errno = errno; 56257736Seric syserr("makeconnection: no socket"); 56357736Seric goto failure; 56457736Seric } 56510347Seric 56657736Seric if (tTd(16, 1)) 56757736Seric printf("makeconnection: fd=%d\n", s); 56857736Seric 56957736Seric /* turn on network debugging? */ 57057736Seric if (tTd(16, 101)) 57157736Seric { 57257736Seric int on = 1; 57357736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 57457736Seric (char *)&on, sizeof on); 57557736Seric } 57657736Seric if (CurEnv->e_xfp != NULL) 57757736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 57857736Seric errno = 0; /* for debugging */ 57958755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 58057736Seric break; 58157736Seric 58257736Seric /* couldn't connect.... figure out why */ 58327744Sbloom sav_errno = errno; 58427744Sbloom (void) close(s); 58529430Sbloom if (hp && hp->h_addr_list[i]) 58629430Sbloom { 58758755Seric extern char *errstring(); 58858755Seric 58957736Seric if (tTd(16, 1)) 59058755Seric printf("Connect failed (%s); trying new address....\n", 59158755Seric errstring(sav_errno)); 59258778Seric switch (addr.sa.sa_family) 59358778Seric { 59458778Seric #ifdef NETINET 59558778Seric case AF_INET: 59658755Seric bcopy(hp->h_addr_list[i++], 59758778Seric &addr.sin.sin_addr, 59858755Seric hp->h_length); 59958778Seric break; 60058778Seric #endif 60158778Seric 60258778Seric default: 60358755Seric bcopy(hp->h_addr_list[i++], 60458778Seric addr.sa.sa_data, 60552106Seric hp->h_length); 60658778Seric break; 60758778Seric } 60857736Seric continue; 60929430Sbloom } 61029430Sbloom 6116039Seric /* failure, decide if temporary or not */ 6126039Seric failure: 61358542Seric if (transienterror(sav_errno)) 61458542Seric return EX_TEMPFAIL; 61558542Seric else 61658542Seric { 61758542Seric extern char *errstring(); 61811147Seric 61958542Seric message("%s", errstring(sav_errno)); 62058542Seric return (EX_UNAVAILABLE); 6216039Seric } 6226039Seric } 6236039Seric 6246039Seric /* connection ok, put it into canonical form */ 62553739Seric mci->mci_out = fdopen(s, "w"); 62653739Seric mci->mci_in = fdopen(dup(s), "r"); 6276039Seric 62810098Seric return (EX_OK); 6296039Seric } 63010758Seric /* 63110758Seric ** MYHOSTNAME -- return the name of this host. 63210758Seric ** 63310758Seric ** Parameters: 63410758Seric ** hostbuf -- a place to return the name of this host. 63512313Seric ** size -- the size of hostbuf. 63610758Seric ** 63710758Seric ** Returns: 63810758Seric ** A list of aliases for this host. 63910758Seric ** 64010758Seric ** Side Effects: 64158110Seric ** Sets the MyIpAddrs buffer to a list of my IP addresses. 64210758Seric */ 6436039Seric 64458110Seric struct in_addr MyIpAddrs[MAXIPADDR + 1]; 64558110Seric 64610758Seric char ** 64712313Seric myhostname(hostbuf, size) 64810758Seric char hostbuf[]; 64912313Seric int size; 65010758Seric { 65158110Seric register struct hostent *hp; 65210758Seric extern struct hostent *gethostbyname(); 65310758Seric 65423120Seric if (gethostname(hostbuf, size) < 0) 65523120Seric { 65623120Seric (void) strcpy(hostbuf, "localhost"); 65723120Seric } 65811147Seric hp = gethostbyname(hostbuf); 65911147Seric if (hp != NULL) 66016877Seric { 66158110Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 66258110Seric hostbuf[size - 1] = '\0'; 66358110Seric 66458110Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 66558110Seric { 66658110Seric register int i; 66758110Seric 66858110Seric for (i = 0; i < MAXIPADDR; i++) 66958110Seric { 67058110Seric if (hp->h_addr_list[i] == NULL) 67158110Seric break; 67258110Seric MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i]; 67358110Seric } 67458110Seric MyIpAddrs[i].s_addr = 0; 67558110Seric } 67658110Seric 67711147Seric return (hp->h_aliases); 67816877Seric } 67910758Seric else 68010758Seric return (NULL); 68110758Seric } 68251315Seric /* 68358308Seric ** GETREALHOSTNAME -- get the real host name asociated with a file descriptor 68458308Seric ** 68558308Seric ** Parameters: 68658308Seric ** fd -- the descriptor 68758308Seric ** 68858308Seric ** Returns: 68958308Seric ** The host name associated with this descriptor, if it can 69058308Seric ** be determined. 69158308Seric ** NULL otherwise. 69258308Seric ** 69358308Seric ** Side Effects: 69458308Seric ** none 69558308Seric */ 69658308Seric 69758308Seric char * 69858308Seric getrealhostname(fd) 69958308Seric int fd; 70058308Seric { 70158308Seric register struct hostent *hp; 70258786Seric SOCKADDR sa; 70358755Seric int salen; 70458308Seric char hbuf[MAXNAME]; 70558308Seric extern struct hostent *gethostbyaddr(); 70658308Seric 70758755Seric salen = sizeof sa; 70858787Seric if (getsockname(fd, &sa.sa, &salen) < 0 || salen <= 0) 70958308Seric return NULL; 71058787Seric hp = gethostbyaddr(sa.sa.sa_data, salen, sa.sa.sa_family); 71158308Seric if (hp != NULL) 71258308Seric (void) strcpy(hbuf, hp->h_name); 71358308Seric else 71458755Seric (void) sprintf(hbuf, "[%s]", anynet_ntoa(&sa)); 71558308Seric return hbuf; 71658308Seric } 71758308Seric /* 71853751Seric ** MAPHOSTNAME -- turn a hostname into canonical form 71953751Seric ** 72053751Seric ** Parameters: 72156823Seric ** map -- a pointer to this map (unused). 72253751Seric ** hbuf -- a buffer containing a hostname. 72353751Seric ** hbsize -- the size of hbuf. 72455019Seric ** avp -- unused -- for compatibility with other mapping 72555019Seric ** functions. 72653751Seric ** 72753751Seric ** Returns: 72853751Seric ** The mapping, if found. 72953751Seric ** NULL if no mapping found. 73053751Seric ** 73153751Seric ** Side Effects: 73253751Seric ** Looks up the host specified in hbuf. If it is not 73353751Seric ** the canonical name for that host, return the canonical 73453751Seric ** name. 73553751Seric */ 73651315Seric 73753751Seric char * 73856823Seric maphostname(map, hbuf, hbsize, avp) 73956823Seric MAP *map; 74016911Seric char *hbuf; 74116911Seric int hbsize; 74253751Seric char **avp; 74316911Seric { 74416911Seric register struct hostent *hp; 74533932Sbostic u_long in_addr; 74656823Seric char *cp; 74758110Seric int i; 74833932Sbostic struct hostent *gethostbyaddr(); 74916911Seric 75056836Seric /* allow room for null */ 75156823Seric hbsize--; 75253751Seric 75325574Smiriam /* 75433932Sbostic * If first character is a bracket, then it is an address 75533932Sbostic * lookup. Address is copied into a temporary buffer to 75633932Sbostic * strip the brackets and to preserve hbuf if address is 75733932Sbostic * unknown. 75833932Sbostic */ 75953751Seric 76051315Seric if (*hbuf != '[') 76153751Seric { 76255019Seric extern bool getcanonname(); 76355019Seric 76458798Seric if (tTd(9, 1)) 76558798Seric printf("maphostname(%s, %d) => ", hbuf, hbsize); 76658674Seric if (getcanonname(hbuf, hbsize)) 76758796Seric { 76858796Seric if (tTd(9, 1)) 76958796Seric printf("%s\n", hbuf); 77053751Seric return hbuf; 77158796Seric } 77253751Seric else 77358796Seric { 77458796Seric if (tTd(9, 1)) 77558796Seric printf("FAIL\n"); 77653751Seric return NULL; 77758796Seric } 77853751Seric } 77956823Seric if ((cp = strchr(hbuf, ']')) == NULL) 78053751Seric return (NULL); 78140994Sbostic *cp = '\0'; 78256823Seric in_addr = inet_addr(&hbuf[1]); 78358110Seric 78458110Seric /* check to see if this is one of our addresses */ 78558110Seric for (i = 0; MyIpAddrs[i].s_addr != 0; i++) 78658110Seric { 78758110Seric if (MyIpAddrs[i].s_addr == in_addr) 78858110Seric { 78958110Seric strncpy(hbuf, MyHostName, hbsize); 79058110Seric hbuf[hbsize] = '\0'; 79158110Seric return hbuf; 79258110Seric } 79358110Seric } 79458110Seric 79558110Seric /* nope -- ask the name server */ 79633932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 79733932Sbostic if (hp == NULL) 79853751Seric return (NULL); 79953751Seric 80058110Seric /* found a match -- copy out */ 80156823Seric if (strlen(hp->h_name) > hbsize) 80256823Seric hp->h_name[hbsize] = '\0'; 80353751Seric (void) strcpy(hbuf, hp->h_name); 80453751Seric return hbuf; 80533932Sbostic } 80658755Seric /* 80758755Seric ** ANYNET_NTOA -- convert a network address to printable form. 80858755Seric ** 80958755Seric ** Parameters: 81058755Seric ** sap -- a pointer to a sockaddr structure. 81158755Seric ** 81258755Seric ** Returns: 81358755Seric ** A printable version of that sockaddr. 81458755Seric */ 81516911Seric 81658755Seric char * 81758755Seric anynet_ntoa(sap) 81858755Seric register SOCKADDR *sap; 81958755Seric { 82058755Seric register char *bp; 82158755Seric register char *ap; 82258755Seric int l; 82358755Seric static char buf[80]; 82458755Seric 82558798Seric /* check for null/zero family */ 82658798Seric if (sap == NULL) 82758798Seric return "NULLADDR"; 82858798Seric if (sap->sa.sa_family == 0) 82958798Seric return "0"; 83058798Seric 83158778Seric #ifdef NETINET 83258778Seric if (sap->sa.sa_family == AF_INET) 83358755Seric { 83458755Seric extern char *inet_ntoa(); 83558755Seric 83658755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 83758755Seric } 83858778Seric #endif 83958755Seric 84058755Seric /* unknown family -- just dump bytes */ 84158778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 84258755Seric bp = &buf[strlen(buf)]; 84358778Seric ap = sap->sa.sa_data; 84458778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 84558755Seric { 84658755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 84758755Seric bp += 3; 84858755Seric } 84958755Seric *--bp = '\0'; 85058755Seric return buf; 85158755Seric } 85258755Seric 85356795Seric # else /* DAEMON */ 85416911Seric /* code for systems without sophisticated networking */ 85510758Seric 85610758Seric /* 85710758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 85811297Seric ** 85911297Seric ** Can't convert to upper case here because might be a UUCP name. 86012313Seric ** 86112313Seric ** Mark, you can change this to be anything you want...... 86210758Seric */ 86310758Seric 86410758Seric char ** 86512313Seric myhostname(hostbuf, size) 86610758Seric char hostbuf[]; 86712313Seric int size; 86810758Seric { 86910758Seric register FILE *f; 87010758Seric 87110758Seric hostbuf[0] = '\0'; 87210758Seric f = fopen("/usr/include/whoami", "r"); 87310758Seric if (f != NULL) 87410758Seric { 87512313Seric (void) fgets(hostbuf, size, f); 87610758Seric fixcrlf(hostbuf, TRUE); 87710758Seric (void) fclose(f); 87810758Seric } 87910758Seric return (NULL); 88010758Seric } 88116911Seric /* 88258308Seric ** GETREALHOSTNAME -- get the real host name asociated with a file descriptor 88358308Seric ** 88458308Seric ** Parameters: 88558308Seric ** fd -- the descriptor 88658308Seric ** 88758308Seric ** Returns: 88858308Seric ** The host name associated with this descriptor, if it can 88958308Seric ** be determined. 89058308Seric ** NULL otherwise. 89158308Seric ** 89258308Seric ** Side Effects: 89358308Seric ** none 89458308Seric */ 89558308Seric 89658308Seric char * 89758308Seric getrealhostname(fd) 89858308Seric int fd; 89958308Seric { 90058308Seric return NULL; 90158308Seric } 90258308Seric /* 90316911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 90416911Seric ** 90516911Seric ** Parameters: 90656823Seric ** map -- a pointer to the database map. 90716911Seric ** hbuf -- a buffer containing a hostname. 90853751Seric ** avp -- a pointer to a (cf file defined) argument vector. 90916911Seric ** 91016911Seric ** Returns: 91153751Seric ** mapped host name 91251315Seric ** FALSE otherwise. 91316911Seric ** 91416911Seric ** Side Effects: 91516911Seric ** Looks up the host specified in hbuf. If it is not 91616911Seric ** the canonical name for that host, replace it with 91716911Seric ** the canonical name. If the name is unknown, or it 91816911Seric ** is already the canonical name, leave it unchanged. 91916911Seric */ 92010758Seric 92116911Seric /*ARGSUSED*/ 92253751Seric char * 92356823Seric maphostname(map, hbuf, hbsize, avp) 92456823Seric MAP *map; 92516911Seric char *hbuf; 92616911Seric int hbsize; 92753751Seric char **avp; 92816911Seric { 92953751Seric return NULL; 93016911Seric } 93116911Seric 93256795Seric #endif /* DAEMON */ 933