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

📄 dnudpserver.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <ip.h>#include "dns.h"static int	udpannounce(char*);static void	reply(int, uchar*, DNSmsg*, Request*);extern char *logfile;static voidding(void *x, char *msg){	USED(x);	if(strcmp(msg, "alarm") == 0)		noted(NCONT);	else		noted(NDFLT);}typedef struct Inprogress Inprogress;struct Inprogress{	int	inuse;	OUdphdr	uh;	DN	*owner;	int	type;	int	id;};Inprogress inprog[Maxactive+2];/* *  record client id and ignore retransmissions. *  we're still single thread at this point. */static Inprogress*clientrxmit(DNSmsg *req, uchar *buf){	Inprogress *p, *empty;	OUdphdr *uh;	uh = (OUdphdr *)buf;	empty = 0;	for(p = inprog; p < &inprog[Maxactive]; p++){		if(p->inuse == 0){			if(empty == 0)				empty = p;			continue;		}		if(req->id == p->id)		if(req->qd->owner == p->owner)		if(req->qd->type == p->type)		if(memcmp(uh, &p->uh, OUdphdrsize) == 0)			return 0;	}	if(empty == 0)		return 0;	/* shouldn't happen - see slave() and definition of Maxactive */	empty->id = req->id;	empty->owner = req->qd->owner;	empty->type = req->qd->type;	memmove(&empty->uh, uh, OUdphdrsize);	empty->inuse = 1;	return empty;}/* *  a process to act as a dns server for outside reqeusts */voiddnudpserver(char *mntpt){	int fd, len, op;	Request req;	DNSmsg reqmsg, repmsg;	uchar buf[OUdphdrsize + Maxudp + 1024];	char *err;	Inprogress *p;	char tname[32];	OUdphdr *uh;	/* fork sharing text, data, and bss with parent */	switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){	case -1:		break;	case 0:		break;	default:		return;	}	fd = -1;	notify(ding);restart:	if(fd >= 0)		close(fd);	while((fd = udpannounce(mntpt)) < 0)		sleep(5000);	if(setjmp(req.mret))		putactivity(0);	req.isslave = 0;	/* loop on requests */	for(;; putactivity(0)){		memset(&repmsg, 0, sizeof(repmsg));		memset(&reqmsg, 0, sizeof(reqmsg));		alarm(60*1000);		len = read(fd, buf, sizeof(buf));		alarm(0);		if(len <= OUdphdrsize)			goto restart;		uh = (OUdphdr*)buf;		len -= OUdphdrsize;		getactivity(&req, 0);		req.aborttime = now + 30;	/* don't spend more than 30 seconds */		err = convM2DNS(&buf[OUdphdrsize], len, &reqmsg);		if(err){			syslog(0, logfile, "server: input error: %s from %I", err, buf);			continue;		}		if(reqmsg.qdcount < 1){			syslog(0, logfile, "server: no questions from %I", buf);			goto freereq;		}		if(reqmsg.flags & Fresp){			syslog(0, logfile, "server: reply not request from %I", buf);			goto freereq;		}		op = reqmsg.flags & Omask;		if(op != Oquery && op != Onotify){			syslog(0, logfile, "server: op %d from %I", reqmsg.flags & Omask, buf);			goto freereq;		}		if(debug || (trace && subsume(trace, reqmsg.qd->owner->name))){			syslog(0, logfile, "%d: serve (%I/%d) %d %s %s",				req.id, buf, ((uh->rport[0])<<8)+uh->rport[1],				reqmsg.id,				reqmsg.qd->owner->name,				rrname(reqmsg.qd->type, tname, sizeof tname));		}		p = clientrxmit(&reqmsg, buf);		if(p == 0){			if(debug)				syslog(0, logfile, "%d: duplicate", req.id);			goto freereq;		}		/* loop through each question */		while(reqmsg.qd){			memset(&repmsg, 0, sizeof(repmsg));			switch(op){			case Oquery:				dnserver(&reqmsg, &repmsg, &req);				break;			case Onotify:				dnnotify(&reqmsg, &repmsg, &req);				break;			}			reply(fd, buf, &repmsg, &req);			rrfreelist(repmsg.qd);			rrfreelist(repmsg.an);			rrfreelist(repmsg.ns);			rrfreelist(repmsg.ar);		}		p->inuse = 0;freereq:		rrfreelist(reqmsg.qd);		rrfreelist(reqmsg.an);		rrfreelist(reqmsg.ns);		rrfreelist(reqmsg.ar);		if(req.isslave){			putactivity(0);			_exits(0);		}	}}/* *  announce on udp port and set message style interface */static char *hmsg = "headers";static char *ohmsg = "oldheaders";static intudpannounce(char *mntpt){	static int whined;	int data, ctl;	char dir[64];	char datafile[64+6];	/* get a udp port */	sprint(datafile, "%s/udp!*!dns", mntpt);	ctl = announce(datafile, dir);	if(ctl < 0){		if(!whined++)			warning("can't announce on dns udp port");		return -1;	}	snprint(datafile, sizeof(datafile), "%s/data", dir);	/* turn on header style interface */	if(write(ctl, hmsg, strlen(hmsg)) , 0)		abort(); /* hmsg */;	write(ctl, ohmsg, strlen(ohmsg));	data = open(datafile, ORDWR);	if(data < 0){		close(ctl);		if(!whined++)			warning("can't announce on dns udp port");		return -1;	}	close(ctl);	return data;}static voidreply(int fd, uchar *buf, DNSmsg *rep, Request *reqp){	int len;	char tname[32];	RR *rp;	if(debug || (trace && subsume(trace, rep->qd->owner->name)))		syslog(0, logfile, "%d: reply (%I/%d) %d %s %s an %R ns %R ar %R",			reqp->id, buf, ((buf[4])<<8)+buf[5],			rep->id, rep->qd->owner->name,			rrname(rep->qd->type, tname, sizeof tname), rep->an, rep->ns, rep->ar);	len = convDNS2M(rep, &buf[OUdphdrsize], Maxudp);	if(len <= 0){		syslog(0, logfile, "error converting reply: %s %d", rep->qd->owner->name,			rep->qd->type);		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);		return;	}	len += OUdphdrsize;	if(write(fd, buf, len) != len)		syslog(0, logfile, "error sending reply: %r");}

⌨️ 快捷键说明

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