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));
}
Exemple #2
0
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));
}