dns_nw.c revision 1.1.1.2 1 1.1 christos /* $NetBSD: dns_nw.c,v 1.1.1.2 2012/09/09 16:07:52 christos Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5 1.1 christos * Copyright (c) 1996-1999 by Internet Software Consortium.
6 1.1 christos *
7 1.1 christos * Permission to use, copy, modify, and distribute this software for any
8 1.1 christos * purpose with or without fee is hereby granted, provided that the above
9 1.1 christos * copyright notice and this permission notice appear in all copies.
10 1.1 christos *
11 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 1.1 christos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 1.1 christos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
14 1.1 christos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 1.1 christos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 1.1 christos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 1.1 christos * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 1.1 christos */
19 1.1 christos
20 1.1 christos #if defined(LIBC_SCCS) && !defined(lint)
21 1.1.1.2 christos static const char rcsid[] = "Id: dns_nw.c,v 1.12 2005/04/27 04:56:22 sra Exp ";
22 1.1 christos #endif /* LIBC_SCCS and not lint */
23 1.1 christos
24 1.1 christos /* Imports. */
25 1.1 christos
26 1.1 christos #include "port_before.h"
27 1.1 christos
28 1.1 christos #include <sys/param.h>
29 1.1 christos #include <sys/socket.h>
30 1.1 christos
31 1.1 christos #include <netinet/in.h>
32 1.1 christos #include <arpa/inet.h>
33 1.1 christos #include <arpa/nameser.h>
34 1.1 christos
35 1.1 christos #include <ctype.h>
36 1.1 christos #include <errno.h>
37 1.1 christos #include <netdb.h>
38 1.1 christos #include <resolv.h>
39 1.1 christos #include <stdio.h>
40 1.1 christos #include <stdlib.h>
41 1.1 christos #include <string.h>
42 1.1 christos
43 1.1 christos #include <isc/memcluster.h>
44 1.1 christos #include <irs.h>
45 1.1 christos
46 1.1 christos #include "port_after.h"
47 1.1 christos
48 1.1 christos #include "irs_p.h"
49 1.1 christos #include "dns_p.h"
50 1.1 christos
51 1.1 christos #ifdef SPRINTF_CHAR
52 1.1 christos # define SPRINTF(x) strlen(sprintf/**/x)
53 1.1 christos #else
54 1.1 christos # define SPRINTF(x) sprintf x
55 1.1 christos #endif
56 1.1 christos
57 1.1 christos /* Definitions. */
58 1.1 christos
59 1.1 christos #define MAXALIASES 35
60 1.1 christos
61 1.1 christos #define MAXPACKET (64*1024)
62 1.1 christos
63 1.1 christos struct pvt {
64 1.1 christos struct nwent net;
65 1.1 christos char * ali[MAXALIASES];
66 1.1 christos char buf[BUFSIZ+1];
67 1.1 christos struct __res_state * res;
68 1.1 christos void (*free_res)(void *);
69 1.1 christos };
70 1.1 christos
71 1.1 christos typedef union {
72 1.1 christos long al;
73 1.1 christos char ac;
74 1.1 christos } align;
75 1.1 christos
76 1.1 christos enum by_what { by_addr, by_name };
77 1.1 christos
78 1.1 christos /* Forwards. */
79 1.1 christos
80 1.1 christos static void nw_close(struct irs_nw *);
81 1.1 christos static struct nwent * nw_byname(struct irs_nw *, const char *, int);
82 1.1 christos static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int);
83 1.1 christos static struct nwent * nw_next(struct irs_nw *);
84 1.1 christos static void nw_rewind(struct irs_nw *);
85 1.1 christos static void nw_minimize(struct irs_nw *);
86 1.1 christos static struct __res_state * nw_res_get(struct irs_nw *this);
87 1.1 christos static void nw_res_set(struct irs_nw *this,
88 1.1 christos struct __res_state *res,
89 1.1 christos void (*free_res)(void *));
90 1.1 christos
91 1.1 christos static struct nwent * get1101byaddr(struct irs_nw *, u_char *, int);
92 1.1 christos static struct nwent * get1101byname(struct irs_nw *, const char *);
93 1.1 christos static struct nwent * get1101answer(struct irs_nw *,
94 1.1 christos u_char *ansbuf, int anslen,
95 1.1 christos enum by_what by_what,
96 1.1 christos int af, const char *name,
97 1.1 christos const u_char *addr, int addrlen);
98 1.1 christos static struct nwent * get1101mask(struct irs_nw *this, struct nwent *);
99 1.1 christos static int make1101inaddr(const u_char *, int, char *, int);
100 1.1 christos static void normalize_name(char *name);
101 1.1 christos static int init(struct irs_nw *this);
102 1.1 christos
103 1.1 christos /* Exports. */
104 1.1 christos
105 1.1 christos struct irs_nw *
106 1.1 christos irs_dns_nw(struct irs_acc *this) {
107 1.1 christos struct irs_nw *nw;
108 1.1 christos struct pvt *pvt;
109 1.1 christos
110 1.1 christos UNUSED(this);
111 1.1 christos
112 1.1 christos if (!(pvt = memget(sizeof *pvt))) {
113 1.1 christos errno = ENOMEM;
114 1.1 christos return (NULL);
115 1.1 christos }
116 1.1 christos memset(pvt, 0, sizeof *pvt);
117 1.1 christos if (!(nw = memget(sizeof *nw))) {
118 1.1 christos memput(pvt, sizeof *pvt);
119 1.1 christos errno = ENOMEM;
120 1.1 christos return (NULL);
121 1.1 christos }
122 1.1 christos memset(nw, 0x5e, sizeof *nw);
123 1.1 christos nw->private = pvt;
124 1.1 christos nw->close = nw_close;
125 1.1 christos nw->byname = nw_byname;
126 1.1 christos nw->byaddr = nw_byaddr;
127 1.1 christos nw->next = nw_next;
128 1.1 christos nw->rewind = nw_rewind;
129 1.1 christos nw->minimize = nw_minimize;
130 1.1 christos nw->res_get = nw_res_get;
131 1.1 christos nw->res_set = nw_res_set;
132 1.1 christos return (nw);
133 1.1 christos }
134 1.1 christos
135 1.1 christos /* Methods. */
136 1.1 christos
137 1.1 christos static void
138 1.1 christos nw_close(struct irs_nw *this) {
139 1.1 christos struct pvt *pvt = (struct pvt *)this->private;
140 1.1 christos
141 1.1 christos nw_minimize(this);
142 1.1 christos
143 1.1 christos if (pvt->res && pvt->free_res)
144 1.1 christos (*pvt->free_res)(pvt->res);
145 1.1 christos
146 1.1 christos memput(pvt, sizeof *pvt);
147 1.1 christos memput(this, sizeof *this);
148 1.1 christos }
149 1.1 christos
150 1.1 christos static struct nwent *
151 1.1 christos nw_byname(struct irs_nw *this, const char *name, int af) {
152 1.1 christos struct pvt *pvt = (struct pvt *)this->private;
153 1.1 christos
154 1.1 christos if (init(this) == -1)
155 1.1 christos return (NULL);
156 1.1 christos
157 1.1 christos switch (af) {
158 1.1 christos case AF_INET:
159 1.1 christos return (get1101byname(this, name));
160 1.1 christos default:
161 1.1 christos (void)NULL;
162 1.1 christos }
163 1.1 christos RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
164 1.1 christos errno = EAFNOSUPPORT;
165 1.1 christos return (NULL);
166 1.1 christos }
167 1.1 christos
168 1.1 christos static struct nwent *
169 1.1 christos nw_byaddr(struct irs_nw *this, void *net, int len, int af) {
170 1.1 christos struct pvt *pvt = (struct pvt *)this->private;
171 1.1 christos
172 1.1 christos if (init(this) == -1)
173 1.1 christos return (NULL);
174 1.1 christos
175 1.1 christos switch (af) {
176 1.1 christos case AF_INET:
177 1.1 christos return (get1101byaddr(this, net, len));
178 1.1 christos default:
179 1.1 christos (void)NULL;
180 1.1 christos }
181 1.1 christos RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
182 1.1 christos errno = EAFNOSUPPORT;
183 1.1 christos return (NULL);
184 1.1 christos }
185 1.1 christos
186 1.1 christos static struct nwent *
187 1.1 christos nw_next(struct irs_nw *this) {
188 1.1 christos
189 1.1 christos UNUSED(this);
190 1.1 christos
191 1.1 christos return (NULL);
192 1.1 christos }
193 1.1 christos
194 1.1 christos static void
195 1.1 christos nw_rewind(struct irs_nw *this) {
196 1.1 christos UNUSED(this);
197 1.1 christos /* NOOP */
198 1.1 christos }
199 1.1 christos
200 1.1 christos static void
201 1.1 christos nw_minimize(struct irs_nw *this) {
202 1.1 christos struct pvt *pvt = (struct pvt *)this->private;
203 1.1 christos
204 1.1 christos if (pvt->res)
205 1.1 christos res_nclose(pvt->res);
206 1.1 christos }
207 1.1 christos
208 1.1 christos static struct __res_state *
209 1.1 christos nw_res_get(struct irs_nw *this) {
210 1.1 christos struct pvt *pvt = (struct pvt *)this->private;
211 1.1 christos
212 1.1 christos if (!pvt->res) {
213 1.1 christos struct __res_state *res;
214 1.1 christos res = (struct __res_state *)malloc(sizeof *res);
215 1.1 christos if (!res) {
216 1.1 christos errno = ENOMEM;
217 1.1 christos return (NULL);
218 1.1 christos }
219 1.1 christos memset(res, 0, sizeof *res);
220 1.1 christos nw_res_set(this, res, free);
221 1.1 christos }
222 1.1 christos
223 1.1 christos return (pvt->res);
224 1.1 christos }
225 1.1 christos
226 1.1 christos static void
227 1.1 christos nw_res_set(struct irs_nw *this, struct __res_state *res,
228 1.1 christos void (*free_res)(void *)) {
229 1.1 christos struct pvt *pvt = (struct pvt *)this->private;
230 1.1 christos
231 1.1 christos if (pvt->res && pvt->free_res) {
232 1.1 christos res_nclose(pvt->res);
233 1.1 christos (*pvt->free_res)(pvt->res);
234 1.1 christos }
235 1.1 christos
236 1.1 christos pvt->res = res;
237 1.1 christos pvt->free_res = free_res;
238 1.1 christos }
239 1.1 christos
240 1.1 christos /* Private. */
241 1.1 christos
242 1.1 christos static struct nwent *
243 1.1 christos get1101byname(struct irs_nw *this, const char *name) {
244 1.1 christos struct pvt *pvt = (struct pvt *)this->private;
245 1.1 christos u_char *ansbuf;
246 1.1 christos int anslen;
247 1.1 christos struct nwent *result;
248 1.1 christos
249 1.1 christos ansbuf = memget(MAXPACKET);
250 1.1 christos if (ansbuf == NULL) {
251 1.1 christos errno = ENOMEM;
252 1.1 christos RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
253 1.1 christos return (NULL);
254 1.1 christos }
255 1.1 christos anslen = res_nsearch(pvt->res, name, C_IN, T_PTR, ansbuf, MAXPACKET);
256 1.1 christos if (anslen < 0) {
257 1.1 christos memput(ansbuf, MAXPACKET);
258 1.1 christos return (NULL);
259 1.1 christos }
260 1.1 christos result = get1101mask(this, get1101answer(this, ansbuf, anslen, by_name,
261 1.1 christos AF_INET, name, NULL, 0));
262 1.1 christos memput(ansbuf, MAXPACKET);
263 1.1 christos return (result);
264 1.1 christos }
265 1.1 christos
266 1.1 christos static struct nwent *
267 1.1 christos get1101byaddr(struct irs_nw *this, u_char *net, int len) {
268 1.1 christos struct pvt *pvt = (struct pvt *)this->private;
269 1.1 christos char qbuf[sizeof "255.255.255.255.in-addr.arpa"];
270 1.1 christos struct nwent *result;
271 1.1 christos u_char *ansbuf;
272 1.1 christos int anslen;
273 1.1 christos
274 1.1 christos if (len < 1 || len > 32) {
275 1.1 christos errno = EINVAL;
276 1.1 christos RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
277 1.1 christos return (NULL);
278 1.1 christos }
279 1.1 christos if (make1101inaddr(net, len, qbuf, sizeof qbuf) < 0)
280 1.1 christos return (NULL);
281 1.1 christos ansbuf = memget(MAXPACKET);
282 1.1 christos if (ansbuf == NULL) {
283 1.1 christos errno = ENOMEM;
284 1.1 christos RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
285 1.1 christos return (NULL);
286 1.1 christos }
287 1.1 christos anslen = res_nquery(pvt->res, qbuf, C_IN, T_PTR, ansbuf, MAXPACKET);
288 1.1 christos if (anslen < 0) {
289 1.1 christos memput(ansbuf, MAXPACKET);
290 1.1 christos return (NULL);
291 1.1 christos }
292 1.1 christos result = get1101mask(this, get1101answer(this, ansbuf, anslen, by_addr,
293 1.1 christos AF_INET, NULL, net, len));
294 1.1 christos memput(ansbuf, MAXPACKET);
295 1.1 christos return (result);
296 1.1 christos }
297 1.1 christos
298 1.1 christos static struct nwent *
299 1.1 christos get1101answer(struct irs_nw *this,
300 1.1 christos u_char *ansbuf, int anslen, enum by_what by_what,
301 1.1 christos int af, const char *name, const u_char *addr, int addrlen)
302 1.1 christos {
303 1.1 christos struct pvt *pvt = (struct pvt *)this->private;
304 1.1 christos int type, class, ancount, qdcount, haveanswer;
305 1.1 christos char *bp, *ep, **ap;
306 1.1 christos u_char *cp, *eom;
307 1.1 christos HEADER *hp;
308 1.1 christos
309 1.1 christos /* Initialize, and parse header. */
310 1.1 christos eom = ansbuf + anslen;
311 1.1 christos if (ansbuf + HFIXEDSZ > eom) {
312 1.1 christos RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
313 1.1 christos return (NULL);
314 1.1 christos }
315 1.1 christos hp = (HEADER *)ansbuf;
316 1.1 christos cp = ansbuf + HFIXEDSZ;
317 1.1 christos qdcount = ntohs(hp->qdcount);
318 1.1 christos while (qdcount-- > 0) {
319 1.1 christos int n = dn_skipname(cp, eom);
320 1.1 christos cp += n + QFIXEDSZ;
321 1.1 christos if (n < 0 || cp > eom) {
322 1.1 christos RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
323 1.1 christos return (NULL);
324 1.1 christos }
325 1.1 christos }
326 1.1 christos ancount = ntohs(hp->ancount);
327 1.1 christos if (!ancount) {
328 1.1 christos if (hp->aa)
329 1.1 christos RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND);
330 1.1 christos else
331 1.1 christos RES_SET_H_ERRNO(pvt->res, TRY_AGAIN);
332 1.1 christos return (NULL);
333 1.1 christos }
334 1.1 christos
335 1.1 christos /* Prepare a return structure. */
336 1.1 christos bp = pvt->buf;
337 1.1 christos ep = pvt->buf + sizeof(pvt->buf);
338 1.1 christos pvt->net.n_name = NULL;
339 1.1 christos pvt->net.n_aliases = pvt->ali;
340 1.1 christos pvt->net.n_addrtype = af;
341 1.1 christos pvt->net.n_addr = NULL;
342 1.1 christos pvt->net.n_length = addrlen;
343 1.1 christos
344 1.1 christos /* Save input key if given. */
345 1.1 christos switch (by_what) {
346 1.1 christos case by_name:
347 1.1 christos if (name != NULL) {
348 1.1 christos int n = strlen(name) + 1;
349 1.1 christos
350 1.1 christos if (n > (ep - bp)) {
351 1.1 christos RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
352 1.1 christos return (NULL);
353 1.1 christos }
354 1.1 christos pvt->net.n_name = strcpy(bp, name); /* (checked) */
355 1.1 christos bp += n;
356 1.1 christos }
357 1.1 christos break;
358 1.1 christos case by_addr:
359 1.1 christos if (addr != NULL && addrlen != 0) {
360 1.1 christos int n = addrlen / 8 + ((addrlen % 8) != 0);
361 1.1 christos
362 1.1 christos if (INADDRSZ > (ep - bp)) {
363 1.1 christos RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
364 1.1 christos return (NULL);
365 1.1 christos }
366 1.1 christos memset(bp, 0, INADDRSZ);
367 1.1 christos memcpy(bp, addr, n);
368 1.1 christos pvt->net.n_addr = bp;
369 1.1 christos bp += INADDRSZ;
370 1.1 christos }
371 1.1 christos break;
372 1.1 christos default:
373 1.1 christos abort();
374 1.1 christos }
375 1.1 christos
376 1.1 christos /* Parse the answer, collect aliases. */
377 1.1 christos ap = pvt->ali;
378 1.1 christos haveanswer = 0;
379 1.1 christos while (--ancount >= 0 && cp < eom) {
380 1.1 christos int n = dn_expand(ansbuf, eom, cp, bp, ep - bp);
381 1.1 christos
382 1.1 christos cp += n; /*%< Owner */
383 1.1 christos if (n < 0 || !maybe_dnok(pvt->res, bp) ||
384 1.1 christos cp + 3 * INT16SZ + INT32SZ > eom) {
385 1.1 christos RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
386 1.1 christos return (NULL);
387 1.1 christos }
388 1.1 christos GETSHORT(type, cp); /*%< Type */
389 1.1 christos GETSHORT(class, cp); /*%< Class */
390 1.1 christos cp += INT32SZ; /*%< TTL */
391 1.1 christos GETSHORT(n, cp); /*%< RDLENGTH */
392 1.1 christos if (class == C_IN && type == T_PTR) {
393 1.1 christos int nn;
394 1.1 christos
395 1.1 christos nn = dn_expand(ansbuf, eom, cp, bp, ep - bp);
396 1.1 christos if (nn < 0 || !maybe_hnok(pvt->res, bp) || nn != n) {
397 1.1 christos RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
398 1.1 christos return (NULL);
399 1.1 christos }
400 1.1 christos normalize_name(bp);
401 1.1 christos switch (by_what) {
402 1.1 christos case by_addr: {
403 1.1 christos if (pvt->net.n_name == NULL)
404 1.1 christos pvt->net.n_name = bp;
405 1.1 christos else if (ns_samename(pvt->net.n_name, bp) == 1)
406 1.1 christos break;
407 1.1 christos else
408 1.1 christos *ap++ = bp;
409 1.1 christos nn = strlen(bp) + 1;
410 1.1 christos bp += nn;
411 1.1 christos haveanswer++;
412 1.1 christos break;
413 1.1 christos }
414 1.1 christos case by_name: {
415 1.1 christos u_int b1, b2, b3, b4;
416 1.1 christos
417 1.1 christos if (pvt->net.n_addr != NULL ||
418 1.1 christos sscanf(bp, "%u.%u.%u.%u.in-addr.arpa",
419 1.1 christos &b1, &b2, &b3, &b4) != 4)
420 1.1 christos break;
421 1.1 christos if ((ep - bp) < INADDRSZ) {
422 1.1 christos RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
423 1.1 christos return (NULL);
424 1.1 christos }
425 1.1 christos pvt->net.n_addr = bp;
426 1.1 christos *bp++ = b4;
427 1.1 christos *bp++ = b3;
428 1.1 christos *bp++ = b2;
429 1.1 christos *bp++ = b1;
430 1.1 christos pvt->net.n_length = INADDRSZ * 8;
431 1.1 christos haveanswer++;
432 1.1 christos }
433 1.1 christos }
434 1.1 christos }
435 1.1 christos cp += n; /*%< RDATA */
436 1.1 christos }
437 1.1 christos if (!haveanswer) {
438 1.1 christos RES_SET_H_ERRNO(pvt->res, TRY_AGAIN);
439 1.1 christos return (NULL);
440 1.1 christos }
441 1.1 christos *ap = NULL;
442 1.1 christos
443 1.1 christos return (&pvt->net);
444 1.1 christos }
445 1.1 christos
446 1.1 christos static struct nwent *
447 1.1 christos get1101mask(struct irs_nw *this, struct nwent *nwent) {
448 1.1 christos struct pvt *pvt = (struct pvt *)this->private;
449 1.1 christos char qbuf[sizeof "255.255.255.255.in-addr.arpa"], owner[MAXDNAME];
450 1.1 christos int anslen, type, class, ancount, qdcount;
451 1.1 christos u_char *ansbuf, *cp, *eom;
452 1.1 christos HEADER *hp;
453 1.1 christos
454 1.1 christos if (!nwent)
455 1.1 christos return (NULL);
456 1.1 christos if (make1101inaddr(nwent->n_addr, nwent->n_length, qbuf, sizeof qbuf)
457 1.1 christos < 0) {
458 1.1 christos /* "First, do no harm." */
459 1.1 christos return (nwent);
460 1.1 christos }
461 1.1 christos
462 1.1 christos ansbuf = memget(MAXPACKET);
463 1.1 christos if (ansbuf == NULL) {
464 1.1 christos errno = ENOMEM;
465 1.1 christos RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
466 1.1 christos return (NULL);
467 1.1 christos }
468 1.1 christos /* Query for the A RR that would hold this network's mask. */
469 1.1 christos anslen = res_nquery(pvt->res, qbuf, C_IN, T_A, ansbuf, MAXPACKET);
470 1.1 christos if (anslen < HFIXEDSZ) {
471 1.1 christos memput(ansbuf, MAXPACKET);
472 1.1 christos return (nwent);
473 1.1 christos }
474 1.1 christos
475 1.1 christos /* Initialize, and parse header. */
476 1.1 christos hp = (HEADER *)ansbuf;
477 1.1 christos cp = ansbuf + HFIXEDSZ;
478 1.1 christos eom = ansbuf + anslen;
479 1.1 christos qdcount = ntohs(hp->qdcount);
480 1.1 christos while (qdcount-- > 0) {
481 1.1 christos int n = dn_skipname(cp, eom);
482 1.1 christos cp += n + QFIXEDSZ;
483 1.1 christos if (n < 0 || cp > eom) {
484 1.1 christos memput(ansbuf, MAXPACKET);
485 1.1 christos return (nwent);
486 1.1 christos }
487 1.1 christos }
488 1.1 christos ancount = ntohs(hp->ancount);
489 1.1 christos
490 1.1 christos /* Parse the answer, collect aliases. */
491 1.1 christos while (--ancount >= 0 && cp < eom) {
492 1.1 christos int n = dn_expand(ansbuf, eom, cp, owner, sizeof owner);
493 1.1 christos
494 1.1 christos if (n < 0 || !maybe_dnok(pvt->res, owner))
495 1.1 christos break;
496 1.1 christos cp += n; /*%< Owner */
497 1.1 christos if (cp + 3 * INT16SZ + INT32SZ > eom)
498 1.1 christos break;
499 1.1 christos GETSHORT(type, cp); /*%< Type */
500 1.1 christos GETSHORT(class, cp); /*%< Class */
501 1.1 christos cp += INT32SZ; /*%< TTL */
502 1.1 christos GETSHORT(n, cp); /*%< RDLENGTH */
503 1.1 christos if (cp + n > eom)
504 1.1 christos break;
505 1.1 christos if (n == INADDRSZ && class == C_IN && type == T_A &&
506 1.1 christos ns_samename(qbuf, owner) == 1) {
507 1.1 christos /* This A RR indicates the actual netmask. */
508 1.1 christos int nn, mm;
509 1.1 christos
510 1.1 christos nwent->n_length = 0;
511 1.1 christos for (nn = 0; nn < INADDRSZ; nn++)
512 1.1 christos for (mm = 7; mm >= 0; mm--)
513 1.1 christos if (cp[nn] & (1 << mm))
514 1.1 christos nwent->n_length++;
515 1.1 christos else
516 1.1 christos break;
517 1.1 christos }
518 1.1 christos cp += n; /*%< RDATA */
519 1.1 christos }
520 1.1 christos memput(ansbuf, MAXPACKET);
521 1.1 christos return (nwent);
522 1.1 christos }
523 1.1 christos
524 1.1 christos static int
525 1.1 christos make1101inaddr(const u_char *net, int bits, char *name, int size) {
526 1.1 christos int n, m;
527 1.1 christos char *ep;
528 1.1 christos
529 1.1 christos ep = name + size;
530 1.1 christos
531 1.1 christos /* Zero fill any whole bytes left out of the prefix. */
532 1.1 christos for (n = (32 - bits) / 8; n > 0; n--) {
533 1.1 christos if (ep - name < (int)(sizeof "0."))
534 1.1 christos goto emsgsize;
535 1.1 christos m = SPRINTF((name, "0."));
536 1.1 christos name += m;
537 1.1 christos }
538 1.1 christos
539 1.1 christos /* Format the partial byte, if any, within the prefix. */
540 1.1 christos if ((n = bits % 8) != 0) {
541 1.1 christos if (ep - name < (int)(sizeof "255."))
542 1.1 christos goto emsgsize;
543 1.1 christos m = SPRINTF((name, "%u.",
544 1.1 christos net[bits / 8] & ~((1 << (8 - n)) - 1)));
545 1.1 christos name += m;
546 1.1 christos }
547 1.1 christos
548 1.1 christos /* Format the whole bytes within the prefix. */
549 1.1 christos for (n = bits / 8; n > 0; n--) {
550 1.1 christos if (ep - name < (int)(sizeof "255."))
551 1.1 christos goto emsgsize;
552 1.1 christos m = SPRINTF((name, "%u.", net[n - 1]));
553 1.1 christos name += m;
554 1.1 christos }
555 1.1 christos
556 1.1 christos /* Add the static text. */
557 1.1 christos if (ep - name < (int)(sizeof "in-addr.arpa"))
558 1.1 christos goto emsgsize;
559 1.1 christos (void) SPRINTF((name, "in-addr.arpa"));
560 1.1 christos return (0);
561 1.1 christos
562 1.1 christos emsgsize:
563 1.1 christos errno = EMSGSIZE;
564 1.1 christos return (-1);
565 1.1 christos }
566 1.1 christos
567 1.1 christos static void
568 1.1 christos normalize_name(char *name) {
569 1.1 christos char *t;
570 1.1 christos
571 1.1 christos /* Make lower case. */
572 1.1 christos for (t = name; *t; t++)
573 1.1 christos if (isascii((unsigned char)*t) && isupper((unsigned char)*t))
574 1.1 christos *t = tolower((*t)&0xff);
575 1.1 christos
576 1.1 christos /* Remove trailing dots. */
577 1.1 christos while (t > name && t[-1] == '.')
578 1.1 christos *--t = '\0';
579 1.1 christos }
580 1.1 christos
581 1.1 christos static int
582 1.1 christos init(struct irs_nw *this) {
583 1.1 christos struct pvt *pvt = (struct pvt *)this->private;
584 1.1 christos
585 1.1 christos if (!pvt->res && !nw_res_get(this))
586 1.1 christos return (-1);
587 1.1 christos if (((pvt->res->options & RES_INIT) == 0U) &&
588 1.1 christos res_ninit(pvt->res) == -1)
589 1.1 christos return (-1);
590 1.1 christos return (0);
591 1.1 christos }
592 1.1 christos
593 1.1 christos /*! \file */
594