1 /*
2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (c) 1996,1998 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 #include "port_before.h"
19
20 #include <syslog.h>
21 #include <sys/types.h>
22 #include <sys/socket.h>
23
24 #ifdef IRS_LCL_SV_DB
25 #include <db.h>
26 #endif
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <limits.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <syslog.h>
34
35 #include <irs.h>
36 #include <irp.h>
37 #include <isc/irpmarshall.h>
38 #include <isc/memcluster.h>
39
40 #include "irs_p.h"
41 #include "lcl_p.h"
42 #include "irp_p.h"
43
44 #include "port_after.h"
45
46 /* Types */
47
48 struct pvt {
49 struct irp_p *girpdata;
50 int warned;
51 struct servent service;
52 };
53
54 /* Forward */
55
56 static void sv_close(struct irs_sv*);
57 static struct servent * sv_next(struct irs_sv *);
58 static struct servent * sv_byname(struct irs_sv *, const char *,
59 const char *);
60 static struct servent * sv_byport(struct irs_sv *, int, const char *);
61 static void sv_rewind(struct irs_sv *);
62 static void sv_minimize(struct irs_sv *);
63
64 static void free_service(struct servent *sv);
65
66
67
68 /* Public */
69
70 /*%
71 * struct irs_sv * irs_irp_sv(struct irs_acc *this)
72 *
73 */
74
75 struct irs_sv *
irs_irp_sv(struct irs_acc * this)76 irs_irp_sv(struct irs_acc *this) {
77 struct irs_sv *sv;
78 struct pvt *pvt;
79
80 if ((sv = memget(sizeof *sv)) == NULL) {
81 errno = ENOMEM;
82 return (NULL);
83 }
84 memset(sv, 0x0, sizeof *sv);
85
86 if ((pvt = memget(sizeof *pvt)) == NULL) {
87 memput(sv, sizeof *sv);
88 errno = ENOMEM;
89 return (NULL);
90 }
91 memset(pvt, 0, sizeof *pvt);
92 pvt->girpdata = this->private;
93
94 sv->private = pvt;
95 sv->close = sv_close;
96 sv->next = sv_next;
97 sv->byname = sv_byname;
98 sv->byport = sv_byport;
99 sv->rewind = sv_rewind;
100 sv->minimize = sv_minimize;
101
102 return (sv);
103 }
104
105 /* Methods */
106
107 /*%
108 * void sv_close(struct irs_sv *this)
109 *
110 */
111
112 static void
sv_close(struct irs_sv * this)113 sv_close(struct irs_sv *this) {
114 struct pvt *pvt = (struct pvt *)this->private;
115
116 sv_minimize(this);
117
118 free_service(&pvt->service);
119
120 memput(pvt, sizeof *pvt);
121 memput(this, sizeof *this);
122 }
123
124 /*%
125 * Fills the cache if necessary and returns the next item from it.
126 *
127 */
128
129 static struct servent *
sv_next(struct irs_sv * this)130 sv_next(struct irs_sv *this) {
131 struct pvt *pvt = (struct pvt *)this->private;
132 struct servent *sv = &pvt->service;
133 char *body;
134 size_t bodylen;
135 int code;
136 char text[256];
137
138 if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
139 return (NULL);
140 }
141
142 if (irs_irp_send_command(pvt->girpdata, "getservent") != 0) {
143 return (NULL);
144 }
145
146 if (irs_irp_get_full_response(pvt->girpdata, &code,
147 text, sizeof text,
148 &body, &bodylen) != 0) {
149 return (NULL);
150 }
151
152 if (code == IRPD_GETSERVICE_OK) {
153 free_service(sv);
154 if (irp_unmarshall_sv(sv, body) != 0) {
155 sv = NULL;
156 }
157 } else {
158 sv = NULL;
159 }
160
161 if (body != NULL) {
162 memput(body, bodylen);
163 }
164
165 return (sv);
166 }
167
168 /*%
169 * struct servent * sv_byname(struct irs_sv *this, const char *name,
170 * const char *proto)
171 *
172 */
173
174 static struct servent *
sv_byname(struct irs_sv * this,const char * name,const char * proto)175 sv_byname(struct irs_sv *this, const char *name, const char *proto) {
176 struct pvt *pvt = (struct pvt *)this->private;
177 struct servent *sv = &pvt->service;
178 char *body;
179 char text[256];
180 size_t bodylen;
181 int code;
182
183 if (sv->s_name != NULL &&
184 strcmp(name, sv->s_name) == 0 &&
185 strcasecmp(proto, sv->s_proto) == 0) {
186 return (sv);
187 }
188
189 if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
190 return (NULL);
191 }
192
193 if (irs_irp_send_command(pvt->girpdata, "getservbyname %s %s",
194 name, proto) != 0)
195 return (NULL);
196
197 if (irs_irp_get_full_response(pvt->girpdata, &code,
198 text, sizeof text,
199 &body, &bodylen) != 0) {
200 return (NULL);
201 }
202
203 if (code == IRPD_GETSERVICE_OK) {
204 free_service(sv);
205 if (irp_unmarshall_sv(sv, body) != 0) {
206 sv = NULL;
207 }
208 } else {
209 sv = NULL;
210 }
211
212 if (body != NULL) {
213 memput(body, bodylen);
214 }
215
216 return (sv);
217 }
218
219 /*%
220 * struct servent * sv_byport(struct irs_sv *this, int port,
221 * const char *proto)
222 *
223 */
224
225 static struct servent *
sv_byport(struct irs_sv * this,int port,const char * proto)226 sv_byport(struct irs_sv *this, int port, const char *proto) {
227 struct pvt *pvt = (struct pvt *)this->private;
228 struct servent *sv = &pvt->service;
229 char *body;
230 size_t bodylen;
231 char text[256];
232 int code;
233
234 if (sv->s_name != NULL &&
235 port == sv->s_port &&
236 strcasecmp(proto, sv->s_proto) == 0) {
237 return (sv);
238 }
239
240 if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
241 return (NULL);
242 }
243
244 if (irs_irp_send_command(pvt->girpdata, "getservbyport %d %s",
245 ntohs((short)port), proto) != 0) {
246 return (NULL);
247 }
248
249 if (irs_irp_get_full_response(pvt->girpdata, &code,
250 text, sizeof text,
251 &body, &bodylen) != 0) {
252 return (NULL);
253 }
254
255 if (code == IRPD_GETSERVICE_OK) {
256 free_service(sv);
257 if (irp_unmarshall_sv(sv, body) != 0) {
258 sv = NULL;
259 }
260 } else {
261 sv = NULL;
262 }
263
264 if (body != NULL) {
265 memput(body, bodylen);
266 }
267
268 return (sv);
269 }
270
271 /*%
272 * void sv_rewind(struct irs_sv *this)
273 *
274 */
275
276 static void
sv_rewind(struct irs_sv * this)277 sv_rewind(struct irs_sv *this) {
278 struct pvt *pvt = (struct pvt *)this->private;
279 char text[256];
280 int code;
281
282 if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
283 return;
284 }
285
286 if (irs_irp_send_command(pvt->girpdata, "setservent") != 0) {
287 return;
288 }
289
290 code = irs_irp_read_response(pvt->girpdata, text, sizeof text);
291 if (code != IRPD_GETSERVICE_SETOK) {
292 if (irp_log_errors) {
293 syslog(LOG_WARNING, "setservent failed: %s", text);
294 }
295 }
296
297 return;
298 }
299
300 /*%
301 * void sv_minimize(struct irs_sv *this)
302 *
303 */
304
305 static void
sv_minimize(struct irs_sv * this)306 sv_minimize(struct irs_sv *this) {
307 struct pvt *pvt = (struct pvt *)this->private;
308
309 irs_irp_disconnect(pvt->girpdata);
310 }
311
312
313
314
315
316
317 static void
free_service(struct servent * sv)318 free_service(struct servent *sv) {
319 char **p;
320
321 if (sv == NULL) {
322 return;
323 }
324
325 if (sv->s_name != NULL) {
326 free(sv->s_name);
327 }
328
329 for (p = sv->s_aliases ; p != NULL && *p != NULL ; p++) {
330 free(*p);
331 }
332
333 if (sv->s_proto != NULL) {
334 free(sv->s_proto);
335 }
336 }
337
338
339
340 /*! \file */
341