⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nsrec.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*      @(#)nsrec.c 1.1 92/07/30 SMI      *//*	Copyright (c) 1984 AT&T	*//*	  All Rights Reserved  	*//*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*//*	The copyright notice above does not evidence any   	*//*	actual or intended publication of such source code.	*//* * nsrec.c contains name server recovery functions and * other related functions. */#ident	"@(#)nserve:nsrec.c	1.21.1.1"#include <stdio.h>#include <string.h>#include <signal.h>#include <sys/utsname.h>#include <sys/stropts.h>#include <errno.h>#include <fcntl.h>#include "nsdb.h"#include "nslog.h"#include <tiuser.h>#include <rfs/nsaddr.h>#include "stdns.h"#include <rfs/nserve.h>#include <sys/mount.h>#include <rfs/cirmgr.h>#include <rfs/pn.h>#include "nsports.h"#include "nsrec.h"#define NLS_Q		"nlsadmin -q"#define NLS_ADDR 	"nlsadmin -l -"#define UNADV_CMD 	"/usr/bin/unadv"#define ADV_CMD		"/usr/bin/adv"#define AUTH_INFO	NSDIRQ/auth.info"#define MNT_CMD		"/etc/mount -d"#define UMNT_CMD	"/etc/umount -d"#define R_TIMEOUT	25extern int	Done;extern char	*Netmaster;extern char	*Net_spec;extern void	(*Alarmsig)();int	Polltime=POLLTIME;char	*Mydomains[MAXDOMAINS];int	Mylastdom=0;struct ns_info {	int		 n_state;	int		 n_pd;	char		*n_dname;	struct address	*n_addr;};static struct ns_info	Nsinfo[MAXNS];static int		getprime();static int		Rdone=FALSE;char	*prec();char	*dompart();char	*aatos();struct address	*getmyaddr();struct address	*astoa();int	r_poll();int	r_checkup();struct ns_info	*pdtonp();struct ns_info	*nmtonp();/* * setmaster takes the information returned from * the NS_INIT call to the primary and writes * a new netmaster file. */intsetmaster(req)struct request	*req;{	struct res_rec	*rns;	struct res_rec	*rar;	long	nscount;	int	i;	char	dname[BUFSIZ];	char	*ptr;	FILE	*fp;	FILE	*fopen();	LOG2(L_COMM,"(%5d) setmaster: enter\n",Logstamp);	/*	 * don't rewrite rfmaster if this machine is listed as "p"	 * in rfmaster.	 */	strcpy(dname,dompart(Dname));	if (domauth(dname) == SOA) {		LOG2(L_COMM,"(%5d) setmaster: don't rewrite rfmaster\n",Logstamp);		return(R_NSFAIL);	}	if (req->rq_head->h_rcode != R_NOERR)		return(R_NSFAIL);	LOG2(L_COMM,"(%5d) setmaster: rcode ok\n",Logstamp);	if ((nscount = req->rq_head->h_nscnt) == 0 ||	    req->rq_head->h_arcnt == 0)		return(R_NSFAIL);	LOG3(L_COMM,"(%5d) setmaster: record count = %d\n",Logstamp,		req->rq_head->h_nscnt);	if ((fp = fopen(Netmaster,"w")) == NULL) {		PLOG2("rfs: ns_init can't write master file %s\n",Netmaster);		return(R_NSFAIL);	}	for (i=0, rns = *req->rq_ns, rar = *req->rq_ar;		i < nscount; i++, rns++, rar++) {		fprintf(fp,"%s\n",prec(rns));		fprintf(fp,"%s%c%s\n",dompart(rns->rr_ns),SEPARATOR,prec(rar));	}	fclose(fp);	return(R_NOERR);}/* * mydom returns TRUE if name is in the list of domains * that this machine has authority over, otherwise it * returns FALSE. */intmydom(name)char	*name;{	register int	i;	for (i=0; i < Mylastdom; i++)		if (strcmp(name,Mydomains[i]) == NULL)			return(TRUE);	return(FALSE);}/* * r_init initializes recovery.  If this machine is just * a normal machine, its state is set, and the function * returns, otherwise, the recovery mechanism is set in * motion. */intr_init(){	if (getprime(dompart(Dname)) == RFS_FAILURE)		return(RFS_FAILURE);	if (!Myaddress && (Myaddress = getmyaddr()) == NULL)		return(RFS_FAILURE);	if (findmydoms() == 0) { /* this is a "regular" machine	*/		alarm(0);		sigset(SIGALRM,SIG_IGN);		getnsinfo();		Primary = FALSE;		return(RFS_SUCCESS);	}	/*	 * This machine "owns" one or more domains.	 * Now set up recovery circuits.	 */	if (getnsinfo() == RFS_FAILURE)		return(RFS_FAILURE);	if (setrstate() == RFS_FAILURE)		return(RFS_FAILURE);	return(RFS_SUCCESS);}/* * find primary machine address(es) from * database. */static intgetprime(dom)char	*dom;{	int	count;	int	i,j;	struct res_rec	**rlist, **arlist=NULL;	struct res_rec	*srlist[MAXREC];	struct res_rec	**srp = srlist;	char	abuf[BUFSIZ];	strcpy(abuf,dom);	if ((rlist = findrr(abuf,NSTYPE)) == NULL ||	    (count = copyrlist(&srp,rlist)) == 0 ||	    getars(srlist,&arlist,count) == 0) {		PLOG1("RFS name server can't find primary name server address\n");		return(RFS_FAILURE);	}	for (i=0; i < MAXNS; i++)		Paddress[i] = NULL;	for (i=0; i < count; i++) {		LOG3(L_OVER,"getprime: add primary %d, name = %s\n",			(srlist[i]->rr_type & ~MASKNS)-1, srlist[i]->rr_ns);		Paddress[(srlist[i]->rr_type & ~MASKNS)-1] = 			astoa(arlist[i]->rr_a,NULL);	}	/* compress addresses in list to eliminate gaps	*/	for (i=0, j=0; j < count && i < MAXNS; i++) {		if (Paddress[i] == NULL)			continue;		if (i != j)			Paddress[j++] = Paddress[i];		else			j++;	}	if (j == 0) {		PLOG1("RFS name server can't find good primary ns address\n");		return(RFS_FAILURE);	}	Paddress[count] = NULL;	for (i=0; Paddress[i]; i++) {		LOG3(L_OVER,"getprime: using addr=%s as primary %d\n",			aatos(abuf,Paddress[i],KEEP | HEX),i);	}	freelist(rlist);	freelist(arlist);	return(RFS_SUCCESS);}/* * look for this machine's listen address using nlsadmin. */struct address *getmyaddr(){	struct address	*retaddr=NULL;	FILE	*fp;	FILE	*popen();	char	buf[BUFSIZ];	sprintf(buf,"%s -z %d %s >/dev/null 2>&1",NLS_Q,RFSD,Net_spec);	switch (system(buf)) {	case 0:		LOG2(L_ALL,"getmyaddr: listener correctly set up for net_spec %s\n",			Net_spec);		break;	case -1:		PLOG4("RFS name server: %s -z %d %s : request failed\n",NLS_Q,RFSD,Net_spec);		return(NULL);	default:		PLOG2("RFS name server: listener not properly set up for RFS on network %s\n",			Net_spec);		return(NULL);	}	sprintf(buf,"%s %s >/dev/null 2>&1",NLS_Q,Net_spec);	switch (system(buf)) {	case 0:		LOG2(L_ALL,"getmyaddr: listener is running for net_spec %s\n",			Net_spec);		break;	case -1:		PLOG3("RFS name server: %s %s : request failed\n",NLS_Q,Net_spec);		return(NULL);	default:		PLOG2("RFS name server: listener not currently active for network %s\n",			Net_spec);		return(NULL);	}	sprintf(buf,"%s %s",NLS_ADDR,Net_spec);	if ((fp = popen(buf,"r")) == NULL) {		PLOG2("RFS name server: %s failed\n",buf);		return(NULL);	}	if (fgets(buf,BUFSIZ,fp) == NULL) {		PLOG1("RFS name server: can't get listen address\n");		pclose(fp);	}	if ((retaddr = astoa(buf,NULL)) == NULL) {		PLOG2("RFS name server: got bad address from listener '%s'\n",buf);	}	else {		LOG2(L_OVER,"getmyaddr: using addr=%s as my address\n",buf);	}	pclose(fp);	return(retaddr);}/* * getnsinfo searches the database for the names of potential * primary name servers for the domains this machine serves. */intgetnsinfo(){	struct res_rec	**rlist;	struct res_rec	**arlist;	struct res_rec	*srlist[MAXREC];	struct res_rec	**srp = srlist;	struct res_rec	*rec;	char		*dom;	struct ns_info	*nptr;	int		i, j;	long		indx;	int		count;	static int	first=TRUE;	LOG2(L_COMM,"(%5d) getnsinfo: enter\n",Logstamp);	/* first clear out Nsinfo	*/	for (i=0, nptr = Nsinfo; i < MAXNS; i++, nptr++) {		if (!first && nptr->n_pd != -1)			nsrclose(nptr->n_pd);		nptr->n_state = R_UNUSED;		nptr->n_pd = -1;		if (!first && nptr->n_dname)			free(nptr->n_dname);			nptr->n_dname = NULL;		if (!first && nptr->n_addr)			free(nptr->n_addr);		nptr->n_addr = NULL;	}	first = FALSE;	for (i=0; i < Mylastdom; i++) {		dom = Mydomains[i];		if ((rlist = findrr(dom,NSTYPE)) == NULL)			continue;		count = copyrlist(&srp,rlist);		if (getars(srlist, &arlist, count) == 0) {			freelist(rlist);			continue;		}		for (j=0, rec=srlist[0]; j < count; rec = srlist[++j]) {			if ((indx = rec->rr_type & ~MASKNS) < 1 || indx > MAXNS)				continue;			indx--;			nptr = &Nsinfo[indx];			if (nptr->n_state == R_UNUSED) {				nptr->n_state = R_NOTPRIME;				nptr->n_dname = copystr(rec->rr_data);				if ((nptr->n_addr = astoa(arlist[j]->rr_a,NULL))					== NULL) {					PLOG2("RFS name server: bad NS addr for %s\n",						nptr->n_dname);					freelist(rlist);					return(RFS_FAILURE);				}				LOG4(L_COMM,"(%5d) getnsinfo: add %s to Nsinfo[%d]\n",					Logstamp, nptr->n_dname,indx);				continue;			}			if (strcmp(rec->rr_data,nptr->n_dname)) {				PLOG3("RFS name server: NS setup conflict, %s & %s\n",					rec->rr_data,nptr->n_dname);				freelist(rlist);				return(RFS_FAILURE);			}		}		freelist(rlist);	}	return(RFS_SUCCESS);}/* * setrstate is called to find out who is primary, and to * set the state of this machine. */intsetrstate(){	int	i;	register struct ns_info	*np;	struct ns_info	*pnp=NULL;	struct ns_info	*npnp=NULL;	struct ns_info	*Mynp=NULL;	void	(*usr2sig)();	char	*block=NULL;	int	size=0;	int	state;	long	code;	int	timesave;	void	rst_alrm();	int	ret;	int	pd = -1;	struct request	*req=NULL;	int	savetime = R_TIMEOUT;	LOG4(L_ALL,"(%5d) recovery: enter setrstate, Primary=%s, Recover=%s\n",		Logstamp, (Primary)?"TRUE":"FALSE", (Recover)?"TRUE":"FALSE");	if (!Recover)		return(R_NOTPRIME);	/* stop polling until after state is set	*/	usr2sig = sigset(SIGUSR2,SIG_HOLD);	sigset(SIGALRM,SIG_IGN);	timesave = alarm(0);	Primary = FALSE;	for (i=0, np=Nsinfo; i < MAXNS; i++, np++) {		if (np->n_state == R_UNUSED)			continue;		if (strcmp(Dname,np->n_dname) == NULL) {			Mynp = np;			Mynp->n_state = R_NOTPRIME;			continue;		}		LOG4(L_COMM,"(%5d) recover: polling %s, current state = %d\n",			Logstamp, np->n_dname, np->n_state);		if (np->n_pd == -1) {			if ((np->n_pd = rconnect(np->n_addr,RECOVER)) == -1)				np->n_state = R_DEAD;			else				np->n_state = R_PENDING;		}		else {			if (r_sndreq(np->n_pd, np, QUERY, NS_IM_NP) == RFS_FAILURE)				np->n_state = R_DEAD;			else				np->n_state = R_UNK;		}		LOG4(L_ALL,"(%5d) recovery: state of %s set to %d\n",			Logstamp,np->n_dname,np->n_state);	}	/* now wait for replies and don't take other requests	*/	sigset(SIGALRM,rst_alrm);	Rdone = FALSE;	while (Rdone == FALSE) {		/* is anything pending or unknown? if not, we are through */		for (i=0, np = Nsinfo; i < MAXNS; i++, np++) {			if (np != Mynp && (np->n_state == R_PENDING ||			    np->n_state == R_UNK))				break;		}		if (i == MAXNS)			break;		alarm(savetime);		ret = nswait(&pd);		if ((savetime = alarm(0)) == 0)			break;		np = pdtonp(pd);		if (block) {			free(block);			block = NULL;		}		if (req) {			freerp(req, TRUE);			req = NULL;		}		switch (ret) {		case LOC_REQ:	/* fail normal request with R_INREC */		case REM_REQ:			LOG3(L_COMM,"(%5d) recovery: rcvd %s, ignore\n",Logstamp,				(ret==LOC_REQ)?"local request":"remote request");			nsread(pd, &block, 0);			sndback(pd,R_INREC);			break;		case REC_IN:			LOG4(L_COMM,"(%5d) recovery: rcvd REC_IN from %s on pd %d\n",				Logstamp,(np)?np->n_dname:"unknown machine",pd);			if ((size = nsread(pd, &block, 0)) == -1 ||			    (req = btoreq(block,size)) == NULL ||			     checkver(req) == RFS_FAILURE) {				LOG3(L_ALL,"(%5d) recovery: REC_IN failed for %s\n",					Logstamp, (np)?np->n_dname:"UNKNOWN");				break;			}			if (!np && (np = nmtonp(req->rq_head->h_dname)) == NULL) {				LOG3(L_ALL,"(%5d) recovery: unexpected ns msg from %s\n",					Logstamp, req->rq_head->h_dname);				break;			}			if (strcmp(np->n_dname,req->rq_head->h_dname) != 0) {				LOG4(L_ALL,"(%5d) recover: expect ns %s got ns %s\n",					Logstamp,np->n_dname,req->rq_head->h_dname);				nsrclose(pd);				if (pd != np->n_pd)					nsrclose(np->n_pd);				if ((np->n_pd = rconnect(np->n_addr,RECOVER)) == -1)					np->n_state = R_DEAD;				else					np->n_state = R_PENDING;				LOG4(L_COMM,"(%5d) recover: set state of %s to %d\n",					Logstamp,np->n_dname,np->n_state);				break;			}			/* only deal with NS_IM_NP and NS_IM_P msg types	*/			code = req->rq_head->h_opcode;			if (code == NS_IM_NP)				state = R_NOTPRIME;			else if (code == NS_IM_P)				state = R_PRIME;			else {				if (req->rq_head->h_flags & QUERY)					sndback(pd,R_INREC);				break;			}			if (np->n_state == R_DEAD) {				np->n_pd = pd;				np->n_state = state;			}			else if (np->n_state == R_UNK) {				if (pd != np->n_pd) {					/*					 * shouldn't happen, but if it does					 * treat like a collision					 */					LOG5(L_ALL,"(%5d) recover: %s, pd %d != %d\n",						Logstamp, np->n_dname, pd, np->n_pd);					if (np > Mynp) {						nsrclose(np->n_pd);						np->n_pd = pd;					}					else {						nsrclose(pd);						break;					}				}				np->n_state = state;			}			else if (np->n_state == R_PENDING) {				if (pd == np->n_pd)					LOG2(L_ALL,"recovery: WARNING NS %s out of state\n",						np->n_dname);				else { /* collision */					if (np > Mynp) {						nsrclose(np->n_pd);						np->n_pd = pd;					}					else {						nsrclose(pd);						break;					}				}				np->n_state = state;			}			else 				np->n_state = state;			if (req->rq_head->h_flags & QUERY)				r_sndreq(pd, np, RESPONSE, NS_IM_NP);			LOG4(L_COMM,"(%5d) recover: set state of %s to %d\n",				Logstamp,np->n_dname,np->n_state);			break;		case REC_ACC:			if (!np) { /* collision */				LOG3(L_ALL,"(%5d) recovery: connects collided ns=%s\n",					Logstamp, np->n_dname);				nsrclose(pd);				break;			}			LOG3(L_COMM,"(%5d) recovery: rcvd REC_ACC from %s\n",				Logstamp, np->n_dname);			/* got connection, send poll	*/			if (r_sndreq(pd, np, QUERY, NS_IM_NP) == RFS_FAILURE) {				nsrclose(pd);				np->n_state = R_DEAD;				np->n_pd = -1;			}			else				np->n_state = R_UNK;			LOG4(L_COMM,"(%5d) recover: set state of %s to %d\n",				Logstamp,np->n_dname,np->n_state);			break;		case REC_HUP:			LOG4(L_COMM,"(%5d) recovery: rcvd hangup from %s, pd=%d\n",				Logstamp, (np)?np->n_dname:"unknown ns",pd);			nsrclose(pd);			if (np) {				if ((np->n_pd = rconnect(np->n_addr,RECOVER)) == -1)					np->n_state = R_DEAD;				else					np->n_state = R_PENDING;				LOG4(L_COMM,"(%5d) recover: set state of %s to %d\n",					Logstamp,np->n_dname,np->n_state);			}			break;		case FATAL:			PLOG3("(%5d) recovery: fatal return from nswait, errno=%d\n",				Logstamp, errno);			sigset(SIGUSR2,usr2sig);			return(RFS_FAILURE);		case REC_CON:	/* wait for poll from connector	*/		case NON_FATAL:		default:			break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -