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