xref: /plan9/sys/src/cmd/ndb/convDNS2M.c (revision cdf9e71c4df09e92569a0ab1012818c6edd03cfd)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <ip.h>
43e12c5d1SDavid du Colombier #include "dns.h"
53e12c5d1SDavid du Colombier 
63e12c5d1SDavid du Colombier /*
73e12c5d1SDavid du Colombier  *  a dictionary of domain names for packing messages
83e12c5d1SDavid du Colombier  */
93e12c5d1SDavid du Colombier enum
103e12c5d1SDavid du Colombier {
113e12c5d1SDavid du Colombier 	Ndict=	64,
123e12c5d1SDavid du Colombier };
133e12c5d1SDavid du Colombier typedef struct Dict	Dict;
143e12c5d1SDavid du Colombier struct Dict
153e12c5d1SDavid du Colombier {
163e12c5d1SDavid du Colombier 	struct {
173e12c5d1SDavid du Colombier 		ushort	offset;		/* pointer to packed name in message */
183e12c5d1SDavid du Colombier 		char	*name;		/* pointer to unpacked name in buf */
193e12c5d1SDavid du Colombier 	} x[Ndict];
203e12c5d1SDavid du Colombier 	int	n;		/* size of dictionary */
213e12c5d1SDavid du Colombier 	uchar	*start;		/* start of packed message */
2276783259SDavid du Colombier 	char	buf[16*1024];	/* buffer for unpacked names (was 4k) */
233e12c5d1SDavid du Colombier 	char	*ep;		/* first free char in buf */
243e12c5d1SDavid du Colombier };
253e12c5d1SDavid du Colombier 
267dd7cddfSDavid du Colombier #define NAME(x)		p = pname(p, ep, x, dp)
2760845620SDavid du Colombier #define SYMBOL(x)	p = psym(p, ep, x)
2860845620SDavid du Colombier #define STRING(x)	p = pstr(p, ep, x)
297dd7cddfSDavid du Colombier #define BYTES(x, n)	p = pbytes(p, ep, x, n)
307dd7cddfSDavid du Colombier #define USHORT(x)	p = pushort(p, ep, x)
317dd7cddfSDavid du Colombier #define UCHAR(x)	p = puchar(p, ep, x)
327dd7cddfSDavid du Colombier #define ULONG(x)	p = pulong(p, ep, x)
335d459b5aSDavid du Colombier #define V4ADDR(x)	p = pv4addr(p, ep, x)
345d459b5aSDavid du Colombier #define V6ADDR(x)	p = pv6addr(p, ep, x)
353e12c5d1SDavid du Colombier 
363e12c5d1SDavid du Colombier static uchar*
psym(uchar * p,uchar * ep,char * np)3760845620SDavid du Colombier psym(uchar *p, uchar *ep, char *np)
3860845620SDavid du Colombier {
3960845620SDavid du Colombier 	int n;
4060845620SDavid du Colombier 
4160845620SDavid du Colombier 	n = strlen(np);
4260845620SDavid du Colombier 	if(n >= Strlen)			/* DNS maximum length string */
4360845620SDavid du Colombier 		n = Strlen - 1;
4460845620SDavid du Colombier 	if(ep - p < n+1)		/* see if it fits in the buffer */
4560845620SDavid du Colombier 		return ep+1;
4660845620SDavid du Colombier 	*p++ = n;
47e8ece30eSDavid du Colombier 	memmove(p, np, n);
4860845620SDavid du Colombier 	return p + n;
4960845620SDavid du Colombier }
5060845620SDavid du Colombier 
5160845620SDavid du Colombier static uchar*
pstr(uchar * p,uchar * ep,char * np)5260845620SDavid du Colombier pstr(uchar *p, uchar *ep, char *np)
533e12c5d1SDavid du Colombier {
544f8f669cSDavid du Colombier 	return psym(p, ep, np);
553e12c5d1SDavid du Colombier }
563e12c5d1SDavid du Colombier 
573e12c5d1SDavid du Colombier static uchar*
pbytes(uchar * p,uchar * ep,uchar * np,int n)587dd7cddfSDavid du Colombier pbytes(uchar *p, uchar *ep, uchar *np, int n)
593e12c5d1SDavid du Colombier {
607dd7cddfSDavid du Colombier 	if(ep - p < n)
617dd7cddfSDavid du Colombier 		return ep+1;
62e8ece30eSDavid du Colombier 	memmove(p, np, n);
637dd7cddfSDavid du Colombier 	return p + n;
643e12c5d1SDavid du Colombier }
657dd7cddfSDavid du Colombier 
667dd7cddfSDavid du Colombier static uchar*
puchar(uchar * p,uchar * ep,int val)677dd7cddfSDavid du Colombier puchar(uchar *p, uchar *ep, int val)
687dd7cddfSDavid du Colombier {
697dd7cddfSDavid du Colombier 	if(ep - p < 1)
707dd7cddfSDavid du Colombier 		return ep+1;
717dd7cddfSDavid du Colombier 	*p++ = val;
727dd7cddfSDavid du Colombier 	return p;
737dd7cddfSDavid du Colombier }
747dd7cddfSDavid du Colombier 
757dd7cddfSDavid du Colombier static uchar*
pushort(uchar * p,uchar * ep,int val)767dd7cddfSDavid du Colombier pushort(uchar *p, uchar *ep, int val)
777dd7cddfSDavid du Colombier {
787dd7cddfSDavid du Colombier 	if(ep - p < 2)
797dd7cddfSDavid du Colombier 		return ep+1;
803e12c5d1SDavid du Colombier 	*p++ = val>>8;
813e12c5d1SDavid du Colombier 	*p++ = val;
823e12c5d1SDavid du Colombier 	return p;
833e12c5d1SDavid du Colombier }
843e12c5d1SDavid du Colombier 
853e12c5d1SDavid du Colombier static uchar*
pulong(uchar * p,uchar * ep,int val)867dd7cddfSDavid du Colombier pulong(uchar *p, uchar *ep, int val)
873e12c5d1SDavid du Colombier {
887dd7cddfSDavid du Colombier 	if(ep - p < 4)
897dd7cddfSDavid du Colombier 		return ep+1;
903e12c5d1SDavid du Colombier 	*p++ = val>>24;
913e12c5d1SDavid du Colombier 	*p++ = val>>16;
923e12c5d1SDavid du Colombier 	*p++ = val>>8;
933e12c5d1SDavid du Colombier 	*p++ = val;
943e12c5d1SDavid du Colombier 	return p;
953e12c5d1SDavid du Colombier }
963e12c5d1SDavid du Colombier 
973e12c5d1SDavid du Colombier static uchar*
pv4addr(uchar * p,uchar * ep,char * name)985d459b5aSDavid du Colombier pv4addr(uchar *p, uchar *ep, char *name)
993e12c5d1SDavid du Colombier {
1007dd7cddfSDavid du Colombier 	uchar ip[IPaddrlen];
1017dd7cddfSDavid du Colombier 
1027dd7cddfSDavid du Colombier 	if(ep - p < 4)
1037dd7cddfSDavid du Colombier 		return ep+1;
1047dd7cddfSDavid du Colombier 	parseip(ip, name);
1057dd7cddfSDavid du Colombier 	v6tov4(p, ip);
1063e12c5d1SDavid du Colombier 	return p + 4;
1073e12c5d1SDavid du Colombier }
1083e12c5d1SDavid du Colombier 
1093e12c5d1SDavid du Colombier static uchar*
pv6addr(uchar * p,uchar * ep,char * name)1105d459b5aSDavid du Colombier pv6addr(uchar *p, uchar *ep, char *name)
1115d459b5aSDavid du Colombier {
1125d459b5aSDavid du Colombier 	if(ep - p < IPaddrlen)
1135d459b5aSDavid du Colombier 		return ep+1;
1145d459b5aSDavid du Colombier 	parseip(p, name);
1155d459b5aSDavid du Colombier 	return p + IPaddrlen;
1165d459b5aSDavid du Colombier }
1175d459b5aSDavid du Colombier 
1185d459b5aSDavid du Colombier static uchar*
pname(uchar * p,uchar * ep,char * np,Dict * dp)1197dd7cddfSDavid du Colombier pname(uchar *p, uchar *ep, char *np, Dict *dp)
1203e12c5d1SDavid du Colombier {
1216b0d5c8bSDavid du Colombier 	int i;
1224f8f669cSDavid du Colombier 	char *cp;
1233e12c5d1SDavid du Colombier 	char *last;		/* last component packed */
1243e12c5d1SDavid du Colombier 
1257dd7cddfSDavid du Colombier 	if(strlen(np) >= Domlen) /* make sure we don't exceed DNS limits */
1267dd7cddfSDavid du Colombier 		return ep+1;
1273e12c5d1SDavid du Colombier 
1283e12c5d1SDavid du Colombier 	last = 0;
1293e12c5d1SDavid du Colombier 	while(*np){
1303e12c5d1SDavid du Colombier 		/* look through every component in the dictionary for a match */
1314f8f669cSDavid du Colombier 		for(i = 0; i < dp->n; i++)
1323e12c5d1SDavid du Colombier 			if(strcmp(np, dp->x[i].name) == 0){
1337dd7cddfSDavid du Colombier 				if(ep - p < 2)
1347dd7cddfSDavid du Colombier 					return ep+1;
1355d34ce99SDavid du Colombier 				if ((dp->x[i].offset>>8) & 0xc0)
1365d34ce99SDavid du Colombier 					dnslog("convDNS2M: offset too big for "
1375d34ce99SDavid du Colombier 						"DNS packet format");
1385d34ce99SDavid du Colombier 				*p++ = dp->x[i].offset>>8 | 0xc0;
1393e12c5d1SDavid du Colombier 				*p++ = dp->x[i].offset;
1403e12c5d1SDavid du Colombier 				return p;
1413e12c5d1SDavid du Colombier 			}
1423e12c5d1SDavid du Colombier 
1433e12c5d1SDavid du Colombier 		/* if there's room, enter this name in dictionary */
1444f8f669cSDavid du Colombier 		if(dp->n < Ndict)
1453e12c5d1SDavid du Colombier 			if(last){
1463e12c5d1SDavid du Colombier 				/* the whole name is already in dp->buf */
1473e12c5d1SDavid du Colombier 				last = strchr(last, '.') + 1;
1483e12c5d1SDavid du Colombier 				dp->x[dp->n].name = last;
1493e12c5d1SDavid du Colombier 				dp->x[dp->n].offset = p - dp->start;
1503e12c5d1SDavid du Colombier 				dp->n++;
1513e12c5d1SDavid du Colombier 			} else {
1523e12c5d1SDavid du Colombier 				/* add to dp->buf */
1533e12c5d1SDavid du Colombier 				i = strlen(np);
1544f8f669cSDavid du Colombier 				if(dp->ep + i + 1 < &dp->buf[sizeof dp->buf]){
1553e12c5d1SDavid du Colombier 					strcpy(dp->ep, np);
1563e12c5d1SDavid du Colombier 					dp->x[dp->n].name = dp->ep;
1573e12c5d1SDavid du Colombier 					last = dp->ep;
1583e12c5d1SDavid du Colombier 					dp->x[dp->n].offset = p - dp->start;
1593e12c5d1SDavid du Colombier 					dp->ep += i + 1;
1603e12c5d1SDavid du Colombier 					dp->n++;
1613e12c5d1SDavid du Colombier 				}
1623e12c5d1SDavid du Colombier 			}
1633e12c5d1SDavid du Colombier 
1643e12c5d1SDavid du Colombier 		/* put next component into message */
1653e12c5d1SDavid du Colombier 		cp = strchr(np, '.');
1664f8f669cSDavid du Colombier 		if(cp == nil){
1673e12c5d1SDavid du Colombier 			i = strlen(np);
1683e12c5d1SDavid du Colombier 			cp = np + i;	/* point to null terminator */
1693e12c5d1SDavid du Colombier 		} else {
1703e12c5d1SDavid du Colombier 			i = cp - np;
1713e12c5d1SDavid du Colombier 			cp++;		/* point past '.' */
1723e12c5d1SDavid du Colombier 		}
1737dd7cddfSDavid du Colombier 		if(ep-p < i+1)
1747dd7cddfSDavid du Colombier 			return ep+1;
17576783259SDavid du Colombier 		if (i > Labellen)
17676783259SDavid du Colombier 			return ep+1;
1773e12c5d1SDavid du Colombier 		*p++ = i;		/* count of chars in label */
178e8ece30eSDavid du Colombier 		memmove(p, np, i);
1793e12c5d1SDavid du Colombier 		np = cp;
1803e12c5d1SDavid du Colombier 		p += i;
1813e12c5d1SDavid du Colombier 	}
1827dd7cddfSDavid du Colombier 
1837dd7cddfSDavid du Colombier 	if(p >= ep)
1847dd7cddfSDavid du Colombier 		return ep+1;
1853e12c5d1SDavid du Colombier 	*p++ = 0;	/* add top level domain */
1863e12c5d1SDavid du Colombier 
1873e12c5d1SDavid du Colombier 	return p;
1883e12c5d1SDavid du Colombier }
1893e12c5d1SDavid du Colombier 
1903e12c5d1SDavid du Colombier static uchar*
convRR2M(RR * rp,uchar * p,uchar * ep,Dict * dp)1917dd7cddfSDavid du Colombier convRR2M(RR *rp, uchar *p, uchar *ep, Dict *dp)
1923e12c5d1SDavid du Colombier {
1933e12c5d1SDavid du Colombier 	uchar *lp, *data;
1947dd7cddfSDavid du Colombier 	int len, ttl;
19560845620SDavid du Colombier 	Txt *t;
1963e12c5d1SDavid du Colombier 
1973e12c5d1SDavid du Colombier 	NAME(rp->owner->name);
1983e12c5d1SDavid du Colombier 	USHORT(rp->type);
1993e12c5d1SDavid du Colombier 	USHORT(rp->owner->class);
2007dd7cddfSDavid du Colombier 
2017dd7cddfSDavid du Colombier 	/* egregious overuse of ttl (it's absolute time in the cache) */
2027dd7cddfSDavid du Colombier 	if(rp->db)
2037dd7cddfSDavid du Colombier 		ttl = rp->ttl;
2047dd7cddfSDavid du Colombier 	else
2057dd7cddfSDavid du Colombier 		ttl = rp->ttl - now;
2067dd7cddfSDavid du Colombier 	if(ttl < 0)
2077dd7cddfSDavid du Colombier 		ttl = 0;
2087dd7cddfSDavid du Colombier 	ULONG(ttl);
2097dd7cddfSDavid du Colombier 
2103e12c5d1SDavid du Colombier 	lp = p;			/* leave room for the rdata length */
2113e12c5d1SDavid du Colombier 	p += 2;
2123e12c5d1SDavid du Colombier 	data = p;
2137dd7cddfSDavid du Colombier 
2147dd7cddfSDavid du Colombier 	if(data >= ep)
2157dd7cddfSDavid du Colombier 		return p+1;
2167dd7cddfSDavid du Colombier 
2173e12c5d1SDavid du Colombier 	switch(rp->type){
2183e12c5d1SDavid du Colombier 	case Thinfo:
21960845620SDavid du Colombier 		SYMBOL(rp->cpu->name);
22060845620SDavid du Colombier 		SYMBOL(rp->os->name);
2213e12c5d1SDavid du Colombier 		break;
2223e12c5d1SDavid du Colombier 	case Tcname:
2233e12c5d1SDavid du Colombier 	case Tmb:
2243e12c5d1SDavid du Colombier 	case Tmd:
2253e12c5d1SDavid du Colombier 	case Tmf:
2263e12c5d1SDavid du Colombier 	case Tns:
2273e12c5d1SDavid du Colombier 		NAME(rp->host->name);
2283e12c5d1SDavid du Colombier 		break;
2293e12c5d1SDavid du Colombier 	case Tmg:
2303e12c5d1SDavid du Colombier 	case Tmr:
2313e12c5d1SDavid du Colombier 		NAME(rp->mb->name);
2323e12c5d1SDavid du Colombier 		break;
2333e12c5d1SDavid du Colombier 	case Tminfo:
2343e12c5d1SDavid du Colombier 		NAME(rp->rmb->name);
2353e12c5d1SDavid du Colombier 		NAME(rp->mb->name);
2363e12c5d1SDavid du Colombier 		break;
2373e12c5d1SDavid du Colombier 	case Tmx:
2383e12c5d1SDavid du Colombier 		USHORT(rp->pref);
2393e12c5d1SDavid du Colombier 		NAME(rp->host->name);
2403e12c5d1SDavid du Colombier 		break;
2413e12c5d1SDavid du Colombier 	case Ta:
2425d459b5aSDavid du Colombier 		V4ADDR(rp->ip->name);
2435d459b5aSDavid du Colombier 		break;
2445d459b5aSDavid du Colombier 	case Taaaa:
2455d459b5aSDavid du Colombier 		V6ADDR(rp->ip->name);
2463e12c5d1SDavid du Colombier 		break;
2473e12c5d1SDavid du Colombier 	case Tptr:
2483e12c5d1SDavid du Colombier 		NAME(rp->ptr->name);
2493e12c5d1SDavid du Colombier 		break;
2503e12c5d1SDavid du Colombier 	case Tsoa:
2513e12c5d1SDavid du Colombier 		NAME(rp->host->name);
2523e12c5d1SDavid du Colombier 		NAME(rp->rmb->name);
2533e12c5d1SDavid du Colombier 		ULONG(rp->soa->serial);
2543e12c5d1SDavid du Colombier 		ULONG(rp->soa->refresh);
2553e12c5d1SDavid du Colombier 		ULONG(rp->soa->retry);
2563e12c5d1SDavid du Colombier 		ULONG(rp->soa->expire);
2573e12c5d1SDavid du Colombier 		ULONG(rp->soa->minttl);
2583e12c5d1SDavid du Colombier 		break;
2594f8f669cSDavid du Colombier 	case Tsrv:
2604f8f669cSDavid du Colombier 		USHORT(rp->srv->pri);
2614f8f669cSDavid du Colombier 		USHORT(rp->srv->weight);
262*225077b0SDavid du Colombier 		USHORT(rp->port);
263*225077b0SDavid du Colombier 		STRING(rp->host->name);	/* rfc2782 sez no name compression */
2644f8f669cSDavid du Colombier 		break;
2657dd7cddfSDavid du Colombier 	case Ttxt:
26660845620SDavid du Colombier 		for(t = rp->txt; t != nil; t = t->next)
26760845620SDavid du Colombier 			STRING(t->p);
2687dd7cddfSDavid du Colombier 		break;
2699a747e4fSDavid du Colombier 	case Tnull:
2709a747e4fSDavid du Colombier 		BYTES(rp->null->data, rp->null->dlen);
2719a747e4fSDavid du Colombier 		break;
2727dd7cddfSDavid du Colombier 	case Trp:
2737dd7cddfSDavid du Colombier 		NAME(rp->rmb->name);
27460845620SDavid du Colombier 		NAME(rp->rp->name);
2757dd7cddfSDavid du Colombier 		break;
2767dd7cddfSDavid du Colombier 	case Tkey:
2777dd7cddfSDavid du Colombier 		USHORT(rp->key->flags);
2787dd7cddfSDavid du Colombier 		UCHAR(rp->key->proto);
2797dd7cddfSDavid du Colombier 		UCHAR(rp->key->alg);
2807dd7cddfSDavid du Colombier 		BYTES(rp->key->data, rp->key->dlen);
2817dd7cddfSDavid du Colombier 		break;
2827dd7cddfSDavid du Colombier 	case Tsig:
2837dd7cddfSDavid du Colombier 		USHORT(rp->sig->type);
2847dd7cddfSDavid du Colombier 		UCHAR(rp->sig->alg);
2857dd7cddfSDavid du Colombier 		UCHAR(rp->sig->labels);
2867dd7cddfSDavid du Colombier 		ULONG(rp->sig->ttl);
2877dd7cddfSDavid du Colombier 		ULONG(rp->sig->exp);
2887dd7cddfSDavid du Colombier 		ULONG(rp->sig->incep);
2897dd7cddfSDavid du Colombier 		USHORT(rp->sig->tag);
2907dd7cddfSDavid du Colombier 		NAME(rp->sig->signer->name);
2917dd7cddfSDavid du Colombier 		BYTES(rp->sig->data, rp->sig->dlen);
2927dd7cddfSDavid du Colombier 		break;
2937dd7cddfSDavid du Colombier 	case Tcert:
2947dd7cddfSDavid du Colombier 		USHORT(rp->cert->type);
2957dd7cddfSDavid du Colombier 		USHORT(rp->cert->tag);
2967dd7cddfSDavid du Colombier 		UCHAR(rp->cert->alg);
2977dd7cddfSDavid du Colombier 		BYTES(rp->cert->data, rp->cert->dlen);
2987dd7cddfSDavid du Colombier 		break;
2993e12c5d1SDavid du Colombier 	}
3003e12c5d1SDavid du Colombier 
3013e12c5d1SDavid du Colombier 	/* stuff in the rdata section length */
3023e12c5d1SDavid du Colombier 	len = p - data;
3033e12c5d1SDavid du Colombier 	*lp++ = len >> 8;
3043e12c5d1SDavid du Colombier 	*lp = len;
3053e12c5d1SDavid du Colombier 
3063e12c5d1SDavid du Colombier 	return p;
3073e12c5d1SDavid du Colombier }
3083e12c5d1SDavid du Colombier 
3093e12c5d1SDavid du Colombier static uchar*
convQ2M(RR * rp,uchar * p,uchar * ep,Dict * dp)3107dd7cddfSDavid du Colombier convQ2M(RR *rp, uchar *p, uchar *ep, Dict *dp)
3113e12c5d1SDavid du Colombier {
3123e12c5d1SDavid du Colombier 	NAME(rp->owner->name);
3133e12c5d1SDavid du Colombier 	USHORT(rp->type);
3143e12c5d1SDavid du Colombier 	USHORT(rp->owner->class);
3153e12c5d1SDavid du Colombier 	return p;
3163e12c5d1SDavid du Colombier }
3173e12c5d1SDavid du Colombier 
3183e12c5d1SDavid du Colombier static uchar*
rrloop(RR * rp,int * countp,uchar * p,uchar * ep,Dict * dp,int quest)3197dd7cddfSDavid du Colombier rrloop(RR *rp, int *countp, uchar *p, uchar *ep, Dict *dp, int quest)
3203e12c5d1SDavid du Colombier {
3213e12c5d1SDavid du Colombier 	uchar *np;
3223e12c5d1SDavid du Colombier 
3233e12c5d1SDavid du Colombier 	*countp = 0;
3247dd7cddfSDavid du Colombier 	for(; rp && p < ep; rp = rp->next){
3253e12c5d1SDavid du Colombier 		if(quest)
3267dd7cddfSDavid du Colombier 			np = convQ2M(rp, p, ep, dp);
3273e12c5d1SDavid du Colombier 		else
3287dd7cddfSDavid du Colombier 			np = convRR2M(rp, p, ep, dp);
3297dd7cddfSDavid du Colombier 		if(np > ep)
3303e12c5d1SDavid du Colombier 			break;
3313e12c5d1SDavid du Colombier 		p = np;
3323e12c5d1SDavid du Colombier 		(*countp)++;
3333e12c5d1SDavid du Colombier 	}
3343e12c5d1SDavid du Colombier 	return p;
3353e12c5d1SDavid du Colombier }
3363e12c5d1SDavid du Colombier 
3373e12c5d1SDavid du Colombier /*
3383e12c5d1SDavid du Colombier  *  convert into a message
3393e12c5d1SDavid du Colombier  */
3403e12c5d1SDavid du Colombier int
convDNS2M(DNSmsg * m,uchar * buf,int len)3413e12c5d1SDavid du Colombier convDNS2M(DNSmsg *m, uchar *buf, int len)
3423e12c5d1SDavid du Colombier {
343d6d99297SDavid du Colombier 	ulong trunc = 0;
3443e12c5d1SDavid du Colombier 	uchar *p, *ep, *np;
3453e12c5d1SDavid du Colombier 	Dict d;
3463e12c5d1SDavid du Colombier 
3473e12c5d1SDavid du Colombier 	d.n = 0;
3483e12c5d1SDavid du Colombier 	d.start = buf;
3493e12c5d1SDavid du Colombier 	d.ep = d.buf;
3503e12c5d1SDavid du Colombier 	memset(buf, 0, len);
3517dd7cddfSDavid du Colombier 	m->qdcount = m->ancount = m->nscount = m->arcount = 0;
3523e12c5d1SDavid du Colombier 
3533e12c5d1SDavid du Colombier 	/* first pack in the RR's so we can get real counts */
3543e12c5d1SDavid du Colombier 	p = buf + 12;
3553e12c5d1SDavid du Colombier 	ep = buf + len;
3567dd7cddfSDavid du Colombier 	p = rrloop(m->qd, &m->qdcount, p, ep, &d, 1);
3577dd7cddfSDavid du Colombier 	p = rrloop(m->an, &m->ancount, p, ep, &d, 0);
3587dd7cddfSDavid du Colombier 	p = rrloop(m->ns, &m->nscount, p, ep, &d, 0);
3597dd7cddfSDavid du Colombier 	p = rrloop(m->ar, &m->arcount, p, ep, &d, 0);
360d6d99297SDavid du Colombier 	if(p > ep) {
361d6d99297SDavid du Colombier 		trunc = Ftrunc;
362d6d99297SDavid du Colombier 		dnslog("udp packet full; truncating my reply");
363d6d99297SDavid du Colombier 		p = ep;
364d6d99297SDavid du Colombier 	}
3653e12c5d1SDavid du Colombier 
3663e12c5d1SDavid du Colombier 	/* now pack the rest */
3673e12c5d1SDavid du Colombier 	np = p;
3683e12c5d1SDavid du Colombier 	p = buf;
3693e12c5d1SDavid du Colombier 	ep = buf + len;
3703e12c5d1SDavid du Colombier 	USHORT(m->id);
371d6d99297SDavid du Colombier 	USHORT(m->flags | trunc);
3723e12c5d1SDavid du Colombier 	USHORT(m->qdcount);
3733e12c5d1SDavid du Colombier 	USHORT(m->ancount);
3743e12c5d1SDavid du Colombier 	USHORT(m->nscount);
3753e12c5d1SDavid du Colombier 	USHORT(m->arcount);
376d6d99297SDavid du Colombier 	USED(p);
3773e12c5d1SDavid du Colombier 	return np - buf;
3783e12c5d1SDavid du Colombier }
379