1 /* $NetBSD: gen.c,v 1.1.1.1 2009/04/12 15:33:38 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(LINT) && !defined(CODECENTER) 21 static const char rcsid[] = "Id: gen.c,v 1.7 2005/04/27 04:56:23 sra Exp"; 22 #endif 23 24 /*! \file 25 * \brief 26 * this is the top level dispatcher 27 * 28 * The dispatcher is implemented as an accessor class; it is an 29 * accessor class that calls other accessor classes, as controlled by a 30 * configuration file. 31 * 32 * A big difference between this accessor class and others is that the 33 * map class initializers are NULL, and the map classes are already 34 * filled in with method functions that will do the right thing. 35 */ 36 37 /* Imports */ 38 39 #include "port_before.h" 40 41 #include <isc/assertions.h> 42 #include <ctype.h> 43 #include <errno.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 48 #include <sys/types.h> 49 #include <netinet/in.h> 50 #include <arpa/nameser.h> 51 #include <resolv.h> 52 53 #include <isc/memcluster.h> 54 #include <irs.h> 55 56 #include "port_after.h" 57 58 #include "irs_p.h" 59 #include "gen_p.h" 60 61 /* Definitions */ 62 63 struct nameval { 64 const char * name; 65 int val; 66 }; 67 68 static const struct nameval acc_names[irs_nacc+1] = { 69 { "local", irs_lcl }, 70 { "dns", irs_dns }, 71 { "nis", irs_nis }, 72 { "irp", irs_irp }, 73 { NULL, irs_nacc } 74 }; 75 76 typedef struct irs_acc *(*accinit) __P((const char *options)); 77 78 static const accinit accs[irs_nacc+1] = { 79 irs_lcl_acc, 80 irs_dns_acc, 81 #ifdef WANT_IRS_NIS 82 irs_nis_acc, 83 #else 84 NULL, 85 #endif 86 irs_irp_acc, 87 NULL 88 }; 89 90 static const struct nameval map_names[irs_nmap+1] = { 91 { "group", irs_gr }, 92 { "passwd", irs_pw }, 93 { "services", irs_sv }, 94 { "protocols", irs_pr }, 95 { "hosts", irs_ho }, 96 { "networks", irs_nw }, 97 { "netgroup", irs_ng }, 98 { NULL, irs_nmap } 99 }; 100 101 static const struct nameval option_names[] = { 102 { "merge", IRS_MERGE }, 103 { "continue", IRS_CONTINUE }, 104 { NULL, 0 } 105 }; 106 107 /* Forward */ 108 109 static void gen_close(struct irs_acc *); 110 static struct __res_state * gen_res_get(struct irs_acc *); 111 static void gen_res_set(struct irs_acc *, struct __res_state *, 112 void (*)(void *)); 113 static int find_name(const char *, const struct nameval nv[]); 114 static void init_map_rules(struct gen_p *, const char *conf_file); 115 static struct irs_rule *release_rule(struct irs_rule *); 116 static int add_rule(struct gen_p *, 117 enum irs_map_id, enum irs_acc_id, 118 const char *); 119 120 /* Public */ 121 122 struct irs_acc * 123 irs_gen_acc(const char *options, const char *conf_file) { 124 struct irs_acc *acc; 125 struct gen_p *irs; 126 127 if (!(acc = memget(sizeof *acc))) { 128 errno = ENOMEM; 129 return (NULL); 130 } 131 memset(acc, 0x5e, sizeof *acc); 132 if (!(irs = memget(sizeof *irs))) { 133 errno = ENOMEM; 134 memput(acc, sizeof *acc); 135 return (NULL); 136 } 137 memset(irs, 0x5e, sizeof *irs); 138 irs->options = strdup(options); 139 irs->res = NULL; 140 irs->free_res = NULL; 141 memset(irs->accessors, 0, sizeof irs->accessors); 142 memset(irs->map_rules, 0, sizeof irs->map_rules); 143 init_map_rules(irs, conf_file); 144 acc->private = irs; 145 #ifdef WANT_IRS_GR 146 acc->gr_map = irs_gen_gr; 147 #else 148 acc->gr_map = NULL; 149 #endif 150 #ifdef WANT_IRS_PW 151 acc->pw_map = irs_gen_pw; 152 #else 153 acc->pw_map = NULL; 154 #endif 155 acc->sv_map = irs_gen_sv; 156 acc->pr_map = irs_gen_pr; 157 acc->ho_map = irs_gen_ho; 158 acc->nw_map = irs_gen_nw; 159 acc->ng_map = irs_gen_ng; 160 acc->res_get = gen_res_get; 161 acc->res_set = gen_res_set; 162 acc->close = gen_close; 163 return (acc); 164 } 165 166 /* Methods */ 167 168 static struct __res_state * 169 gen_res_get(struct irs_acc *this) { 170 struct gen_p *irs = (struct gen_p *)this->private; 171 172 if (irs->res == NULL) { 173 struct __res_state *res; 174 res = (struct __res_state *)malloc(sizeof *res); 175 if (res == NULL) 176 return (NULL); 177 memset(res, 0, sizeof *res); 178 gen_res_set(this, res, free); 179 } 180 181 if (((irs->res->options & RES_INIT) == 0U) && res_ninit(irs->res) < 0) 182 return (NULL); 183 184 return (irs->res); 185 } 186 187 static void 188 gen_res_set(struct irs_acc *this, struct __res_state *res, 189 void (*free_res)(void *)) { 190 struct gen_p *irs = (struct gen_p *)this->private; 191 #if 0 192 struct irs_rule *rule; 193 struct irs_ho *ho; 194 struct irs_nw *nw; 195 #endif 196 197 if (irs->res && irs->free_res) { 198 res_nclose(irs->res); 199 (*irs->free_res)(irs->res); 200 } 201 202 irs->res = res; 203 irs->free_res = free_res; 204 205 #if 0 206 for (rule = irs->map_rules[irs_ho]; rule; rule = rule->next) { 207 ho = rule->inst->ho; 208 209 (*ho->res_set)(ho, res, NULL); 210 } 211 for (rule = irs->map_rules[irs_nw]; rule; rule = rule->next) { 212 nw = rule->inst->nw; 213 214 (*nw->res_set)(nw, res, NULL); 215 } 216 #endif 217 } 218 219 static void 220 gen_close(struct irs_acc *this) { 221 struct gen_p *irs = (struct gen_p *)this->private; 222 int n; 223 224 /* Search rules. */ 225 for (n = 0; n < irs_nmap; n++) 226 while (irs->map_rules[n] != NULL) 227 irs->map_rules[n] = release_rule(irs->map_rules[n]); 228 229 /* Access methods. */ 230 for (n = 0; n < irs_nacc; n++) { 231 /* Map objects. */ 232 if (irs->accessors[n].gr != NULL) 233 (*irs->accessors[n].gr->close)(irs->accessors[n].gr); 234 if (irs->accessors[n].pw != NULL) 235 (*irs->accessors[n].pw->close)(irs->accessors[n].pw); 236 if (irs->accessors[n].sv != NULL) 237 (*irs->accessors[n].sv->close)(irs->accessors[n].sv); 238 if (irs->accessors[n].pr != NULL) 239 (*irs->accessors[n].pr->close)(irs->accessors[n].pr); 240 if (irs->accessors[n].ho != NULL) 241 (*irs->accessors[n].ho->close)(irs->accessors[n].ho); 242 if (irs->accessors[n].nw != NULL) 243 (*irs->accessors[n].nw->close)(irs->accessors[n].nw); 244 if (irs->accessors[n].ng != NULL) 245 (*irs->accessors[n].ng->close)(irs->accessors[n].ng); 246 /* Enclosing accessor. */ 247 if (irs->accessors[n].acc != NULL) 248 (*irs->accessors[n].acc->close)(irs->accessors[n].acc); 249 } 250 251 /* The options string was strdup'd. */ 252 free((void*)irs->options); 253 254 if (irs->res && irs->free_res) 255 (*irs->free_res)(irs->res); 256 257 /* The private data container. */ 258 memput(irs, sizeof *irs); 259 260 /* The object. */ 261 memput(this, sizeof *this); 262 } 263 264 /* Private */ 265 266 static int 267 find_name(const char *name, const struct nameval names[]) { 268 int n; 269 270 for (n = 0; names[n].name != NULL; n++) 271 if (strcmp(name, names[n].name) == 0) 272 return (names[n].val); 273 return (-1); 274 } 275 276 static struct irs_rule * 277 release_rule(struct irs_rule *rule) { 278 struct irs_rule *next = rule->next; 279 280 memput(rule, sizeof *rule); 281 return (next); 282 } 283 284 static int 285 add_rule(struct gen_p *irs, 286 enum irs_map_id map, enum irs_acc_id acc, 287 const char *options) 288 { 289 struct irs_rule **rules, *last, *tmp, *new; 290 struct irs_inst *inst; 291 const char *cp; 292 int n; 293 294 #ifndef WANT_IRS_GR 295 if (map == irs_gr) 296 return (-1); 297 #endif 298 #ifndef WANT_IRS_PW 299 if (map == irs_pw) 300 return (-1); 301 #endif 302 #ifndef WANT_IRS_NIS 303 if (acc == irs_nis) 304 return (-1); 305 #endif 306 new = memget(sizeof *new); 307 if (new == NULL) 308 return (-1); 309 memset(new, 0x5e, sizeof *new); 310 new->next = NULL; 311 312 new->inst = &irs->accessors[acc]; 313 314 new->flags = 0; 315 cp = options; 316 while (cp && *cp) { 317 char option[50], *next; 318 319 next = strchr(cp, ','); 320 if (next) 321 n = next++ - cp; 322 else 323 n = strlen(cp); 324 if ((size_t)n > sizeof option - 1) 325 n = sizeof option - 1; 326 strncpy(option, cp, n); 327 option[n] = '\0'; 328 329 n = find_name(option, option_names); 330 if (n >= 0) 331 new->flags |= n; 332 333 cp = next; 334 } 335 336 rules = &irs->map_rules[map]; 337 for (last = NULL, tmp = *rules; 338 tmp != NULL; 339 last = tmp, tmp = tmp->next) 340 (void)NULL; 341 if (last == NULL) 342 *rules = new; 343 else 344 last->next = new; 345 346 /* Try to instantiate map accessors for this if necessary & approp. */ 347 inst = &irs->accessors[acc]; 348 if (inst->acc == NULL && accs[acc] != NULL) 349 inst->acc = (*accs[acc])(irs->options); 350 if (inst->acc != NULL) { 351 if (inst->gr == NULL && inst->acc->gr_map != NULL) 352 inst->gr = (*inst->acc->gr_map)(inst->acc); 353 if (inst->pw == NULL && inst->acc->pw_map != NULL) 354 inst->pw = (*inst->acc->pw_map)(inst->acc); 355 if (inst->sv == NULL && inst->acc->sv_map != NULL) 356 inst->sv = (*inst->acc->sv_map)(inst->acc); 357 if (inst->pr == NULL && inst->acc->pr_map != NULL) 358 inst->pr = (*inst->acc->pr_map)(inst->acc); 359 if (inst->ho == NULL && inst->acc->ho_map != NULL) 360 inst->ho = (*inst->acc->ho_map)(inst->acc); 361 if (inst->nw == NULL && inst->acc->nw_map != NULL) 362 inst->nw = (*inst->acc->nw_map)(inst->acc); 363 if (inst->ng == NULL && inst->acc->ng_map != NULL) 364 inst->ng = (*inst->acc->ng_map)(inst->acc); 365 } 366 367 return (0); 368 } 369 370 static void 371 default_map_rules(struct gen_p *irs) { 372 /* Install time honoured and proved BSD style rules as default. */ 373 add_rule(irs, irs_gr, irs_lcl, ""); 374 add_rule(irs, irs_pw, irs_lcl, ""); 375 add_rule(irs, irs_sv, irs_lcl, ""); 376 add_rule(irs, irs_pr, irs_lcl, ""); 377 add_rule(irs, irs_ho, irs_dns, "continue"); 378 add_rule(irs, irs_ho, irs_lcl, ""); 379 add_rule(irs, irs_nw, irs_dns, "continue"); 380 add_rule(irs, irs_nw, irs_lcl, ""); 381 add_rule(irs, irs_ng, irs_lcl, ""); 382 } 383 384 static void 385 init_map_rules(struct gen_p *irs, const char *conf_file) { 386 char line[1024], pattern[40], mapname[20], accname[20], options[100]; 387 FILE *conf; 388 389 if (conf_file == NULL) 390 conf_file = _PATH_IRS_CONF ; 391 392 /* A conf file of "" means compiled in defaults. Irpd wants this */ 393 if (conf_file[0] == '\0' || (conf = fopen(conf_file, "r")) == NULL) { 394 default_map_rules(irs); 395 return; 396 } 397 (void) sprintf(pattern, "%%%lus %%%lus %%%lus\n", 398 (unsigned long)sizeof mapname, 399 (unsigned long)sizeof accname, 400 (unsigned long)sizeof options); 401 while (fgets(line, sizeof line, conf)) { 402 enum irs_map_id map; 403 enum irs_acc_id acc; 404 char *tmp; 405 int n; 406 407 for (tmp = line; 408 isascii((unsigned char)*tmp) && 409 isspace((unsigned char)*tmp); 410 tmp++) 411 (void)NULL; 412 if (*tmp == '#' || *tmp == '\n' || *tmp == '\0') 413 continue; 414 n = sscanf(tmp, pattern, mapname, accname, options); 415 if (n < 2) 416 continue; 417 if (n < 3) 418 options[0] = '\0'; 419 420 n = find_name(mapname, map_names); 421 INSIST(n < irs_nmap); 422 if (n < 0) 423 continue; 424 map = (enum irs_map_id) n; 425 426 n = find_name(accname, acc_names); 427 INSIST(n < irs_nacc); 428 if (n < 0) 429 continue; 430 acc = (enum irs_acc_id) n; 431 432 add_rule(irs, map, acc, options); 433 } 434 fclose(conf); 435 } 436