xref: /minix3/external/bsd/bind/dist/lib/dns/rdata/in_1/wks_11.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1 /*	$NetBSD: wks_11.c,v 1.6 2014/12/10 04:37:59 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2004, 2007, 2009, 2011-2014  Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (C) 1999-2002  Internet Software Consortium.
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /* Id */
21 
22 /* Reviewed: Fri Mar 17 15:01:49 PST 2000 by explorer */
23 
24 #ifndef RDATA_IN_1_WKS_11_C
25 #define RDATA_IN_1_WKS_11_C
26 
27 #include <limits.h>
28 #include <stdlib.h>
29 
30 #include <isc/net.h>
31 #include <isc/netdb.h>
32 #include <isc/once.h>
33 
34 #define RRTYPE_WKS_ATTRIBUTES (0)
35 
36 static isc_mutex_t wks_lock;
37 
init_lock(void)38 static void init_lock(void) {
39 	RUNTIME_CHECK(isc_mutex_init(&wks_lock) == ISC_R_SUCCESS);
40 }
41 
42 static isc_boolean_t
mygetprotobyname(const char * name,long * proto)43 mygetprotobyname(const char *name, long *proto) {
44 	struct protoent *pe;
45 
46 	LOCK(&wks_lock);
47 	pe = getprotobyname(name);
48 	if (pe != NULL)
49 		*proto = pe->p_proto;
50 	UNLOCK(&wks_lock);
51 	return (ISC_TF(pe != NULL));
52 }
53 
54 static isc_boolean_t
mygetservbyname(const char * name,const char * proto,long * port)55 mygetservbyname(const char *name, const char *proto, long *port) {
56 	struct servent *se;
57 
58 	LOCK(&wks_lock);
59 	se = getservbyname(name, proto);
60 	if (se != NULL)
61 		*port = ntohs(se->s_port);
62 	UNLOCK(&wks_lock);
63 	return (ISC_TF(se != NULL));
64 }
65 
66 static inline isc_result_t
fromtext_in_wks(ARGS_FROMTEXT)67 fromtext_in_wks(ARGS_FROMTEXT) {
68 	static isc_once_t once = ISC_ONCE_INIT;
69 	isc_token_t token;
70 	isc_region_t region;
71 	struct in_addr addr;
72 	char *e;
73 	long proto;
74 	unsigned char bm[8*1024]; /* 64k bits */
75 	long port;
76 	long maxport = -1;
77 	const char *ps = NULL;
78 	unsigned int n;
79 	char service[32];
80 	int i;
81 
82 	REQUIRE(type == 11);
83 	REQUIRE(rdclass == 1);
84 
85 	UNUSED(type);
86 	UNUSED(origin);
87 	UNUSED(options);
88 	UNUSED(rdclass);
89 
90 	RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS);
91 
92 	/*
93 	 * IPv4 dotted quad.
94 	 */
95 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
96 				      ISC_FALSE));
97 
98 	isc_buffer_availableregion(target, &region);
99 	if (getquad(DNS_AS_STR(token), &addr, lexer, callbacks) != 1)
100 		RETTOK(DNS_R_BADDOTTEDQUAD);
101 	if (region.length < 4)
102 		return (ISC_R_NOSPACE);
103 	memmove(region.base, &addr, 4);
104 	isc_buffer_add(target, 4);
105 
106 	/*
107 	 * Protocol.
108 	 */
109 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
110 				      ISC_FALSE));
111 
112 	proto = strtol(DNS_AS_STR(token), &e, 10);
113 	if (*e == 0)
114 		;
115 	else if (!mygetprotobyname(DNS_AS_STR(token), &proto))
116 		RETTOK(DNS_R_UNKNOWNPROTO);
117 
118 	if (proto < 0 || proto > 0xff)
119 		RETTOK(ISC_R_RANGE);
120 
121 	if (proto == IPPROTO_TCP)
122 		ps = "tcp";
123 	else if (proto == IPPROTO_UDP)
124 		ps = "udp";
125 
126 	RETERR(uint8_tobuffer(proto, target));
127 
128 	memset(bm, 0, sizeof(bm));
129 	do {
130 		RETERR(isc_lex_getmastertoken(lexer, &token,
131 					      isc_tokentype_string, ISC_TRUE));
132 		if (token.type != isc_tokentype_string)
133 			break;
134 
135 		/*
136 		 * Lowercase the service string as some getservbyname() are
137 		 * case sensitive and the database is usually in lowercase.
138 		 */
139 		strncpy(service, DNS_AS_STR(token), sizeof(service));
140 		service[sizeof(service)-1] = '\0';
141 		for (i = strlen(service) - 1; i >= 0; i--)
142 			if (isupper(service[i]&0xff))
143 				service[i] = tolower(service[i]&0xff);
144 
145 		port = strtol(DNS_AS_STR(token), &e, 10);
146 		if (*e == 0)
147 			;
148 		else if (!mygetservbyname(service, ps, &port) &&
149 			 !mygetservbyname(DNS_AS_STR(token), ps, &port))
150 			RETTOK(DNS_R_UNKNOWNSERVICE);
151 		if (port < 0 || port > 0xffff)
152 			RETTOK(ISC_R_RANGE);
153 		if (port > maxport)
154 			maxport = port;
155 		bm[port / 8] |= (0x80 >> (port % 8));
156 	} while (1);
157 
158 	/*
159 	 * Let upper layer handle eol/eof.
160 	 */
161 	isc_lex_ungettoken(lexer, &token);
162 
163 	n = (maxport + 8) / 8;
164 	return (mem_tobuffer(target, bm, n));
165 }
166 
167 static inline isc_result_t
totext_in_wks(ARGS_TOTEXT)168 totext_in_wks(ARGS_TOTEXT) {
169 	isc_region_t sr;
170 	unsigned short proto;
171 	char buf[sizeof("65535")];
172 	unsigned int i, j;
173 
174 	UNUSED(tctx);
175 
176 	REQUIRE(rdata->type == 11);
177 	REQUIRE(rdata->rdclass == 1);
178 	REQUIRE(rdata->length >= 5);
179 
180 	dns_rdata_toregion(rdata, &sr);
181 	RETERR(inet_totext(AF_INET, &sr, target));
182 	isc_region_consume(&sr, 4);
183 
184 	proto = uint8_fromregion(&sr);
185 	sprintf(buf, "%u", proto);
186 	RETERR(str_totext(" ", target));
187 	RETERR(str_totext(buf, target));
188 	isc_region_consume(&sr, 1);
189 
190 	INSIST(sr.length <= 8*1024);
191 	for (i = 0; i < sr.length; i++) {
192 		if (sr.base[i] != 0)
193 			for (j = 0; j < 8; j++)
194 				if ((sr.base[i] & (0x80 >> j)) != 0) {
195 					sprintf(buf, "%u", i * 8 + j);
196 					RETERR(str_totext(" ", target));
197 					RETERR(str_totext(buf, target));
198 				}
199 	}
200 
201 	return (ISC_R_SUCCESS);
202 }
203 
204 static inline isc_result_t
fromwire_in_wks(ARGS_FROMWIRE)205 fromwire_in_wks(ARGS_FROMWIRE) {
206 	isc_region_t sr;
207 	isc_region_t tr;
208 
209 	REQUIRE(type == 11);
210 	REQUIRE(rdclass == 1);
211 
212 	UNUSED(type);
213 	UNUSED(dctx);
214 	UNUSED(options);
215 	UNUSED(rdclass);
216 
217 	isc_buffer_activeregion(source, &sr);
218 	isc_buffer_availableregion(target, &tr);
219 
220 	if (sr.length < 5)
221 		return (ISC_R_UNEXPECTEDEND);
222 	if (sr.length > 8 * 1024 + 5)
223 		return (DNS_R_EXTRADATA);
224 	if (tr.length < sr.length)
225 		return (ISC_R_NOSPACE);
226 
227 	memmove(tr.base, sr.base, sr.length);
228 	isc_buffer_add(target, sr.length);
229 	isc_buffer_forward(source, sr.length);
230 
231 	return (ISC_R_SUCCESS);
232 }
233 
234 static inline isc_result_t
towire_in_wks(ARGS_TOWIRE)235 towire_in_wks(ARGS_TOWIRE) {
236 	isc_region_t sr;
237 
238 	UNUSED(cctx);
239 
240 	REQUIRE(rdata->type == 11);
241 	REQUIRE(rdata->rdclass == 1);
242 	REQUIRE(rdata->length != 0);
243 
244 	dns_rdata_toregion(rdata, &sr);
245 	return (mem_tobuffer(target, sr.base, sr.length));
246 }
247 
248 static inline int
compare_in_wks(ARGS_COMPARE)249 compare_in_wks(ARGS_COMPARE) {
250 	isc_region_t r1;
251 	isc_region_t r2;
252 
253 	REQUIRE(rdata1->type == rdata2->type);
254 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
255 	REQUIRE(rdata1->type == 11);
256 	REQUIRE(rdata1->rdclass == 1);
257 	REQUIRE(rdata1->length != 0);
258 	REQUIRE(rdata2->length != 0);
259 
260 	dns_rdata_toregion(rdata1, &r1);
261 	dns_rdata_toregion(rdata2, &r2);
262 	return (isc_region_compare(&r1, &r2));
263 }
264 
265 static inline isc_result_t
fromstruct_in_wks(ARGS_FROMSTRUCT)266 fromstruct_in_wks(ARGS_FROMSTRUCT) {
267 	dns_rdata_in_wks_t *wks = source;
268 	isc_uint32_t a;
269 
270 	REQUIRE(type == 11);
271 	REQUIRE(rdclass == 1);
272 	REQUIRE(source != NULL);
273 	REQUIRE(wks->common.rdtype == type);
274 	REQUIRE(wks->common.rdclass == rdclass);
275 	REQUIRE((wks->map != NULL && wks->map_len <= 8*1024) ||
276 		 wks->map_len == 0);
277 
278 	UNUSED(type);
279 	UNUSED(rdclass);
280 
281 	a = ntohl(wks->in_addr.s_addr);
282 	RETERR(uint32_tobuffer(a, target));
283 	RETERR(uint8_tobuffer(wks->protocol, target));
284 	return (mem_tobuffer(target, wks->map, wks->map_len));
285 }
286 
287 static inline isc_result_t
tostruct_in_wks(ARGS_TOSTRUCT)288 tostruct_in_wks(ARGS_TOSTRUCT) {
289 	dns_rdata_in_wks_t *wks = target;
290 	isc_uint32_t n;
291 	isc_region_t region;
292 
293 	REQUIRE(rdata->type == 11);
294 	REQUIRE(rdata->rdclass == 1);
295 	REQUIRE(rdata->length != 0);
296 
297 	wks->common.rdclass = rdata->rdclass;
298 	wks->common.rdtype = rdata->type;
299 	ISC_LINK_INIT(&wks->common, link);
300 
301 	dns_rdata_toregion(rdata, &region);
302 	n = uint32_fromregion(&region);
303 	wks->in_addr.s_addr = htonl(n);
304 	isc_region_consume(&region, 4);
305 	wks->protocol = uint8_fromregion(&region);
306 	isc_region_consume(&region, 1);
307 	wks->map_len = region.length;
308 	wks->map = mem_maybedup(mctx, region.base, region.length);
309 	if (wks->map == NULL)
310 		return (ISC_R_NOMEMORY);
311 	wks->mctx = mctx;
312 	return (ISC_R_SUCCESS);
313 }
314 
315 static inline void
freestruct_in_wks(ARGS_FREESTRUCT)316 freestruct_in_wks(ARGS_FREESTRUCT) {
317 	dns_rdata_in_wks_t *wks = source;
318 
319 	REQUIRE(source != NULL);
320 	REQUIRE(wks->common.rdtype == 11);
321 	REQUIRE(wks->common.rdclass == 1);
322 
323 	if (wks->mctx == NULL)
324 		return;
325 
326 	if (wks->map != NULL)
327 		isc_mem_free(wks->mctx, wks->map);
328 	wks->mctx = NULL;
329 }
330 
331 static inline isc_result_t
additionaldata_in_wks(ARGS_ADDLDATA)332 additionaldata_in_wks(ARGS_ADDLDATA) {
333 	UNUSED(rdata);
334 	UNUSED(add);
335 	UNUSED(arg);
336 
337 	REQUIRE(rdata->type == 11);
338 	REQUIRE(rdata->rdclass == 1);
339 
340 	return (ISC_R_SUCCESS);
341 }
342 
343 static inline isc_result_t
digest_in_wks(ARGS_DIGEST)344 digest_in_wks(ARGS_DIGEST) {
345 	isc_region_t r;
346 
347 	REQUIRE(rdata->type == 11);
348 	REQUIRE(rdata->rdclass == 1);
349 
350 	dns_rdata_toregion(rdata, &r);
351 
352 	return ((digest)(arg, &r));
353 }
354 
355 static inline isc_boolean_t
checkowner_in_wks(ARGS_CHECKOWNER)356 checkowner_in_wks(ARGS_CHECKOWNER) {
357 
358 	REQUIRE(type == 11);
359 	REQUIRE(rdclass == 1);
360 
361 	UNUSED(type);
362 	UNUSED(rdclass);
363 
364 	return (dns_name_ishostname(name, wildcard));
365 }
366 
367 static inline isc_boolean_t
checknames_in_wks(ARGS_CHECKNAMES)368 checknames_in_wks(ARGS_CHECKNAMES) {
369 
370 	REQUIRE(rdata->type == 11);
371 	REQUIRE(rdata->rdclass == 1);
372 
373 	UNUSED(rdata);
374 	UNUSED(owner);
375 	UNUSED(bad);
376 
377 	return (ISC_TRUE);
378 }
379 
380 static inline int
casecompare_in_wks(ARGS_COMPARE)381 casecompare_in_wks(ARGS_COMPARE) {
382 	return (compare_in_wks(rdata1, rdata2));
383 }
384 
385 #endif	/* RDATA_IN_1_WKS_11_C */
386