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_pr.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
30#include <errno.h>
31#include <resolv.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			pr_close(struct irs_pr*);
55static struct protoent *	pr_next(struct irs_pr *);
56static struct protoent *	pr_byname(struct irs_pr *, const char *);
57static struct protoent * 	pr_bynumber(struct irs_pr *, int);
58static void 			pr_rewind(struct irs_pr *);
59static void			pr_minimize(struct irs_pr *);
60static struct __res_state *	pr_res_get(struct irs_pr *);
61static void			pr_res_set(struct irs_pr *,
62					   struct __res_state *,
63					   void (*)(void *));
64
65/* Public */
66
67struct irs_pr *
68irs_gen_pr(struct irs_acc *this) {
69	struct gen_p *accpvt = (struct gen_p *)this->private;
70	struct irs_pr *pr;
71	struct pvt *pvt;
72
73	if (!(pr = memget(sizeof *pr))) {
74		errno = ENOMEM;
75		return (NULL);
76	}
77	memset(pr, 0x5e, sizeof *pr);
78	if (!(pvt = memget(sizeof *pvt))) {
79		memput(pr, sizeof *pr);
80		errno = ENOMEM;
81		return (NULL);
82	}
83	memset(pvt, 0, sizeof *pvt);
84	pvt->rules = accpvt->map_rules[irs_pr];
85	pvt->rule = pvt->rules;
86	pr->private = pvt;
87	pr->close = pr_close;
88	pr->next = pr_next;
89	pr->byname = pr_byname;
90	pr->bynumber = pr_bynumber;
91	pr->rewind = pr_rewind;
92	pr->minimize = pr_minimize;
93	pr->res_get = pr_res_get;
94	pr->res_set = pr_res_set;
95	return (pr);
96}
97
98/* Methods */
99
100static void
101pr_close(struct irs_pr *this) {
102	struct pvt *pvt = (struct pvt *)this->private;
103
104	memput(pvt, sizeof *pvt);
105	memput(this, sizeof *this);
106}
107
108static struct protoent *
109pr_next(struct irs_pr *this) {
110	struct pvt *pvt = (struct pvt *)this->private;
111	struct protoent *rval;
112	struct irs_pr *pr;
113
114	while (pvt->rule) {
115		pr = pvt->rule->inst->pr;
116		rval = (*pr->next)(pr);
117		if (rval)
118			return (rval);
119		if (!(pvt->rules->flags & IRS_CONTINUE))
120			break;
121		pvt->rule = pvt->rule->next;
122		if (pvt->rule) {
123			pr = pvt->rule->inst->pr;
124			(*pr->rewind)(pr);
125		}
126	}
127	return (NULL);
128}
129
130static struct protoent *
131pr_byname(struct irs_pr *this, const char *name) {
132	struct pvt *pvt = (struct pvt *)this->private;
133	struct irs_rule *rule;
134	struct protoent *rval;
135	struct irs_pr *pr;
136
137	rval = NULL;
138	for (rule = pvt->rules; rule; rule = rule->next) {
139		pr = rule->inst->pr;
140		rval = (*pr->byname)(pr, name);
141		if (rval || !(rule->flags & IRS_CONTINUE))
142			break;
143	}
144	return (rval);
145}
146
147static struct protoent *
148pr_bynumber(struct irs_pr *this, int proto) {
149	struct pvt *pvt = (struct pvt *)this->private;
150	struct irs_rule *rule;
151	struct protoent *rval;
152	struct irs_pr *pr;
153
154	rval = NULL;
155	for (rule = pvt->rules; rule; rule = rule->next) {
156		pr = rule->inst->pr;
157		rval = (*pr->bynumber)(pr, proto);
158		if (rval || !(rule->flags & IRS_CONTINUE))
159			break;
160	}
161	return (rval);
162}
163
164static void
165pr_rewind(struct irs_pr *this) {
166	struct pvt *pvt = (struct pvt *)this->private;
167	struct irs_pr *pr;
168
169	pvt->rule = pvt->rules;
170	if (pvt->rule) {
171		pr = pvt->rule->inst->pr;
172		(*pr->rewind)(pr);
173	}
174}
175
176static void
177pr_minimize(struct irs_pr *this) {
178	struct pvt *pvt = (struct pvt *)this->private;
179	struct irs_rule *rule;
180
181	for (rule = pvt->rules; rule != NULL; rule = rule->next) {
182		struct irs_pr *pr = rule->inst->pr;
183
184		(*pr->minimize)(pr);
185	}
186}
187
188static struct __res_state *
189pr_res_get(struct irs_pr *this) {
190	struct pvt *pvt = (struct pvt *)this->private;
191
192	if (!pvt->res) {
193		struct __res_state *res;
194		res = (struct __res_state *)malloc(sizeof *res);
195		if (!res) {
196			errno = ENOMEM;
197			return (NULL);
198		}
199		memset(res, 0, sizeof *res);
200		pr_res_set(this, res, free);
201	}
202
203	return (pvt->res);
204}
205
206static void
207pr_res_set(struct irs_pr *this, struct __res_state *res,
208		void (*free_res)(void *)) {
209	struct pvt *pvt = (struct pvt *)this->private;
210	struct irs_rule *rule;
211
212	if (pvt->res && pvt->free_res) {
213		res_nclose(pvt->res);
214		(*pvt->free_res)(pvt->res);
215	}
216
217	pvt->res = res;
218	pvt->free_res = free_res;
219
220	for (rule = pvt->rules; rule != NULL; rule = rule->next) {
221		struct irs_pr *pr = rule->inst->pr;
222
223		if (pr->res_set)
224			(*pr->res_set)(pr, pvt->res, NULL);
225	}
226}
227
228/*! \file */
229