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