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