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