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