&ifreq.ifr_addr)->sin_addr.s_addr;
&ifa->ifa_dstaddr)->sin_addr.s_addr;
				setdumpflg __P(()),				onhup __P(()),#if defined(QRYLOG) && defined(SIGWINCH)				setQrylogFlg __P(()),#endif				setIncrDbgFlg __P(()),				setNoDbgFlg __P(()),#ifdef SIGSYS				sigprof __P(()),#endif /* SIGSYS */				setchkptflg __P(()),				setstatsflg __P(());static voidusage(){	fprintf(stderr,"Usage: named [-d #] [-q] [-r] [-p port[/localport]] [[-b] bootfile]\n""             [-t directory] [-u (username|uid)] [-g (groupname|gid)]\n");	exit(1);}/*ARGSUSED*/intmain(argc, argv, envp)	int argc;	char *argv[], *envp[];{	register int n, udpcnt;	register char *arg;	register struct qstream *sp;	register struct qdatagram *dqp;	struct qstream *nextsp;	int nfds;	const int on = 1;	int rfd, size, len;	time_t lasttime, maxctime;	u_char buf[PACKETSZ];#ifdef NeXT	int old_sigmask;#endif	fd_set *tmpmask;	struct timeval t, *tp;	struct qstream *candidate = QSTREAM_NULL;	char **argp, *p;	char *chroot_dir = NULL;	char *user_name = NULL;	char *group_name = NULL;	uid_t user_id;	gid_t group_id;	struct group *gr;	struct passwd *pw;#ifdef PID_FIX	char oldpid[10];	char oldargs[BUFSIZ];#endif#ifdef WANT_PIDFILE	FILE	*fp;			/* file descriptor for pid file */	char	*nsargs;#endif#ifdef IP_OPTIONS	struct ipoption ip_opts;#endif#ifdef	RLIMIT_NOFILE	struct rlimit rl;#endif	user_id = getuid();	group_id = getgid();	local_ns_port = ns_port = htons(NAMESERVER_PORT);	/* BSD has a better random number generator but it's not clear	 * that we need it here.	 */	gettime(&tt);	srand(((unsigned)getpid()) + (unsigned)tt.tv_usec);	/*	**  Save start and extent of argv for ns_setproctitle().	*/	Argv = argp = argv;	while (*argp)		argp++;	LastArg = argp[-1] + strlen(argp[-1]);	(void) umask(022);	/* XXX - should use getopt here */	while (--argc > 0) {		arg = *++argv;		if (*arg == '-') {			while (*++arg)				switch (*arg) {				case 'b':					if (--argc <= 0)						usage();					bootfile = savestr(*++argv);					break;  				case 'd': 					++argv; 					if (*argv != 0) { 					    if (**argv == '-') { 						argv--; 						break; 					    }#ifdef DEBUG 					    debug = atoi(*argv);#endif 					    --argc; 					}#ifdef DEBUG					if (debug <= 0)						debug = 1;					setdebug(1);#endif					break;				case 'p':					/* use nonstandard port number.					 * usage: -p remote/local					 * remote is the port number to which					 * we send queries.  local is the port					 * on which we listen for queries.					 * local defaults to same as remote.					 */					if (--argc <= 0)						usage();					ns_port = htons((u_int16_t)							atoi(*++argv));					{					    p = strchr(*argv, '/');					    if (p) {						local_ns_port =						    htons((u_int16_t)							  atoi(p+1));					    } else {						local_ns_port = ns_port;					    }					}					break;#ifdef QRYLOG				case 'q':					qrylog = 1;					break;#endif				case 'r':					NoRecurse = 1;					break;				case 't':					if (--argc <= 0)						usage();					chroot_dir = savestr(*++argv);					break;				case 'u':					if (--argc <= 0)						usage();					user_name = *++argv;					if ((pw = getpwnam(user_name))) {						user_name = savestr(pw->pw_name);						user_id = pw->pw_uid;						group_id = pw->pw_gid;						if ((gr = getgrgid(pw->pw_gid)))							group_name =							   savestr(gr->gr_name);						else {							char name[256];							sprintf(name, "%lu",							    (u_long)pw->pw_gid);							group_name = savestr(name);						}					} else if (only_digits(user_name)) {						user_name = savestr(user_name);						user_id = atoi(user_name);					} else {						fprintf(stderr,						    "user \"%s\" unknown\n",						    user_name);						exit(1);					}					break;				case 'g':					if (--argc <= 0)						usage();					if (group_name != NULL)						free(group_name);					group_name = *++argv;					if ((gr = getgrnam(group_name))) {						group_name = savestr(gr->gr_name);						group_id = gr->gr_gid;					} else if (only_digits(group_name)) {						group_name = savestr(group_name);						group_id = atoi(group_name);					} else {						fprintf(stderr,						    "group \"%s\" unknown\n",						    group_name);						exit(1);					}					break;				default:					usage();				}		} else			bootfile = savestr(*argv);	}	endgrent();	endpwent();#ifdef DEBUG	if (!debug)#endif		for (n = getdtablesize() - 1; n > 2; n--)			(void) close(n);	/* don't use my_close() here */#ifdef DEBUG	else {		fprintf(ddt, "Debug turned ON, Level %d\n",debug);		fprintf(ddt, "Version = %s\n", Version);		fprintf(ddt, "bootfile = %s\n", bootfile);	}		#endif	/*	 * Chroot if desired.	 */	if (chroot_dir != NULL) {		struct stat sb;		if (chroot(chroot_dir) < 0) {			fprintf(stderr, "chroot %s failed: %s\n", chroot_dir,				strerror(errno));			exit(1);		}		if (chdir("/") < 0) {			fprintf(stderr, "chdir(\"/\") failed: %s\n",				strerror(errno));			exit(1);		}		/*		 * Paths to boot file, pid file and named-xfer need to		 * be relative if their parent dirs do not exist.  This		 * is to allow chroot'ing to the named homedir.		 */		p = dirname(bootfile);		if ((stat(bootfile, &sb) != 0 || !S_ISDIR(sb.st_mode)) &&		    (p = strrchr(bootfile, '/')))			bootfile = p;		p = dirname(PidFile);		if ((stat(PidFile, &sb) != 0 || !S_ISDIR(sb.st_mode)) &&		    (p = strrchr(PidFile, '/')))			PidFile = p;		p = dirname(NamedXfer);		if ((stat(NamedXfer, &sb) != 0 || !S_ISDIR(sb.st_mode)) &&		    (p = strrchr(NamedXfer, '/')))			NamedXfer = p;	}	n = 0;#if defined(DEBUG) && defined(LOG_PERROR)	if (debug)		n |= LOG_PERROR;#endif#ifdef LOG_NOWAIT	n |= LOG_NOWAIT;#endif#ifdef LOG_DAEMON	openlog("named", LOG_PID|LOG_CONS|LOG_NDELAY|n, LOGFAC);#else	openlog("named", LOG_PID);#endif#ifdef	RLIMIT_NOFILE	rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;	if (setrlimit(RLIMIT_NOFILE, &rl) == -1)		syslog(LOG_ERR, "setrlimit(RLIMIT_FSIZE,RLIM_INFINITY): %m");#endif	/* check that udp checksums are on */	ns_udp();#ifdef WANT_PIDFILE	/* build up argument string to stash in pid file */	nsargs = malloc(LastArg - Argv[0] + 1);	if (nsargs == NULL) {		syslog(LOG_ERR,		       "building argument string, malloc: %m - exiting");		exit(1);	}	for (p=nsargs, argp=Argv; *argp; argp++) {		strcpy(p, *argp);		p += strlen(p);		*p++ = ' ';	}	*--p = '\0';	/* tuck my process id away */#ifdef PID_FIX	fp = fopen(PidFile, "w");	if (fp != NULL) {		(void) fgets(oldpid, sizeof(oldpid), fp);		(void) fgets(oldargs, sizeof(oldargs), fp);		(void) rewind(fp);		fprintf(fp, "%ld\n", (long)getpid());		fprintf(fp, "%s\n", nsargs);		(void) my_fclose(fp);	}#else /*PID_FIX*/	fp = fopen(PidFile, "w");	if (fp != NULL) {		fprintf(fp, "%d\n", getpid());		fprintf(fp, "%s\n", nsargs);		(void) my_fclose(fp);	}#endif /*PID_FIX*/#endif /*WANT_PIDFILE*/	syslog(LOG_NOTICE, "starting.  %s", Version);	if (chroot_dir != NULL)		syslog(LOG_NOTICE, "chrooted to %s", chroot_dir);	_res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE);	nsaddr.sin_family = AF_INET;	nsaddr.sin_addr.s_addr = INADDR_ANY;	nsaddr.sin_port = local_ns_port;	nsid_init();	/*	** Open stream port.	*/	for (n = 0; ; n++) {		int fd;		if ((vs = socket(AF_INET, SOCK_STREAM, 0)) < 0) {			syslog(LOG_ERR, "socket(SOCK_STREAM): %m");			exit(1);		}	#ifdef F_DUPFD		/*		 * leave a space for stdio to work in		 */		if ((fd = fcntl(vs, F_DUPFD, 20)) != -1) {			close(vs);			vs = fd;		} else 			syslog(LOG_NOTICE, "fcntl(vs, F_DUPFD, 20): %m");#endif		if (setsockopt(vs, SOL_SOCKET, SO_REUSEADDR, (char *)&on,			sizeof(on)) != 0)		{			syslog(LOG_NOTICE, "setsockopt(vs, reuseaddr): %m");			(void) my_close(vs);			continue;		}		if (bind(vs, (struct sockaddr *)&nsaddr, sizeof(nsaddr)) == 0)			break;		if (errno != EADDRINUSE || n > 4) {			if (errno == EADDRINUSE) {				syslog(LOG_NOTICE,				 "There may be a name server already running");				syslog(LOG_ERR, "exiting");			} else {				syslog(LOG_ERR, "bind(vs, [%s].%d): %m",					inet_ntoa(nsaddr.sin_addr),					ntohs(nsaddr.sin_port));			}#if defined(WANT_PIDFILE) && defined(PID_FIX)			/* put old pid back */			if (atoi(oldpid) && (fp = fopen(PidFile, "w"))) {				fputs(oldpid, fp);				fputs(oldargs, fp);				(void) my_fclose(fp);				_exit(1);			}#endif /*WANT_PIDFILE && PID_FIX*/			exit(1);		}		/* Retry opening the socket a few times */		my_close(vs);		sleep(3);	}	if (listen(vs, 5) != 0) {		syslog(LOG_ERR, "listen(vs, 5): %m");		exit(1);	}  	/*	 * named would be terminated if one of these is sent and no handler.	 */	setsignal(SIGINT, -1, setdumpflg);	setsignal(SIGQUIT, -1, setchkptflg);	setsignal(SIGIOT, -1, setstatsflg);	setsignal(SIGUSR1, -1, setIncrDbgFlg);	setsignal(SIGUSR2, -1, setNoDbgFlg);	setsignal(SIGHUP, -1, onhup);#if defined(SIGWINCH) && defined(QRYLOG)	setsignal(SIGWINCH, -1, setQrylogFlg);#endif	/*	 * Get list of local addresses and set up datagram sockets.	 */	nfds = getdtablesize();       /* get the number of file descriptors */	mask_size = howmany(nfds, NFDBITS) * sizeof(fd_mask);	mask = (fd_set *) malloc(mask_size);	if (mask == NULL) {		syslog(LOG_ERR, "malloc(%d) for fd_set: %m - exiting",			mask_size);		exit(1);	}	memset ((void *)mask, 0, mask_size);	tmpmask = (fd_set *) malloc(mask_size);	if (tmpmask == NULL) {		syslog(LOG_ERR, "malloc(%d) for fd_set: %m - exiting",			mask_size);		exit(1);	}	memset ((void *)tmpmask, 0, mask_size);	FD_SET(vs, mask);	getnetconf();	/*	** Initialize and load database.	*/	gettime(&tt);	buildservicelist();	buildprotolist();	ns_init(bootfile);#ifdef DEBUG	if (debug) {		fprintf(ddt, "Network and sort list:\n");		printnetinfo(nettab);	}#endif	time(&boottime);	resettime = boottime;	setsignal(SIGALRM, SIGCHLD, maint_alarm);	setsignal(SIGCHLD, SIGALRM, reapchild);	setsignal(SIGPIPE, -1, (SIG_FN (*)())SIG_IGN);#if defined(SIGXFSZ)	/* Wierd DEC Hesiodism, harmless. */	setsignal(SIGXFSZ, -1, onhup);#endif#ifdef SIGSYS	setsignal(SIGSYS, -1, sigprof);#endif /* SIGSYS */#ifdef XSTATS        /* Catch SIGTERM so we can write stats before exiting. */	setsignal(SIGTERM, -1, onintr);#endif	dprintf(1, (ddt, "database initialized\n"));	t.tv_usec = 0;	/*	 * Fork and go into background now that	 * we've done any slow initialization	 * and are ready to answer queries.	 */#if defined(USE_SETSID) && !defined(HAVE_DAEMON)	if (#ifdef DEBUG	    !debug ||#endif	    !isatty(0)) {		if (fork() > 0)			exit(0);		setsid();#ifdef DEBUG		if (!debug)#endif		{			n = open(_PATH_DEVNULL, O_RDONLY);			(void) dup2(n, 0);			(void) dup2(n, 1);			(void) dup2(n, 2);			if (n > 2)				(void) my_close(n);		}	}#else#ifdef DEBUG	if (!debug)#endif	{#ifdef HAVE_DAEMON		daemon(1, 0);#else		switch (fork()) {		case -1:			syslog(LOG_ERR, "fork: %m");			exit(1);			/*FALLTHROUGH*/		case 0:			/* child */			break;		default:			/* parent */			exit(0);		}		n = open(_PATH_DEVNULL, O_RDONLY);		(void) dup2(n, 0);		(void) dup2(n, 1);		(void) dup2(n, 2);		if (n > 2)			(void) my_close(n);#if defined(SYSV) || defined(hpux)		setpgrp();#else		{			struct itimerval ival;			/*			 * The open below may hang on pseudo ttys if the person			 * who starts named logs out before this point.			 *			 * needmaint may get set inapropriately if the open			 * hangs, but all that will happen is we will see that			 * no maintenance is required.			 */			bzero((char *)&ival, sizeof(ival));			ival.it_value.tv_sec = 120;			(void) setitimer(ITIMER_REAL, &ival,				    (struct itimerval *)NULL);			n = open(_PATH_TTY, O_RDWR);			ival.it_value.tv_sec = 0;			(void) setitimer(ITIMER_REAL, &ival,				    (struct itimerval *)NULL);			if (n > 0) {				(void) ioctl(n, TIOCNOTTY, (char *)NULL);				(void) my_close(n);			}		}#endif /* SYSV */#endif /* HAVE_DAEMON */	}#endif /* USE_SETSID */#ifdef WANT_PIDFILE	/* tuck my process id away again */	fp = fopen(PidFile, "w");	if (fp != NULL) {		fprintf(fp, "%ld\n", (long)getpid());		fprintf(fp, "%s\n", nsargs);		(void) my_fclose(fp);	}#endif	/*	 * Set user if desired.	 */	if (group_name != NULL) {		if (setgid(group_id) < 0) {			syslog(LOG_ERR, "setgid(%s): %m", group_name);			exit(1);		}		if (user_name == NULL)			syslog(LOG_NOTICE, "group = %s", group_name);	}	if (user_name != NULL) {		if (getuid() == 0 && initgroups(user_name, group_id) < 0) {			syslog(LOG_ERR, "initgroups(%s, %d): %m", user_name,			       (int)group_id);			exit(1);		}		if (setuid(user_id) < 0) {			syslog(LOG_ERR, "setuid(%s): %m", user_name);			exit(1);		}		syslog(LOG_NOTICE, "user = %s, group = %s", user_name,		       group_name);	}	syslog(LOG_NOTICE, "Ready to answer queries.\n");	prime_cache();#ifdef NeXT	old_sigmask = sigblock(sigmask(SIGCHLD));#endif	for (;;) {#ifdef DEBUG		if (ddt && debug == 0) {			fprintf(ddt,"Debug turned OFF\n");			(void) my_fclose(ddt);			ddt = 0;		}#endif#ifdef XSTATS                if (needToExit) {		  	ns_logstats();		  	exit(0);                }#endif /* XSTATS */		if (needreload) {			needreload = 0;			db_reload((user_name == NULL));		}		if (needStatsDump) {			needStatsDump = 0;			ns_stats();		}		if (needendxfer) {			holdsigchld();			needendxfer = 0; /* should be safe even if not held */			endxfer(); /* releases SIGCHLD */		}		releasesigchld();		if (needzoneload) {			needzoneload = 0;			loadxfer();		}		if (needmaint) {                        needmaint = 0;                        ns_maint();                }	        if(needToChkpt) {                        needToChkpt = 0;                        doachkpt();	        }                if(needToDoadump) {                        needToDoadump = 0;                        doadump();                }		/*		** Wait until a query arrives		*/		if (retryqp != NULL) {			gettime(&tt);			/*			** The tv_sec field might be unsigned 			** and thus cannot be negative.			*/			if ((int32_t) retryqp->q_time <= tt.tv_sec) {				retry(retryqp);				continue;			}			t.tv_sec = (int32_t) retryqp->q_time - tt.tv_sec;			tp = &t;		} else			tp = NULL;		memcpy ((void *)tmpmask, (void *)mask, mask_size);#ifdef NeXT		sigsetmask(old_sigmask);	/* Let queued signals run. */#endif		n = select(nfds, tmpmask, (fd_set *)NULL, (fd_set *)NULL, tp);#ifdef NeXT		old_sigmask = sigblock(sigmask(SIGCHLD));#endif		if (n < 0 && errno != EINTR) {			syslog(LOG_ERR, "select: %m");			sleep(60);		}		if (n <= 0)			continue;		for (dqp = datagramq;		     dqp != QDATAGRAM_NULL;		     dqp = dqp->dq_next) {		    if (FD_ISSET(dqp->dq_dfd, tmpmask))		        for (udpcnt = 0; udpcnt < 42; udpcnt++) {  /*XXX*/			    int from_len = sizeof(from_addr);			    if ((n = recvfrom(dqp->dq_dfd, (char *)buf,					      MIN(PACKETSZ, sizeof buf), 0,				(struct sockaddr *)&from_addr, &from_len)) < 0)			    {#if defined(SPURIOUS_ECONNREFUSED)				if ((n < 0) && (errno == ECONNREFUSED))					break;#endif				if ((n < 0) && (errno == PORT_WOULDBLK))					break;				syslog(LOG_INFO, "recvfrom: %m");				break;			    }			    if (n == 0)				break;			    gettime(&tt);			    dprintf(1, (ddt,			     "\ndatagram from [%s].%d, fd %d, len %d; now %s",					inet_ntoa(from_addr.sin_addr),					ntohs(from_addr.sin_port),					dqp->dq_dfd, n,				        ctimel(tt.tv_sec)));			    if (n < HFIXEDSZ)				break;#ifdef DEBUG			    if (debug >= 10)				fp_nquery(buf, n, ddt);#endif			    /*			     * Consult database to get the answer.			     */			    gettime(&tt);			    ns_req(buf, n, PACKETSZ, QSTREAM_NULL, &from_addr,				    dqp->dq_dfd);		        }		}		/*		** Process stream connection.		**		** Note that a "continue" in here takes us back to the select()		** which, if our accept() failed, will bring us back here.		*/		if (FD_ISSET(vs, tmpmask)) {			int from_len = sizeof(from_addr);			rfd = accept(vs,				     (struct sockaddr *)&from_addr,				     &from_len);			if (rfd < 0 && errno == EINTR)				continue;			if (rfd < 0 && errno == EMFILE && streamq) {				maxctime = 0;				candidate = NULL;				for (sp = streamq; sp; sp = nextsp) {					nextsp = sp->s_next;					if (sp->s_refcnt)						continue;					gettime(&tt);					lasttime = tt.tv_sec - sp->s_time;					if (lasttime >= VQEXPIRY)						sqrm(sp);					else if (lasttime > maxctime) {						candidate = sp;						maxctime = lasttime;					}				}				if (candidate)					sqrm(candidate);				continue;			}			if (rfd < 0) {				syslog(LOG_INFO, "accept: %m");				continue;			}			if ((n = fcntl(rfd, F_GETFL, 0)) < 0) {				syslog(LOG_INFO, "fcntl(rfd, F_GETFL): %m");				(void) my_close(rfd);				continue;			}			if (fcntl(rfd, F_SETFL, n|PORT_NONBLOCK) != 0) {				syslog(LOG_INFO, "fcntl(rfd, NONBLOCK): %m");				(void) my_close(rfd);				continue;			}#if defined(IP_OPTIONS)			len = sizeof ip_opts;			if (getsockopt(rfd, IPPROTO_IP, IP_OPTIONS,				       (char *)&ip_opts, &len) < 0) {				syslog(LOG_INFO,				       "getsockopt(rfd, IP_OPTIONS): %m");				(void) my_close(rfd);				continue;			}			if (len != 0) {				int i;				nameserIncr(from_addr.sin_addr, nssRcvdOpts);				/* any socket with an LSRR or SSRR option				 * must be killed immediately or it can be				 * tcp sequenced */				for (i = 0; (void *)&ip_opts.ipopt_list[i] -				    (void *)&ip_opts < len && rfd != -1; ) {						u_char c = (u_char)ip_opts.ipopt_list[i];					if (c == IPOPT_LSRR || c == IPOPT_SSRR) {						my_close(rfd);						rfd = -1;						break;					}					if (c == IPOPT_EOL)						break;					i += (c == IPOPT_NOP) ? 1 :					    (u_char)ip_opts.ipopt_list[i+1];				}				if (!haveComplained((char*)						    from_addr.sin_addr.s_addr,						    "rcvd ip options")) {					syslog(LOG_INFO,				      "rcvd IP_OPTIONS from [%s].%d (ignored)",					       inet_ntoa(from_addr.sin_addr),					       ntohs(from_addr.sin_port));				}				if (rfd == -1) /* LSRR or SSRR killed it */					continue;				if (setsockopt(rfd, IPPROTO_IP, IP_OPTIONS,					       NULL, 0) < 0) {					syslog(LOG_INFO,					       "setsockopt(!IP_OPTIONS): %m");					(void) my_close(rfd);					continue;				}			}#endif			if (setsockopt(rfd, SOL_SOCKET, SO_SNDBUF,				      (char*)&sbufsize, sizeof(sbufsize)) < 0){				syslog(LOG_INFO,					  "setsockopt(rfd, SO_SNDBUF, %d): %m",				       sbufsize);				(void) my_close(rfd);				continue;			}			if (setsockopt(rfd, SOL_SOCKET, SO_KEEPALIVE,				       (char *)&on, sizeof(on)) < 0) {				syslog(LOG_INFO,				       "setsockopt(rfd, KEEPALIVE): %m");				(void) my_close(rfd);				continue;			}			if ((sp = sqadd()) == QSTREAM_NULL) {				(void) my_close(rfd);				continue;			}			sp->s_rfd = rfd;	/* stream file descriptor */			sp->s_size = -1;	/* amount of data to receive */			gettime(&tt);			sp->s_time = tt.tv_sec;	/* last transaction time */			sp->s_from = from_addr;	/* address to respond to */			sp->s_bufp = (u_char *)&sp->s_tempsize;			FD_SET(rfd, mask);			FD_SET(rfd, tmpmask);#ifdef DEBUG			if (debug)				syslog(LOG_DEBUG,				       "IP/TCP connection from %s (fd %d)\n",				       sin_ntoa(&sp->s_from), rfd);#endif		}		if (streamq)			dprintf(3, (ddt, "streamq = 0x%lx\n",				    (u_long)streamq));		for (sp = streamq;  sp != QSTREAM_NULL;  sp = nextsp) {			nextsp = sp->s_next;			if (!FD_ISSET(sp->s_rfd, tmpmask))				continue;			dprintf(5, (ddt,				  "sp x%lx rfd %d size %d time %d next x%lx\n",				    (u_long)sp, sp->s_rfd, sp->s_size,				    sp->s_time, (u_long)sp->s_next));			dprintf(5, (ddt,				    "\tbufsize %d buf x%lx bufp x%lx\n",				    sp->s_bufsize,				    (u_long)sp->s_buf, (u_long)sp->s_bufp));			if (sp->s_size < 0) {				size = INT16SZ				    - (sp->s_bufp - (u_char *)&sp->s_tempsize);			        while (size > 0 &&			           (n = read(sp->s_rfd, sp->s_bufp, size)) > 0				       ) {					sp->s_bufp += n;					size -= n;			        }				if ((n < 0) && (errno == PORT_WOULDBLK))					continue;				if (n <= 0) {					sqrm(sp);					continue;			        }			        if ((sp->s_bufp - (u_char *)&sp->s_tempsize) ==					INT16SZ) {					sp->s_size = ntohs(sp->s_tempsize);					if (sp->s_bufsize == 0) {					    if (!(sp->s_buf = (u_char *)						  malloc(rbufsize))						) {						    sp->s_buf = buf;						    sp->s_bufsize=sizeof(buf);					    } else {						    sp->s_bufsize = rbufsize;					    }					}					if (sp->s_size > sp->s_bufsize &&					    sp->s_bufsize != 0					) {					    u_char *s_buf = (u_char *)						realloc((void *)sp->s_buf,							(size_t)sp->s_size);					    if (s_buf == NULL) {						free(sp->s_buf);						sp->s_buf = buf;						sp->s_bufsize = 0;						sp->s_size = sizeof(buf);					    } else {						sp->s_buf = s_buf;						sp->s_bufsize = sp->s_size;					    }					}					sp->s_bufp = sp->s_buf;					}			}			gettime(&tt);			sp->s_time = tt.tv_sec;			while (sp->s_size > 0 &&			      (n = read(sp->s_rfd,					sp->s_bufp,					sp->s_size)			       ) > 0			) {				sp->s_bufp += n;				sp->s_size -= n;			}			if (sp->s_size > 0 &&			    (n == -1) &&			    (errno == PORT_WOULDBLK))				continue;			/*			 * we don't have enough memory for the query.			 * if we have a query id, then we will send an			 * error back to the user.			 */			if (sp->s_bufsize == 0) {			    if (sp->s_bufp - sp->s_buf > INT16SZ) {				HEADER *hp;				hp = (HEADER *)sp->s_buf;				hp->qr = 1;				hp->ra = (NoRecurse == 0);				hp->ancount = 0;				hp->qdcount = 0;				hp->nscount = 0;				hp->arcount = 0;				hp->rcode = SERVFAIL;				(void) writemsg(sp->s_rfd, sp->s_buf,						HFIXEDSZ);			    }			    sqrm(sp);			    continue;			}			/*			 * If the message is too short to contain a valid			 * header, try to send back an error, and drop the			 * message.			 */			if (sp->s_bufp - sp->s_buf < HFIXEDSZ) {			    if (sp->s_bufp - sp->s_buf > INT16SZ) {				HEADER *hp;				hp = (HEADER *)sp->s_buf;				hp->qr = 1;				hp->ra = (NoRecurse == 0);				hp->ancount = 0;				hp->qdcount = 0;				hp->nscount = 0;				hp->arcount = 0;				hp->rcode = SERVFAIL;				(void) writemsg(sp->s_rfd, sp->s_buf,						HFIXEDSZ);			    }			    sqrm(sp);			    continue;			}			if (n <= 0) {				sqrm(sp);				continue;			}			/*			 * Consult database to get the answer.			 */			if (sp->s_size == 0) {#ifdef XSTATS				nameserIncr(sp->s_from.sin_addr, nssRcvdTCP);#endif				sq_query(sp);				ns_req(sp->s_buf,				       sp->s_bufp - sp->s_buf,				       sp->s_bufsize, sp,				       &sp->s_from, -1);				/* ns_req() can call sqrm() - check for it */				if (sq_here(sp)) {					sp->s_bufp = (u_char *)&sp->s_tempsize;					sp->s_size = -1;				}				continue;			}		}	}	/* NOTREACHED */}voidgetnetconf(){	register struct netinfo *ntp;	struct netinfo *ontp;	struct ifconf ifc;	struct ifreq ifreq, *ifr;	struct qdatagram *dqp;	static int first = 1;	char *buf = NULL, *cp, *cplim;	int len = 8192;	u_int32_t nm;	time_t my_generation = time(NULL);	while (1) {		ifc.ifc_len = len;		ifc.ifc_buf = buf = realloc(buf, len);		if (buf == NULL) {			syslog(LOG_ERR,				"get interface config, malloc: %m - exiting");			exit(1);		}		if (ioctl(vs, SIOCGIFCONF, &ifc) < 0) {			syslog(LOG_ERR,				"get interface configuration: %m - exiting");			exit(1);		}		if (ifc.ifc_len + sizeof(ifreq) < len)			break;		len *= 2;	}	ntp = NULL;#if defined(AF_LINK) && \	!defined(RISCOS_BSD) && !defined(M_UNIX) && \	!defined(sgi) && !defined(sun) && !defined(NO_SA_LEN)#define my_max(a, b) (a > b ? a : b)#define my_size(p)	my_max((p).sa_len, sizeof(p))#else#define my_size(p) (sizeof (p))#endif	cplim = buf + ifc.ifc_len;    /* skip over if's with big ifr_addr's */	for (cp = buf;	     cp < cplim;	     cp += sizeof (ifr->ifr_name) + my_size(ifr->ifr_addr)) {#undef my_size		ifr = (struct ifreq *)cp;		if (ifr->ifr_addr.sa_family != AF_INET ||		   ((struct sockaddr_in *)		    &ifr->ifr_addr)->sin_addr.s_addr == 0) {			continue;		}		ifreq = *ifr;		/*		 * Don't test IFF_UP, packets may still be received at this		 * address if any other interface is up.		 */#if !defined(BSD) || (BSD < 199103)		if (ioctl(vs, SIOCGIFADDR, (char *)&ifreq) < 0) {			syslog(LOG_NOTICE, "get interface addr: %m");			continue;		}#endif		dprintf(1, (ddt, "considering [%s]\n",			    inet_ntoa(((struct sockaddr_in *)				       &ifreq.ifr_addr)->sin_addr)));		/* build datagram queue */		/* 		 * look for an already existing source interface address.		 * This happens mostly when reinitializing.  Also, if		 * the machine has multiple point to point interfaces, then 		 * the local address may appear more than once.		 */		if (dqp = aIsUs(((struct sockaddr_in *)&ifreq.ifr_addr)				->sin_addr)) {			dprintf(1, (ddt,				    "dup interface address %s on %s\n",				    inet_ntoa(((struct sockaddr_in *)					       &ifreq.ifr_addr)->sin_addr),				    ifreq.ifr_name));			dqp->dq_gen = my_generation;			continue;		}		/*		 * Skip over address 0.0.0.0 since this will conflict		 * with binding to wildcard address later.  Interfaces		 * which are not completely configured can have this addr.		 */		if (((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr		    == 0x00000000) {	/* XXX */			dprintf(1, (ddt, "skipping address 0.0.0.0 on %s\n",				    ifreq.ifr_name));			continue;		}		if ((dqp = (struct qdatagram *)			   calloc(1, sizeof(struct qdatagram))		     ) == NULL) {			syslog(LOG_ERR, "getnetconf: malloc: %m");			exit(12);		}		dqp->dq_next = datagramq;		datagramq = dqp;		dqp->dq_addr = ((struct sockaddr_in *)				&ifreq.ifr_addr)->sin_addr;		dqp->dq_gen = my_generation;		/* XXX - this will fail on reload if we run as non-root */		opensocket(dqp);		dprintf(1, (ddt, "listening [%s]\n",			    inet_ntoa(((struct sockaddr_in *)				       &ifreq.ifr_addr)->sin_addr)));		/*		 * Add interface to list of directly-attached (sub)nets		 * for use in sorting addresses.		 */		if (ntp == NULL) {			ntp = (struct netinfo *)malloc(sizeof(struct netinfo));			if (!ntp)				panic(errno, "malloc(netinfo)");		}		ntp->my_addr = ((struct sockaddr_in *)				&ifreq.ifr_addr)->sin_addr;#ifdef SIOCGIFNETMASK		if (ioctl(vs, SIOCGIFNETMASK, (char *)&ifreq) < 0) {			syslog(LOG_NOTICE, "get netmask: %m");			ntp->mask = net_mask(ntp->my_addr);		} else			ntp->mask = ((struct sockaddr_in *)			    &ifreq.ifr_addr)->sin_addr.s_addr;#else		/* 4.2 does not support subnets */		ntp->mask = net_mask(ntp->my_addr);#endif		if (ioctl(vs, SIOCGIFFLAGS, (char *)&ifreq) < 0) {			syslog(LOG_NOTICE, "get interface flags: %m");			continue;		}#ifdef IFF_LOOPBACK		if (ifreq.ifr_flags & IFF_LOOPBACK)#else		/* test against 127.0.0.1 (yuck!!) */		if (ntp->my_addr.s_addr == inet_addr("127.0.0.1"))  /* XXX */#endif		{			if (netloop.my_addr.s_addr == 0) {				netloop.my_addr = ntp->my_addr;				netloop.mask = 0xffffffff;				netloop.addr = ntp->my_addr.s_addr;				dprintf(1, (ddt, "loopback address: x%lx\n",					    (u_long)netloop.my_addr.s_addr));			}			continue;		} else if ((ifreq.ifr_flags & IFF_POINTOPOINT)) {			((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr =				ntp->my_addr;			if (ioctl(vs, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {				syslog(LOG_NOTICE, "get dst addr: %m");				continue;			}			ntp->mask = 0xffffffff;			ntp->addr = ((struct sockaddr_in *)				     &ifreq.ifr_addr)->sin_addr.s_addr;		} else {			ntp->addr = ntp->mask & ntp->my_addr.s_addr;		}		/*		 * Place on end of list of locally-attached (sub)nets,		 * but before logical nets for subnetted nets.		 */		ntp->next = *elocal;		*elocal = ntp;		if (elocal == enettab)			enettab = &ntp->next;		elocal = &ntp->next;		ntp = NULL;	}	if (ntp)		free((char *)ntp);	free(buf);	/*	 * now go through the datagramq and delete anything that	 * does not have the current generation number.  this is	 * how we catch interfaces that go away or change their	 * addresses.  note that 0.0.0.0 is the wildcard element	 * and should never be deleted by this code.	 *	 * XXX - need to update enettab/elocal as well.	 */	dqflush(my_generation);		/* With apologies to The Who. */	/*	 * Create separate qdatagram structure for socket	 * wildcard address.	 */	if (first) {		if (!(dqp = (struct qdatagram *)calloc(1, sizeof(*dqp))))			panic(errno, "malloc(qdatagram)");		dqp->dq_next = datagramq;		datagramq = dqp;		dqp->dq_addr.s_addr = INADDR_ANY;		opensocket(dqp);		ds = dqp->dq_dfd;	}	/*	 * Compute logical networks to which we're connected	 * based on attached subnets;	 * used for sorting based on network configuration.	 */	for (ntp = nettab; ntp != NULL; ntp = ntp->next) {		nm = net_mask(ntp->my_addr);		if (nm != ntp->mask) {			if (findnetinfo(ntp->my_addr))				continue;			ontp = (struct netinfo *)				malloc(sizeof(struct netinfo));			if (!ontp)				panic(errno, "malloc(netinfo)");			ontp->my_addr = ntp->my_addr;			ontp->mask = nm;			ontp->addr = ontp->my_addr.s_addr & nm;			ontp->next = *enettab;			*enettab = ontp;			enettab = &ontp->next;		}	}	first = 0;}/* * Find netinfo structure for logical network implied by address "addr", * if it's on list of local/favored networks. */struct netinfo *findnetinfo(addr)	struct in_addr addr;{	register struct netinfo *ntp;	u_int32_t net, mask;	mask = net_mask(addr);	net = addr.s_addr & mask;	for (ntp = nettab; ntp != NULL; ntp = ntp->next)		if (ntp->addr == net && ntp->mask == mask)			return (ntp);	return ((struct netinfo *) NULL);}#ifdef DEBUGstatic voidprintnetinfo(ntp)	register struct netinfo *ntp;{	for ( ; ntp != NULL; ntp = ntp->next) {		fprintf(ddt, "addr x%lx mask x%lx",			(u_long)ntp->addr, (u_long)ntp->mask);		fprintf(ddt, " my_addr x%lx", ntp->my_addr.s_addr);		fprintf(ddt, " %s\n", inet_ntoa(ntp->my_addr));	}}#endifstatic voidopensocket(dqp)	register struct qdatagram *dqp;{	int m, n;	int on = 1;	int fd;	/*	 * Open datagram sockets bound to interface address.	 */	if ((dqp->dq_dfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {		syslog(LOG_ERR, "socket(SOCK_DGRAM): %m - exiting");		exit(1);	}	#ifdef F_DUPFD	/*	 * leave a space for stdio to work in	 */	if ((fd = fcntl(dqp->dq_dfd, F_DUPFD, 20)) != -1) {		close(dqp->dq_dfd);		dqp->dq_dfd = fd;	} else 		syslog(LOG_NOTICE, "fcntl(dfd, F_DUPFD, 20): %m");#endif	dprintf(1, (ddt, "dqp->dq_addr %s d_dfd %d\n",		    inet_ntoa(dqp->dq_addr), dqp->dq_dfd));	if (setsockopt(dqp->dq_dfd, SOL_SOCKET, SO_REUSEADDR,	    (char *)&on, sizeof(on)) != 0)	{		syslog(LOG_NOTICE, "setsockopt(dqp->dq_dfd, reuseaddr): %m");		/* XXX press on regardless, this is not too serious. */	}#ifdef SO_RCVBUF	m = sizeof(n);	if ((getsockopt(dqp->dq_dfd, SOL_SOCKET, SO_RCVBUF, (char*)&n, &m) >= 0)	    && (m == sizeof(n))	    && (n < rbufsize)) {		(void) setsockopt(dqp->dq_dfd, SOL_SOCKET, SO_RCVBUF,				  (char *)&rbufsize, sizeof(rbufsize));	}#endif /* SO_RCVBUF */	if ((n = fcntl(dqp->dq_dfd, F_GETFL, 0)) < 0) {		syslog(LOG_NOTICE, "fcntl(dfd, F_GETFL): %m");		/* XXX press on regardless, but this really is a problem. */	} else if (fcntl(dqp->dq_dfd, F_SETFL, n|PORT_NONBLOCK) != 0) {		syslog(LOG_NOTICE, "fcntl(dqp->dq_dfd, non-blocking): %m");		/* XXX press on regardless, but this really is a problem. */	}	/*	 *   NOTE: Some versions of SunOS have problems with the following	 *   call to bind.  Bind still seems to function on these systems	 *   if you comment out the exit inside the if.  This may cause	 *   Suns with multiple interfaces to reply strangely.	 */	nsaddr.sin_addr = dqp->dq_addr;	if (bind(dqp->dq_dfd, (struct sockaddr *)&nsaddr, sizeof(nsaddr))) {		syslog(LOG_NOTICE, "bind(dfd=%d, [%s].%d): %m",			dqp->dq_dfd, inet_ntoa(nsaddr.sin_addr),			ntohs(nsaddr.sin_port));#if !defined(sun)		syslog(LOG_ERR, "exiting");		exit(1);#endif	}	FD_SET(dqp->dq_dfd, mask);}/*** Set flag saying to reload database upon receiving SIGHUP.** Must make sure that someone isn't walking through a data** structure at the time.*/static SIG_FNonhup(){	int save_errno = errno;	resignal(SIGHUP, -1, onhup);	needreload = 1;	errno = save_errno;}/*** Set flag saying to call ns_maint()** Must make sure that someone isn't walking through a data** structure at the time.*/static SIG_FNmaint_alarm(){	int save_errno = errno;	resignal(SIGALRM, SIGCHLD, maint_alarm);	needmaint = 1;	errno = save_errno;}#ifdef XSTATS/* * Signal handler to write log information */static SIG_FNonintr(){	int save_errno = errno;	resignal(SIGTERM, -1, onintr);        needToExit = 1;		/* XXX variable reuse */	errno = save_errno;}#endif /* XSTATS *//* * Signal handler to schedule a data base dump.  Do this instead of dumping the * data base immediately, to avoid seeing it in a possibly inconsistent state * (due to updates), and to avoid long disk I/O delays at signal-handler * level */static SIG_FNsetdumpflg(){	int save_errno = errno;	resignal(SIGINT, -1, setdumpflg);        needToDoadump = 1;	errno = save_errno;}