xref: /illumos-gate/usr/src/lib/libresolv2/common/irs/irp_ho.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
1 /*
2  * Copyright 1999-2002 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * Portions Copyright (c) 1996,1998 by Internet Software Consortium.
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
14  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
16  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
17  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
18  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
19  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20  * SOFTWARE.
21  */
22 
23 #pragma ident	"%Z%%M%	%I%	%E% SMI"
24 
25 #if defined(LIBC_SCCS) && !defined(lint)
26 static const char rcsid[] = "$Id: irp_ho.c,v 8.3 2001/05/29 05:48:59 marka Exp $";
27 #endif /* LIBC_SCCS and not lint */
28 
29 /* Imports. */
30 
31 #include "port_before.h"
32 
33 #include <syslog.h>
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
37 
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
40 #include <arpa/nameser.h>
41 
42 #include <ctype.h>
43 #include <errno.h>
44 #include <fcntl.h>
45 #include <netdb.h>
46 #include <resolv.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <syslog.h>
51 
52 #include <irs.h>
53 #include <irp.h>
54 #include <isc/irpmarshall.h>
55 #include <isc/memcluster.h>
56 
57 #include "irs_p.h"
58 #include "dns_p.h"
59 #include "irp_p.h"
60 
61 #include "port_after.h"
62 
63 /* Definitions. */
64 
65 #define	MAXALIASES	35
66 #define	MAXADDRS	35
67 #define	Max(a,b)	((a) > (b) ? (a) : (b))
68 
69 
70 struct pvt {
71 	struct irp_p	       *girpdata;
72 	int			warned;
73 	struct hostent		host;
74 };
75 
76 /* Forward. */
77 
78 static void		ho_close(struct irs_ho *this);
79 static struct hostent *	ho_byname(struct irs_ho *this, const char *name);
80 static struct hostent *	ho_byname2(struct irs_ho *this, const char *name,
81 				   int af);
82 static struct hostent *	ho_byaddr(struct irs_ho *this, const void *addr,
83 				  int len, int af);
84 static struct hostent *	ho_next(struct irs_ho *this);
85 static void		ho_rewind(struct irs_ho *this);
86 static void		ho_minimize(struct irs_ho *this);
87 
88 static void		free_host(struct hostent *ho);
89 static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name,
90 				     const struct addrinfo *pai);
91 
92 /* Public. */
93 
94 
95 
96 /*
97  * struct irs_ho * irs_irp_ho(struct irs_acc *this)
98  *
99  * Notes:
100  *
101  *	Initializes the irp_ho module.
102  *
103  */
104 
105 struct irs_ho *
106 irs_irp_ho(struct irs_acc *this) {
107 	struct irs_ho *ho;
108 	struct pvt *pvt;
109 
110 	if (!(ho = memget(sizeof *ho))) {
111 		errno = ENOMEM;
112 		return (NULL);
113 	}
114 	memset(ho, 0x0, sizeof *ho);
115 
116 	if (!(pvt = memget(sizeof *pvt))) {
117 		memput(ho, sizeof *ho);
118 		errno = ENOMEM;
119 		return (NULL);
120 	}
121 	memset(pvt, 0, sizeof *pvt);
122 	pvt->girpdata = this->private;
123 
124 	ho->private = pvt;
125 	ho->close = ho_close;
126 	ho->byname = ho_byname;
127 	ho->byname2 = ho_byname2;
128 	ho->byaddr = ho_byaddr;
129 	ho->next = ho_next;
130 	ho->rewind = ho_rewind;
131 	ho->minimize = ho_minimize;
132 	ho->addrinfo = ho_addrinfo;
133 
134 	return (ho);
135 }
136 
137 /* Methods. */
138 
139 
140 
141 /*
142  * void ho_close(struct irs_ho *this)
143  *
144  * Notes:
145  *
146  *	Closes down the module.
147  *
148  */
149 
150 static void
151 ho_close(struct irs_ho *this) {
152 	struct pvt *pvt = (struct pvt *)this->private;
153 
154 	ho_minimize(this);
155 
156 	free_host(&pvt->host);
157 
158 	memput(pvt, sizeof *pvt);
159 	memput(this, sizeof *this);
160 }
161 
162 
163 
164 /*
165  * struct hostent * ho_byname(struct irs_ho *this, const char *name)
166  *
167  */
168 
169 static struct hostent *
170 ho_byname(struct irs_ho *this, const char *name) {
171 	return (ho_byname2(this, name, AF_INET));
172 }
173 
174 
175 
176 
177 
178 /*
179  * struct hostent * ho_byname2(struct irs_ho *this, const char *name, int af)
180  *
181  */
182 
183 static struct hostent *
184 ho_byname2(struct irs_ho *this, const char *name, int af) {
185 	struct pvt *pvt = (struct pvt *)this->private;
186 	struct hostent *ho = &pvt->host;
187 	char *body = NULL;
188 	size_t bodylen;
189 	int code;
190 	char text[256];
191 
192 	if (ho->h_name != NULL &&
193 	    strcmp(name, ho->h_name) == 0 &&
194 	    af == ho->h_addrtype) {
195 		return (ho);
196 	}
197 
198 	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
199 		return (NULL);
200 	}
201 
202 	if (irs_irp_send_command(pvt->girpdata, "gethostbyname2 %s %s",
203 				 name, ADDR_T_STR(af)) != 0)
204 		return (NULL);
205 
206 	if (irs_irp_get_full_response(pvt->girpdata, &code,
207 				      text, sizeof text,
208 				      &body, &bodylen) != 0) {
209 		return (NULL);
210 	}
211 
212 	if (code == IRPD_GETHOST_OK) {
213 		free_host(ho);
214 		if (irp_unmarshall_ho(ho, body) != 0) {
215 			ho = NULL;
216 		}
217 	} else {
218 		ho = NULL;
219 	}
220 
221 	if (body != NULL) {
222 		memput(body, bodylen);
223 	}
224 
225 	return (ho);
226 }
227 
228 
229 
230 /*
231  * struct hostent * ho_byaddr(struct irs_ho *this, const void *addr,
232  *			   int len, int af)
233  *
234  */
235 
236 static struct hostent *
237 ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) {
238 	struct pvt *pvt = (struct pvt *)this->private;
239 	struct hostent *ho = &pvt->host;
240 	char *body = NULL;
241 	size_t bodylen;
242 	int code;
243 	char **p;
244 	char paddr[MAXPADDRSIZE];
245 	char text[256];
246 
247 	if (ho->h_name != NULL &&
248 	    af == ho->h_addrtype &&
249 	    len == ho->h_length) {
250 		for (p = ho->h_addr_list ; *p != NULL ; p++) {
251 			if (memcmp(*p, addr, len) == 0)
252 				return (ho);
253 		}
254 	}
255 
256 	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
257 		return (NULL);
258 	}
259 
260 	if (inet_ntop(af, addr, paddr, sizeof paddr) == NULL) {
261 		return (NULL);
262 	}
263 
264 	if (irs_irp_send_command(pvt->girpdata, "gethostbyaddr %s %s",
265 				 paddr, ADDR_T_STR(af)) != 0) {
266 		return (NULL);
267 	}
268 
269 	if (irs_irp_get_full_response(pvt->girpdata, &code,
270 				      text, sizeof text,
271 				      &body, &bodylen) != 0) {
272 		return (NULL);
273 	}
274 
275 	if (code == IRPD_GETHOST_OK) {
276 		free_host(ho);
277 		if (irp_unmarshall_ho(ho, body) != 0) {
278 			ho = NULL;
279 		}
280 	} else {
281 		ho = NULL;
282 	}
283 
284 	if (body != NULL) {
285 		memput(body, bodylen);
286 	}
287 
288 	return (ho);
289 }
290 
291 
292 
293 
294 
295 /*
296  * struct hostent * ho_next(struct irs_ho *this)
297  *
298  * Notes:
299  *
300  *	The implementation for gethostent(3). The first time it's
301  *	called all the data is pulled from the remote(i.e. what
302  *	the maximum number of gethostent(3) calls would return)
303  *	and that data is cached.
304  *
305  */
306 
307 static struct hostent *
308 ho_next(struct irs_ho *this) {
309 	struct pvt *pvt = (struct pvt *)this->private;
310 	struct hostent *ho = &pvt->host;
311 	char *body;
312 	size_t bodylen;
313 	int code;
314 	char text[256];
315 
316 	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
317 		return (NULL);
318 	}
319 
320 	if (irs_irp_send_command(pvt->girpdata, "gethostent") != 0) {
321 		return (NULL);
322 	}
323 
324 	if (irs_irp_get_full_response(pvt->girpdata, &code,
325 				      text, sizeof text,
326 				      &body, &bodylen) != 0) {
327 		return (NULL);
328 	}
329 
330 	if (code == IRPD_GETHOST_OK) {
331 		free_host(ho);
332 		if (irp_unmarshall_ho(ho, body) != 0) {
333 			ho = NULL;
334 		}
335 	} else {
336 		ho = NULL;
337 	}
338 
339 	if (body != NULL) {
340 		memput(body, bodylen);
341 	}
342 
343 	return (ho);
344 }
345 
346 
347 
348 
349 
350 /*
351  * void ho_rewind(struct irs_ho *this)
352  *
353  */
354 
355 static void
356 ho_rewind(struct irs_ho *this) {
357 	struct pvt *pvt = (struct pvt *)this->private;
358 	char text[256];
359 	int code;
360 
361 	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
362 		return;
363 	}
364 
365 	if (irs_irp_send_command(pvt->girpdata, "sethostent") != 0) {
366 		return;
367 	}
368 
369 	code = irs_irp_read_response(pvt->girpdata, text, sizeof text);
370 	if (code != IRPD_GETHOST_SETOK) {
371 		if (irp_log_errors) {
372 			syslog(LOG_WARNING, "sethostent failed: %s", text);
373 		}
374 	}
375 
376 	return;
377 }
378 
379 
380 
381 
382 /*
383  * void ho_minimize(struct irs_ho *this)
384  *
385  */
386 
387 static void
388 ho_minimize(struct irs_ho *this) {
389 	struct pvt *pvt = (struct pvt *)this->private;
390 
391 	free_host(&pvt->host);
392 
393 	irs_irp_disconnect(pvt->girpdata);
394 }
395 
396 
397 
398 
399 /*
400  * void free_host(struct hostent *ho)
401  *
402  */
403 
404 static void
405 free_host(struct hostent *ho) {
406 	char **p;
407 
408 	if (ho == NULL) {
409 		return;
410 	}
411 
412 	if (ho->h_name != NULL)
413 		free(ho->h_name);
414 
415 	if (ho->h_aliases != NULL) {
416 		for (p = ho->h_aliases ; *p != NULL ; p++)
417 			free(*p);
418 		free(ho->h_aliases);
419 	}
420 
421 	if (ho->h_addr_list != NULL) {
422 		for (p = ho->h_addr_list ; *p != NULL ; p++)
423 			free(*p);
424 		free(ho->h_addr_list);
425 	}
426 }
427 
428 /* dummy */
429 static struct addrinfo *
430 ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai)
431 {
432 	UNUSED(this);
433 	UNUSED(name);
434 	UNUSED(pai);
435 	return(NULL);
436 }
437