xref: /csrg-svn/lib/libc/net/res_comp.c (revision 18140)
1*18140Sralph #ifndef lint
2*18140Sralph static char sccsid[] = "@(#)res_comp.c	4.1 (Berkeley) 03/01/85";
3*18140Sralph #endif
4*18140Sralph 
5*18140Sralph #include <sys/types.h>
6*18140Sralph #include <stdio.h>
7*18140Sralph #include <ctype.h>
8*18140Sralph #include <nameser.h>
9*18140Sralph 
10*18140Sralph 
11*18140Sralph /*
12*18140Sralph  * Expand compressed domain name format to full domain name.
13*18140Sralph  * Return size of compressed name or -1 if there was an error.
14*18140Sralph  */
15*18140Sralph dn_expand(msg, comp_dn, exp_dn, length)
16*18140Sralph 	char *msg, *comp_dn, *exp_dn;
17*18140Sralph 	int length;
18*18140Sralph {
19*18140Sralph 	register char *cp, *dn;
20*18140Sralph 	register int n, c;
21*18140Sralph 	char *eom;
22*18140Sralph 	int len = 0;
23*18140Sralph 
24*18140Sralph 	dn = exp_dn;
25*18140Sralph 	cp = comp_dn;
26*18140Sralph 	eom = exp_dn + length - 1;
27*18140Sralph 	/*
28*18140Sralph 	 * fetch next label in domain name
29*18140Sralph 	 */
30*18140Sralph 	while (n = *cp++) {
31*18140Sralph 		/*
32*18140Sralph 		 * Check for indirection
33*18140Sralph 		 */
34*18140Sralph 		switch (n & INDIR_MASK) {
35*18140Sralph 		case 0:
36*18140Sralph 			if (dn != exp_dn)
37*18140Sralph 				*dn++ = '.';
38*18140Sralph 			if (dn+n >= eom)
39*18140Sralph 				return (-1);
40*18140Sralph 			while (--n >= 0)
41*18140Sralph 				if (islower(c = *cp++))
42*18140Sralph 					*dn++ = toupper(c);
43*18140Sralph 				else
44*18140Sralph 					*dn++ = c;
45*18140Sralph 			break;
46*18140Sralph 
47*18140Sralph 		case INDIR_MASK:
48*18140Sralph 			if (len == 0)
49*18140Sralph 				len = cp - comp_dn + 1;
50*18140Sralph 			cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
51*18140Sralph 			break;
52*18140Sralph 
53*18140Sralph 		default:
54*18140Sralph 			return (-1);			/* flag error */
55*18140Sralph 		}
56*18140Sralph 	}
57*18140Sralph 	*dn = '\0';
58*18140Sralph 	if (len == 0)
59*18140Sralph 		len = cp - comp_dn;
60*18140Sralph 	return (len);
61*18140Sralph }
62*18140Sralph 
63*18140Sralph /*
64*18140Sralph  * Compress domain name. Return the size of the compressed name or -1.
65*18140Sralph  * Dnptrs is a list of pointers to previous compressed names. dnptrs[0]
66*18140Sralph  * is a pointer to the beginning of the message. The list ends with NULL.
67*18140Sralph  */
68*18140Sralph dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
69*18140Sralph 	char *exp_dn, *comp_dn;
70*18140Sralph 	int length;
71*18140Sralph 	char **dnptrs, **lastdnptr;
72*18140Sralph {
73*18140Sralph 	register char *cp, *dn;
74*18140Sralph 	register int c, l;
75*18140Sralph 	char **cpp, **lpp, *sp, *eob;
76*18140Sralph 	char *msg;
77*18140Sralph 
78*18140Sralph 	dn = exp_dn;
79*18140Sralph 	cp = comp_dn;
80*18140Sralph 	eob = comp_dn + length;
81*18140Sralph 	if (dnptrs != NULL) {
82*18140Sralph 		if ((msg = *dnptrs++) != NULL) {
83*18140Sralph 			for (cpp = dnptrs; *cpp != NULL; cpp++)
84*18140Sralph 				;
85*18140Sralph 			lpp = cpp;	/* end of list to search */
86*18140Sralph 		}
87*18140Sralph 	} else
88*18140Sralph 		msg = NULL;
89*18140Sralph 	for (c = *dn++; c != '\0'; ) {
90*18140Sralph 		/* look to see if we can use pointers */
91*18140Sralph 		if (msg != NULL) {
92*18140Sralph 			if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
93*18140Sralph 				if (cp+1 >= eob)
94*18140Sralph 					return (-1);
95*18140Sralph 				*cp++ = (l >> 8) | INDIR_MASK;
96*18140Sralph 				*cp++ = l;
97*18140Sralph 				return (cp - comp_dn);
98*18140Sralph 			}
99*18140Sralph 			/* not found, save it */
100*18140Sralph 			if (lastdnptr != NULL && cpp < lastdnptr-1) {
101*18140Sralph 				*cpp++ = cp;
102*18140Sralph 				*cpp = NULL;
103*18140Sralph 			}
104*18140Sralph 		}
105*18140Sralph 		sp = cp++;	/* save ptr to length byte */
106*18140Sralph 		do {
107*18140Sralph 			if (c == '.') {
108*18140Sralph 				c = *dn++;
109*18140Sralph 				break;
110*18140Sralph 			}
111*18140Sralph 			if (cp >= eob)
112*18140Sralph 				return (-1);
113*18140Sralph 			*cp++ = c;
114*18140Sralph 		} while ((c = *dn++) != '\0');
115*18140Sralph 		if ((l = cp - sp - 1) <= 0 || l > MAXLABEL)
116*18140Sralph 			return (-1);
117*18140Sralph 		*sp = l;
118*18140Sralph 	}
119*18140Sralph 	if (cp >= eob)
120*18140Sralph 		return (-1);
121*18140Sralph 	*cp++ = '\0';
122*18140Sralph 	return (cp - comp_dn);
123*18140Sralph }
124*18140Sralph 
125*18140Sralph /*
126*18140Sralph  * Skip over a compressed domain name. Return the size.
127*18140Sralph  */
128*18140Sralph dn_skip(buf)
129*18140Sralph 	char *buf;
130*18140Sralph {
131*18140Sralph 	register char *cp;
132*18140Sralph 	register int n;
133*18140Sralph 
134*18140Sralph 	cp = buf;
135*18140Sralph 	while (n = *cp++) {
136*18140Sralph 		/*
137*18140Sralph 		 * check for indirection
138*18140Sralph 		 */
139*18140Sralph 		switch (n & INDIR_MASK) {
140*18140Sralph 		case 0:		/* normal case, n == len */
141*18140Sralph 			cp += n;
142*18140Sralph 			continue;
143*18140Sralph 		default:	/* illegal type */
144*18140Sralph 			return (-1);
145*18140Sralph 		case INDIR_MASK:	/* indirection */
146*18140Sralph 			cp++;
147*18140Sralph 		}
148*18140Sralph 		break;
149*18140Sralph 	}
150*18140Sralph 	return (cp - buf);
151*18140Sralph }
152*18140Sralph 
153*18140Sralph /*
154*18140Sralph  * Search for expanded name from a list of previously compressed names.
155*18140Sralph  * Return the offset from msg if found or -1.
156*18140Sralph  */
157*18140Sralph dn_find(exp_dn, msg, dnptrs, lastdnptr)
158*18140Sralph 	char *exp_dn, *msg;
159*18140Sralph 	char **dnptrs, **lastdnptr;
160*18140Sralph {
161*18140Sralph 	register char *dn, *cp, **cpp;
162*18140Sralph 	register int n;
163*18140Sralph 	char *sp;
164*18140Sralph 
165*18140Sralph 	for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
166*18140Sralph 		dn = exp_dn;
167*18140Sralph 		sp = cp = *cpp;
168*18140Sralph 		while (n = *cp++) {
169*18140Sralph 			/*
170*18140Sralph 			 * check for indirection
171*18140Sralph 			 */
172*18140Sralph 			switch (n & INDIR_MASK) {
173*18140Sralph 			case 0:		/* normal case, n == len */
174*18140Sralph 				while (--n >= 0)
175*18140Sralph 					if (*dn++ != *cp++)
176*18140Sralph 						goto next;
177*18140Sralph 				if ((n = *dn++) == '\0' && *cp == '\0')
178*18140Sralph 					return (sp - msg);
179*18140Sralph 				if (n == '.')
180*18140Sralph 					continue;
181*18140Sralph 				goto next;
182*18140Sralph 
183*18140Sralph 			default:	/* illegal type */
184*18140Sralph 				return (-1);
185*18140Sralph 
186*18140Sralph 			case INDIR_MASK:	/* indirection */
187*18140Sralph 				cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
188*18140Sralph 			}
189*18140Sralph 		}
190*18140Sralph 		if (*dn == '\0')
191*18140Sralph 			return (sp - msg);
192*18140Sralph 	next:	;
193*18140Sralph 	}
194*18140Sralph 	return (-1);
195*18140Sralph }
196