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