]> git.ipfire.org Git - thirdparty/glibc.git/blame - resolv/nss_dns/dns-network.c
Update.
[thirdparty/glibc.git] / resolv / nss_dns / dns-network.c
CommitLineData
67479a70 1/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
84384f5b
UD
2 This file is part of the GNU C Library.
3 Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996.
5f0e6fc7 4
84384f5b
UD
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
5f0e6fc7 9
84384f5b
UD
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
5f0e6fc7 14
84384f5b
UD
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
5f0e6fc7
RM
19
20/* Parts of this file are plain copies of the file `getnetnamadr.c' from
21 the bind package and it has the following copyright. */
22
23/* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
24 * Dep. Matematica Universidade de Coimbra, Portugal, Europe
25 *
26 * Permission to use, copy, modify, and distribute this software for any
27 * purpose with or without fee is hereby granted, provided that the above
28 * copyright notice and this permission notice appear in all copies.
29 */
30/*
31 * Copyright (c) 1983, 1993
32 * The Regents of the University of California. All rights reserved.
33 *
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
36 * are met:
37 * 1. Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
39 * 2. Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in the
41 * documentation and/or other materials provided with the distribution.
42 * 3. All advertising materials mentioning features or use of this software
43 * must display the following acknowledgement:
44 * This product includes software developed by the University of
45 * California, Berkeley and its contributors.
46 * 4. 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#include <ctype.h>
64#include <errno.h>
65#include <netdb.h>
66#include <stdio.h>
67#include <stdlib.h>
68#include <string.h>
69
70#include "nsswitch.h"
71#include <arpa/inet.h>
72
73/* Maximum number of aliases we allow. */
74#define MAX_NR_ALIASES 48
75
76
77#if PACKETSZ > 1024
78#define MAXPACKET PACKETSZ
79#else
80#define MAXPACKET 1024
81#endif
82
83
84typedef enum
85{
86 BYADDR,
87 BYNAME
88} lookup_method;
89
90
91/* We need this time later. */
92typedef union querybuf
93{
94 HEADER hdr;
95 u_char buf[MAXPACKET];
96} querybuf;
97
98
6d52618b 99/* Prototypes for local functions. */
84384f5b
UD
100static enum nss_status getanswer_r (const querybuf *answer, int anslen,
101 struct netent *result, char *buffer,
df4ef2ab 102 size_t buflen, lookup_method net_i);
5f0e6fc7
RM
103
104
84384f5b 105enum nss_status
5f0e6fc7 106_nss_dns_getnetbyname_r (const char *name, struct netent *result,
67479a70 107 char *buffer, size_t buflen, int *errnop)
5f0e6fc7
RM
108{
109 /* Return entry for network with NAME. */
110 querybuf net_buffer;
111 int anslen;
112 char *qbuf;
113
114 qbuf = strdupa (name);
115 anslen = res_search (qbuf, C_IN, T_PTR, (u_char *) &net_buffer,
116 sizeof (querybuf));
117 if (anslen < 0)
67479a70
UD
118 {
119 /* Nothing found. */
120 *errnop = errno;
121 return (errno == ECONNREFUSED
122 || errno == EPFNOSUPPORT
123 || errno == EAFNOSUPPORT)
124 ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
125 }
5f0e6fc7
RM
126
127 return getanswer_r (&net_buffer, anslen, result, buffer, buflen, BYNAME);
128}
129
130
84384f5b 131enum nss_status
5f0e6fc7 132_nss_dns_getnetbyaddr_r (long net, int type, struct netent *result,
67479a70 133 char *buffer, size_t buflen, int *errnop)
5f0e6fc7
RM
134{
135 /* Return entry for network with NAME. */
84384f5b 136 enum nss_status status;
5f0e6fc7
RM
137 querybuf net_buffer;
138 unsigned int net_bytes[4];
139 char qbuf[MAXDNAME];
140 int cnt, anslen;
141 u_int32_t net2;
142
143 /* No net address lookup for IPv6 yet. */
144 if (type != AF_INET)
145 return NSS_STATUS_UNAVAIL;
146
147 net2 = (u_int32_t) net;
148 for (cnt = 4; net2 != 0; net2 >>= 8)
149 net_bytes[--cnt] = net2 & 0xff;
150
151 switch (cnt)
152 {
153 case 3:
154 /* Class A network. */
155 sprintf (qbuf, "0.0.0.%u.in-addr.arpa", net_bytes[3]);
156 break;
157 case 2:
158 /* Class B network. */
159 sprintf (qbuf, "0.0.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2]);
160 break;
161 case 1:
162 /* Class C network. */
163 sprintf (qbuf, "0.%u.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2],
164 net_bytes[1]);
165 break;
166 case 0:
167 /* Class D - E network. */
168 sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2],
169 net_bytes[1], net_bytes[0]);
170 break;
171 }
172
173 anslen = res_query (qbuf, C_IN, T_PTR, (u_char *) &net_buffer,
174 sizeof (querybuf));
175 if (anslen < 0)
67479a70
UD
176 {
177 /* Nothing found. */
178 *errnop = errno;
179 return (errno == ECONNREFUSED
180 || errno == EPFNOSUPPORT
181 || errno == EAFNOSUPPORT)
182 ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
183 }
5f0e6fc7
RM
184
185 status = getanswer_r (&net_buffer, anslen, result, buffer, buflen, BYADDR);
186 if (status == NSS_STATUS_SUCCESS)
187 {
188 /* Strip trailing zeros. */
189 unsigned int u_net = net; /* Maybe net should be unsigned? */
190
191 while ((u_net & 0xff) == 0 && u_net != 0)
192 u_net >>= 8;
193 result->n_net = u_net;
194 }
195
196 return status;
197}
198
199
200#undef offsetof
201#define offsetof(Type, Member) ((size_t) &((Type *) NULL)->Member)
202
84384f5b 203static enum nss_status
5f0e6fc7 204getanswer_r (const querybuf *answer, int anslen, struct netent *result,
df4ef2ab 205 char *buffer, size_t buflen, lookup_method net_i)
5f0e6fc7
RM
206{
207 /*
208 * Find first satisfactory answer
209 *
210 * answer --> +------------+ ( MESSAGE )
211 * | Header |
212 * +------------+
213 * | Question | the question for the name server
214 * +------------+
215 * | Answer | RRs answering the question
216 * +------------+
217 * | Authority | RRs pointing toward an authority
218 * | Additional | RRs holding additional information
219 * +------------+
220 */
221 struct net_data
222 {
223 char *aliases[MAX_NR_ALIASES];
224 char linebuffer[0];
225 } *net_data = (struct net_data *) buffer;
226 int linebuflen = buflen - offsetof (struct net_data, linebuffer);
227 const char *end_of_message = &answer->buf[anslen];
228 const HEADER *header_pointer = &answer->hdr;
229 /* #/records in the answer section. */
230 int answer_count = ntohs (header_pointer->ancount);
231 /* #/entries in the question section. */
232 int question_count = ntohs (header_pointer->qdcount);
233 char *bp = net_data->linebuffer;
234 const char *cp = &answer->buf[HFIXEDSZ];
235 char **alias_pointer;
236 int have_answer;
237 char *ans;
238
239 if (question_count == 0)
7ef90c15
UD
240 {
241 /* FIXME: the Sun version uses for host name lookup an additional
242 parameter for pointing to h_errno. this is missing here.
243 OSF/1 has a per-thread h_errno variable. */
244 if (header_pointer->aa != 0)
245 {
246 __set_h_errno (HOST_NOT_FOUND);
247 return NSS_STATUS_NOTFOUND;
248 }
249 else
250 {
251 __set_h_errno (TRY_AGAIN);
252 return NSS_STATUS_TRYAGAIN;
253 }
254 }
5f0e6fc7
RM
255
256 /* Skip the question part. */
257 while (question_count-- > 0)
258 cp += __dn_skipname (cp, end_of_message) + QFIXEDSZ;
259
260 alias_pointer = result->n_aliases = &net_data->aliases[0];
261 *alias_pointer = NULL;
262 have_answer = 0;
263 ans = NULL;
264
265 while (--answer_count >= 0 && cp < end_of_message)
266 {
267 int n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
268 int type, class;
269
270 if (n < 0 || res_dnok (bp) == 0)
271 break;
272 cp += n;
273 ans = strdupa (bp);
274 GETSHORT (type, cp);
275 GETSHORT (class, cp);
276 cp += INT32SZ; /* TTL */
277 GETSHORT (n, cp);
278
279 if (class == C_IN && type == T_PTR)
280 {
281 n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
282 if (n < 0 || !res_hnok (bp))
283 {
284 /* XXX What does this mean? The original form from bind
285 returns NULL. Incrementing cp has no effect in any case.
286 What should I return here. ??? */
287 cp += n;
288 return NSS_STATUS_UNAVAIL;
289 }
290 cp += n;
291 *alias_pointer++ = bp;
292 bp += strlen (bp) + 1;
293 result->n_addrtype = class == C_IN ? AF_INET : AF_UNSPEC;
294 ++have_answer;
295 }
296 }
297
298 if (have_answer)
299 {
300 char *tmp;
301 int len;
302 char *in, *cp, *rp, *wp;
303 int cnt, first_flag;
304
305 *alias_pointer = NULL;
306 switch (net_i)
307 {
308 case BYADDR:
309 result->n_name = result->n_aliases[0];
310 result->n_net = 0L;
311 break;
312 case BYNAME:
313 len = strlen (result->n_aliases[0]);
314 tmp = (char *) alloca (len + 1);
315 tmp[len] = 0;
316 wp = &tmp[len - 1];
317
318 rp = in = result->n_aliases[0];
319 result->n_name = ans;
320
321 first_flag = 1;
322 for (cnt = 0; cnt < 4; ++cnt)
323 {
324 char *startp;
325
326 startp = rp;
327 while (*rp != '.')
328 ++rp;
329 if (rp - startp > 1 || *startp != '0' || !first_flag)
330 {
331 first_flag = 0;
332 if (cnt > 0)
333 *wp-- = '.';
334 cp = rp;
335 while (cp > startp)
336 *wp-- = *--cp;
337 }
338 in = rp + 1;
339 }
340
341 result->n_net = inet_network (wp);
342 break;
343 }
344
345 ++result->n_aliases;
346 return NSS_STATUS_SUCCESS;
347 }
348
a68b0d31 349 __set_h_errno (TRY_AGAIN);
5f0e6fc7
RM
350 return NSS_STATUS_TRYAGAIN;
351}