1/*
2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (c) 1996,1999 by Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#if !defined(LINT) && !defined(CODECENTER)
19static const char rcsid[] = "$Id: gen_nw.c,v 1.4 2005/04/27 04:56:23 sra Exp $";
20#endif
21
22/* Imports */
23
24#include "port_before.h"
25
26#include <sys/types.h>
27
28#include <netinet/in.h>
29#include <arpa/nameser.h>
30
31#include <errno.h>
32#include <resolv.h>
33#include <stdlib.h>
34#include <string.h>
35
36#include <isc/memcluster.h>
37#include <irs.h>
38
39#include "port_after.h"
40
41#include "irs_p.h"
42#include "gen_p.h"
43
44/* Types */
45
46struct pvt {
47	struct irs_rule *	rules;
48	struct irs_rule *	rule;
49	struct __res_state *	res;
50	void 			(*free_res)(void *);
51};
52
53/* Forward */
54
55static void		nw_close(struct irs_nw*);
56static struct nwent *	nw_next(struct irs_nw *);
57static struct nwent *	nw_byname(struct irs_nw *, const char *, int);
58static struct nwent *	nw_byaddr(struct irs_nw *, void *, int, int);
59static void    		nw_rewind(struct irs_nw *);
60static void		nw_minimize(struct irs_nw *);
61static struct __res_state * nw_res_get(struct irs_nw *this);
62static void		nw_res_set(struct irs_nw *this,
63				   struct __res_state *res,
64				   void (*free_res)(void *));
65
66static int		init(struct irs_nw *this);
67
68/* Public */
69
70struct irs_nw *
71irs_gen_nw(struct irs_acc *this) {
72	struct gen_p *accpvt = (struct gen_p *)this->private;
73	struct irs_nw *nw;
74	struct pvt *pvt;
75
76	if (!(pvt = memget(sizeof *pvt))) {
77		errno = ENOMEM;
78		return (NULL);
79	}
80	memset(pvt, 0, sizeof *pvt);
81	if (!(nw = memget(sizeof *nw))) {
82		memput(pvt, sizeof *pvt);
83		errno = ENOMEM;
84		return (NULL);
85	}
86	memset(nw, 0x5e, sizeof *nw);
87	pvt->rules = accpvt->map_rules[irs_nw];
88	pvt->rule = pvt->rules;
89	nw->private = pvt;
90	nw->close = nw_close;
91	nw->next = nw_next;
92	nw->byname = nw_byname;
93	nw->byaddr = nw_byaddr;
94	nw->rewind = nw_rewind;
95	nw->minimize = nw_minimize;
96	nw->res_get = nw_res_get;
97	nw->res_set = nw_res_set;
98	return (nw);
99}
100
101/* Methods */
102
103static void
104nw_close(struct irs_nw *this) {
105	struct pvt *pvt = (struct pvt *)this->private;
106
107	nw_minimize(this);
108
109	if (pvt->res && pvt->free_res)
110		(*pvt->free_res)(pvt->res);
111
112	memput(pvt, sizeof *pvt);
113	memput(this, sizeof *this);
114}
115
116static struct nwent *
117nw_next(struct irs_nw *this) {
118	struct pvt *pvt = (struct pvt *)this->private;
119	struct nwent *rval;
120	struct irs_nw *nw;
121
122	if (init(this) == -1)
123		return(NULL);
124
125	while (pvt->rule) {
126		nw = pvt->rule->inst->nw;
127		rval = (*nw->next)(nw);
128		if (rval)
129			return (rval);
130		if (!(pvt->rules->flags & IRS_CONTINUE))
131			break;
132		pvt->rule = pvt->rule->next;
133		if (pvt->rule) {
134			nw = pvt->rule->inst->nw;
135			(*nw->rewind)(nw);
136		}
137	}
138	return (NULL);
139}
140
141static struct nwent *
142nw_byname(struct irs_nw *this, const char *name, int type) {
143	struct pvt *pvt = (struct pvt *)this->private;
144	struct irs_rule *rule;
145	struct nwent *rval;
146	struct irs_nw *nw;
147
148	if (init(this) == -1)
149		return(NULL);
150
151	for (rule = pvt->rules; rule; rule = rule->next) {
152		nw = rule->inst->nw;
153		RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
154		rval = (*nw->byname)(nw, name, type);
155		if (rval != NULL)
156			return (rval);
157		if (pvt->res->res_h_errno != TRY_AGAIN &&
158		    !(rule->flags & IRS_CONTINUE))
159			break;
160	}
161	return (NULL);
162}
163
164static struct nwent *
165nw_byaddr(struct irs_nw *this, void *net, int length, int type) {
166	struct pvt *pvt = (struct pvt *)this->private;
167	struct irs_rule *rule;
168	struct nwent *rval;
169	struct irs_nw *nw;
170
171	if (init(this) == -1)
172		return(NULL);
173
174	for (rule = pvt->rules; rule; rule = rule->next) {
175		nw = rule->inst->nw;
176		RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);
177		rval = (*nw->byaddr)(nw, net, length, type);
178		if (rval != NULL)
179			return (rval);
180		if (pvt->res->res_h_errno != TRY_AGAIN &&
181		    !(rule->flags & IRS_CONTINUE))
182			break;
183	}
184	return (NULL);
185}
186
187static void
188nw_rewind(struct irs_nw *this) {
189	struct pvt *pvt = (struct pvt *)this->private;
190	struct irs_nw *nw;
191
192	pvt->rule = pvt->rules;
193	if (pvt->rule) {
194		nw = pvt->rule->inst->nw;
195		(*nw->rewind)(nw);
196	}
197}
198
199static void
200nw_minimize(struct irs_nw *this) {
201	struct pvt *pvt = (struct pvt *)this->private;
202	struct irs_rule *rule;
203
204	if (pvt->res)
205		res_nclose(pvt->res);
206	for (rule = pvt->rules; rule != NULL; rule = rule->next) {
207		struct irs_nw *nw = rule->inst->nw;
208
209		(*nw->minimize)(nw);
210	}
211}
212
213static struct __res_state *
214nw_res_get(struct irs_nw *this) {
215	struct pvt *pvt = (struct pvt *)this->private;
216
217	if (!pvt->res) {
218		struct __res_state *res;
219		res = (struct __res_state *)malloc(sizeof *res);
220		if (!res) {
221			errno = ENOMEM;
222			return (NULL);
223		}
224		memset(res, 0, sizeof *res);
225		nw_res_set(this, res, free);
226	}
227
228	return (pvt->res);
229}
230
231static void
232nw_res_set(struct irs_nw *this, struct __res_state *res,
233		void (*free_res)(void *)) {
234	struct pvt *pvt = (struct pvt *)this->private;
235	struct irs_rule *rule;
236
237	if (pvt->res && pvt->free_res) {
238		res_nclose(pvt->res);
239		(*pvt->free_res)(pvt->res);
240	}
241
242	pvt->res = res;
243	pvt->free_res = free_res;
244
245	for (rule = pvt->rules; rule != NULL; rule = rule->next) {
246		struct irs_nw *nw = rule->inst->nw;
247
248		(*nw->res_set)(nw, pvt->res, NULL);
249	}
250}
251
252static int
253init(struct irs_nw *this) {
254	struct pvt *pvt = (struct pvt *)this->private;
255
256	if (!pvt->res && !nw_res_get(this))
257		return (-1);
258	if (((pvt->res->options & RES_INIT) == 0U) &&
259	    res_ninit(pvt->res) == -1)
260		return (-1);
261	return (0);
262}
263
264/*! \file */
265