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*58849Seric static char sccsid[] = "@(#)daemon.c 6.26 (Berkeley) 03/29/93 (with daemon mode)"; 1633780Sbostic #else 17*58849Seric static char sccsid[] = "@(#)daemon.c 6.26 (Berkeley) 03/29/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 80*58849Seric int DaemonSocket = -1; /* fd describing socket */ 81*58849Seric 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 96*58849Seric if (DaemonAddr.sin.sin_family == 0) 97*58849Seric DaemonAddr.sin.sin_family = AF_INET; 98*58849Seric if (DaemonAddr.sin.sin_addr.s_addr == 0) 99*58849Seric DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; 100*58849Seric if (DaemonAddr.sin.sin_port == 0) 1019610Seric { 102*58849Seric sp = getservbyname("smtp", "tcp"); 103*58849Seric if (sp == NULL) 104*58849Seric { 105*58849Seric syserr("554 server \"smtp\" unknown"); 106*58849Seric goto severe; 107*58849Seric } 108*58849Seric DaemonAddr.sin.sin_port = sp->s_port; 1099610Seric } 1109610Seric 1119610Seric /* 1129610Seric ** Try to actually open the connection. 1139610Seric */ 1149610Seric 1159610Seric if (tTd(15, 1)) 116*58849Seric 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 139*58849Seric 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 /* 321*58849Seric ** SETDAEMONOPTIONS -- set options for running the daemon 322*58849Seric ** 323*58849Seric ** Parameters: 324*58849Seric ** p -- the options line. 325*58849Seric ** 326*58849Seric ** Returns: 327*58849Seric ** none. 328*58849Seric */ 329*58849Seric 330*58849Seric setdaemonoptions(p) 331*58849Seric register char *p; 332*58849Seric { 333*58849Seric while (p != NULL) 334*58849Seric { 335*58849Seric register char *f; 336*58849Seric register char *v; 337*58849Seric 338*58849Seric while (isascii(*p) && isspace(*p)) 339*58849Seric p++; 340*58849Seric if (*p == '\0') 341*58849Seric break; 342*58849Seric f = p; 343*58849Seric p = strchr(p, ','); 344*58849Seric if (p != NULL) 345*58849Seric *p++ = '\0'; 346*58849Seric v = strchr(f, '='); 347*58849Seric if (v == NULL) 348*58849Seric continue; 349*58849Seric while (isascii(*++v) && isspace(*v)) 350*58849Seric continue; 351*58849Seric 352*58849Seric switch (*f) 353*58849Seric { 354*58849Seric case 'P': /* port */ 355*58849Seric case 'p': 356*58849Seric if (isascii(*v) && isdigit(*v)) 357*58849Seric DaemonAddr.sin.sin_port = atoi(v); 358*58849Seric else 359*58849Seric { 360*58849Seric register struct servent *sp; 361*58849Seric 362*58849Seric sp = getservbyname(v, "tcp"); 363*58849Seric if (sp == NULL) 364*58849Seric syserr("554 server \"%s\" unknown", v); 365*58849Seric else 366*58849Seric DaemonAddr.sin.sin_port = sp->s_port; 367*58849Seric } 368*58849Seric break; 369*58849Seric 370*58849Seric case 'A': /* address */ 371*58849Seric case 'a': 372*58849Seric if (isascii(*v) && isdigit(*v)) 373*58849Seric (void) inet_aton(v, &DaemonAddr.sin.sin_addr); 374*58849Seric else 375*58849Seric { 376*58849Seric register struct netent *np; 377*58849Seric 378*58849Seric np = getnetbyname(v); 379*58849Seric if (np == NULL) 380*58849Seric syserr("554 network \"%s\" unknown", v); 381*58849Seric else 382*58849Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 383*58849Seric } 384*58849Seric break; 385*58849Seric } 386*58849Seric } 387*58849Seric } 388*58849Seric /* 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; 43425475Smiriam 4359308Seric if (host[0] == '[') 4369308Seric { 43711147Seric long hid; 43856795Seric register char *p = strchr(host, ']'); 4399308Seric 44011147Seric if (p != NULL) 4419308Seric { 44211147Seric *p = '\0'; 44311147Seric hid = inet_addr(&host[1]); 44458360Seric if (hid == -1) 44558360Seric { 44658360Seric /* try it as a host name (avoid MX lookup) */ 44758360Seric hp = gethostbyname(&host[1]); 44858360Seric *p = ']'; 44958360Seric goto gothostent; 45058360Seric } 45111147Seric *p = ']'; 4529308Seric } 45358360Seric if (p == NULL) 4549308Seric { 45558151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 4569308Seric return (EX_NOHOST); 4579308Seric } 45858778Seric addr.sin.sin_family = AF_INET; 45958778Seric addr.sin.sin_addr.s_addr = hid; 4609308Seric } 4619610Seric else 4629610Seric { 46329430Sbloom hp = gethostbyname(host); 46458360Seric gothostent: 46525475Smiriam if (hp == NULL) 46624945Seric { 46735651Seric #ifdef NAMED_BIND 46825475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 46925475Smiriam return (EX_TEMPFAIL); 47025657Seric 47135651Seric /* if name server is specified, assume temp fail */ 47235651Seric if (errno == ECONNREFUSED && UseNameServer) 47335651Seric return (EX_TEMPFAIL); 47435651Seric #endif 47525475Smiriam return (EX_NOHOST); 47624945Seric } 47758778Seric addr.sa.sa_family = hp->h_addrtype; 47858778Seric switch (hp->h_addrtype) 47958778Seric { 48058778Seric #ifdef NETINET 48158778Seric case AF_INET: 48258755Seric bcopy(hp->h_addr, 48358778Seric &addr.sin.sin_addr, 48458755Seric hp->h_length); 48558778Seric break; 48658778Seric #endif 48758778Seric 48858778Seric default: 48958755Seric bcopy(hp->h_addr, 49058778Seric addr.sa.sa_data, 49158755Seric hp->h_length); 49258778Seric break; 49358778Seric } 49429430Sbloom i = 1; 4959610Seric } 4969610Seric 4979610Seric /* 4989610Seric ** Determine the port number. 4999610Seric */ 5009610Seric 50110011Seric if (port != 0) 50258755Seric port = htons(port); 50310011Seric else 5049610Seric { 5059610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 5069610Seric 5079610Seric if (sp == NULL) 5089610Seric { 50958151Seric syserr("554 makeconnection: server \"smtp\" unknown"); 51057977Seric return (EX_OSERR); 5119610Seric } 51258755Seric port = sp->s_port; 5139610Seric } 5146039Seric 51558778Seric switch (addr.sa.sa_family) 51658755Seric { 51758755Seric case AF_INET: 51858778Seric addr.sin.sin_port = port; 51958755Seric addrlen = sizeof (struct sockaddr_in); 52058755Seric break; 52158755Seric 52258755Seric #ifdef NETISO 52358755Seric case AF_ISO: 52458755Seric /* assume two byte transport selector */ 52558755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 52658755Seric addrlen = sizeof (struct sockaddr_iso); 52758755Seric break; 52858755Seric #endif 52958755Seric 53058755Seric default: 53158778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 53258755Seric return (EX_NOHOST); 53358755Seric } 53458755Seric 5356039Seric /* 5366039Seric ** Try to actually open the connection. 5376039Seric */ 5386039Seric 53957736Seric for (;;) 54052106Seric { 54157736Seric if (tTd(16, 1)) 54258755Seric printf("makeconnection (%s [%s])\n", 54358755Seric host, anynet_ntoa(&addr)); 54452106Seric 54558588Seric /* save for logging */ 54658588Seric CurHostAddr = addr; 54758588Seric 54857736Seric if (usesecureport) 54957736Seric { 55057736Seric int rport = IPPORT_RESERVED - 1; 5516039Seric 55257736Seric s = rresvport(&rport); 55357736Seric } 55457736Seric else 55557736Seric { 55657736Seric s = socket(AF_INET, SOCK_STREAM, 0); 55757736Seric } 55857736Seric if (s < 0) 55957736Seric { 56057736Seric sav_errno = errno; 56157736Seric syserr("makeconnection: no socket"); 56257736Seric goto failure; 56357736Seric } 56410347Seric 56557736Seric if (tTd(16, 1)) 56657736Seric printf("makeconnection: fd=%d\n", s); 56757736Seric 56857736Seric /* turn on network debugging? */ 56957736Seric if (tTd(16, 101)) 57057736Seric { 57157736Seric int on = 1; 57257736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 57357736Seric (char *)&on, sizeof on); 57457736Seric } 57557736Seric if (CurEnv->e_xfp != NULL) 57657736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 57757736Seric errno = 0; /* for debugging */ 57858755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 57957736Seric break; 58057736Seric 58157736Seric /* couldn't connect.... figure out why */ 58227744Sbloom sav_errno = errno; 58327744Sbloom (void) close(s); 58429430Sbloom if (hp && hp->h_addr_list[i]) 58529430Sbloom { 58658755Seric extern char *errstring(); 58758755Seric 58857736Seric if (tTd(16, 1)) 58958755Seric printf("Connect failed (%s); trying new address....\n", 59058755Seric errstring(sav_errno)); 59158778Seric switch (addr.sa.sa_family) 59258778Seric { 59358778Seric #ifdef NETINET 59458778Seric case AF_INET: 59558755Seric bcopy(hp->h_addr_list[i++], 59658778Seric &addr.sin.sin_addr, 59758755Seric hp->h_length); 59858778Seric break; 59958778Seric #endif 60058778Seric 60158778Seric default: 60258755Seric bcopy(hp->h_addr_list[i++], 60358778Seric addr.sa.sa_data, 60452106Seric hp->h_length); 60558778Seric break; 60658778Seric } 60757736Seric continue; 60829430Sbloom } 60929430Sbloom 6106039Seric /* failure, decide if temporary or not */ 6116039Seric failure: 61258542Seric if (transienterror(sav_errno)) 61358542Seric return EX_TEMPFAIL; 61458542Seric else 61558542Seric { 61658542Seric extern char *errstring(); 61711147Seric 61858542Seric message("%s", errstring(sav_errno)); 61958542Seric return (EX_UNAVAILABLE); 6206039Seric } 6216039Seric } 6226039Seric 6236039Seric /* connection ok, put it into canonical form */ 62453739Seric mci->mci_out = fdopen(s, "w"); 62553739Seric mci->mci_in = fdopen(dup(s), "r"); 6266039Seric 62710098Seric return (EX_OK); 6286039Seric } 62910758Seric /* 63010758Seric ** MYHOSTNAME -- return the name of this host. 63110758Seric ** 63210758Seric ** Parameters: 63310758Seric ** hostbuf -- a place to return the name of this host. 63412313Seric ** size -- the size of hostbuf. 63510758Seric ** 63610758Seric ** Returns: 63710758Seric ** A list of aliases for this host. 63810758Seric ** 63910758Seric ** Side Effects: 64058110Seric ** Sets the MyIpAddrs buffer to a list of my IP addresses. 64110758Seric */ 6426039Seric 64358110Seric struct in_addr MyIpAddrs[MAXIPADDR + 1]; 64458110Seric 64510758Seric char ** 64612313Seric myhostname(hostbuf, size) 64710758Seric char hostbuf[]; 64812313Seric int size; 64910758Seric { 65058110Seric register struct hostent *hp; 65110758Seric extern struct hostent *gethostbyname(); 65210758Seric 65323120Seric if (gethostname(hostbuf, size) < 0) 65423120Seric { 65523120Seric (void) strcpy(hostbuf, "localhost"); 65623120Seric } 65711147Seric hp = gethostbyname(hostbuf); 65811147Seric if (hp != NULL) 65916877Seric { 66058110Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 66158110Seric hostbuf[size - 1] = '\0'; 66258110Seric 66358110Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 66458110Seric { 66558110Seric register int i; 66658110Seric 66758110Seric for (i = 0; i < MAXIPADDR; i++) 66858110Seric { 66958110Seric if (hp->h_addr_list[i] == NULL) 67058110Seric break; 67158110Seric MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i]; 67258110Seric } 67358110Seric MyIpAddrs[i].s_addr = 0; 67458110Seric } 67558110Seric 67611147Seric return (hp->h_aliases); 67716877Seric } 67810758Seric else 67910758Seric return (NULL); 68010758Seric } 68151315Seric /* 68258308Seric ** GETREALHOSTNAME -- get the real host name asociated with a file descriptor 68358308Seric ** 68458308Seric ** Parameters: 68558308Seric ** fd -- the descriptor 68658308Seric ** 68758308Seric ** Returns: 68858308Seric ** The host name associated with this descriptor, if it can 68958308Seric ** be determined. 69058308Seric ** NULL otherwise. 69158308Seric ** 69258308Seric ** Side Effects: 69358308Seric ** none 69458308Seric */ 69558308Seric 69658308Seric char * 69758308Seric getrealhostname(fd) 69858308Seric int fd; 69958308Seric { 70058308Seric register struct hostent *hp; 70158786Seric SOCKADDR sa; 70258755Seric int salen; 70358308Seric char hbuf[MAXNAME]; 70458308Seric extern struct hostent *gethostbyaddr(); 70558308Seric 70658755Seric salen = sizeof sa; 70758787Seric if (getsockname(fd, &sa.sa, &salen) < 0 || salen <= 0) 70858308Seric return NULL; 70958787Seric hp = gethostbyaddr(sa.sa.sa_data, salen, sa.sa.sa_family); 71058308Seric if (hp != NULL) 71158308Seric (void) strcpy(hbuf, hp->h_name); 71258308Seric else 71358755Seric (void) sprintf(hbuf, "[%s]", anynet_ntoa(&sa)); 71458308Seric return hbuf; 71558308Seric } 71658308Seric /* 71753751Seric ** MAPHOSTNAME -- turn a hostname into canonical form 71853751Seric ** 71953751Seric ** Parameters: 72056823Seric ** map -- a pointer to this map (unused). 72153751Seric ** hbuf -- a buffer containing a hostname. 72253751Seric ** hbsize -- the size of hbuf. 72355019Seric ** avp -- unused -- for compatibility with other mapping 72455019Seric ** functions. 72553751Seric ** 72653751Seric ** Returns: 72753751Seric ** The mapping, if found. 72853751Seric ** NULL if no mapping found. 72953751Seric ** 73053751Seric ** Side Effects: 73153751Seric ** Looks up the host specified in hbuf. If it is not 73253751Seric ** the canonical name for that host, return the canonical 73353751Seric ** name. 73453751Seric */ 73551315Seric 73653751Seric char * 73756823Seric maphostname(map, hbuf, hbsize, avp) 73856823Seric MAP *map; 73916911Seric char *hbuf; 74016911Seric int hbsize; 74153751Seric char **avp; 74216911Seric { 74316911Seric register struct hostent *hp; 74433932Sbostic u_long in_addr; 74556823Seric char *cp; 74658110Seric int i; 74733932Sbostic struct hostent *gethostbyaddr(); 74816911Seric 74956836Seric /* allow room for null */ 75056823Seric hbsize--; 75153751Seric 75225574Smiriam /* 75333932Sbostic * If first character is a bracket, then it is an address 75433932Sbostic * lookup. Address is copied into a temporary buffer to 75533932Sbostic * strip the brackets and to preserve hbuf if address is 75633932Sbostic * unknown. 75733932Sbostic */ 75853751Seric 75951315Seric if (*hbuf != '[') 76053751Seric { 76155019Seric extern bool getcanonname(); 76255019Seric 76358798Seric if (tTd(9, 1)) 76458798Seric printf("maphostname(%s, %d) => ", hbuf, hbsize); 76558674Seric if (getcanonname(hbuf, hbsize)) 76658796Seric { 76758796Seric if (tTd(9, 1)) 76858796Seric printf("%s\n", hbuf); 76953751Seric return hbuf; 77058796Seric } 77153751Seric else 77258796Seric { 77358796Seric if (tTd(9, 1)) 77458796Seric printf("FAIL\n"); 77553751Seric return NULL; 77658796Seric } 77753751Seric } 77856823Seric if ((cp = strchr(hbuf, ']')) == NULL) 77953751Seric return (NULL); 78040994Sbostic *cp = '\0'; 78156823Seric in_addr = inet_addr(&hbuf[1]); 78258110Seric 78358110Seric /* check to see if this is one of our addresses */ 78458110Seric for (i = 0; MyIpAddrs[i].s_addr != 0; i++) 78558110Seric { 78658110Seric if (MyIpAddrs[i].s_addr == in_addr) 78758110Seric { 78858110Seric strncpy(hbuf, MyHostName, hbsize); 78958110Seric hbuf[hbsize] = '\0'; 79058110Seric return hbuf; 79158110Seric } 79258110Seric } 79358110Seric 79458110Seric /* nope -- ask the name server */ 79533932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 79633932Sbostic if (hp == NULL) 79753751Seric return (NULL); 79853751Seric 79958110Seric /* found a match -- copy out */ 80056823Seric if (strlen(hp->h_name) > hbsize) 80156823Seric hp->h_name[hbsize] = '\0'; 80253751Seric (void) strcpy(hbuf, hp->h_name); 80353751Seric return hbuf; 80433932Sbostic } 80558755Seric /* 80658755Seric ** ANYNET_NTOA -- convert a network address to printable form. 80758755Seric ** 80858755Seric ** Parameters: 80958755Seric ** sap -- a pointer to a sockaddr structure. 81058755Seric ** 81158755Seric ** Returns: 81258755Seric ** A printable version of that sockaddr. 81358755Seric */ 81416911Seric 81558755Seric char * 81658755Seric anynet_ntoa(sap) 81758755Seric register SOCKADDR *sap; 81858755Seric { 81958755Seric register char *bp; 82058755Seric register char *ap; 82158755Seric int l; 82258755Seric static char buf[80]; 82358755Seric 82458798Seric /* check for null/zero family */ 82558798Seric if (sap == NULL) 82658798Seric return "NULLADDR"; 82758798Seric if (sap->sa.sa_family == 0) 82858798Seric return "0"; 82958798Seric 83058778Seric #ifdef NETINET 83158778Seric if (sap->sa.sa_family == AF_INET) 83258755Seric { 83358755Seric extern char *inet_ntoa(); 83458755Seric 83558755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 83658755Seric } 83758778Seric #endif 83858755Seric 83958755Seric /* unknown family -- just dump bytes */ 84058778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 84158755Seric bp = &buf[strlen(buf)]; 84258778Seric ap = sap->sa.sa_data; 84358778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 84458755Seric { 84558755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 84658755Seric bp += 3; 84758755Seric } 84858755Seric *--bp = '\0'; 84958755Seric return buf; 85058755Seric } 85158755Seric 85256795Seric # else /* DAEMON */ 85316911Seric /* code for systems without sophisticated networking */ 85410758Seric 85510758Seric /* 85610758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 85711297Seric ** 85811297Seric ** Can't convert to upper case here because might be a UUCP name. 85912313Seric ** 86012313Seric ** Mark, you can change this to be anything you want...... 86110758Seric */ 86210758Seric 86310758Seric char ** 86412313Seric myhostname(hostbuf, size) 86510758Seric char hostbuf[]; 86612313Seric int size; 86710758Seric { 86810758Seric register FILE *f; 86910758Seric 87010758Seric hostbuf[0] = '\0'; 87110758Seric f = fopen("/usr/include/whoami", "r"); 87210758Seric if (f != NULL) 87310758Seric { 87412313Seric (void) fgets(hostbuf, size, f); 87510758Seric fixcrlf(hostbuf, TRUE); 87610758Seric (void) fclose(f); 87710758Seric } 87810758Seric return (NULL); 87910758Seric } 88016911Seric /* 88158308Seric ** GETREALHOSTNAME -- get the real host name asociated with a file descriptor 88258308Seric ** 88358308Seric ** Parameters: 88458308Seric ** fd -- the descriptor 88558308Seric ** 88658308Seric ** Returns: 88758308Seric ** The host name associated with this descriptor, if it can 88858308Seric ** be determined. 88958308Seric ** NULL otherwise. 89058308Seric ** 89158308Seric ** Side Effects: 89258308Seric ** none 89358308Seric */ 89458308Seric 89558308Seric char * 89658308Seric getrealhostname(fd) 89758308Seric int fd; 89858308Seric { 89958308Seric return NULL; 90058308Seric } 90158308Seric /* 90216911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 90316911Seric ** 90416911Seric ** Parameters: 90556823Seric ** map -- a pointer to the database map. 90616911Seric ** hbuf -- a buffer containing a hostname. 90753751Seric ** avp -- a pointer to a (cf file defined) argument vector. 90816911Seric ** 90916911Seric ** Returns: 91053751Seric ** mapped host name 91151315Seric ** FALSE otherwise. 91216911Seric ** 91316911Seric ** Side Effects: 91416911Seric ** Looks up the host specified in hbuf. If it is not 91516911Seric ** the canonical name for that host, replace it with 91616911Seric ** the canonical name. If the name is unknown, or it 91716911Seric ** is already the canonical name, leave it unchanged. 91816911Seric */ 91910758Seric 92016911Seric /*ARGSUSED*/ 92153751Seric char * 92256823Seric maphostname(map, hbuf, hbsize, avp) 92356823Seric MAP *map; 92416911Seric char *hbuf; 92516911Seric int hbsize; 92653751Seric char **avp; 92716911Seric { 92853751Seric return NULL; 92916911Seric } 93016911Seric 93156795Seric #endif /* DAEMON */ 932