1 /* $NetBSD: dns_pr.c,v 1.1.1.1 2009/04/12 15:33:36 christos Exp $ */ 2 3 /* 4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (c) 1996,1999 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: dns_pr.c,v 1.5 2005/04/27 04:56:22 sra Exp"; 22 #endif 23 24 /* Imports */ 25 26 #include "port_before.h" 27 28 #include <sys/types.h> 29 #include <netinet/in.h> 30 #include <arpa/nameser.h> 31 #include <resolv.h> 32 33 #include <stdio.h> 34 #include <string.h> 35 #include <netdb.h> 36 #include <ctype.h> 37 #include <stdlib.h> 38 #include <errno.h> 39 40 #include <isc/memcluster.h> 41 #include <irs.h> 42 43 #include "port_after.h" 44 45 #include "irs_p.h" 46 #include "hesiod.h" 47 #include "dns_p.h" 48 49 /* Types. */ 50 51 struct pvt { 52 struct dns_p * dns; 53 struct protoent proto; 54 char * prbuf; 55 }; 56 57 /* Forward. */ 58 59 static void pr_close(struct irs_pr *); 60 static struct protoent * pr_byname(struct irs_pr *, const char *); 61 static struct protoent * pr_bynumber(struct irs_pr *, int); 62 static struct protoent * pr_next(struct irs_pr *); 63 static void pr_rewind(struct irs_pr *); 64 static void pr_minimize(struct irs_pr *); 65 static struct __res_state * pr_res_get(struct irs_pr *); 66 static void pr_res_set(struct irs_pr *, 67 struct __res_state *, 68 void (*)(void *)); 69 70 static struct protoent * parse_hes_list(struct irs_pr *, char **); 71 72 /* Public. */ 73 74 struct irs_pr * 75 irs_dns_pr(struct irs_acc *this) { 76 struct dns_p *dns = (struct dns_p *)this->private; 77 struct pvt *pvt; 78 struct irs_pr *pr; 79 80 if (!dns->hes_ctx) { 81 errno = ENODEV; 82 return (NULL); 83 } 84 if (!(pvt = memget(sizeof *pvt))) { 85 errno = ENOMEM; 86 return (NULL); 87 } 88 memset(pvt, 0, sizeof *pvt); 89 if (!(pr = memget(sizeof *pr))) { 90 memput(pvt, sizeof *pvt); 91 errno = ENOMEM; 92 return (NULL); 93 } 94 memset(pr, 0x5e, sizeof *pr); 95 pvt->dns = dns; 96 pr->private = pvt; 97 pr->byname = pr_byname; 98 pr->bynumber = pr_bynumber; 99 pr->next = pr_next; 100 pr->rewind = pr_rewind; 101 pr->close = pr_close; 102 pr->minimize = pr_minimize; 103 pr->res_get = pr_res_get; 104 pr->res_set = pr_res_set; 105 return (pr); 106 } 107 108 /* Methods. */ 109 110 static void 111 pr_close(struct irs_pr *this) { 112 struct pvt *pvt = (struct pvt *)this->private; 113 114 if (pvt->proto.p_aliases) 115 free(pvt->proto.p_aliases); 116 if (pvt->prbuf) 117 free(pvt->prbuf); 118 119 memput(pvt, sizeof *pvt); 120 memput(this, sizeof *this); 121 } 122 123 static struct protoent * 124 pr_byname(struct irs_pr *this, const char *name) { 125 struct pvt *pvt = (struct pvt *)this->private; 126 struct dns_p *dns = pvt->dns; 127 struct protoent *proto; 128 char **hes_list; 129 130 if (!(hes_list = hesiod_resolve(dns->hes_ctx, name, "protocol"))) 131 return (NULL); 132 133 proto = parse_hes_list(this, hes_list); 134 hesiod_free_list(dns->hes_ctx, hes_list); 135 return (proto); 136 } 137 138 static struct protoent * 139 pr_bynumber(struct irs_pr *this, int num) { 140 struct pvt *pvt = (struct pvt *)this->private; 141 struct dns_p *dns = pvt->dns; 142 struct protoent *proto; 143 char numstr[16]; 144 char **hes_list; 145 146 sprintf(numstr, "%d", num); 147 if (!(hes_list = hesiod_resolve(dns->hes_ctx, numstr, "protonum"))) 148 return (NULL); 149 150 proto = parse_hes_list(this, hes_list); 151 hesiod_free_list(dns->hes_ctx, hes_list); 152 return (proto); 153 } 154 155 static struct protoent * 156 pr_next(struct irs_pr *this) { 157 UNUSED(this); 158 errno = ENODEV; 159 return (NULL); 160 } 161 162 static void 163 pr_rewind(struct irs_pr *this) { 164 UNUSED(this); 165 /* NOOP */ 166 } 167 168 static void 169 pr_minimize(struct irs_pr *this) { 170 UNUSED(this); 171 /* NOOP */ 172 } 173 174 static struct __res_state * 175 pr_res_get(struct irs_pr *this) { 176 struct pvt *pvt = (struct pvt *)this->private; 177 struct dns_p *dns = pvt->dns; 178 179 return (__hesiod_res_get(dns->hes_ctx)); 180 } 181 182 static void 183 pr_res_set(struct irs_pr *this, struct __res_state * res, 184 void (*free_res)(void *)) { 185 struct pvt *pvt = (struct pvt *)this->private; 186 struct dns_p *dns = pvt->dns; 187 188 __hesiod_res_set(dns->hes_ctx, res, free_res); 189 } 190 191 /* Private. */ 192 193 static struct protoent * 194 parse_hes_list(struct irs_pr *this, char **hes_list) { 195 struct pvt *pvt = (struct pvt *)this->private; 196 char *p, *cp, **cpp, **new; 197 int num = 0; 198 int max = 0; 199 200 for (cpp = hes_list; *cpp; cpp++) { 201 cp = *cpp; 202 203 /* Strip away comments, if any. */ 204 if ((p = strchr(cp, '#'))) 205 *p = 0; 206 207 /* Skip blank lines. */ 208 p = cp; 209 while (*p && !isspace((unsigned char)*p)) 210 p++; 211 if (!*p) 212 continue; 213 214 /* OK, we've got a live one. Let's parse it for real. */ 215 if (pvt->prbuf) 216 free(pvt->prbuf); 217 pvt->prbuf = strdup(cp); 218 219 p = pvt->prbuf; 220 pvt->proto.p_name = p; 221 while (*p && !isspace((unsigned char)*p)) 222 p++; 223 if (!*p) 224 continue; 225 *p++ = '\0'; 226 227 pvt->proto.p_proto = atoi(p); 228 while (*p && !isspace((unsigned char)*p)) 229 p++; 230 if (*p) 231 *p++ = '\0'; 232 233 while (*p) { 234 if ((num + 1) >= max || !pvt->proto.p_aliases) { 235 max += 10; 236 new = realloc(pvt->proto.p_aliases, 237 max * sizeof(char *)); 238 if (!new) { 239 errno = ENOMEM; 240 goto cleanup; 241 } 242 pvt->proto.p_aliases = new; 243 } 244 pvt->proto.p_aliases[num++] = p; 245 while (*p && !isspace((unsigned char)*p)) 246 p++; 247 if (*p) 248 *p++ = '\0'; 249 } 250 if (!pvt->proto.p_aliases) 251 pvt->proto.p_aliases = malloc(sizeof(char *)); 252 if (!pvt->proto.p_aliases) 253 goto cleanup; 254 pvt->proto.p_aliases[num] = NULL; 255 return (&pvt->proto); 256 } 257 258 cleanup: 259 if (pvt->proto.p_aliases) { 260 free(pvt->proto.p_aliases); 261 pvt->proto.p_aliases = NULL; 262 } 263 if (pvt->prbuf) { 264 free(pvt->prbuf); 265 pvt->prbuf = NULL; 266 } 267 return (NULL); 268 } 269 270 /*! \file */ 271