getnetnamadr.c revision 1.19.4.4 1 /* $NetBSD: getnetnamadr.c,v 1.19.4.4 2002/11/14 14:37:17 itojun Exp $ */
2
3 /* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
4 * Dep. Matematica Universidade de Coimbra, Portugal, Europe
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 */
10 /*
11 * Copyright (c) 1983, 1993
12 * The Regents of the University of California. All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by the University of
25 * California, Berkeley and its contributors.
26 * 4. Neither the name of the University nor the names of its contributors
27 * may be used to endorse or promote products derived from this software
28 * without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE.
41 */
42
43 #include <sys/cdefs.h>
44 #if defined(LIBC_SCCS) && !defined(lint)
45 #if 0
46 static char sccsid[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93";
47 static char sccsid_[] = "from getnetnamadr.c 1.4 (Coimbra) 93/06/03";
48 static char rcsid[] = "Id: getnetnamadr.c,v 8.8 1997/06/01 20:34:37 vixie Exp ";
49 #else
50 __RCSID("$NetBSD: getnetnamadr.c,v 1.19.4.4 2002/11/14 14:37:17 itojun Exp $");
51 #endif
52 #endif /* LIBC_SCCS and not lint */
53
54 #include "namespace.h"
55 #include <sys/types.h>
56 #include <sys/param.h>
57 #include <sys/socket.h>
58 #include <netinet/in.h>
59 #include <arpa/inet.h>
60 #include <arpa/nameser.h>
61
62 #include <assert.h>
63 #include <ctype.h>
64 #include <errno.h>
65 #include <netdb.h>
66 #include <nsswitch.h>
67 #include <resolv.h>
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <string.h>
71
72 #ifdef __STDC__
73 #include <stdarg.h>
74 #else
75 #include <varargs.h>
76 #endif
77
78 #ifdef YP
79 #include <rpc/rpc.h>
80 #include <rpcsvc/yp_prot.h>
81 #include <rpcsvc/ypclnt.h>
82 #endif
83
84 #ifdef __weak_alias
85 __weak_alias(getnetbyaddr,_getnetbyaddr)
86 __weak_alias(getnetbyname,_getnetbyname)
87 #endif
88
89 extern int _net_stayopen;
90
91 #define BYADDR 0
92 #define BYNAME 1
93 #define MAXALIASES 35
94
95 #define MAXPACKET (64*1024)
96
97 typedef union {
98 HEADER hdr;
99 u_char buf[MAXPACKET];
100 } querybuf;
101
102 typedef union {
103 long al;
104 char ac;
105 } align;
106
107 #ifdef YP
108 static char *__ypdomain;
109 static char *__ypcurrent;
110 static int __ypcurrentlen;
111 #endif
112
113 static struct netent net_entry;
114 static char *net_aliases[MAXALIASES];
115
116 static struct netent *getnetanswer __P((querybuf *, int, int));
117 int _files_getnetbyaddr __P((void *, void *, va_list));
118 int _files_getnetbyname __P((void *, void *, va_list));
119 int _dns_getnetbyaddr __P((void *, void *, va_list));
120 int _dns_getnetbyname __P((void *, void *, va_list));
121 #ifdef YP
122 int _yp_getnetbyaddr __P((void *, void *, va_list));
123 int _yp_getnetbyname __P((void *, void *, va_list));
124 struct netent *_ypnetent __P((char *));
125 #endif
126
127 static struct netent *
128 getnetanswer(answer, anslen, net_i)
129 querybuf *answer;
130 int anslen;
131 int net_i;
132 {
133 HEADER *hp;
134 u_char *cp;
135 int n;
136 u_char *eom;
137 int type, class, ancount, qdcount, haveanswer, i, nchar;
138 char aux1[MAXDNAME], aux2[MAXDNAME], ans[MAXDNAME];
139 char *in, *st, *pauxt, *bp, **ap;
140 char *paux1 = &aux1[0], *paux2 = &aux2[0], *ep;
141 static char netbuf[PACKETSZ];
142
143 _DIAGASSERT(answer != NULL);
144
145 /*
146 * find first satisfactory answer
147 *
148 * answer --> +------------+ ( MESSAGE )
149 * | Header |
150 * +------------+
151 * | Question | the question for the name server
152 * +------------+
153 * | Answer | RRs answering the question
154 * +------------+
155 * | Authority | RRs pointing toward an authority
156 * | Additional | RRs holding additional information
157 * +------------+
158 */
159 eom = answer->buf + anslen;
160 hp = &answer->hdr;
161 ancount = ntohs(hp->ancount); /* #/records in the answer section */
162 qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
163 bp = netbuf;
164 ep = netbuf + sizeof(netbuf);
165 cp = answer->buf + HFIXEDSZ;
166 if (!qdcount) {
167 if (hp->aa)
168 h_errno = HOST_NOT_FOUND;
169 else
170 h_errno = TRY_AGAIN;
171 return (NULL);
172 }
173 while (qdcount-- > 0) {
174 n = __dn_skipname(cp, eom);
175 if (n < 0 || (cp + n + QFIXEDSZ) > eom) {
176 h_errno = NO_RECOVERY;
177 return(NULL);
178 }
179 cp += n + QFIXEDSZ;
180 }
181 ap = net_aliases;
182 *ap = NULL;
183 net_entry.n_aliases = net_aliases;
184 haveanswer = 0;
185 while (--ancount >= 0 && cp < eom) {
186 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
187 if ((n < 0) || !res_dnok(bp))
188 break;
189 cp += n;
190 ans[0] = '\0';
191 (void)strlcpy(ans, bp, sizeof(ans));
192 GETSHORT(type, cp);
193 GETSHORT(class, cp);
194 cp += INT32SZ; /* TTL */
195 GETSHORT(n, cp);
196 if (class == C_IN && type == T_PTR) {
197 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
198 if ((n < 0) || !res_hnok(bp)) {
199 cp += n;
200 return (NULL);
201 }
202 cp += n;
203 *ap++ = bp;
204 bp += strlen(bp) + 1;
205 net_entry.n_addrtype =
206 (class == C_IN) ? AF_INET : AF_UNSPEC;
207 haveanswer++;
208 }
209 }
210 if (haveanswer) {
211 *ap = NULL;
212 switch (net_i) {
213 case BYADDR:
214 net_entry.n_name = *net_entry.n_aliases;
215 net_entry.n_net = 0L;
216 break;
217 case BYNAME:
218 ap = net_entry.n_aliases;
219 next_alias:
220 in = *ap++;
221 if (in == NULL) {
222 h_errno = HOST_NOT_FOUND;
223 return (NULL);
224 }
225 net_entry.n_name = ans;
226 aux2[0] = '\0';
227 for (i = 0; i < 4; i++) {
228 for (st = in, nchar = 0;
229 isdigit((unsigned char)*st);
230 st++, nchar++)
231 ;
232 if (*st != '.' || nchar == 0 || nchar > 3)
233 goto next_alias;
234 if (i != 0)
235 nchar++;
236 (void)strlcpy(paux1, in, (size_t)nchar);
237 paux1[nchar] = '\0';
238 pauxt = paux2;
239 paux2 = strcat(paux1, paux2);
240 paux1 = pauxt;
241 in = ++st;
242 }
243 net_entry.n_net = inet_network(paux2);
244 break;
245 }
246 if (strcasecmp(in, "IN-ADDR.ARPA") != 0)
247 goto next_alias;
248 net_entry.n_aliases++;
249 return (&net_entry);
250 }
251 h_errno = TRY_AGAIN;
252 return (NULL);
253 }
254
255 /*ARGSUSED*/
256 int
257 _files_getnetbyaddr(rv, cb_data, ap)
258 void *rv;
259 void *cb_data;
260 va_list ap;
261 {
262 struct netent *p;
263 unsigned long net;
264 int type;
265
266 _DIAGASSERT(rv != NULL);
267
268 net = va_arg(ap, unsigned long);
269 type = va_arg(ap, int);
270
271 setnetent(_net_stayopen);
272 while ((p = getnetent()) != NULL)
273 if (p->n_addrtype == type && p->n_net == net)
274 break;
275 if (!_net_stayopen)
276 endnetent();
277 *((struct netent **)rv) = p;
278 if (p==NULL) {
279 h_errno = HOST_NOT_FOUND;
280 return NS_NOTFOUND;
281 }
282 return NS_SUCCESS;
283 }
284
285 /*ARGSUSED*/
286 int
287 _dns_getnetbyaddr(rv, cb_data, ap)
288 void *rv;
289 void *cb_data;
290 va_list ap;
291 {
292 unsigned int netbr[4];
293 int nn, anslen;
294 querybuf *buf;
295 char qbuf[MAXDNAME];
296 unsigned long net2;
297 struct netent *np;
298 unsigned long net;
299 int type;
300
301 _DIAGASSERT(rv != NULL);
302
303 net = va_arg(ap, unsigned long);
304 type = va_arg(ap, int);
305
306 if (type != AF_INET)
307 return NS_UNAVAIL;
308
309 for (nn = 4, net2 = net; net2; net2 >>= 8)
310 netbr[--nn] = (unsigned int)(net2 & 0xff);
311 switch (nn) {
312 default:
313 return NS_UNAVAIL;
314 case 3: /* Class A */
315 snprintf(qbuf, sizeof(qbuf), "0.0.0.%u.in-addr.arpa", netbr[3]);
316 break;
317 case 2: /* Class B */
318 snprintf(qbuf, sizeof(qbuf), "0.0.%u.%u.in-addr.arpa",
319 netbr[3], netbr[2]);
320 break;
321 case 1: /* Class C */
322 snprintf(qbuf, sizeof(qbuf), "0.%u.%u.%u.in-addr.arpa",
323 netbr[3], netbr[2], netbr[1]);
324 break;
325 case 0: /* Class D - E */
326 snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa",
327 netbr[3], netbr[2], netbr[1], netbr[0]);
328 break;
329 }
330 buf = malloc(sizeof(*buf));
331 if (buf == NULL) {
332 h_errno = NETDB_INTERNAL;
333 return NS_NOTFOUND;
334 }
335 anslen = res_query(qbuf, C_IN, T_PTR, buf->buf, sizeof(buf->buf));
336 if (anslen < 0) {
337 free(buf);
338 #ifdef DEBUG
339 if (_res.options & RES_DEBUG)
340 printf("res_query failed\n");
341 #endif
342 return NS_NOTFOUND;
343 }
344 np = getnetanswer(buf, anslen, BYADDR);
345 free(buf);
346 if (np) {
347 /* maybe net should be unsigned? */
348 unsigned long u_net = net;
349
350 /* Strip trailing zeros */
351 while ((u_net & 0xff) == 0 && u_net != 0)
352 u_net >>= 8;
353 np->n_net = u_net;
354 }
355 *((struct netent **)rv) = np;
356 if (np == NULL) {
357 h_errno = HOST_NOT_FOUND;
358 return NS_NOTFOUND;
359 }
360 return NS_SUCCESS;
361 }
362
363
364 struct netent *
365 getnetbyaddr(net, net_type)
366 u_long net;
367 int net_type;
368 {
369 struct netent *np;
370 static const ns_dtab dtab[] = {
371 NS_FILES_CB(_files_getnetbyaddr, NULL)
372 { NSSRC_DNS, _dns_getnetbyaddr, NULL }, /* force -DHESIOD */
373 NS_NIS_CB(_yp_getnetbyaddr, NULL)
374 { 0 }
375 };
376
377 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
378 h_errno = NETDB_INTERNAL;
379 return (NULL);
380 }
381
382 np = NULL;
383 h_errno = NETDB_INTERNAL;
384 if (nsdispatch(&np, dtab, NSDB_NETWORKS, "getnetbyaddr", __nsdefaultsrc,
385 net, net_type) != NS_SUCCESS)
386 return (NULL);
387 h_errno = NETDB_SUCCESS;
388 return (np);
389 }
390
391 /*ARGSUSED*/
392 int
393 _files_getnetbyname(rv, cb_data, ap)
394 void *rv;
395 void *cb_data;
396 va_list ap;
397 {
398 struct netent *p;
399 char **cp;
400 const char *name;
401
402 _DIAGASSERT(rv != NULL);
403
404 name = va_arg(ap, const char *);
405 setnetent(_net_stayopen);
406 while ((p = getnetent()) != NULL) {
407 if (strcasecmp(p->n_name, name) == 0)
408 break;
409 for (cp = p->n_aliases; *cp != 0; cp++)
410 if (strcasecmp(*cp, name) == 0)
411 goto found;
412 }
413 found:
414 if (!_net_stayopen)
415 endnetent();
416 *((struct netent **)rv) = p;
417 if (p==NULL) {
418 h_errno = HOST_NOT_FOUND;
419 return NS_NOTFOUND;
420 }
421 return NS_SUCCESS;
422 }
423
424 /*ARGSUSED*/
425 int
426 _dns_getnetbyname(rv, cb_data, ap)
427 void *rv;
428 void *cb_data;
429 va_list ap;
430 {
431 int anslen;
432 querybuf *buf;
433 char qbuf[MAXDNAME];
434 struct netent *np;
435 const char *net;
436
437 _DIAGASSERT(rv != NULL);
438
439 net = va_arg(ap, const char *);
440 strlcpy(&qbuf[0], net, sizeof(qbuf));
441 buf = malloc(sizeof(*buf));
442 if (buf == NULL) {
443 h_errno = NETDB_INTERNAL;
444 return NS_NOTFOUND;
445 }
446 anslen = res_search(qbuf, C_IN, T_PTR, buf->buf, sizeof(buf->buf));
447 if (anslen < 0) {
448 free(buf);
449 #ifdef DEBUG
450 if (_res.options & RES_DEBUG)
451 printf("res_search failed\n");
452 #endif
453 return NS_NOTFOUND;
454 }
455 np = getnetanswer(buf, anslen, BYNAME);
456 free(buf);
457 *((struct netent **)rv) = np;
458 if (np == NULL) {
459 h_errno = HOST_NOT_FOUND;
460 return NS_NOTFOUND;
461 }
462 return NS_SUCCESS;
463 }
464
465 struct netent *
466 getnetbyname(net)
467 const char *net;
468 {
469 struct netent *np;
470 static const ns_dtab dtab[] = {
471 NS_FILES_CB(_files_getnetbyname, NULL)
472 { NSSRC_DNS, _dns_getnetbyname, NULL }, /* force -DHESIOD */
473 NS_NIS_CB(_yp_getnetbyname, NULL)
474 { 0 }
475 };
476
477 _DIAGASSERT(net != NULL);
478
479 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
480 h_errno = NETDB_INTERNAL;
481 return (NULL);
482 }
483
484 np = NULL;
485 h_errno = NETDB_INTERNAL;
486 if (nsdispatch(&np, dtab, NSDB_NETWORKS, "getnetbyname", __nsdefaultsrc,
487 net) != NS_SUCCESS)
488 return (NULL);
489 h_errno = NETDB_SUCCESS;
490 return (np);
491 }
492
493 #ifdef YP
494 /*ARGSUSED*/
495 int
496 _yp_getnetbyaddr(rv, cb_data, ap)
497 void *rv;
498 void *cb_data;
499 va_list ap;
500 {
501 struct netent *np;
502 char qbuf[MAXDNAME];
503 unsigned int netbr[4];
504 unsigned long net, net2;
505 int type, r;
506
507 _DIAGASSERT(rv != NULL);
508
509 net = va_arg(ap, unsigned long);
510 type = va_arg(ap, int);
511
512 if (type != AF_INET)
513 return NS_UNAVAIL;
514
515 if (!__ypdomain) {
516 if (_yp_check(&__ypdomain) == 0)
517 return NS_UNAVAIL;
518 }
519 np = NULL;
520 if (__ypcurrent)
521 free(__ypcurrent);
522 __ypcurrent = NULL;
523 for (r = 4, net2 = net; net2; net2 >>= 8)
524 netbr[--r] = (unsigned int)(net2 & 0xff);
525 switch (r) {
526 default:
527 return NS_UNAVAIL;
528 case 3: /* Class A */
529 snprintf(qbuf, sizeof(qbuf), "%u", netbr[0]);
530 break;
531 case 2: /* Class B */
532 snprintf(qbuf, sizeof(qbuf), "%u.%u", netbr[0], netbr[1]);
533 break;
534 case 1: /* Class C */
535 snprintf(qbuf, sizeof(qbuf), "%u.%u.%u", netbr[0], netbr[1],
536 netbr[2]);
537 break;
538 case 0: /* Class D - E */
539 snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u", netbr[0], netbr[1],
540 netbr[2], netbr[3]);
541 break;
542 }
543 r = yp_match(__ypdomain, "networks.byaddr", qbuf, (int)strlen(qbuf),
544 &__ypcurrent, &__ypcurrentlen);
545 if (r == 0)
546 np = _ypnetent(__ypcurrent);
547
548 *((struct netent **)rv) = np;
549 if (np == NULL) {
550 h_errno = HOST_NOT_FOUND;
551 return NS_NOTFOUND;
552 }
553 return NS_SUCCESS;
554
555 }
556
557 int
558 /*ARGSUSED*/
559 _yp_getnetbyname(rv, cb_data, ap)
560 void *rv;
561 void *cb_data;
562 va_list ap;
563 {
564 struct netent *np;
565 const char *name;
566 int r;
567
568 _DIAGASSERT(rv != NULL);
569
570 name = va_arg(ap, const char *);
571
572 if (!__ypdomain) {
573 if (_yp_check(&__ypdomain) == 0)
574 return NS_UNAVAIL;
575 }
576 np = NULL;
577 if (__ypcurrent)
578 free(__ypcurrent);
579 __ypcurrent = NULL;
580 r = yp_match(__ypdomain, "networks.byname", name, (int)strlen(name),
581 &__ypcurrent, &__ypcurrentlen);
582 if (r == 0)
583 np = _ypnetent(__ypcurrent);
584
585 *((struct netent **)rv) = np;
586 if (np == NULL) {
587 h_errno = HOST_NOT_FOUND;
588 return NS_NOTFOUND;
589 }
590 return NS_SUCCESS;
591 }
592
593 struct netent *
594 _ypnetent(line)
595 char *line;
596 {
597 char *cp, *p, **q;
598
599 _DIAGASSERT(line != NULL);
600
601 net_entry.n_name = line;
602 cp = strpbrk(line, " \t");
603 if (cp == NULL)
604 return (NULL);
605 *cp++ = '\0';
606 while (*cp == ' ' || *cp == '\t')
607 cp++;
608 p = strpbrk(cp, " \t");
609 if (p != NULL)
610 *p++ = '\0';
611 net_entry.n_net = inet_network(cp);
612 net_entry.n_addrtype = AF_INET;
613 q = net_entry.n_aliases = net_aliases;
614 if (p != NULL) {
615 cp = p;
616 while (cp && *cp) {
617 if (*cp == ' ' || *cp == '\t') {
618 cp++;
619 continue;
620 }
621 if (q < &net_aliases[MAXALIASES - 1])
622 *q++ = cp;
623 cp = strpbrk(cp, " \t");
624 if (cp != NULL)
625 *cp++ = '\0';
626 }
627 }
628 *q = NULL;
629
630 return (&net_entry);
631 }
632 #endif
633