1 /*
2  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3  * Portions Copyright (c) 1996 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 
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <netdb.h>
29 #include <syslog.h>
30 
31 #include <irs.h>
32 #include <irp.h>
33 #include <isc/memcluster.h>
34 #include <isc/irpmarshall.h>
35 
36 #include "irs_p.h"
37 #include "lcl_p.h"
38 #include "irp_p.h"
39 
40 #include "port_after.h"
41 
42 
43 #define MAXALIASES	35
44 
45 /* Types */
46 
47 struct pvt {
48 	struct irp_p	       *girpdata;
49 	int			warned;
50 	struct protoent		proto;
51 };
52 
53 /* Forward */
54 
55 static void			pr_close(struct irs_pr *);
56 static struct protoent *	pr_next(struct irs_pr *);
57 static struct protoent *	pr_byname(struct irs_pr *, const char *);
58 static struct protoent *	pr_bynumber(struct irs_pr *, int);
59 static void			pr_rewind(struct irs_pr *);
60 static void			pr_minimize(struct irs_pr *);
61 
62 static void			free_proto(struct protoent *pr);
63 
64 /* Public */
65 
66 /*%
67  * struct irs_pr * irs_irp_pr(struct irs_acc *this)
68  *
69  */
70 
71 struct irs_pr *
irs_irp_pr(struct irs_acc * this)72 irs_irp_pr(struct irs_acc *this) {
73 	struct irs_pr *pr;
74 	struct pvt *pvt;
75 
76 	if (!(pr = memget(sizeof *pr))) {
77 		errno = ENOMEM;
78 		return (NULL);
79 	}
80 	memset(pr, 0x0, sizeof *pr);
81 
82 	if (!(pvt = memget(sizeof *pvt))) {
83 		memput(pr, sizeof *pr);
84 		errno = ENOMEM;
85 		return (NULL);
86 	}
87 	memset(pvt, 0, sizeof *pvt);
88 	pvt->girpdata = this->private;
89 
90 	pr->private = pvt;
91 	pr->close = pr_close;
92 	pr->byname = pr_byname;
93 	pr->bynumber = pr_bynumber;
94 	pr->next = pr_next;
95 	pr->rewind = pr_rewind;
96 	pr->minimize = pr_minimize;
97 	return (pr);
98 }
99 
100 /* Methods */
101 
102 /*%
103  * void pr_close(struct irs_pr *this)
104  *
105  */
106 
107 static void
pr_close(struct irs_pr * this)108 pr_close(struct irs_pr *this) {
109 	struct pvt *pvt = (struct pvt *)this->private;
110 
111 	pr_minimize(this);
112 
113 	free_proto(&pvt->proto);
114 
115 	memput(pvt, sizeof *pvt);
116 	memput(this, sizeof *this);
117 }
118 
119 /*%
120  * struct protoent * pr_byname(struct irs_pr *this, const char *name)
121  *
122  */
123 
124 static struct protoent *
pr_byname(struct irs_pr * this,const char * name)125 pr_byname(struct irs_pr *this, const char *name) {
126 	struct pvt *pvt = (struct pvt *)this->private;
127 	struct protoent *pr = &pvt->proto;
128 	char *body = NULL;
129 	size_t bodylen;
130 	int code;
131 	int i;
132 	char text[256];
133 
134 	if (pr->p_name != NULL && strcmp(name, pr->p_name) == 0) {
135 		return (pr);
136 	}
137 
138 	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
139 		return (NULL);
140 	}
141 
142 	i = irs_irp_send_command(pvt->girpdata, "getprotobyname %s", name);
143 	if (i != 0)
144 		return (NULL);
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_GETPROTO_OK) {
153 		free_proto(pr);
154 		if (irp_unmarshall_pr(pr, body) != 0) {
155 			pr = NULL;
156 		}
157 	} else {
158 		pr = NULL;
159 	}
160 
161 	if (body != NULL) {
162 		memput(body, bodylen);
163 	}
164 
165 	return (pr);
166 }
167 
168 /*%
169  * struct protoent * pr_bynumber(struct irs_pr *this, int proto)
170  *
171  */
172 
173 static struct protoent *
pr_bynumber(struct irs_pr * this,int proto)174 pr_bynumber(struct irs_pr *this, int proto) {
175 	struct pvt *pvt = (struct pvt *)this->private;
176 	struct protoent *pr = &pvt->proto;
177 	char *body = NULL;
178 	size_t bodylen;
179 	int code;
180 	int i;
181 	char text[256];
182 
183 	if (pr->p_name != NULL && proto == pr->p_proto) {
184 		return (pr);
185 	}
186 
187 	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
188 		return (NULL);
189 	}
190 
191 	i = irs_irp_send_command(pvt->girpdata, "getprotobynumber %d", proto);
192 	if (i != 0)
193 		return (NULL);
194 
195 	if (irs_irp_get_full_response(pvt->girpdata, &code,
196 				      text, sizeof text,
197 				      &body, &bodylen) != 0) {
198 		return (NULL);
199 	}
200 
201 	if (code == IRPD_GETPROTO_OK) {
202 		free_proto(pr);
203 		if (irp_unmarshall_pr(pr, body) != 0) {
204 			pr = NULL;
205 		}
206 	} else {
207 		pr = NULL;
208 	}
209 
210 	if (body != NULL) {
211 		memput(body, bodylen);
212 	}
213 
214 	return (pr);
215 }
216 
217 /*%
218  * void pr_rewind(struct irs_pr *this)
219  *
220  */
221 
222 static void
pr_rewind(struct irs_pr * this)223 pr_rewind(struct irs_pr *this) {
224 	struct pvt *pvt = (struct pvt *)this->private;
225 	char text[256];
226 	int code;
227 
228 	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
229 		return;
230 	}
231 
232 	if (irs_irp_send_command(pvt->girpdata, "setprotoent") != 0) {
233 		return;
234 	}
235 
236 	code = irs_irp_read_response(pvt->girpdata, text, sizeof text);
237 	if (code != IRPD_GETPROTO_SETOK) {
238 		if (irp_log_errors) {
239 			syslog(LOG_WARNING, "setprotoent failed: %s", text);
240 		}
241 	}
242 
243 	return;
244 }
245 
246 /*%
247  *	Prepares the cache if necessary and returns the next item in it.
248  *
249  */
250 
251 static struct protoent *
pr_next(struct irs_pr * this)252 pr_next(struct irs_pr *this) {
253 	struct pvt *pvt = (struct pvt *)this->private;
254 	struct protoent *pr = &pvt->proto;
255 	char *body;
256 	size_t bodylen;
257 	int code;
258 	char text[256];
259 
260 	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
261 		return (NULL);
262 	}
263 
264 	if (irs_irp_send_command(pvt->girpdata, "getprotoent") != 0) {
265 		return (NULL);
266 	}
267 
268 	if (irs_irp_get_full_response(pvt->girpdata, &code,
269 				      text, sizeof text,
270 				      &body, &bodylen) != 0) {
271 		return (NULL);
272 	}
273 
274 	if (code == IRPD_GETPROTO_OK) {
275 		free_proto(pr);
276 		if (irp_unmarshall_pr(pr, body) != 0) {
277 			pr = NULL;
278 		}
279 	} else {
280 		pr = NULL;
281 	}
282 
283 	if (body != NULL) {
284 		memput(body, bodylen);
285 	}
286 
287 	return (pr);
288 }
289 
290 /*%
291  * void pr_minimize(struct irs_pr *this)
292  *
293  */
294 
295 static void
pr_minimize(struct irs_pr * this)296 pr_minimize(struct irs_pr *this) {
297 	struct pvt *pvt = (struct pvt *)this->private;
298 
299 	irs_irp_disconnect(pvt->girpdata);
300 }
301 
302 /*%
303  *	Deallocate all the memory irp_unmarshall_pr allocated.
304  *
305  */
306 
307 static void
free_proto(struct protoent * pr)308 free_proto(struct protoent *pr) {
309 	char **p;
310 
311 	if (pr == NULL)
312 		return;
313 
314 	if (pr->p_name != NULL)
315 		free(pr->p_name);
316 
317 	for (p = pr->p_aliases ; p != NULL && *p != NULL ; p++)
318 		free(*p);
319 }
320 
321 /*! \file */
322