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