DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags) { DICT_CIDR *dict_cidr; VSTREAM *map_fp; VSTRING *line_buffer = vstring_alloc(100); VSTRING *why = vstring_alloc(100); DICT_CIDR_ENTRY *rule; DICT_CIDR_ENTRY *last_rule = 0; int lineno = 0; /* * Sanity checks. */ if (open_flags != O_RDONLY) msg_fatal("%s:%s map requires O_RDONLY access mode", DICT_TYPE_CIDR, mapname); /* * XXX Eliminate unnecessary queries by setting a flag that says "this * map matches network addresses only". */ dict_cidr = (DICT_CIDR *) dict_alloc(DICT_TYPE_CIDR, mapname, sizeof(*dict_cidr)); dict_cidr->dict.lookup = dict_cidr_lookup; dict_cidr->dict.close = dict_cidr_close; dict_cidr->dict.flags = dict_flags | DICT_FLAG_PATTERN; dict_cidr->head = 0; if ((map_fp = vstream_fopen(mapname, O_RDONLY, 0)) == 0) msg_fatal("open %s: %m", mapname); while (readlline(line_buffer, map_fp, &lineno)) { rule = dict_cidr_parse_rule(vstring_str(line_buffer), why); if (rule == 0) { msg_warn("cidr map %s, line %d: %s: skipping this rule", mapname, lineno, vstring_str(why)); continue; } if (last_rule == 0) dict_cidr->head = rule; else last_rule->cidr_info.next = &(rule->cidr_info); last_rule = rule; } /* * Clean up. */ if (vstream_fclose(map_fp)) msg_fatal("cidr map %s: read error: %m", mapname); vstring_free(line_buffer); vstring_free(why); return (DICT_DEBUG (&dict_cidr->dict)); }
DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags) { const char myname[] = "dict_cidr_open"; DICT_CIDR *dict_cidr; VSTREAM *map_fp = 0; struct stat st; VSTRING *line_buffer = 0; VSTRING *why = 0; DICT_CIDR_ENTRY *rule; DICT_CIDR_ENTRY *last_rule = 0; int last_line = 0; int lineno; int nesting = 0; DICT_CIDR_ENTRY **rule_stack = 0; MVECT mvect; /* * Let the optimizer worry about eliminating redundant code. */ #define DICT_CIDR_OPEN_RETURN(d) do { \ DICT *__d = (d); \ if (map_fp != 0 && vstream_fclose(map_fp)) \ msg_fatal("cidr map %s: read error: %m", mapname); \ if (line_buffer != 0) \ vstring_free(line_buffer); \ if (why != 0) \ vstring_free(why); \ return (__d); \ } while (0) /* * Sanity checks. */ if (open_flags != O_RDONLY) DICT_CIDR_OPEN_RETURN(dict_surrogate(DICT_TYPE_CIDR, mapname, open_flags, dict_flags, "%s:%s map requires O_RDONLY access mode", DICT_TYPE_CIDR, mapname)); /* * Open the configuration file. */ if ((map_fp = vstream_fopen(mapname, O_RDONLY, 0)) == 0) DICT_CIDR_OPEN_RETURN(dict_surrogate(DICT_TYPE_CIDR, mapname, open_flags, dict_flags, "open %s: %m", mapname)); if (fstat(vstream_fileno(map_fp), &st) < 0) msg_fatal("fstat %s: %m", mapname); line_buffer = vstring_alloc(100); why = vstring_alloc(100); /* * XXX Eliminate unnecessary queries by setting a flag that says "this * map matches network addresses only". */ dict_cidr = (DICT_CIDR *) dict_alloc(DICT_TYPE_CIDR, mapname, sizeof(*dict_cidr)); dict_cidr->dict.lookup = dict_cidr_lookup; dict_cidr->dict.close = dict_cidr_close; dict_cidr->dict.flags = dict_flags | DICT_FLAG_PATTERN; dict_cidr->head = 0; dict_cidr->dict.owner.uid = st.st_uid; dict_cidr->dict.owner.status = (st.st_uid != 0); while (readllines(line_buffer, map_fp, &last_line, &lineno)) { rule = dict_cidr_parse_rule(vstring_str(line_buffer), lineno, nesting, why); if (rule == 0) { msg_warn("cidr map %s, line %d: %s: skipping this rule", mapname, lineno, vstring_str(why)); continue; } if (rule->cidr_info.op == CIDR_MATCH_OP_IF) { if (rule_stack == 0) rule_stack = (DICT_CIDR_ENTRY **) mvect_alloc(&mvect, sizeof(*rule_stack), nesting + 1, (MVECT_FN) 0, (MVECT_FN) 0); else rule_stack = (DICT_CIDR_ENTRY **) mvect_realloc(&mvect, nesting + 1); rule_stack[nesting] = rule; nesting++; } else if (rule->cidr_info.op == CIDR_MATCH_OP_ENDIF) { DICT_CIDR_ENTRY *if_rule; if (nesting-- <= 0) /* Already handled in dict_cidr_parse_rule(). */ msg_panic("%s: ENDIF without IF", myname); if_rule = rule_stack[nesting]; if (if_rule->cidr_info.op != CIDR_MATCH_OP_IF) msg_panic("%s: unexpected rule stack element type %d", myname, if_rule->cidr_info.op); if_rule->cidr_info.block_end = &(rule->cidr_info); } if (last_rule == 0) dict_cidr->head = rule; else last_rule->cidr_info.next = &(rule->cidr_info); last_rule = rule; } while (nesting-- > 0) msg_warn("cidr map %s, line %d: IF has no matching ENDIF", mapname, rule_stack[nesting]->lineno); if (rule_stack) (void) mvect_free(&mvect); DICT_CIDR_OPEN_RETURN(DICT_DEBUG (&dict_cidr->dict)); }