summaryrefslogtreecommitdiff
path: root/src/lib/libc/net/getnetnamadr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/net/getnetnamadr.c')
-rw-r--r--src/lib/libc/net/getnetnamadr.c400
1 files changed, 400 insertions, 0 deletions
diff --git a/src/lib/libc/net/getnetnamadr.c b/src/lib/libc/net/getnetnamadr.c
new file mode 100644
index 0000000000..149216ffd8
--- /dev/null
+++ b/src/lib/libc/net/getnetnamadr.c
@@ -0,0 +1,400 @@
1/* $OpenBSD: getnetnamadr.c,v 1.23 2003/06/03 21:09:00 deraadt Exp $ */
2
3/*
4 * Copyright (c) 1997, Jason Downs. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27/* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
28 * Dep. Matematica Universidade de Coimbra, Portugal, Europe
29 *
30 * Permission to use, copy, modify, and distribute this software for any
31 * purpose with or without fee is hereby granted, provided that the above
32 * copyright notice and this permission notice appear in all copies.
33 */
34/*
35 * Copyright (c) 1983, 1993
36 * The Regents of the University of California. All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. Neither the name of the University nor the names of its contributors
47 * may be used to endorse or promote products derived from this software
48 * without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * SUCH DAMAGE.
61 */
62
63#if defined(LIBC_SCCS) && !defined(lint)
64#if 0
65static char sccsid[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93";
66static char sccsid_[] = "from getnetnamadr.c 1.4 (Coimbra) 93/06/03";
67static char rcsid[] = "$From: getnetnamadr.c,v 8.7 1996/08/05 08:31:35 vixie Exp $";
68#else
69static char rcsid[] = "$OpenBSD: getnetnamadr.c,v 1.23 2003/06/03 21:09:00 deraadt Exp $";
70#endif
71#endif /* LIBC_SCCS and not lint */
72
73#include <sys/types.h>
74#include <sys/param.h>
75#include <sys/socket.h>
76#include <netinet/in.h>
77#include <arpa/inet.h>
78#include <arpa/nameser.h>
79
80#include <stdio.h>
81#include <netdb.h>
82#include <resolv.h>
83#include <ctype.h>
84#include <errno.h>
85#include <string.h>
86#include <stdlib.h>
87
88#include "thread_private.h"
89
90extern int h_errno;
91
92struct netent *_getnetbyaddr(in_addr_t net, int type);
93struct netent *_getnetbyname(const char *name);
94
95int _hokchar(const char *);
96
97#define BYADDR 0
98#define BYNAME 1
99#define MAXALIASES 35
100
101#define MAXPACKET (64*1024)
102
103typedef union {
104 HEADER hdr;
105 u_char buf[MAXPACKET];
106} querybuf;
107
108typedef union {
109 long al;
110 char ac;
111} align;
112
113static struct netent *
114getnetanswer(answer, anslen, net_i)
115 querybuf *answer;
116 int anslen;
117 int net_i;
118{
119
120 register HEADER *hp;
121 register u_char *cp;
122 register int n;
123 u_char *eom;
124 int type, class, ancount, qdcount, haveanswer, i, nchar;
125 char aux1[MAXHOSTNAMELEN], aux2[MAXHOSTNAMELEN], ans[MAXHOSTNAMELEN];
126 char *in, *st, *pauxt, *bp, **ap, *ep;
127 char *paux1 = &aux1[0], *paux2 = &aux2[0];
128 static struct netent net_entry;
129 static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
130
131 /*
132 * find first satisfactory answer
133 *
134 * answer --> +------------+ ( MESSAGE )
135 * | Header |
136 * +------------+
137 * | Question | the question for the name server
138 * +------------+
139 * | Answer | RRs answering the question
140 * +------------+
141 * | Authority | RRs pointing toward an authority
142 * | Additional | RRs holding additional information
143 * +------------+
144 */
145 eom = answer->buf + anslen;
146 hp = &answer->hdr;
147 ancount = ntohs(hp->ancount); /* #/records in the answer section */
148 qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
149 bp = netbuf;
150 ep = netbuf + sizeof(netbuf);
151 cp = answer->buf + HFIXEDSZ;
152 if (!qdcount) {
153 if (hp->aa)
154 h_errno = HOST_NOT_FOUND;
155 else
156 h_errno = TRY_AGAIN;
157 return (NULL);
158 }
159 while (qdcount-- > 0) {
160 n = __dn_skipname(cp, eom);
161 if (n < 0 || (cp + n + QFIXEDSZ) > eom) {
162 h_errno = NO_RECOVERY;
163 return(NULL);
164 }
165 cp += n + QFIXEDSZ;
166 }
167 ap = net_aliases;
168 *ap = NULL;
169 net_entry.n_aliases = net_aliases;
170 haveanswer = 0;
171 while (--ancount >= 0 && cp < eom) {
172 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
173#ifdef USE_RESOLV_NAME_OK
174 if ((n < 0) || !res_dnok(bp))
175#else
176 if ((n < 0) || !_hokchar(bp))
177#endif
178 break;
179 cp += n;
180 ans[0] = '\0';
181 strlcpy(&ans[0], bp, sizeof ans);
182 GETSHORT(type, cp);
183 GETSHORT(class, cp);
184 cp += INT32SZ; /* TTL */
185 GETSHORT(n, cp);
186 if (class == C_IN && type == T_PTR) {
187 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
188#ifdef USE_RESOLV_NAME_OK
189 if ((n < 0) || !res_hnok(bp))
190#else
191 if ((n < 0) || !_hokchar(bp))
192#endif
193 {
194 cp += n;
195 return (NULL);
196 }
197 cp += n;
198 if ((ap + 2) < &net_aliases[MAXALIASES]) {
199 *ap++ = bp;
200 bp += strlen(bp) + 1;
201 net_entry.n_addrtype =
202 (class == C_IN) ? AF_INET : AF_UNSPEC;
203 haveanswer++;
204 }
205 }
206 }
207 if (haveanswer) {
208 *ap = NULL;
209 switch (net_i) {
210 case BYADDR:
211 net_entry.n_name = *net_entry.n_aliases;
212 net_entry.n_net = 0L;
213 break;
214 case BYNAME:
215 ap = net_entry.n_aliases;
216 next_alias:
217 in = *ap++;
218 if (in == NULL) {
219 h_errno = HOST_NOT_FOUND;
220 return (NULL);
221 }
222 net_entry.n_name = ans;
223 aux2[0] = '\0';
224 for (i = 0; i < 4; i++) {
225 for (st = in, nchar = 0;
226 isdigit((unsigned char)*st);
227 st++, nchar++)
228 ;
229 if (*st != '.' || nchar == 0 || nchar > 3)
230 goto next_alias;
231 if (i != 0)
232 nchar++;
233 strlcpy(paux1, in, nchar+1);
234 strlcat(paux1, paux2, MAXHOSTNAMELEN);
235 pauxt = paux2;
236 paux2 = paux1;
237 paux1 = pauxt;
238 in = ++st;
239 }
240 if (strcasecmp(in, "IN-ADDR.ARPA") != 0)
241 goto next_alias;
242 net_entry.n_net = inet_network(paux2);
243 break;
244 }
245 net_entry.n_aliases++;
246 return (&net_entry);
247 }
248 h_errno = TRY_AGAIN;
249 return (NULL);
250}
251
252struct netent *
253getnetbyaddr(net, net_type)
254 register in_addr_t net;
255 register int net_type;
256{
257 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
258 unsigned int netbr[4];
259 int nn, anslen;
260 querybuf *buf;
261 char qbuf[MAXDNAME];
262 in_addr_t net2;
263 struct netent *net_entry = NULL;
264 char lookups[MAXDNSLUS];
265 int i;
266
267 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
268 return(_getnetbyaddr(net, net_type));
269
270 bcopy(_resp->lookups, lookups, sizeof lookups);
271 if (lookups[0] == '\0')
272 strlcpy(lookups, "bf", sizeof lookups);
273
274 for (i = 0; i < MAXDNSLUS && lookups[i]; i++) {
275 switch (lookups[i]) {
276#ifdef YP
277 case 'y':
278 /* There is no YP support. */
279 break;
280#endif /* YP */
281 case 'b':
282 if (net_type != AF_INET)
283 break; /* DNS only supports AF_INET? */
284
285 for (nn = 4, net2 = net; net2; net2 >>= 8)
286 netbr[--nn] = net2 & 0xff;
287 switch (nn) {
288 case 3: /* Class A */
289 snprintf(qbuf, sizeof(qbuf),
290 "0.0.0.%u.in-addr.arpa", netbr[3]);
291 break;
292 case 2: /* Class B */
293 snprintf(qbuf, sizeof(qbuf),
294 "0.0.%u.%u.in-addr.arpa",
295 netbr[3], netbr[2]);
296 break;
297 case 1: /* Class C */
298 snprintf(qbuf, sizeof(qbuf),
299 "0.%u.%u.%u.in-addr.arpa",
300 netbr[3], netbr[2], netbr[1]);
301 break;
302 case 0: /* Class D - E */
303 snprintf(qbuf, sizeof(qbuf),
304 "%u.%u.%u.%u.in-addr.arpa",
305 netbr[3], netbr[2], netbr[1], netbr[0]);
306 break;
307 }
308 buf = malloc(sizeof(*buf));
309 if (buf == NULL)
310 break;
311 anslen = res_query(qbuf, C_IN, T_PTR, buf->buf,
312 sizeof(buf->buf));
313 if (anslen < 0) {
314 free(buf);
315#ifdef DEBUG
316 if (_resp->options & RES_DEBUG)
317 printf("res_query failed\n");
318#endif
319 break;
320 }
321 net_entry = getnetanswer(buf, anslen, BYADDR);
322 free(buf);
323 if (net_entry != NULL) {
324 unsigned u_net = net; /* maybe net should be unsigned ? */
325
326 /* Strip trailing zeros */
327 while ((u_net & 0xff) == 0 && u_net != 0)
328 u_net >>= 8;
329 net_entry->n_net = u_net;
330 return (net_entry);
331 }
332 break;
333 case 'f':
334 net_entry = _getnetbyaddr(net, net_type);
335 if (net_entry != NULL)
336 return (net_entry);
337 }
338 }
339
340 /* Nothing matched. */
341 return (NULL);
342}
343
344struct netent *
345getnetbyname(net)
346 register const char *net;
347{
348 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
349 int anslen;
350 querybuf *buf;
351 char qbuf[MAXDNAME];
352 struct netent *net_entry = NULL;
353 char lookups[MAXDNSLUS];
354 int i;
355
356 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
357 return (_getnetbyname(net));
358
359 bcopy(_resp->lookups, lookups, sizeof lookups);
360 if (lookups[0] == '\0')
361 strlcpy(lookups, "bf", sizeof lookups);
362
363 for (i = 0; i < MAXDNSLUS && lookups[i]; i++) {
364 switch (lookups[i]) {
365#ifdef YP
366 case 'y':
367 /* There is no YP support. */
368 break;
369#endif /* YP */
370 case 'b':
371 strlcpy(qbuf, net, sizeof qbuf);
372 buf = malloc(sizeof(*buf));
373 if (buf == NULL)
374 break;
375 anslen = res_search(qbuf, C_IN, T_PTR, buf->buf,
376 sizeof(buf->buf));
377 if (anslen < 0) {
378 free(buf);
379#ifdef DEBUG
380 if (_resp->options & RES_DEBUG)
381 printf("res_query failed\n");
382#endif
383 break;
384 }
385 net_entry = getnetanswer(buf, anslen, BYNAME);
386 free(buf);
387 if (net_entry != NULL)
388 return (net_entry);
389 break;
390 case 'f':
391 net_entry = _getnetbyname(net);
392 if (net_entry != NULL)
393 return (net_entry);
394 break;
395 }
396 }
397
398 /* Nothing matched. */
399 return (NULL);
400}