update the readme files for bind-9.3.4 import
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / bind / irs / lcl_nw.c
1 /*
2  * Copyright (c) 1989, 1993, 1995
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 /*
35  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
36  * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
37  *
38  * Permission to use, copy, modify, and distribute this software for any
39  * purpose with or without fee is hereby granted, provided that the above
40  * copyright notice and this permission notice appear in all copies.
41  *
42  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
43  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
44  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
45  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
46  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
47  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
48  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
49  */
50
51 #if defined(LIBC_SCCS) && !defined(lint)
52 static const char rcsid[] = "$Id: lcl_nw.c,v 1.1.2.2 2004/03/17 00:40:13 marka Exp $";
53 /* from getgrent.c 8.2 (Berkeley) 3/21/94"; */
54 /* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $      */
55 #endif /* LIBC_SCCS and not lint */
56
57 /* Imports */
58
59 #include "port_before.h"
60
61 #include <sys/types.h>
62 #include <sys/socket.h>
63
64 #include <netinet/in.h>
65 #include <arpa/inet.h>
66 #include <arpa/nameser.h>
67
68 #include <errno.h>
69 #include <fcntl.h>
70 #include <resolv.h>
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <string.h>
74
75 #include <irs.h>
76 #include <isc/memcluster.h>
77
78 #include "port_after.h"
79
80 #include <isc/misc.h>
81 #include "irs_p.h"
82 #include "lcl_p.h"
83
84 #define MAXALIASES 35
85 #define MAXADDRSIZE 4
86
87 struct pvt {
88         FILE *          fp;
89         char            line[BUFSIZ+1];
90         struct nwent    net;
91         char *          aliases[MAXALIASES];
92         char            addr[MAXADDRSIZE];
93         struct __res_state *  res;
94         void            (*free_res)(void *);
95 };
96
97 /* Forward */
98
99 static void             nw_close(struct irs_nw *);
100 static struct nwent *   nw_byname(struct irs_nw *, const char *, int);
101 static struct nwent *   nw_byaddr(struct irs_nw *, void *, int, int);
102 static struct nwent *   nw_next(struct irs_nw *);
103 static void             nw_rewind(struct irs_nw *);
104 static void             nw_minimize(struct irs_nw *);
105 static struct __res_state * nw_res_get(struct irs_nw *this);
106 static void             nw_res_set(struct irs_nw *this,
107                                    struct __res_state *res,
108                                    void (*free_res)(void *));
109
110 static int              init(struct irs_nw *this);
111
112 /* Portability. */
113
114 #ifndef SEEK_SET
115 # define SEEK_SET 0
116 #endif
117
118 /* Public */
119
120 struct irs_nw *
121 irs_lcl_nw(struct irs_acc *this) {
122         struct irs_nw *nw;
123         struct pvt *pvt;
124
125         UNUSED(this);
126
127         if (!(pvt = memget(sizeof *pvt))) {
128                 errno = ENOMEM;
129                 return (NULL);
130         }
131         memset(pvt, 0, sizeof *pvt);
132         if (!(nw = memget(sizeof *nw))) {
133                 memput(pvt, sizeof *pvt);
134                 errno = ENOMEM;
135                 return (NULL);
136         }
137         memset(nw, 0x5e, sizeof *nw);
138         nw->private = pvt;
139         nw->close = nw_close;
140         nw->byname = nw_byname;
141         nw->byaddr = nw_byaddr;
142         nw->next = nw_next;
143         nw->rewind = nw_rewind;
144         nw->minimize = nw_minimize;
145         nw->res_get = nw_res_get;
146         nw->res_set = nw_res_set;
147         return (nw);
148 }
149
150 /* Methods */
151
152 static void
153 nw_close(struct irs_nw *this) {
154         struct pvt *pvt = (struct pvt *)this->private;
155         
156         nw_minimize(this);
157         if (pvt->res && pvt->free_res)
158                 (*pvt->free_res)(pvt->res);
159         if (pvt->fp)
160                 (void)fclose(pvt->fp);
161         memput(pvt, sizeof *pvt);
162         memput(this, sizeof *this);
163 }
164
165 static struct nwent *
166 nw_byaddr(struct irs_nw *this, void *net, int length, int type) {
167         struct nwent *p;
168         
169         if (init(this) == -1)
170                 return(NULL);
171
172         nw_rewind(this);
173         while ((p = nw_next(this)) != NULL)
174                 if (p->n_addrtype == type && p->n_length == length)
175                         if (bitncmp(p->n_addr, net, length) == 0)
176                                 break;
177         return (p);
178 }
179
180 static struct nwent *
181 nw_byname(struct irs_nw *this, const char *name, int type) {
182         struct nwent *p;
183         char **ap;
184         
185         if (init(this) == -1)
186                 return(NULL);
187
188         nw_rewind(this);
189         while ((p = nw_next(this)) != NULL) {
190                 if (ns_samename(p->n_name, name) == 1 &&
191                     p->n_addrtype == type)
192                         break;
193                 for (ap = p->n_aliases; *ap; ap++)
194                         if ((ns_samename(*ap, name) == 1) &&
195                             (p->n_addrtype == type))
196                                 goto found;
197         }
198  found:
199         return (p);
200 }
201
202 static void
203 nw_rewind(struct irs_nw *this) {
204         struct pvt *pvt = (struct pvt *)this->private;
205         
206         if (pvt->fp) {
207                 if (fseek(pvt->fp, 0L, SEEK_SET) == 0)
208                         return;
209                 (void)fclose(pvt->fp);
210         }
211         if (!(pvt->fp = fopen(_PATH_NETWORKS, "r")))
212                 return;
213         if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) {
214                 (void)fclose(pvt->fp);
215                 pvt->fp = NULL;
216         }
217 }
218
219 static struct nwent *
220 nw_next(struct irs_nw *this) {
221         struct pvt *pvt = (struct pvt *)this->private;
222         struct nwent *ret = NULL;
223         char *p, *cp, **q;
224         char *bufp, *ndbuf, *dbuf = NULL;
225         int c, bufsiz, offset = 0;
226
227         if (init(this) == -1)
228                 return(NULL);
229
230         if (pvt->fp == NULL)
231                 nw_rewind(this);
232         if (pvt->fp == NULL) {
233                 RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
234                 return (NULL);
235         }
236         bufp = pvt->line;
237         bufsiz = sizeof(pvt->line);
238
239  again:
240         p = fgets(bufp + offset, bufsiz - offset, pvt->fp);
241         if (p == NULL)
242                 goto cleanup;
243         if (!strchr(p, '\n') && !feof(pvt->fp)) {
244 #define GROWBUF 1024
245                 /* allocate space for longer line */
246                 if (dbuf == NULL) {
247                         if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL)
248                                 strcpy(ndbuf, bufp);
249                 } else
250                         ndbuf = realloc(dbuf, bufsiz + GROWBUF);
251                 if (ndbuf) {
252                         dbuf = ndbuf;
253                         bufp = dbuf;
254                         bufsiz += GROWBUF;
255                         offset = strlen(dbuf);
256                 } else {
257                         /* allocation failed; skip this long line */
258                         while ((c = getc(pvt->fp)) != EOF)
259                                 if (c == '\n')
260                                         break;
261                         if (c != EOF)
262                                 ungetc(c, pvt->fp);
263                 }
264                 goto again;
265         }
266
267         p -= offset;
268         offset = 0;
269
270         if (*p == '#')
271                 goto again;
272
273         cp = strpbrk(p, "#\n");
274         if (cp != NULL)
275                 *cp = '\0';
276         pvt->net.n_name = p;
277         cp = strpbrk(p, " \t");
278         if (cp == NULL)
279                 goto again;
280         *cp++ = '\0';
281         while (*cp == ' ' || *cp == '\t')
282                 cp++;
283         p = strpbrk(cp, " \t");
284         if (p != NULL)
285                 *p++ = '\0';
286         pvt->net.n_length = inet_net_pton(AF_INET, cp, pvt->addr,
287                                           sizeof pvt->addr);
288         if (pvt->net.n_length < 0)
289                 goto again;
290         pvt->net.n_addrtype = AF_INET;
291         pvt->net.n_addr = pvt->addr;
292         q = pvt->net.n_aliases = pvt->aliases;
293         if (p != NULL) {
294                 cp = p;
295                 while (cp && *cp) {
296                         if (*cp == ' ' || *cp == '\t') {
297                                 cp++;
298                                 continue;
299                         }
300                         if (q < &pvt->aliases[MAXALIASES - 1])
301                                 *q++ = cp;
302                         cp = strpbrk(cp, " \t");
303                         if (cp != NULL)
304                                 *cp++ = '\0';
305                 }
306         }
307         *q = NULL;
308         ret = &pvt->net;
309
310  cleanup:
311         if (dbuf)
312                 free(dbuf);
313
314         return (ret);
315 }
316
317 static void
318 nw_minimize(struct irs_nw *this) {
319         struct pvt *pvt = (struct pvt *)this->private;
320
321         if (pvt->res)
322                 res_nclose(pvt->res);
323         if (pvt->fp != NULL) {
324                 (void)fclose(pvt->fp);
325                 pvt->fp = NULL;
326         }
327 }
328
329 static struct __res_state *
330 nw_res_get(struct irs_nw *this) {
331         struct pvt *pvt = (struct pvt *)this->private;
332
333         if (!pvt->res) {
334                 struct __res_state *res;
335                 res = (struct __res_state *)malloc(sizeof *res);
336                 if (!res) {
337                         errno = ENOMEM;
338                         return (NULL);
339                 }
340                 memset(res, 0, sizeof *res);
341                 nw_res_set(this, res, free);
342         }
343
344         return (pvt->res);
345 }
346
347 static void
348 nw_res_set(struct irs_nw *this, struct __res_state *res,
349                 void (*free_res)(void *)) {
350         struct pvt *pvt = (struct pvt *)this->private;
351
352         if (pvt->res && pvt->free_res) {
353                 res_nclose(pvt->res);
354                 (*pvt->free_res)(pvt->res);
355         }
356
357         pvt->res = res;
358         pvt->free_res = free_res;
359 }
360
361 static int
362 init(struct irs_nw *this) {
363         struct pvt *pvt = (struct pvt *)this->private;
364         
365         if (!pvt->res && !nw_res_get(this))
366                 return (-1);
367         if (((pvt->res->options & RES_INIT) == 0U) &&
368             res_ninit(pvt->res) == -1)
369                 return (-1);
370         return (0);
371 }