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