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