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

📄 dnstcp.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <ip.h>#include "dns.h"enum{	Maxpath=		128,};char	*logfile = "dns";char	*dbfile;int	debug;int	cachedb = 1;int	testing;int traceactivity;int	needrefresh;int 	resolver;char	mntpt[Maxpath];char	*caller = "";ulong	now;int	maxage;uchar	ipaddr[IPaddrlen];	/* my ip address */char	*LOG;char	*zonerefreshprogram;static int	readmsg(int, uchar*, int);static void	reply(int, DNSmsg*, Request*);static void	dnzone(DNSmsg*, DNSmsg*, Request*);static void	getcaller(char*);static void	refreshmain(char*);voidusage(void){	fprint(2, "usage: %s [-rR] [-f ndb-file] [-x netmtpt]\n", argv0);	exits("usage");}voidmain(int argc, char *argv[]){	int len;	Request req;	DNSmsg reqmsg, repmsg;	uchar buf[512];	char tname[32];	char *err;	char *ext = "";	ARGBEGIN{	case 'R':		norecursion = 1;		break;	case 'd':		debug++;		break;	case 'f':		dbfile = EARGF(usage());		break;	case 'r':		resolver = 1;		break;	case 'x':		ext = EARGF(usage());		break;	default:		usage();		break;	}ARGEND	if(debug < 2)		debug = 0;	if(argc > 0)		getcaller(argv[0]);	dninit();	snprint(mntpt, sizeof(mntpt), "/net%s", ext);	if(myipaddr(ipaddr, mntpt) < 0)		sysfatal("can't read my ip address");	syslog(0, logfile, "dnstcp call from %s to %I", caller, ipaddr);	db2cache(1);	setjmp(req.mret);	req.isslave = 0;	/* loop on requests */	for(;; putactivity(0)){		now = time(0);		memset(&repmsg, 0, sizeof(repmsg));		alarm(10*60*1000);		len = readmsg(0, buf, sizeof(buf));		alarm(0);		if(len <= 0)			break;		getactivity(&req, 0);		req.aborttime = now + 15*Min;		err = convM2DNS(buf, len, &reqmsg);		if(err){			syslog(0, logfile, "server: input error: %s from %I", err, buf);			break;		}		if(reqmsg.qdcount < 1){			syslog(0, logfile, "server: no questions from %I", buf);			break;		}		if(reqmsg.flags & Fresp){			syslog(0, logfile, "server: reply not request from %I", buf);			break;		}		if((reqmsg.flags & Omask) != Oquery){			syslog(0, logfile, "server: op %d from %I", reqmsg.flags & Omask, buf);			break;		}		if(debug)			syslog(0, logfile, "[%d] %d: serve (%s) %d %s %s",				getpid(),				req.id, caller,				reqmsg.id,				reqmsg.qd->owner->name,				rrname(reqmsg.qd->type, tname, sizeof tname));		/* loop through each question */		while(reqmsg.qd){			if(reqmsg.qd->type == Taxfr){				dnzone(&reqmsg, &repmsg, &req);			} else {				dnserver(&reqmsg, &repmsg, &req);				reply(1, &repmsg, &req);				rrfreelist(repmsg.qd);				rrfreelist(repmsg.an);				rrfreelist(repmsg.ns);				rrfreelist(repmsg.ar);			}		}		rrfreelist(reqmsg.qd);		rrfreelist(reqmsg.an);		rrfreelist(reqmsg.ns);		rrfreelist(reqmsg.ar);		if(req.isslave){			putactivity(0);			_exits(0);		}	}	refreshmain(mntpt);}static intreadmsg(int fd, uchar *buf, int max){	int n;	uchar x[2];	if(readn(fd, x, 2) != 2)		return -1;	n = (x[0]<<8) | x[1];	if(n > max)		return -1;	if(readn(fd, buf, n) != n)		return -1;	return n;}static voidreply(int fd, DNSmsg *rep, Request *req){	int len, rv;	char tname[32];	uchar buf[4096];	RR *rp;	if(debug){		syslog(0, logfile, "%d: reply (%s) %s %s %ux",			req->id, caller,			rep->qd->owner->name,			rrname(rep->qd->type, tname, sizeof tname),			rep->flags);		for(rp = rep->an; rp; rp = rp->next)			syslog(0, logfile, "an %R", rp);		for(rp = rep->ns; rp; rp = rp->next)			syslog(0, logfile, "ns %R", rp);		for(rp = rep->ar; rp; rp = rp->next)			syslog(0, logfile, "ar %R", rp);	}	len = convDNS2M(rep, buf+2, sizeof(buf) - 2);	if(len <= 0)		abort(); /* "dnserver: converting reply" */;	buf[0] = len>>8;	buf[1] = len;	rv = write(fd, buf, len+2);	if(rv != len+2){		syslog(0, logfile, "[%d] sending reply: %d instead of %d", getpid(), rv, len+2);		exits(0);	}}/* *  Hash table for domain names.  The hash is based only on the *  first element of the domain name. */extern DN	*ht[HTLEN];static intnumelem(char *name){	int i;	i = 1;	for(; *name; name++)		if(*name == '.')			i++;	return i;}intinzone(DN *dp, char *name, int namelen, int depth){	int n;	if(dp->name == 0)		return 0;	if(numelem(dp->name) != depth)		return 0;	n = strlen(dp->name);	if(n < namelen)		return 0;	if(strcmp(name, dp->name + n - namelen) != 0)		return 0;	if(n > namelen && dp->name[n - namelen - 1] != '.')		return 0;	return 1;}static voiddnzone(DNSmsg *reqp, DNSmsg *repp, Request *req){	DN *dp, *ndp;	RR r, *rp;	int h, depth, found, nlen;	memset(repp, 0, sizeof(*repp));	repp->id = reqp->id;	repp->qd = reqp->qd;	reqp->qd = reqp->qd->next;	repp->qd->next = 0;	repp->flags = Fauth | Fresp | Oquery;	if(!norecursion)		repp->flags |= Fcanrec;	dp = repp->qd->owner;	/* send the soa */	repp->an = rrlookup(dp, Tsoa, NOneg);	reply(1, repp, req);	if(repp->an == 0)		goto out;	rrfreelist(repp->an);	nlen = strlen(dp->name);	/* construct a breadth first search of the name space (hard with a hash) */	repp->an = &r;	for(depth = numelem(dp->name); ; depth++){		found = 0;		for(h = 0; h < HTLEN; h++)			for(ndp = ht[h]; ndp; ndp = ndp->next)				if(inzone(ndp, dp->name, nlen, depth)){					for(rp = ndp->rr; rp; rp = rp->next){						/* there shouldn't be negatives, but just in case */						if(rp->negative)							continue;						/* don't send an soa's, ns's are enough */						if(rp->type == Tsoa)							continue;						r = *rp;						r.next = 0;						reply(1, repp, req);					}					found = 1;				}		if(!found)			break;	}	/* resend the soa */	repp->an = rrlookup(dp, Tsoa, NOneg);	reply(1, repp, req);	rrfreelist(repp->an);out:	rrfree(repp->qd);}static voidgetcaller(char *dir){	int fd, n;	static char remote[128];	snprint(remote, sizeof(remote), "%s/remote", dir);	fd = open(remote, OREAD);	if(fd < 0)		return;	n = read(fd, remote, sizeof(remote)-1);	close(fd);	if(n <= 0)		return;	if(remote[n-1] == '\n')		n--;	remote[n] = 0;	caller = remote;}static voidrefreshmain(char *net){	int fd;	char file[128];	snprint(file, sizeof(file), "%s/dns", net);	if(debug)		syslog(0, logfile, "refreshing %s", file);	fd = open(file, ORDWR);	if(fd < 0){		syslog(0, logfile, "can't refresh %s", file);		return;	}	fprint(fd, "refresh");	close(fd);}/* *  the following varies between dnsdebug and dns */voidlogreply(int id, uchar *addr, DNSmsg *mp){	RR *rp;	syslog(0, LOG, "%d: rcvd %I flags:%s%s%s%s%s", id, addr,		mp->flags & Fauth ? " auth" : "",		mp->flags & Ftrunc ? " trunc" : "",		mp->flags & Frecurse ? " rd" : "",		mp->flags & Fcanrec ? " ra" : "",		mp->flags & (Fauth|Rname) == (Fauth|Rname) ?		" nx" : "");	for(rp = mp->qd; rp != nil; rp = rp->next)		syslog(0, LOG, "%d: rcvd %I qd %s", id, addr, rp->owner->name);	for(rp = mp->an; rp != nil; rp = rp->next)		syslog(0, LOG, "%d: rcvd %I an %R", id, addr, rp);	for(rp = mp->ns; rp != nil; rp = rp->next)		syslog(0, LOG, "%d: rcvd %I ns %R", id, addr, rp);	for(rp = mp->ar; rp != nil; rp = rp->next)		syslog(0, LOG, "%d: rcvd %I ar %R", id, addr, rp);}voidlogsend(int id, int subid, uchar *addr, char *sname, char *rname, int type){	char buf[12];	syslog(0, LOG, "%d.%d: sending to %I/%s %s %s",		id, subid, addr, sname, rname, rrname(type, buf, sizeof buf));}RR*getdnsservers(int class){	return dnsservers(class);}

⌨️ 快捷键说明

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