Libinfo-173.tar.gz
[apple/libinfo.git] / dns.subproj / getnetnamadr.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
26 * Dep. Matematica Universidade de Coimbra, Portugal, Europe
27 *
28 * Permission to use, copy, modify, and distribute this software for any
29 * purpose with or without fee is hereby granted, provided that the above
30 * copyright notice and this permission notice appear in all copies.
31 */
32 /*
33 * Copyright (c) 1983, 1993
34 * The Regents of the University of California. All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by the University of
47 * California, Berkeley and its contributors.
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 */
64
65 #if defined(LIBC_SCCS) && !defined(lint)
66 static char sccsid[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93";
67 static char sccsid_[] = "from getnetnamadr.c 1.4 (Coimbra) 93/06/03";
68 static char rcsid[] = "$Id: getnetnamadr.c,v 1.4 2003/02/18 17:29:23 majka Exp $";
69 #endif /* LIBC_SCCS and not lint */
70
71 #include <sys/param.h>
72 #include <sys/socket.h>
73 #include <netinet/in.h>
74 #include <arpa/inet.h>
75 #include <arpa/nameser8_compat.h>
76
77 #include <stdio.h>
78 #include <stdlib.h>
79 #include <netdb.h>
80 #include <resolv8_compat.h>
81 #include <ctype.h>
82 #include <errno.h>
83 #include <string.h>
84
85 extern int h_errno;
86
87 #if defined(mips) && defined(SYSTYPE_BSD43)
88 extern int errno;
89 #endif
90
91 struct netent *_getnetbyaddr __P((long net, int type));
92 struct netent *_getnetbyname __P((const char *name));
93
94 #define BYADDR 0
95 #define BYNAME 1
96 #define MAXALIASES 35
97
98 #if PACKETSZ > 1024
99 #define MAXPACKET PACKETSZ
100 #else
101 #define MAXPACKET 1024
102 #endif
103
104 typedef union {
105 HEADER hdr;
106 u_char buf[MAXPACKET];
107 } querybuf;
108
109 typedef union {
110 long al;
111 char ac;
112 } align;
113
114 static struct netent *
115 getnetanswer(answer, anslen, net_i)
116 querybuf *answer;
117 int anslen;
118 int net_i;
119 {
120
121 register HEADER *hp;
122 register u_char *cp;
123 register int n;
124 u_char *eom;
125 int type, class, buflen, ancount, qdcount, haveanswer, i, nchar;
126 char aux1[30], aux2[30], ans[30], *in, *st, *pauxt, *bp, **ap,
127 *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0;
128 static struct netent net_entry;
129 static char *net_aliases[MAXALIASES], *netbuf = NULL;
130
131 if (netbuf == NULL) {
132 netbuf = malloc(BUFSIZ+1);
133 if (netbuf == NULL)
134 return (NULL);
135 }
136 buflen = BUFSIZ+1;
137
138 /*
139 * find first satisfactory answer
140 *
141 * answer --> +------------+ ( MESSAGE )
142 * | Header |
143 * +------------+
144 * | Question | the question for the name server
145 * +------------+
146 * | Answer | RRs answering the question
147 * +------------+
148 * | Authority | RRs pointing toward an authority
149 * | Additional | RRs holding additional information
150 * +------------+
151 */
152 eom = answer->buf + anslen;
153 hp = &answer->hdr;
154 ancount = ntohs(hp->ancount); /* #/records in the answer section */
155 qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
156 bp = netbuf;
157 cp = answer->buf + HFIXEDSZ;
158 if (!qdcount) {
159 if (hp->aa)
160 h_errno = HOST_NOT_FOUND;
161 else
162 h_errno = TRY_AGAIN;
163 return (NULL);
164 }
165 while (qdcount-- > 0)
166 cp += __dn_skipname(cp, eom) + QFIXEDSZ;
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, buflen);
173 if (n < 0)
174 break;
175 cp += n;
176 ans[0] = '\0';
177 (void)strcpy(&ans[0], bp);
178 GETSHORT(type, cp);
179 GETSHORT(class, cp);
180 cp += INT32SZ; /* TTL */
181 GETSHORT(n, cp);
182 if (class == C_IN && type == T_PTR) {
183 n = dn_expand(answer->buf, eom, cp, bp, buflen);
184 if (n < 0) {
185 cp += n;
186 return (NULL);
187 }
188 cp += n;
189 *ap++ = bp;
190 bp += strlen(bp) + 1;
191 net_entry.n_addrtype =
192 (class == C_IN) ? AF_INET : AF_UNSPEC;
193 haveanswer++;
194 }
195 }
196 if (haveanswer) {
197 *ap = NULL;
198 switch (net_i) {
199 case BYADDR:
200 net_entry.n_name = *net_entry.n_aliases;
201 net_entry.n_net = 0L;
202 break;
203 case BYNAME:
204 in = *net_entry.n_aliases;
205 net_entry.n_name = &ans[0];
206 aux2[0] = '\0';
207 for (i = 0; i < 4; i++) {
208 for (st = in, nchar = 0;
209 *st != '.';
210 st++, nchar++)
211 ;
212 if (nchar != 1 || *in != '0' || flag) {
213 flag = 1;
214 (void)strncpy(paux1,
215 (i==0) ? in : in-1,
216 (i==0) ?nchar : nchar+1);
217 paux1[(i==0) ? nchar : nchar+1] = '\0';
218 pauxt = paux2;
219 paux2 = strcat(paux1, paux2);
220 paux1 = pauxt;
221 }
222 in = ++st;
223 }
224 net_entry.n_net = inet_network(paux2);
225 break;
226 }
227 net_entry.n_aliases++;
228 return (&net_entry);
229 }
230 h_errno = TRY_AGAIN;
231 return (NULL);
232 }
233
234 struct netent *
235 getnetbyaddr(net, net_type)
236 register long net;
237 register int net_type;
238 {
239 unsigned int netbr[4];
240 int nn, anslen;
241 querybuf buf;
242 char qbuf[MAXDNAME];
243 unsigned long net2;
244 struct netent *net_entry;
245
246 if (net_type != AF_INET)
247 #if defined(__APPLE__)
248 return NULL;
249 #else
250 return (_getnetbyaddr(net, net_type));
251 #endif /* !NeXT */
252
253 for (nn = 4, net2 = net; net2; net2 >>= 8)
254 netbr[--nn] = net2 & 0xff;
255 switch (nn) {
256 case 3: /* Class A */
257 sprintf(qbuf, "0.0.0.%u.in-addr.arpa", netbr[3]);
258 break;
259 case 2: /* Class B */
260 sprintf(qbuf, "0.0.%u.%u.in-addr.arpa", netbr[3], netbr[2]);
261 break;
262 case 1: /* Class C */
263 sprintf(qbuf, "0.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2],
264 netbr[1]);
265 break;
266 case 0: /* Class D - E */
267 sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2],
268 netbr[1], netbr[0]);
269 break;
270 }
271 anslen = res_query(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf));
272 if (anslen < 0) {
273 #ifdef DEBUG
274 if (_res.options & RES_DEBUG)
275 printf("res_query failed\n");
276 #endif
277 #if !defined(__APPLE__)
278 if (errno == ECONNREFUSED)
279 return (_getnetbyaddr(net, net_type));
280 #endif /* !NeXT */
281 return (NULL);
282 }
283 net_entry = getnetanswer(&buf, anslen, BYADDR);
284 if (net_entry) {
285 unsigned u_net = net; /* maybe net should be unsigned ? */
286
287 /* Strip trailing zeros */
288 while ((u_net & 0xff) == 0 && u_net != 0)
289 u_net >>= 8;
290 net_entry->n_net = u_net;
291 return (net_entry);
292 }
293 #if defined(__APPLE__)
294 return NULL;
295 #else
296 return (_getnetbyaddr(net, net_type));
297 #endif /* !NeXT */
298 }
299
300 struct netent *
301 getnetbyname(net)
302 register const char *net;
303 {
304 int anslen;
305 querybuf buf;
306 char qbuf[MAXDNAME];
307 struct netent *net_entry;
308
309 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
310 h_errno = NETDB_INTERNAL;
311 return (NULL);
312 }
313 strcpy(&qbuf[0], net);
314 anslen = res_search(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf));
315 if (anslen < 0) {
316 #ifdef DEBUG
317 if (_res.options & RES_DEBUG)
318 printf("res_query failed\n");
319 #endif
320 #if defined(__APPLE__)
321 return NULL;
322 #else
323 if (errno == ECONNREFUSED)
324 return (_getnetbyname(net));
325 return (_getnetbyname(net));
326 #endif /* !NeXT */
327 }
328 net_entry = getnetanswer(&buf, anslen, BYNAME);
329 if (net_entry)
330 return (net_entry);
331 #if defined(__APPLE__)
332 return NULL;
333 #else
334 return (_getnetbyname(net));
335 #endif /* !NeXT */
336 }