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.4 2005/04/27 04:56:31 sra 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 *
irs_lcl_nw(struct irs_acc * this)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
nw_close(struct irs_nw * this)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 *
nw_byaddr(struct irs_nw * this,void * net,int length,int type)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 *
nw_byname(struct irs_nw * this,const char * name,int type)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
nw_rewind(struct irs_nw * this)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 *
nw_next(struct irs_nw * this)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
nw_minimize(struct irs_nw * this)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 *
nw_res_get(struct irs_nw * this)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
nw_res_set(struct irs_nw * this,struct __res_state * res,void (* free_res)(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
init(struct irs_nw * this)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 }
372
373 /*! \file */
374