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