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