1 /* $NetBSD: getnetnamadr.c,v 1.40 2008/05/08 13:01:42 lukem Exp $ */
3 /* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
4 * Dep. Matematica Universidade de Coimbra, Portugal, Europe
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.
11 * Copyright (c) 1983, 1993
12 * The Regents of the University of California. All rights reserved.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
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. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 #include <sys/cdefs.h>
40 #if defined(LIBC_SCCS) && !defined(lint)
42 static char sccsid
[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93";
43 static char sccsid_
[] = "from getnetnamadr.c 1.4 (Coimbra) 93/06/03";
44 static char rcsid
[] = "Id: getnetnamadr.c,v 8.8 1997/06/01 20:34:37 vixie Exp ";
46 __RCSID("$NetBSD: getnetnamadr.c,v 1.40 2008/05/08 13:01:42 lukem Exp $");
48 #endif /* LIBC_SCCS and not lint */
50 #include "namespace.h"
51 #include <sys/types.h>
52 #include <sys/param.h>
53 #include <sys/socket.h>
54 #include <netinet/in.h>
55 #include <arpa/inet.h>
56 #include <arpa/nameser.h>
71 #include <rpcsvc/yp_prot.h>
72 #include <rpcsvc/ypclnt.h>
76 __weak_alias(getnetbyaddr
,_getnetbyaddr
)
77 __weak_alias(getnetbyname
,_getnetbyname
)
80 extern int _net_stayopen
;
86 #define MAXPACKET (64*1024)
90 u_char buf
[MAXPACKET
];
99 static char *__ypdomain
;
100 static char *__ypcurrent
;
101 static int __ypcurrentlen
;
104 static struct netent net_entry
;
105 static char *net_aliases
[MAXALIASES
];
107 static int parse_reversed_addr(const char *, in_addr_t
*);
108 static struct netent
*getnetanswer(querybuf
*, int, int);
109 static int _files_getnetbyaddr(void *, void *, va_list);
110 static int _files_getnetbyname(void *, void *, va_list);
111 static int _dns_getnetbyaddr(void *, void *, va_list);
112 static int _dns_getnetbyname(void *, void *, va_list);
114 static int _yp_getnetbyaddr(void *, void *, va_list);
115 static int _yp_getnetbyname(void *, void *, va_list);
116 static struct netent
*_ypnetent(char *);
120 * parse_reversed_addr --
121 * parse str, which should be of the form 'd.c.b.a.IN-ADDR.ARPA'
122 * (a PTR as per RFC 1101) and convert into an in_addr_t of the
124 * returns 0 on success (storing in *result), or -1 on error.
127 parse_reversed_addr(const char *str
, in_addr_t
*result
)
129 unsigned long octet
[4];
135 /* find the four octets 'd.b.c.a.' */
136 for (octidx
= 0; octidx
< 4; octidx
++) {
137 /* ensure it's a number */
138 if (!isdigit((unsigned char)*sp
))
140 octet
[octidx
] = strtoul(sp
, &ep
, 10);
141 /* with a trailing '.' */
144 /* and is 0 <= octet <= 255 */
145 if (octet
[octidx
] > 255)
149 /* ensure trailer is correct */
150 if (strcasecmp(sp
, "IN-ADDR.ARPA") != 0)
153 /* build result from octets in reverse */
154 for (octidx
= 3; octidx
>= 0; octidx
--) {
156 *result
|= (octet
[octidx
] & 0xff);
161 static struct netent
*
162 getnetanswer(querybuf
*answer
, int anslen
, int net_i
)
164 static char n_name
[MAXDNAME
];
165 static char netbuf
[PACKETSZ
];
171 int type
, class, ancount
, qdcount
, haveanswer
;
172 char *in
, *bp
, **ap
, *ep
;
174 _DIAGASSERT(answer
!= NULL
);
177 * find first satisfactory answer
179 * answer --> +------------+ ( MESSAGE )
182 * | Question | the question for the name server
184 * | Answer | RRs answering the question
186 * | Authority | RRs pointing toward an authority
187 * | Additional | RRs holding additional information
190 eom
= answer
->buf
+ anslen
;
192 ancount
= ntohs(hp
->ancount
); /* #/records in the answer section */
193 qdcount
= ntohs(hp
->qdcount
); /* #/entries in the question section */
195 ep
= netbuf
+ sizeof(netbuf
);
196 cp
= answer
->buf
+ HFIXEDSZ
;
199 h_errno
= HOST_NOT_FOUND
;
204 while (qdcount
-- > 0) {
205 n
= __dn_skipname(cp
, eom
);
206 if (n
< 0 || (cp
+ n
+ QFIXEDSZ
) > eom
) {
207 h_errno
= NO_RECOVERY
;
214 net_entry
.n_aliases
= net_aliases
;
217 while (--ancount
>= 0 && cp
< eom
) {
218 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, ep
- bp
);
219 if ((n
< 0) || !res_dnok(bp
))
222 (void)strlcpy(n_name
, bp
, sizeof(n_name
));
225 cp
+= INT32SZ
; /* TTL */
227 if (class == C_IN
&& type
== T_PTR
) {
228 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, ep
- bp
);
229 if ((n
< 0) || !res_hnok(bp
)) {
235 bp
+= strlen(bp
) + 1;
236 net_entry
.n_addrtype
=
237 (class == C_IN
) ? AF_INET
: AF_UNSPEC
;
245 net_entry
.n_name
= *net_entry
.n_aliases
;
246 net_entry
.n_net
= 0L;
249 ap
= net_entry
.n_aliases
;
253 h_errno
= HOST_NOT_FOUND
;
256 net_entry
.n_name
= n_name
;
257 if (parse_reversed_addr(in
, &net_entry
.n_net
) == -1)
261 net_entry
.n_aliases
++;
262 #if (defined(__sparc__) && defined(_LP64)) || \
263 defined(__alpha__) || \
264 (defined(__i386__) && defined(_LP64)) || \
265 (defined(__sh__) && defined(_LP64))
266 net_entry
.__n_pad0
= 0;
276 _files_getnetbyaddr(void *cbrv
, void *cbdata
, va_list ap
)
278 struct netent
**retval
= va_arg(ap
, struct netent
**);
279 uint32_t net
= va_arg(ap
, uint32_t);
280 int type
= va_arg(ap
, int);
284 setnetent(_net_stayopen
);
285 while ((np
= getnetent()) != NULL
)
286 if (np
->n_addrtype
== type
&& np
->n_net
== net
)
295 h_errno
= HOST_NOT_FOUND
;
302 _dns_getnetbyaddr(void *cbrv
, void *cbdata
, va_list ap
)
304 struct netent
**retval
= va_arg(ap
, struct netent
**);
305 uint32_t net
= va_arg(ap
, uint32_t);
306 int type
= va_arg(ap
, int);
308 unsigned int netbr
[4];
319 for (nn
= 4, net2
= net
; net2
; net2
>>= 8)
320 netbr
[--nn
] = (unsigned int)(net2
& 0xff);
324 case 3: /* Class A */
325 snprintf(qbuf
, sizeof(qbuf
), "0.0.0.%u.in-addr.arpa", netbr
[3]);
327 case 2: /* Class B */
328 snprintf(qbuf
, sizeof(qbuf
), "0.0.%u.%u.in-addr.arpa",
331 case 1: /* Class C */
332 snprintf(qbuf
, sizeof(qbuf
), "0.%u.%u.%u.in-addr.arpa",
333 netbr
[3], netbr
[2], netbr
[1]);
335 case 0: /* Class D - E */
336 snprintf(qbuf
, sizeof(qbuf
), "%u.%u.%u.%u.in-addr.arpa",
337 netbr
[3], netbr
[2], netbr
[1], netbr
[0]);
340 buf
= malloc(sizeof(*buf
));
342 h_errno
= NETDB_INTERNAL
;
345 res
= __res_get_state();
350 anslen
= res_nquery(res
, qbuf
, C_IN
, T_PTR
, buf
->buf
, sizeof(buf
->buf
));
354 if (res
->options
& RES_DEBUG
)
355 printf("res_query failed\n");
357 __res_put_state(res
);
360 __res_put_state(res
);
361 np
= getnetanswer(buf
, anslen
, BYADDR
);
364 /* maybe net should be unsigned? */
365 uint32_t u_net
= net
;
367 /* Strip trailing zeros */
368 while ((u_net
& 0xff) == 0 && u_net
!= 0)
377 h_errno
= HOST_NOT_FOUND
;
383 getnetbyaddr(uint32_t net
, int net_type
)
386 struct netent
*retval
;
388 static const ns_dtab dtab
[] = {
389 NS_FILES_CB(_files_getnetbyaddr
, NULL
)
390 { NSSRC_DNS
, _dns_getnetbyaddr
, NULL
}, /* force -DHESIOD */
391 NS_NIS_CB(_yp_getnetbyaddr
, NULL
)
396 h_errno
= NETDB_INTERNAL
;
397 rv
= nsdispatch(NULL
, dtab
, NSDB_NETWORKS
, "getnetbyaddr",
398 __nsdefaultsrc
, &retval
, net
, net_type
);
399 if (rv
== NS_SUCCESS
) {
400 h_errno
= NETDB_SUCCESS
;
408 _files_getnetbyname(void *cbrv
, void *cbdata
, va_list ap
)
410 struct netent
**retval
= va_arg(ap
, struct netent
**);
411 const char *name
= va_arg(ap
, const char *);
416 setnetent(_net_stayopen
);
417 while ((np
= getnetent()) != NULL
) {
418 if (strcasecmp(np
->n_name
, name
) == 0)
420 for (cp
= np
->n_aliases
; *cp
!= 0; cp
++)
421 if (strcasecmp(*cp
, name
) == 0)
432 h_errno
= HOST_NOT_FOUND
;
439 _dns_getnetbyname(void *cbrv
, void *cbdata
, va_list ap
)
441 struct netent
**retval
= va_arg(ap
, struct netent
**);
442 const char *name
= va_arg(ap
, const char *);
450 strlcpy(&qbuf
[0], name
, sizeof(qbuf
));
451 buf
= malloc(sizeof(*buf
));
453 h_errno
= NETDB_INTERNAL
;
456 res
= __res_get_state();
461 anslen
= res_nsearch(res
, qbuf
, C_IN
, T_PTR
, buf
->buf
,
466 if (res
->options
& RES_DEBUG
)
467 printf("res_search failed\n");
469 __res_put_state(res
);
472 __res_put_state(res
);
473 np
= getnetanswer(buf
, anslen
, BYNAME
);
480 h_errno
= HOST_NOT_FOUND
;
486 getnetbyname(const char *name
)
489 struct netent
*retval
;
491 static const ns_dtab dtab
[] = {
492 NS_FILES_CB(_files_getnetbyname
, NULL
)
493 { NSSRC_DNS
, _dns_getnetbyname
, NULL
}, /* force -DHESIOD */
494 NS_NIS_CB(_yp_getnetbyname
, NULL
)
498 _DIAGASSERT(name
!= NULL
);
501 h_errno
= NETDB_INTERNAL
;
502 rv
= nsdispatch(NULL
, dtab
, NSDB_NETWORKS
, "getnetbyname",
503 __nsdefaultsrc
, &retval
, name
);
504 if (rv
== NS_SUCCESS
) {
505 h_errno
= NETDB_SUCCESS
;
514 _yp_getnetbyaddr(void *cbrv
, void *cb_data
, va_list ap
)
516 struct netent
**retval
= va_arg(ap
, struct netent
**);
517 uint32_t net
= va_arg(ap
, uint32_t);
518 int type
= va_arg(ap
, int);
522 unsigned int netbr
[4];
530 if (_yp_check(&__ypdomain
) == 0)
537 for (r
= 4, net2
= net
; net2
; net2
>>= 8)
538 netbr
[--r
] = (unsigned int)(net2
& 0xff);
542 case 3: /* Class A */
543 snprintf(qbuf
, sizeof(qbuf
), "%u", netbr
[3]);
545 case 2: /* Class B */
546 snprintf(qbuf
, sizeof(qbuf
), "%u.%u", netbr
[2], netbr
[3]);
548 case 1: /* Class C */
549 snprintf(qbuf
, sizeof(qbuf
), "%u.%u.%u", netbr
[1], netbr
[2],
552 case 0: /* Class D - E */
553 snprintf(qbuf
, sizeof(qbuf
), "%u.%u.%u.%u", netbr
[0], netbr
[1],
557 r
= yp_match(__ypdomain
, "networks.byaddr", qbuf
, (int)strlen(qbuf
),
558 &__ypcurrent
, &__ypcurrentlen
);
560 np
= _ypnetent(__ypcurrent
);
566 h_errno
= HOST_NOT_FOUND
;
573 _yp_getnetbyname(void *cbrv
, void *cbdata
, va_list ap
)
575 struct netent
**retval
= va_arg(ap
, struct netent
**);
576 const char *name
= va_arg(ap
, const char *);
582 if (_yp_check(&__ypdomain
) == 0)
589 r
= yp_match(__ypdomain
, "networks.byname", name
, (int)strlen(name
),
590 &__ypcurrent
, &__ypcurrentlen
);
592 np
= _ypnetent(__ypcurrent
);
598 h_errno
= HOST_NOT_FOUND
;
603 static struct netent
*
604 _ypnetent(char *line
)
608 _DIAGASSERT(line
!= NULL
);
610 net_entry
.n_name
= line
;
611 cp
= strpbrk(line
, " \t");
615 while (*cp
== ' ' || *cp
== '\t')
617 p
= strpbrk(cp
, " \t");
620 net_entry
.n_net
= inet_network(cp
);
621 #if (defined(__sparc__) && defined(_LP64)) || \
622 defined(__alpha__) || \
623 (defined(__i386__) && defined(_LP64)) || \
624 (defined(__sh__) && defined(_LP64))
625 net_entry
.__n_pad0
= 0;
627 net_entry
.n_addrtype
= AF_INET
;
628 q
= net_entry
.n_aliases
= net_aliases
;
632 if (*cp
== ' ' || *cp
== '\t') {
636 if (q
< &net_aliases
[MAXALIASES
- 1])
638 cp
= strpbrk(cp
, " \t");