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 /* from getgrent.c 8.2 (Berkeley) 3/21/94"; */
52 /* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $	*/
53 
54 /* Imports */
55 
56 #include "port_before.h"
57 
58 #include <sys/types.h>
59 #include <sys/socket.h>
60 
61 #include <netinet/in.h>
62 #include <arpa/inet.h>
63 #include <arpa/nameser.h>
64 
65 #include <errno.h>
66 #include <fcntl.h>
67 #include <resolv.h>
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <string.h>
71 
72 #include <irs.h>
73 #include <isc/memcluster.h>
74 
75 #include "port_after.h"
76 
77 #include <isc/misc.h>
78 #include "irs_p.h"
79 #include "lcl_p.h"
80 
81 #define MAXALIASES 35
82 #define MAXADDRSIZE 4
83 
84 struct pvt {
85 	FILE *		fp;
86 	char 		line[BUFSIZ+1];
87 	struct nwent 	net;
88 	char *		aliases[MAXALIASES];
89 	char		addr[MAXADDRSIZE];
90 	struct __res_state *  res;
91 	void		(*free_res)(void *);
92 };
93 
94 /* Forward */
95 
96 static void 		nw_close(struct irs_nw *);
97 static struct nwent *	nw_byname(struct irs_nw *, const char *, int);
98 static struct nwent *	nw_byaddr(struct irs_nw *, void *, int, int);
99 static struct nwent *	nw_next(struct irs_nw *);
100 static void		nw_rewind(struct irs_nw *);
101 static void		nw_minimize(struct irs_nw *);
102 static struct __res_state * nw_res_get(struct irs_nw *this);
103 static void		nw_res_set(struct irs_nw *this,
104 				   struct __res_state *res,
105 				   void (*free_res)(void *));
106 
107 static int		init(struct irs_nw *this);
108 
109 /* Portability. */
110 
111 #ifndef SEEK_SET
112 # define SEEK_SET 0
113 #endif
114 
115 /* Public */
116 
117 struct irs_nw *
irs_lcl_nw(struct irs_acc * this)118 irs_lcl_nw(struct irs_acc *this) {
119 	struct irs_nw *nw;
120 	struct pvt *pvt;
121 
122 	UNUSED(this);
123 
124 	if (!(pvt = memget(sizeof *pvt))) {
125 		errno = ENOMEM;
126 		return (NULL);
127 	}
128 	memset(pvt, 0, sizeof *pvt);
129 	if (!(nw = memget(sizeof *nw))) {
130 		memput(pvt, sizeof *pvt);
131 		errno = ENOMEM;
132 		return (NULL);
133 	}
134 	memset(nw, 0x5e, sizeof *nw);
135 	nw->private = pvt;
136 	nw->close = nw_close;
137 	nw->byname = nw_byname;
138 	nw->byaddr = nw_byaddr;
139 	nw->next = nw_next;
140 	nw->rewind = nw_rewind;
141 	nw->minimize = nw_minimize;
142 	nw->res_get = nw_res_get;
143 	nw->res_set = nw_res_set;
144 	return (nw);
145 }
146 
147 /* Methods */
148 
149 static void
nw_close(struct irs_nw * this)150 nw_close(struct irs_nw *this) {
151 	struct pvt *pvt = (struct pvt *)this->private;
152 
153 	nw_minimize(this);
154 	if (pvt->res && pvt->free_res)
155 		(*pvt->free_res)(pvt->res);
156 	if (pvt->fp)
157 		(void)fclose(pvt->fp);
158 	memput(pvt, sizeof *pvt);
159 	memput(this, sizeof *this);
160 }
161 
162 static struct nwent *
nw_byaddr(struct irs_nw * this,void * net,int length,int type)163 nw_byaddr(struct irs_nw *this, void *net, int length, int type) {
164 	struct nwent *p;
165 
166 	if (init(this) == -1)
167 		return(NULL);
168 
169 	nw_rewind(this);
170 	while ((p = nw_next(this)) != NULL)
171 		if (p->n_addrtype == type && p->n_length == length)
172 			if (bitncmp(p->n_addr, net, length) == 0)
173 				break;
174 	return (p);
175 }
176 
177 static struct nwent *
nw_byname(struct irs_nw * this,const char * name,int type)178 nw_byname(struct irs_nw *this, const char *name, int type) {
179 	struct nwent *p;
180 	char **ap;
181 
182 	if (init(this) == -1)
183 		return(NULL);
184 
185 	nw_rewind(this);
186 	while ((p = nw_next(this)) != NULL) {
187 		if (ns_samename(p->n_name, name) == 1 &&
188 		    p->n_addrtype == type)
189 			break;
190 		for (ap = p->n_aliases; *ap; ap++)
191 			if ((ns_samename(*ap, name) == 1) &&
192 			    (p->n_addrtype == type))
193 				goto found;
194 	}
195  found:
196 	return (p);
197 }
198 
199 static void
nw_rewind(struct irs_nw * this)200 nw_rewind(struct irs_nw *this) {
201 	struct pvt *pvt = (struct pvt *)this->private;
202 
203 	if (pvt->fp) {
204 		if (fseek(pvt->fp, 0L, SEEK_SET) == 0)
205 			return;
206 		(void)fclose(pvt->fp);
207 	}
208 	if (!(pvt->fp = fopen(_PATH_NETWORKS, "r")))
209 		return;
210 	if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) {
211 		(void)fclose(pvt->fp);
212 		pvt->fp = NULL;
213 	}
214 }
215 
216 static struct nwent *
nw_next(struct irs_nw * this)217 nw_next(struct irs_nw *this) {
218 	struct pvt *pvt = (struct pvt *)this->private;
219 	struct nwent *ret = NULL;
220 	char *p, *cp, **q;
221 	char *bufp, *ndbuf, *dbuf = NULL;
222 	int c, bufsiz, offset = 0;
223 
224 	if (init(this) == -1)
225 		return(NULL);
226 
227 	if (pvt->fp == NULL)
228 		nw_rewind(this);
229 	if (pvt->fp == NULL) {
230 		RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
231 		return (NULL);
232 	}
233 	bufp = pvt->line;
234 	bufsiz = sizeof(pvt->line);
235 
236  again:
237 	p = fgets(bufp + offset, bufsiz - offset, pvt->fp);
238 	if (p == NULL)
239 		goto cleanup;
240 	if (!strchr(p, '\n') && !feof(pvt->fp)) {
241 #define GROWBUF 1024
242 		/* allocate space for longer line */
243 	  	if (dbuf == NULL) {
244 			if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL)
245 				strcpy(ndbuf, bufp);
246 		} else
247 			ndbuf = realloc(dbuf, bufsiz + GROWBUF);
248 		if (ndbuf) {
249 			dbuf = ndbuf;
250 			bufp = dbuf;
251 			bufsiz += GROWBUF;
252 			offset = strlen(dbuf);
253 		} else {
254 			/* allocation failed; skip this long line */
255 			while ((c = getc(pvt->fp)) != EOF)
256 				if (c == '\n')
257 					break;
258 			if (c != EOF)
259 				ungetc(c, pvt->fp);
260 		}
261 		goto again;
262 	}
263 
264 	p -= offset;
265 	offset = 0;
266 
267 	if (*p == '#')
268 		goto again;
269 
270 	cp = strpbrk(p, "#\n");
271 	if (cp != NULL)
272 		*cp = '\0';
273 	pvt->net.n_name = p;
274 	cp = strpbrk(p, " \t");
275 	if (cp == NULL)
276 		goto again;
277 	*cp++ = '\0';
278 	while (*cp == ' ' || *cp == '\t')
279 		cp++;
280 	p = strpbrk(cp, " \t");
281 	if (p != NULL)
282 		*p++ = '\0';
283 	pvt->net.n_length = inet_net_pton(AF_INET, cp, pvt->addr,
284 					  sizeof pvt->addr);
285 	if (pvt->net.n_length < 0)
286 		goto again;
287 	pvt->net.n_addrtype = AF_INET;
288 	pvt->net.n_addr = pvt->addr;
289 	q = pvt->net.n_aliases = pvt->aliases;
290 	if (p != NULL) {
291 		cp = p;
292 		while (cp && *cp) {
293 			if (*cp == ' ' || *cp == '\t') {
294 				cp++;
295 				continue;
296 			}
297 			if (q < &pvt->aliases[MAXALIASES - 1])
298 				*q++ = cp;
299 			cp = strpbrk(cp, " \t");
300 			if (cp != NULL)
301 				*cp++ = '\0';
302 		}
303 	}
304 	*q = NULL;
305 	ret = &pvt->net;
306 
307  cleanup:
308 	if (dbuf)
309 		free(dbuf);
310 
311 	return (ret);
312 }
313 
314 static void
nw_minimize(struct irs_nw * this)315 nw_minimize(struct irs_nw *this) {
316 	struct pvt *pvt = (struct pvt *)this->private;
317 
318 	if (pvt->res)
319 		res_nclose(pvt->res);
320 	if (pvt->fp != NULL) {
321 		(void)fclose(pvt->fp);
322 		pvt->fp = NULL;
323 	}
324 }
325 
326 static struct __res_state *
nw_res_get(struct irs_nw * this)327 nw_res_get(struct irs_nw *this) {
328 	struct pvt *pvt = (struct pvt *)this->private;
329 
330 	if (!pvt->res) {
331 		struct __res_state *res;
332 		res = (struct __res_state *)malloc(sizeof *res);
333 		if (!res) {
334 			errno = ENOMEM;
335 			return (NULL);
336 		}
337 		memset(res, 0, sizeof *res);
338 		nw_res_set(this, res, free);
339 	}
340 
341 	return (pvt->res);
342 }
343 
344 static void
nw_res_set(struct irs_nw * this,struct __res_state * res,void (* free_res)(void *))345 nw_res_set(struct irs_nw *this, struct __res_state *res,
346 		void (*free_res)(void *)) {
347 	struct pvt *pvt = (struct pvt *)this->private;
348 
349 	if (pvt->res && pvt->free_res) {
350 		res_nclose(pvt->res);
351 		(*pvt->free_res)(pvt->res);
352 	}
353 
354 	pvt->res = res;
355 	pvt->free_res = free_res;
356 }
357 
358 static int
init(struct irs_nw * this)359 init(struct irs_nw *this) {
360 	struct pvt *pvt = (struct pvt *)this->private;
361 
362 	if (!pvt->res && !nw_res_get(this))
363 		return (-1);
364 	if (((pvt->res->options & RES_INIT) == 0U) &&
365 	    res_ninit(pvt->res) == -1)
366 		return (-1);
367 	return (0);
368 }
369 
370 /*! \file */
371