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