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