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

📄 convm2dns.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <ip.h>#include "dns.h"typedef struct Scan	Scan;struct Scan{	uchar	*base;	uchar	*p;	uchar	*ep;	char	*err;};#define NAME(x)		gname(x, sp)#define SYMBOL(x)	(x = gsym(sp))#define STRING(x)	(x = gstr(sp))#define USHORT(x)	(x = gshort(sp))#define ULONG(x)	(x = glong(sp))#define UCHAR(x)	(x = gchar(sp))#define V4ADDR(x)	(x = gv4addr(sp))#define V6ADDR(x)	(x = gv6addr(sp))#define BYTES(x, y)	(y = gbytes(sp, &x, len - (sp->p - data)))static char *toolong = "too long";/* *  get a ushort/ulong */static ushortgchar(Scan *sp){	ushort x;	if(sp->err)		return 0;	if(sp->ep - sp->p < 1){		sp->err = toolong;		return 0;	}	x = sp->p[0];	sp->p += 1;	return x;}static ushortgshort(Scan *sp){	ushort x;	if(sp->err)		return 0;	if(sp->ep - sp->p < 2){		sp->err = toolong;		return 0;	}	x = (sp->p[0]<<8) | sp->p[1];	sp->p += 2;	return x;}static ulongglong(Scan *sp){	ulong x;	if(sp->err)		return 0;	if(sp->ep - sp->p < 4){		sp->err = toolong;		return 0;	}	x = (sp->p[0]<<24) | (sp->p[1]<<16) | (sp->p[2]<<8) | sp->p[3];	sp->p += 4;	return x;}/* *  get an ip address */static DN*gv4addr(Scan *sp){	char addr[32];	if(sp->err)		return 0;	if(sp->ep - sp->p < 4){		sp->err = toolong;		return 0;	}	snprint(addr, sizeof(addr), "%V", sp->p);	sp->p += 4;	return dnlookup(addr, Cin, 1);}static DN*gv6addr(Scan *sp){	char addr[64];	if(sp->err)		return 0;	if(sp->ep - sp->p < IPaddrlen){		sp->err = toolong;		return 0;	}	snprint(addr, sizeof(addr), "%I", sp->p);	sp->p += IPaddrlen;	return dnlookup(addr, Cin, 1);}/* *  get a string.  make it an internal symbol. */static DN*gsym(Scan *sp){	int n;	char sym[Strlen+1];	if(sp->err)		return 0;	n = *(sp->p++);	if(sp->p+n > sp->ep){		sp->err = toolong;		return 0;	}	if(n > Strlen){		sp->err = "illegal string";		return 0;	}	strncpy(sym, (char*)sp->p, n);	sym[n] = 0;	sp->p += n;	return dnlookup(sym, Csym, 1);}/* *  get a string.  don't make it an internal symbol. */static Txt*gstr(Scan *sp){	int n;	char sym[Strlen+1];	Txt *t;	if(sp->err)		return 0;	n = *(sp->p++);	if(sp->p+n > sp->ep){		sp->err = toolong;		return 0;	}	if(n > Strlen){		sp->err = "illegal string";		return 0;	}	strncpy(sym, (char*)sp->p, n);	sym[n] = 0;	sp->p += n;	t = emalloc(sizeof(*t));	t->next = nil;	t->p = estrdup(sym);	return t;}/* *  get a sequence of bytes */static intgbytes(Scan *sp, uchar **p, int n){	if(sp->err)		return 0;	if(sp->p+n > sp->ep || n < 0){		sp->err = toolong;		return 0;	}	*p = emalloc(n);	memmove(*p, sp->p, n);	sp->p += n;	return n;}/* *  get a domain name.  'to' must point to a buffer at least Domlen+1 long. */static char*gname(char *to, Scan *sp){	int len, off;	int pointer;	int n;	char *tostart;	char *toend;	uchar *p;	tostart = to;	if(sp->err)		goto err;	pointer = 0;	p = sp->p;	toend = to + Domlen;	for(len = 0; *p; len += pointer ? 0 : (n+1)){		if((*p & 0xc0) == 0xc0){			/* pointer to other spot in message */			if(pointer++ > 10){				sp->err = "pointer loop";				goto err;			}			off = ((p[0]<<8) + p[1]) & 0x3ff;			p = sp->base + off;			if(p >= sp->ep){				sp->err = "bad pointer";				goto err;			}			n = 0;			continue;		}		n = *p++;		if(len + n < Domlen - 1){			if(to + n > toend){				sp->err = toolong;				goto err;			}			memmove(to, p, n);			to += n;		}		p += n;		if(*p){			if(to >= toend){				sp->err = toolong;				goto err;			}			*to++ = '.';		}	}	*to = 0;	if(pointer)		sp->p += len + 2;	/* + 2 for pointer */	else		sp->p += len + 1;	/* + 1 for the null domain */	return tostart;err:	*tostart = 0;	return tostart;}/* *  convert the next RR from a message */static RR*convM2RR(Scan *sp){	RR *rp;	int type;	int class;	uchar *data;	int len;	char dname[Domlen+1];	Txt *t, **l;retry:	NAME(dname);	USHORT(type);	USHORT(class);	rp = rralloc(type);	rp->owner = dnlookup(dname, class, 1);	rp->type = type;	ULONG(rp->ttl);	rp->ttl += now;	USHORT(len);	data = sp->p;	if(sp->p + len > sp->ep)		sp->err = toolong;	if(sp->err){		rrfree(rp);		return 0;	}	switch(type){	default:		/* unknown type, just ignore it */		sp->p = data + len;		rrfree(rp);		goto retry;	case Thinfo:		SYMBOL(rp->cpu);		SYMBOL(rp->os);		break;	case Tcname:	case Tmb:	case Tmd:	case Tmf:	case Tns:		rp->host = dnlookup(NAME(dname), Cin, 1);		break;	case Tmg:	case Tmr:		rp->mb = dnlookup(NAME(dname), Cin, 1);		break;	case Tminfo:		rp->rmb = dnlookup(NAME(dname), Cin, 1);		rp->mb = dnlookup(NAME(dname), Cin, 1);		break;	case Tmx:		USHORT(rp->pref);		rp->host = dnlookup(NAME(dname), Cin, 1);		break;	case Ta:		V4ADDR(rp->ip);		break;	case Taaaa:		V6ADDR(rp->ip);		break;	case Tptr:		rp->ptr = dnlookup(NAME(dname), Cin, 1);		break;	case Tsoa:		rp->host = dnlookup(NAME(dname), Cin, 1);		rp->rmb = dnlookup(NAME(dname), Cin, 1);		ULONG(rp->soa->serial);		ULONG(rp->soa->refresh);		ULONG(rp->soa->retry);		ULONG(rp->soa->expire);		ULONG(rp->soa->minttl);		break;	case Ttxt:		l = &rp->txt;		*l = nil;		while(sp->p-data < len){			STRING(t);			*l = t;			l = &t->next;		}		break;	case Tnull:		BYTES(rp->null->data, rp->null->dlen);		break;	case Trp:		rp->rmb = dnlookup(NAME(dname), Cin, 1);		rp->rp = dnlookup(NAME(dname), Cin, 1);		break;	case Tkey:		USHORT(rp->key->flags);		UCHAR(rp->key->proto);		UCHAR(rp->key->alg);		BYTES(rp->key->data, rp->key->dlen);		break;	case Tsig:		USHORT(rp->sig->type);		UCHAR(rp->sig->alg);		UCHAR(rp->sig->labels);		ULONG(rp->sig->ttl);		ULONG(rp->sig->exp);		ULONG(rp->sig->incep);		USHORT(rp->sig->tag);		rp->sig->signer = dnlookup(NAME(dname), Cin, 1);		BYTES(rp->sig->data, rp->sig->dlen);		break;	case Tcert:		USHORT(rp->cert->type);		USHORT(rp->cert->tag);		UCHAR(rp->cert->alg);		BYTES(rp->cert->data, rp->cert->dlen);		break;	}	if(sp->p - data != len)		sp->err = "bad RR len";	return rp;}/* *  convert the next question from a message */static RR*convM2Q(Scan *sp){	char dname[Domlen+1];	int type;	int class;	RR *rp;	NAME(dname);	USHORT(type);	USHORT(class);	if(sp->err)		return 0;	rp = rralloc(type);	rp->owner = dnlookup(dname, class, 1);	return rp;}static RR*rrloop(Scan *sp, int count, int quest){	int i;	static char errbuf[64];	RR *first, *rp, **l;	if(sp->err)		return 0;	l = &first;	first = 0;	for(i = 0; i < count; i++){		rp = quest ? convM2Q(sp) : convM2RR(sp);		if(rp == 0)			break;		if(sp->err){			rrfree(rp);			break;		}		*l = rp;		l = &rp->next;	}	return first;}/* *  convert the next DNS from a message stream */char*convM2DNS(uchar *buf, int len, DNSmsg *m){	Scan scan;	Scan *sp;	char *err;	scan.base = buf;	scan.p = buf;	scan.ep = buf + len;	scan.err = 0;	sp = &scan;	memset(m, 0, sizeof(DNSmsg));	USHORT(m->id);	USHORT(m->flags);	USHORT(m->qdcount);	USHORT(m->ancount);	USHORT(m->nscount);	USHORT(m->arcount);	m->qd = rrloop(sp, m->qdcount, 1);	m->an = rrloop(sp, m->ancount, 0);	m->ns = rrloop(sp, m->nscount, 0);	err = scan.err;				/* live with bad ar's */	m->ar = rrloop(sp, m->arcount, 0);	return err;}

⌨️ 快捷键说明

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