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

📄 dn.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
 */RR*rrlookup(DN *dp, int type, int flag){	RR *rp, *first, **last;	assert(dp->magic == DNmagic);	first = 0;	last = &first;	lock(&dnlock);	/* try for an authoritative db entry */	for(rp = dp->rr; rp; rp = rp->next){		assert(rp->magic == RRmagic && rp->cached);		if(rp->db)		if(rp->auth)		if(tsame(type, rp->type))			last = rrcopy(rp, last);	}	if(first)		goto out;	/* try for an living authoritative network entry */	for(rp = dp->rr; rp; rp = rp->next){		if(!rp->db)		if(rp->auth)		if(rp->ttl + 60 > now)		if(tsame(type, rp->type)){			if(flag == NOneg && rp->negative)				goto out;			last = rrcopy(rp, last);		}	}	if(first)		goto out;	/* try for an living unauthoritative network entry */	for(rp = dp->rr; rp; rp = rp->next){		if(!rp->db)		if(rp->ttl + 60 > now)		if(tsame(type, rp->type)){			if(flag == NOneg && rp->negative)				goto out;			last = rrcopy(rp, last);		}	}	if(first)		goto out;	/* try for an unauthoritative db entry */	for(rp = dp->rr; rp; rp = rp->next){		if(rp->db)		if(tsame(type, rp->type))			last = rrcopy(rp, last);	}	if(first)		goto out;	/* otherwise, settle for anything we got (except for negative caches)  */	for(rp = dp->rr; rp; rp = rp->next){		if(tsame(type, rp->type)){			if(rp->negative)				goto out;			last = rrcopy(rp, last);		}	}out:	unlock(&dnlock);	unique(first);	return first;}/* *  convert an ascii RR type name to its integer representation */intrrtype(char *atype){	int i;	for(i = 0; i <= Tall; i++)		if(rrtname[i] && strcmp(rrtname[i], atype) == 0)			return i;	// make any a synonym for all	if(strcmp(atype, "any") == 0)		return Tall;	return atoi(atype);}/* *  convert an integer RR type to it's ascii name */char*rrname(int type, char *buf, int len){	char *t;	t = 0;	if(type <= Tall)		t = rrtname[type];	if(t==0){		snprint(buf, len, "%d", type);		t = buf;	}	return t;}/* *  return 0 if not a supported rr type */intrrsupported(int type){	if(type < 0 || type >Tall)		return 0;	return rrtname[type] != 0;}/* *  compare 2 types */inttsame(int t1, int t2){	return t1 == t2 || t1 == Tall;}/* *  Add resource records to a list, duplicate them if they are cached *  RR's since these are shared. */RR*rrcat(RR **start, RR *rp){	RR **last;	last = start;	while(*last != 0)		last = &(*last)->next;	*last = rp;	return *start;}/* *  remove negative cache rr's from an rr list */RR*rrremneg(RR **l){	RR **nl, *rp;	RR *first;	first = nil;	nl = &first;	while(*l != nil){		rp = *l;		if(rp->negative){			*l = rp->next;			*nl = rp;			nl = &rp->next;			*nl = nil;		} else			l = &rp->next;	}	return first;}/* *  remove rr's of a particular type from an rr list */RR*rrremtype(RR **l, int type){	RR **nl, *rp;	RR *first;	first = nil;	nl = &first;	while(*l != nil){		rp = *l;		if(rp->type == type){			*l = rp->next;			*nl = rp;			nl = &rp->next;			*nl = nil;		} else			l = &(*l)->next;	}	return first;}/* *  print conversion for rr records */intrrfmt(Fmt *f){	RR *rp;	char *strp;	Fmt fstr;	int rv;	char buf[Domlen];	Server *s;	Txt *t;	fmtstrinit(&fstr);	rp = va_arg(f->args, RR*);	if(rp == 0){		fmtprint(&fstr, "<null>");		goto out;	}	fmtprint(&fstr, "%s %s", rp->owner->name,		rrname(rp->type, buf, sizeof buf));	if(rp->negative){		fmtprint(&fstr, "\tnegative - rcode %d", rp->negrcode);		goto out;	}	switch(rp->type){	case Thinfo:		fmtprint(&fstr, "\t%s %s", rp->cpu->name, rp->os->name);		break;	case Tcname:	case Tmb:	case Tmd:	case Tmf:	case Tns:		fmtprint(&fstr, "\t%s", rp->host->name);		break;	case Tmg:	case Tmr:		fmtprint(&fstr, "\t%s", rp->mb->name);		break;	case Tminfo:		fmtprint(&fstr, "\t%s %s", rp->mb->name, rp->rmb->name);		break;	case Tmx:		fmtprint(&fstr, "\t%lud %s", rp->pref, rp->host->name);		break;	case Ta:	case Taaaa:		fmtprint(&fstr, "\t%s", rp->ip->name);		break;	case Tptr://		fmtprint(&fstr, "\t%s(%lud)", rp->ptr->name, rp->ptr->ordinal);		fmtprint(&fstr, "\t%s", rp->ptr->name);		break;	case Tsoa:		fmtprint(&fstr, "\t%s %s %lud %lud %lud %lud %lud", rp->host->name,			rp->rmb->name, rp->soa->serial, rp->soa->refresh, rp->soa->retry,			rp->soa->expire, rp->soa->minttl);		for(s = rp->soa->slaves; s != nil; s = s->next)			fmtprint(&fstr, " %s", s->name);		break;	case Tnull:		fmtprint(&fstr, "\t%.*H", rp->null->dlen, rp->null->data);		break;	case Ttxt:		fmtprint(&fstr, "\t");		for(t = rp->txt; t != nil; t = t->next)			fmtprint(&fstr, "%s", t->p);		break;	case Trp:		fmtprint(&fstr, "\t%s %s", rp->rmb->name, rp->rp->name);		break;	case Tkey:		fmtprint(&fstr, "\t%d %d %d", rp->key->flags, rp->key->proto,			rp->key->alg);		break;	case Tsig:		fmtprint(&fstr, "\t%d %d %d %lud %lud %lud %d %s",			rp->sig->type, rp->sig->alg, rp->sig->labels, rp->sig->ttl,			rp->sig->exp, rp->sig->incep, rp->sig->tag, rp->sig->signer->name);		break;	case Tcert:		fmtprint(&fstr, "\t%d %d %d",			rp->sig->type, rp->sig->tag, rp->sig->alg);		break;	default:		break;	}out:	strp = fmtstrflush(&fstr);	rv = fmtstrcpy(f, strp);	free(strp);	return rv;}/* *  print conversion for rr records in attribute value form */intrravfmt(Fmt *f){	RR *rp;	char *strp;	Fmt fstr;	int rv;	Server *s;	Txt *t;	int quote;	fmtstrinit(&fstr);	rp = va_arg(f->args, RR*);	if(rp == 0){		fmtprint(&fstr, "<null>");		goto out;	}	if(rp->type == Tptr)		fmtprint(&fstr, "ptr=%s", rp->owner->name);	else		fmtprint(&fstr, "dom=%s", rp->owner->name);	switch(rp->type){	case Thinfo:		fmtprint(&fstr, " cpu=%s os=%s", rp->cpu->name, rp->os->name);		break;	case Tcname:		fmtprint(&fstr, " cname=%s", rp->host->name);		break;	case Tmb:	case Tmd:	case Tmf:		fmtprint(&fstr, " mbox=%s", rp->host->name);		break;	case Tns:		fmtprint(&fstr,  " ns=%s", rp->host->name);		break;	case Tmg:	case Tmr:		fmtprint(&fstr, " mbox=%s", rp->mb->name);		break;	case Tminfo:		fmtprint(&fstr, " mbox=%s mbox=%s", rp->mb->name, rp->rmb->name);		break;	case Tmx:		fmtprint(&fstr, " pref=%lud mx=%s", rp->pref, rp->host->name);		break;	case Ta:	case Taaaa:		fmtprint(&fstr, " ip=%s", rp->ip->name);		break;	case Tptr:		fmtprint(&fstr, " dom=%s", rp->ptr->name);		break;	case Tsoa:		fmtprint(&fstr, " ns=%s mbox=%s serial=%lud refresh=%lud retry=%lud expire=%lud ttl=%lud",			rp->host->name, rp->rmb->name, rp->soa->serial,			rp->soa->refresh, rp->soa->retry,			rp->soa->expire, rp->soa->minttl);		for(s = rp->soa->slaves; s != nil; s = s->next)			fmtprint(&fstr, " dnsslave=%s", s->name);		break;	case Tnull:		fmtprint(&fstr, " null=%.*H", rp->null->dlen, rp->null->data);		break;	case Ttxt:		fmtprint(&fstr, " txt=");		quote = 0;		for(t = rp->txt; t != nil; t = t->next)			if(strchr(t->p, ' '))				quote = 1;		if(quote)			fmtprint(&fstr, "\"");		for(t = rp->txt; t != nil; t = t->next)			fmtprint(&fstr, "%s", t->p);		if(quote)			fmtprint(&fstr, "\"");		break;	case Trp:		fmtprint(&fstr, " rp=%s txt=%s", rp->rmb->name, rp->rp->name);		break;	case Tkey:		fmtprint(&fstr, " flags=%d proto=%d alg=%d",			rp->key->flags, rp->key->proto, rp->key->alg);		break;	case Tsig:		fmtprint(&fstr, " type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d signer=%s",			rp->sig->type, rp->sig->alg, rp->sig->labels, rp->sig->ttl,			rp->sig->exp, rp->sig->incep, rp->sig->tag, rp->sig->signer->name);		break;	case Tcert:		fmtprint(&fstr, " type=%d tag=%d alg=%d",			rp->sig->type, rp->sig->tag, rp->sig->alg);		break;	default:		break;	}out:	strp = fmtstrflush(&fstr);	rv = fmtstrcpy(f, strp);	free(strp);	return rv;}voidwarning(char *fmt, ...){	char dnserr[128];	va_list arg;	va_start(arg, fmt);	vseprint(dnserr, dnserr+sizeof(dnserr), fmt, arg);	va_end(arg);	syslog(1, "dns", dnserr);}/* *  create a slave process to handle a request to avoid one request blocking *  another */voidslave(Request *req){	static int slaveid;	int ppid;	if(req->isslave)		return;		/* we're already a slave process */	/*	 * These calls to putactivity cannot block. 	 * After getactivity(), the current process is counted	 * twice in dnvars.active (one will pass to the child).	 * If putactivity tries to wait for dnvars.active == 0,	 * it will never happen.	 */	/* limit parallelism */	if(getactivity(req, 1) > Maxactive){		if(traceactivity) syslog(0, "dns", "[%d] too much activity", getpid());		putactivity(1);		return;	}	ppid = getpid();	switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){	case -1:		putactivity(1);		break;	case 0:		if(traceactivity) syslog(0, "dns", "[%d] take activity from %d", ppid, getpid());		req->isslave = 1;		break;	default:		longjmp(req->mret, 1);	}}/* *  chasing down double free's */voiddncheck(void *p, int dolock){	int i;	DN *dp;	RR *rp;	extern Pool *mainmem;	if(p != nil){		dp = p;		assert(dp->magic == DNmagic);	}	if(!testing)		return;	if(dolock)		lock(&dnlock);	poolcheck(mainmem);	for(i = 0; i < HTLEN; i++)		for(dp = ht[i]; dp; dp = dp->next){			assert(dp != p);			assert(dp->magic == DNmagic);			for(rp = dp->rr; rp; rp = rp->next){				assert(rp->magic == RRmagic);				assert(rp->cached);				assert(rp->owner == dp);			}		}	if(dolock)		unlock(&dnlock);}static intrrequiv(RR *r1, RR *r2){	return r1->owner == r2->owner		&& r1->type == r2->type		&& r1->arg0 == r2->arg0		&& r1->arg1 == r2->arg1;}voidunique(RR *rp){	RR **l, *nrp;	for(; rp; rp = rp->next){		l = &rp->next;		for(nrp = *l; nrp; nrp = *l){			if(rrequiv(rp, nrp)){				*l = nrp->next;				rrfree(nrp);			} else				l = &nrp->next;		}	}}/* *  true if second domain is subsumed by the first */intsubsume(char *higher, char *lower){	int hn, ln;	ln = strlen(lower);	hn = strlen(higher);	if(ln < hn)		return 0;	if(cistrcmp(lower + ln - hn, higher) != 0)		return 0;	if(ln > hn && hn != 0 && lower[ln - hn - 1] != '.')		return 0;	return 1;}/* *  randomize the order we return items to provide some *  load balancing for servers. * *  only randomize the first class of entries */RR*randomize(RR *rp){	RR *first, *last, *x, *base;	ulong n;	if(rp == nil || rp->next == nil)		return rp;	/* just randomize addresses and mx's */	for(x = rp; x; x = x->next)		if(x->type != Ta && x->type != Tmx && x->type != Tns)			return rp;	base = rp; 	n = rand();	last = first = nil;	while(rp != nil){		/* stop randomizing if we've moved past our class */		if(base->auth != rp->auth || base->db != rp->db){			last->next = rp;			break;		}		/* unchain */		x = rp;		rp = x->next;		x->next = nil;		if(n&1){			/* add to tail */			if(last == nil)				first = x;			else				last->next = x;			last = x;		} else {			/* add to head */			if(last == nil)				last = x;			x->next = first;			first = x;		}		/* reroll the dice */		n >>= 1;	}	return first;}static intsencodefmt(Fmt *f){	char *out;	char *buf;	int i, len;	int ilen;	int rv;	uchar *b;	char obuf[64];	// rsc optimization	if(!(f->flags&FmtPrec) || f->prec < 1)		goto error;	b = va_arg(f->args, uchar*);	if(b == nil)		goto error;	/* if it's a printable, go for it */	len = f->prec;	for(i = 0; i < len; i++)		if(!isprint(b[i]))			break;	if(i == len){		if(len >= sizeof obuf)			len = sizeof(obuf)-1;		memmove(obuf, b, len);		obuf[len] = 0;		fmtstrcpy(f, obuf);		return 0;	}	ilen = f->prec;	f->prec = 0;	f->flags &= ~FmtPrec;	switch(f->r){	case '<':		len = (8*ilen+4)/5 + 3;		break;	case '[':		len = (8*ilen+5)/6 + 4;		break;	case 'H':		len = 2*ilen + 1;		break;	default:		goto error;	}	if(len > sizeof(obuf)){		buf = malloc(len);		if(buf == nil)			goto error;	} else		buf = obuf;	// convert	out = buf;	switch(f->r){	case '<':		rv = enc32(out, len, b, ilen);		break;	case '[':		rv = enc64(out, len, b, ilen);		break;	case 'H':		rv = enc16(out, len, b, ilen);		break;	default:		rv = -1;		break;	}	if(rv < 0)		goto error;	fmtstrcpy(f, buf);	if(buf != obuf)		free(buf);	return 0;error:	return fmtstrcpy(f, "<encodefmt>");}void*emalloc(int size){	char *x;	x = mallocz(size, 1);	if(x == nil)		abort();	setmalloctag(x, getcallerpc(&size));	return x;}char*estrdup(char *s){	int size;	char *p;	size = strlen(s)+1;	p = mallocz(size, 0);	if(p == nil)		abort();	memmove(p, s, size);	setmalloctag(p, getcallerpc(&s));	return p;}/* *  create a pointer record */static RR*mkptr(DN *dp, char *ptr, ulong ttl){	DN *ipdp;	RR *rp;	ipdp = dnlookup(ptr, Cin, 1);	rp = rralloc(Tptr);	rp->ptr = dp;	rp->owner = ipdp;	rp->db = 1;	if(ttl)		rp->ttl = ttl;	return rp;}/* *  look for all ip addresses in this network and make *  pointer records for them. */voiddnptr(uchar *net, uchar *mask, char *dom, int bytes, int ttl){	int i, j;	DN *dp;	RR *rp, *nrp, *first, **l;	uchar ip[IPaddrlen];	uchar nnet[IPaddrlen];	char ptr[Domlen];	char *p, *e;	l = &first;	first = nil;	for(i = 0; i < HTLEN; i++){		for(dp = ht[i]; dp; dp = dp->next){			for(rp = dp->rr; rp; rp = rp->next){				if(rp->type != Ta || rp->negative)					continue;				parseip(ip, rp->ip->name);				maskip(ip, mask, nnet);				if(ipcmp(net, nnet) != 0)					continue;				p = ptr;				e = ptr+sizeof(ptr);				for(j = IPaddrlen-1; j >= IPaddrlen-bytes; j--)					p = seprint(p, e, "%d.", ip[j]);				seprint(p, e, "%s", dom);				nrp = mkptr(dp, ptr, ttl);				*l = nrp;				l = &nrp->next;			}		}	}	for(rp = first; rp != nil; rp = nrp){		nrp = rp->next;		rp->next = nil;		rrattach(rp, 1);	}}voidfreeserverlist(Server *s){	Server *next;	for(; s != nil; s = next){		next = s->next;		free(s);	}}voidaddserver(Server **l, char *name){	Server *s;	while(*l)		l = &(*l)->next;	s = malloc(sizeof(Server)+strlen(name)+1);	if(s == nil)		return;	s->name = (char*)(s+1);	strcpy(s->name, name);	s->next = nil;	*l = s;}Server*copyserverlist(Server *s){	Server *ns;		for(ns = nil; s != nil; s = s->next)		addserver(&ns, s->name);	return ns;}

⌨️ 快捷键说明

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