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 /* Imports */ 19 20 #include "port_before.h" 21 22 #include <sys/types.h> 23 24 #include <netinet/in.h> 25 #include <arpa/nameser.h> 26 27 #include <errno.h> 28 #include <resolv.h> 29 #include <stdlib.h> 30 #include <string.h> 31 32 #include <isc/memcluster.h> 33 #include <irs.h> 34 35 #include "port_after.h" 36 37 #include "irs_p.h" 38 #include "gen_p.h" 39 40 /* Types */ 41 42 struct pvt { 43 struct irs_rule * rules; 44 struct irs_rule * rule; 45 struct __res_state * res; 46 void (*free_res)(void *); 47 }; 48 49 /* Forward */ 50 51 static void nw_close(struct irs_nw*); 52 static struct nwent * nw_next(struct irs_nw *); 53 static struct nwent * nw_byname(struct irs_nw *, const char *, int); 54 static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); 55 static void nw_rewind(struct irs_nw *); 56 static void nw_minimize(struct irs_nw *); 57 static struct __res_state * nw_res_get(struct irs_nw *this); 58 static void nw_res_set(struct irs_nw *this, 59 struct __res_state *res, 60 void (*free_res)(void *)); 61 62 static int init(struct irs_nw *this); 63 64 /* Public */ 65 66 struct irs_nw * 67 irs_gen_nw(struct irs_acc *this) { 68 struct gen_p *accpvt = (struct gen_p *)this->private; 69 struct irs_nw *nw; 70 struct pvt *pvt; 71 72 if (!(pvt = memget(sizeof *pvt))) { 73 errno = ENOMEM; 74 return (NULL); 75 } 76 memset(pvt, 0, sizeof *pvt); 77 if (!(nw = memget(sizeof *nw))) { 78 memput(pvt, sizeof *pvt); 79 errno = ENOMEM; 80 return (NULL); 81 } 82 memset(nw, 0x5e, sizeof *nw); 83 pvt->rules = accpvt->map_rules[irs_nw]; 84 pvt->rule = pvt->rules; 85 nw->private = pvt; 86 nw->close = nw_close; 87 nw->next = nw_next; 88 nw->byname = nw_byname; 89 nw->byaddr = nw_byaddr; 90 nw->rewind = nw_rewind; 91 nw->minimize = nw_minimize; 92 nw->res_get = nw_res_get; 93 nw->res_set = nw_res_set; 94 return (nw); 95 } 96 97 /* Methods */ 98 99 static void 100 nw_close(struct irs_nw *this) { 101 struct pvt *pvt = (struct pvt *)this->private; 102 103 nw_minimize(this); 104 105 if (pvt->res && pvt->free_res) 106 (*pvt->free_res)(pvt->res); 107 108 memput(pvt, sizeof *pvt); 109 memput(this, sizeof *this); 110 } 111 112 static struct nwent * 113 nw_next(struct irs_nw *this) { 114 struct pvt *pvt = (struct pvt *)this->private; 115 struct nwent *rval; 116 struct irs_nw *nw; 117 118 if (init(this) == -1) 119 return(NULL); 120 121 while (pvt->rule) { 122 nw = pvt->rule->inst->nw; 123 rval = (*nw->next)(nw); 124 if (rval) 125 return (rval); 126 if (!(pvt->rules->flags & IRS_CONTINUE)) 127 break; 128 pvt->rule = pvt->rule->next; 129 if (pvt->rule) { 130 nw = pvt->rule->inst->nw; 131 (*nw->rewind)(nw); 132 } 133 } 134 return (NULL); 135 } 136 137 static struct nwent * 138 nw_byname(struct irs_nw *this, const char *name, int type) { 139 struct pvt *pvt = (struct pvt *)this->private; 140 struct irs_rule *rule; 141 struct nwent *rval; 142 struct irs_nw *nw; 143 144 if (init(this) == -1) 145 return(NULL); 146 147 for (rule = pvt->rules; rule; rule = rule->next) { 148 nw = rule->inst->nw; 149 RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 150 rval = (*nw->byname)(nw, name, type); 151 if (rval != NULL) 152 return (rval); 153 if (pvt->res->res_h_errno != TRY_AGAIN && 154 !(rule->flags & IRS_CONTINUE)) 155 break; 156 } 157 return (NULL); 158 } 159 160 static struct nwent * 161 nw_byaddr(struct irs_nw *this, void *net, int length, int type) { 162 struct pvt *pvt = (struct pvt *)this->private; 163 struct irs_rule *rule; 164 struct nwent *rval; 165 struct irs_nw *nw; 166 167 if (init(this) == -1) 168 return(NULL); 169 170 for (rule = pvt->rules; rule; rule = rule->next) { 171 nw = rule->inst->nw; 172 RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); 173 rval = (*nw->byaddr)(nw, net, length, type); 174 if (rval != NULL) 175 return (rval); 176 if (pvt->res->res_h_errno != TRY_AGAIN && 177 !(rule->flags & IRS_CONTINUE)) 178 break; 179 } 180 return (NULL); 181 } 182 183 static void 184 nw_rewind(struct irs_nw *this) { 185 struct pvt *pvt = (struct pvt *)this->private; 186 struct irs_nw *nw; 187 188 pvt->rule = pvt->rules; 189 if (pvt->rule) { 190 nw = pvt->rule->inst->nw; 191 (*nw->rewind)(nw); 192 } 193 } 194 195 static void 196 nw_minimize(struct irs_nw *this) { 197 struct pvt *pvt = (struct pvt *)this->private; 198 struct irs_rule *rule; 199 200 if (pvt->res) 201 res_nclose(pvt->res); 202 for (rule = pvt->rules; rule != NULL; rule = rule->next) { 203 struct irs_nw *nw = rule->inst->nw; 204 205 (*nw->minimize)(nw); 206 } 207 } 208 209 static struct __res_state * 210 nw_res_get(struct irs_nw *this) { 211 struct pvt *pvt = (struct pvt *)this->private; 212 213 if (!pvt->res) { 214 struct __res_state *res; 215 res = (struct __res_state *)malloc(sizeof *res); 216 if (!res) { 217 errno = ENOMEM; 218 return (NULL); 219 } 220 memset(res, 0, sizeof *res); 221 nw_res_set(this, res, free); 222 } 223 224 return (pvt->res); 225 } 226 227 static void 228 nw_res_set(struct irs_nw *this, struct __res_state *res, 229 void (*free_res)(void *)) { 230 struct pvt *pvt = (struct pvt *)this->private; 231 struct irs_rule *rule; 232 233 if (pvt->res && pvt->free_res) { 234 res_nclose(pvt->res); 235 (*pvt->free_res)(pvt->res); 236 } 237 238 pvt->res = res; 239 pvt->free_res = free_res; 240 241 for (rule = pvt->rules; rule != NULL; rule = rule->next) { 242 struct irs_nw *nw = rule->inst->nw; 243 244 (*nw->res_set)(nw, pvt->res, NULL); 245 } 246 } 247 248 static int 249 init(struct irs_nw *this) { 250 struct pvt *pvt = (struct pvt *)this->private; 251 252 if (!pvt->res && !nw_res_get(this)) 253 return (-1); 254 if (((pvt->res->options & RES_INIT) == 0U) && 255 res_ninit(pvt->res) == -1) 256 return (-1); 257 return (0); 258 } 259 260 /*! \file */ 261