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_sv.c,v 1.3 2005/04/27 04:56:24 sra Exp $";
20#endif
21
22/* Imports */
23
24#include "port_before.h"
25
26#include <sys/types.h>
27#include <netinet/in.h>
28#include <arpa/nameser.h>
29#include <resolv.h>
30
31#include <errno.h>
32#include <stdlib.h>
33#include <string.h>
34
35#include <isc/memcluster.h>
36#include <irs.h>
37
38#include "port_after.h"
39
40#include "irs_p.h"
41#include "gen_p.h"
42
43/* Types */
44
45struct pvt {
46	struct irs_rule *	rules;
47	struct irs_rule *	rule;
48	struct __res_state *	res;
49	void			(*free_res)(void *);
50};
51
52/* Forward */
53
54static void			sv_close(struct irs_sv*);
55static struct servent *		sv_next(struct irs_sv *);
56static struct servent *		sv_byname(struct irs_sv *, const char *,
57					  const char *);
58static struct servent *		sv_byport(struct irs_sv *, int, const char *);
59static void			sv_rewind(struct irs_sv *);
60static void			sv_minimize(struct irs_sv *);
61static struct __res_state *	sv_res_get(struct irs_sv *);
62static void			sv_res_set(struct irs_sv *,
63					      struct __res_state *,
64					      void (*)(void *));
65
66/* Public */
67
68struct irs_sv *
69irs_gen_sv(struct irs_acc *this) {
70	struct gen_p *accpvt = (struct gen_p *)this->private;
71	struct irs_sv *sv;
72	struct pvt *pvt;
73
74	if (!(sv = memget(sizeof *sv))) {
75		errno = ENOMEM;
76		return (NULL);
77	}
78	memset(sv, 0x5e, sizeof *sv);
79	if (!(pvt = memget(sizeof *pvt))) {
80		memput(sv, sizeof *sv);
81		errno = ENOMEM;
82		return (NULL);
83	}
84	memset(pvt, 0, sizeof *pvt);
85	pvt->rules = accpvt->map_rules[irs_sv];
86	pvt->rule = pvt->rules;
87	sv->private = pvt;
88	sv->close = sv_close;
89	sv->next = sv_next;
90	sv->byname = sv_byname;
91	sv->byport = sv_byport;
92	sv->rewind = sv_rewind;
93	sv->minimize = sv_minimize;
94	sv->res_get = sv_res_get;
95	sv->res_set = sv_res_set;
96	return (sv);
97}
98
99/* Methods */
100
101static void
102sv_close(struct irs_sv *this) {
103	struct pvt *pvt = (struct pvt *)this->private;
104
105	memput(pvt, sizeof *pvt);
106	memput(this, sizeof *this);
107}
108
109static struct servent *
110sv_next(struct irs_sv *this) {
111	struct pvt *pvt = (struct pvt *)this->private;
112	struct servent *rval;
113	struct irs_sv *sv;
114
115	while (pvt->rule) {
116		sv = pvt->rule->inst->sv;
117		rval = (*sv->next)(sv);
118		if (rval)
119			return (rval);
120		if (!(pvt->rule->flags & IRS_CONTINUE))
121			break;
122		pvt->rule = pvt->rule->next;
123		if (pvt->rule) {
124			sv = pvt->rule->inst->sv;
125			(*sv->rewind)(sv);
126		}
127	}
128	return (NULL);
129}
130
131static struct servent *
132sv_byname(struct irs_sv *this, const char *name, const char *proto) {
133	struct pvt *pvt = (struct pvt *)this->private;
134	struct irs_rule *rule;
135	struct servent *rval;
136	struct irs_sv *sv;
137
138	rval = NULL;
139	for (rule = pvt->rules; rule; rule = rule->next) {
140		sv = rule->inst->sv;
141		rval = (*sv->byname)(sv, name, proto);
142		if (rval || !(rule->flags & IRS_CONTINUE))
143			break;
144	}
145	return (rval);
146}
147
148static struct servent *
149sv_byport(struct irs_sv *this, int port, const char *proto) {
150	struct pvt *pvt = (struct pvt *)this->private;
151	struct irs_rule *rule;
152	struct servent *rval;
153	struct irs_sv *sv;
154
155	rval = NULL;
156	for (rule = pvt->rules; rule; rule = rule->next) {
157		sv = rule->inst->sv;
158		rval = (*sv->byport)(sv, port, proto);
159		if (rval || !(rule->flags & IRS_CONTINUE))
160			break;
161	}
162	return (rval);
163}
164
165static void
166sv_rewind(struct irs_sv *this) {
167	struct pvt *pvt = (struct pvt *)this->private;
168	struct irs_sv *sv;
169
170	pvt->rule = pvt->rules;
171	if (pvt->rule) {
172		sv = pvt->rule->inst->sv;
173		(*sv->rewind)(sv);
174	}
175}
176
177static void
178sv_minimize(struct irs_sv *this) {
179	struct pvt *pvt = (struct pvt *)this->private;
180	struct irs_rule *rule;
181
182	for (rule = pvt->rules; rule != NULL; rule = rule->next) {
183		struct irs_sv *sv = rule->inst->sv;
184
185		(*sv->minimize)(sv);
186	}
187}
188
189static struct __res_state *
190sv_res_get(struct irs_sv *this) {
191	struct pvt *pvt = (struct pvt *)this->private;
192
193	if (!pvt->res) {
194		struct __res_state *res;
195		res = (struct __res_state *)malloc(sizeof *res);
196		if (!res) {
197			errno = ENOMEM;
198			return (NULL);
199		}
200		memset(res, 0, sizeof *res);
201		sv_res_set(this, res, free);
202	}
203
204	return (pvt->res);
205}
206
207static void
208sv_res_set(struct irs_sv *this, struct __res_state *res,
209		void (*free_res)(void *)) {
210	struct pvt *pvt = (struct pvt *)this->private;
211	struct irs_rule *rule;
212
213	if (pvt->res && pvt->free_res) {
214		res_nclose(pvt->res);
215		(*pvt->free_res)(pvt->res);
216	}
217
218	pvt->res = res;
219	pvt->free_res = free_res;
220
221	for (rule = pvt->rules; rule != NULL; rule = rule->next) {
222		struct irs_sv *sv = rule->inst->sv;
223
224		if (sv->res_set)
225			(*sv->res_set)(sv, pvt->res, NULL);
226	}
227}
228
229/*! \file */
230