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