xref: /netbsd-src/external/bsd/libbind/dist/irs/irp_sv.c (revision 5bbd2a12505d72a8177929a37b5cee489d0a1cfd)
1 /*	$NetBSD: irp_sv.c,v 1.1.1.2 2012/09/09 16:07:57 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5  * Portions Copyright (c) 1996,1998 by Internet Software Consortium.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #if defined(LIBC_SCCS) && !defined(lint)
21 static const char rcsid[] = "Id: irp_sv.c,v 1.3 2005/04/27 04:56:29 sra Exp ";
22 #endif /* LIBC_SCCS and not lint */
23 
24 /* extern */
25 
26 #include "port_before.h"
27 
28 #include <syslog.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 
32 #ifdef IRS_LCL_SV_DB
33 #include <db.h>
34 #endif
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <limits.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <stdlib.h>
41 #include <syslog.h>
42 
43 #include <irs.h>
44 #include <irp.h>
45 #include <isc/irpmarshall.h>
46 #include <isc/memcluster.h>
47 
48 #include "irs_p.h"
49 #include "lcl_p.h"
50 #include "irp_p.h"
51 
52 #include "port_after.h"
53 
54 /* Types */
55 
56 struct pvt {
57 	struct irp_p	       *girpdata;
58 	int			warned;
59 	struct servent		service;
60 };
61 
62 /* Forward */
63 
64 static void			sv_close(struct irs_sv*);
65 static struct servent *		sv_next(struct irs_sv *);
66 static struct servent *		sv_byname(struct irs_sv *, const char *,
67 					  const char *);
68 static struct servent *		sv_byport(struct irs_sv *, int, const char *);
69 static void			sv_rewind(struct irs_sv *);
70 static void			sv_minimize(struct irs_sv *);
71 
72 static void			free_service(struct servent *sv);
73 
74 
75 
76 /* Public */
77 
78 /*%
79  * struct irs_sv * irs_irp_sv(struct irs_acc *this)
80  *
81  */
82 
83 struct irs_sv *
irs_irp_sv(struct irs_acc * this)84 irs_irp_sv(struct irs_acc *this) {
85 	struct irs_sv *sv;
86 	struct pvt *pvt;
87 
88 	if ((sv = memget(sizeof *sv)) == NULL) {
89 		errno = ENOMEM;
90 		return (NULL);
91 	}
92 	memset(sv, 0x0, sizeof *sv);
93 
94 	if ((pvt = memget(sizeof *pvt)) == NULL) {
95 		memput(sv, sizeof *sv);
96 		errno = ENOMEM;
97 		return (NULL);
98 	}
99 	memset(pvt, 0, sizeof *pvt);
100 	pvt->girpdata = this->private;
101 
102 	sv->private = pvt;
103 	sv->close = sv_close;
104 	sv->next = sv_next;
105 	sv->byname = sv_byname;
106 	sv->byport = sv_byport;
107 	sv->rewind = sv_rewind;
108 	sv->minimize = sv_minimize;
109 
110 	return (sv);
111 }
112 
113 /* Methods */
114 
115 /*%
116  * void sv_close(struct irs_sv *this)
117  *
118  */
119 
120 static void
sv_close(struct irs_sv * this)121 sv_close(struct irs_sv *this) {
122 	struct pvt *pvt = (struct pvt *)this->private;
123 
124 	sv_minimize(this);
125 
126 	free_service(&pvt->service);
127 
128 	memput(pvt, sizeof *pvt);
129 	memput(this, sizeof *this);
130 }
131 
132 /*%
133  *	Fills the cache if necessary and returns the next item from it.
134  *
135  */
136 
137 static struct servent *
sv_next(struct irs_sv * this)138 sv_next(struct irs_sv *this) {
139 	struct pvt *pvt = (struct pvt *)this->private;
140 	struct servent *sv = &pvt->service;
141 	char *body;
142 	size_t bodylen;
143 	int code;
144 	char text[256];
145 
146 	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
147 		return (NULL);
148 	}
149 
150 	if (irs_irp_send_command(pvt->girpdata, "getservent") != 0) {
151 		return (NULL);
152 	}
153 
154 	if (irs_irp_get_full_response(pvt->girpdata, &code,
155 				      text, sizeof text,
156 				      &body, &bodylen) != 0) {
157 		return (NULL);
158 	}
159 
160 	if (code == IRPD_GETSERVICE_OK) {
161 		free_service(sv);
162 		if (irp_unmarshall_sv(sv, body) != 0) {
163 			sv = NULL;
164 		}
165 	} else {
166 		sv = NULL;
167 	}
168 
169 	if (body != NULL) {
170 		memput(body, bodylen);
171 	}
172 
173 	return (sv);
174 }
175 
176 /*%
177  * struct servent * sv_byname(struct irs_sv *this, const char *name,
178  *				const char *proto)
179  *
180  */
181 
182 static struct servent *
sv_byname(struct irs_sv * this,const char * name,const char * proto)183 sv_byname(struct irs_sv *this, const char *name, const char *proto) {
184 	struct pvt *pvt = (struct pvt *)this->private;
185 	struct servent *sv = &pvt->service;
186 	char *body;
187 	char text[256];
188 	size_t bodylen;
189 	int code;
190 
191 	if (sv->s_name != NULL &&
192 	    strcmp(name, sv->s_name) == 0 &&
193 	    strcasecmp(proto, sv->s_proto) == 0) {
194 		return (sv);
195 	}
196 
197 	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
198 		return (NULL);
199 	}
200 
201 	if (irs_irp_send_command(pvt->girpdata, "getservbyname %s %s",
202 				 name, proto) != 0)
203 		return (NULL);
204 
205 	if (irs_irp_get_full_response(pvt->girpdata, &code,
206 				      text, sizeof text,
207 				      &body, &bodylen) != 0) {
208 		return (NULL);
209 	}
210 
211 	if (code == IRPD_GETSERVICE_OK) {
212 		free_service(sv);
213 		if (irp_unmarshall_sv(sv, body) != 0) {
214 			sv = NULL;
215 		}
216 	} else {
217 		sv = NULL;
218 	}
219 
220 	if (body != NULL) {
221 		memput(body, bodylen);
222 	}
223 
224 	return (sv);
225 }
226 
227 /*%
228  * struct servent * sv_byport(struct irs_sv *this, int port,
229  *				const char *proto)
230  *
231  */
232 
233 static struct servent *
sv_byport(struct irs_sv * this,int port,const char * proto)234 sv_byport(struct irs_sv *this, int port, const char *proto) {
235 	struct pvt *pvt = (struct pvt *)this->private;
236 	struct servent *sv = &pvt->service;
237 	char *body;
238 	size_t bodylen;
239 	char text[256];
240 	int code;
241 
242 	if (sv->s_name != NULL &&
243 	    port == sv->s_port &&
244 	    strcasecmp(proto, sv->s_proto) == 0) {
245 		return (sv);
246 	}
247 
248 	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
249 		return (NULL);
250 	}
251 
252 	if (irs_irp_send_command(pvt->girpdata, "getservbyport %d %s",
253 				 ntohs((short)port), proto) != 0) {
254 		return (NULL);
255 	}
256 
257 	if (irs_irp_get_full_response(pvt->girpdata, &code,
258 				      text, sizeof text,
259 				      &body, &bodylen) != 0) {
260 		return (NULL);
261 	}
262 
263 	if (code == IRPD_GETSERVICE_OK) {
264 		free_service(sv);
265 		if (irp_unmarshall_sv(sv, body) != 0) {
266 			sv = NULL;
267 		}
268 	} else {
269 		sv = NULL;
270 	}
271 
272 	if (body != NULL) {
273 		memput(body, bodylen);
274 	}
275 
276 	return (sv);
277 }
278 
279 /*%
280  * void sv_rewind(struct irs_sv *this)
281  *
282  */
283 
284 static void
sv_rewind(struct irs_sv * this)285 sv_rewind(struct irs_sv *this) {
286 	struct pvt *pvt = (struct pvt *)this->private;
287 	char text[256];
288 	int code;
289 
290 	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
291 		return;
292 	}
293 
294 	if (irs_irp_send_command(pvt->girpdata, "setservent") != 0) {
295 		return;
296 	}
297 
298 	code = irs_irp_read_response(pvt->girpdata, text, sizeof text);
299 	if (code != IRPD_GETSERVICE_SETOK) {
300 		if (irp_log_errors) {
301 			syslog(LOG_WARNING, "setservent failed: %s", text);
302 		}
303 	}
304 
305 	return;
306 }
307 
308 /*%
309  * void sv_minimize(struct irs_sv *this)
310  *
311  */
312 
313 static void
sv_minimize(struct irs_sv * this)314 sv_minimize(struct irs_sv *this) {
315 	struct pvt *pvt = (struct pvt *)this->private;
316 
317 	irs_irp_disconnect(pvt->girpdata);
318 }
319 
320 
321 
322 
323 
324 
325 static void
free_service(struct servent * sv)326 free_service(struct servent *sv) {
327 	char **p;
328 
329 	if (sv == NULL) {
330 		return;
331 	}
332 
333 	if (sv->s_name != NULL) {
334 		free(sv->s_name);
335 	}
336 
337 	for (p = sv->s_aliases ; p != NULL && *p != NULL ; p++) {
338 		free(*p);
339 	}
340 
341 	if (sv->s_proto != NULL) {
342 		free(sv->s_proto);
343 	}
344 }
345 
346 
347 
348 /*! \file */
349