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