📄 fttag.c
字号:
return -1; } } return 0;} /* parse_action_type *//* * function: parse_action_match * * process the 'match/set' line. The match action depends on the type which * must be configured first. An AS match is added to a table, a next-hop * is added to a hash (chash_*) and a prefix is added to a radix trie. * * returns: 0 ok * <0 fail */int parse_action_match(struct line_parser *lp, struct fttag *fttag){ struct radix_sockaddr_in sock1, sock2; struct fttag_as_look *as_look; struct fttag_next_hop_look *nh_look, nh_look2; struct fttag_prefix_look *prefix_look; struct fttag_port_look *port_look; struct fttag_tos_look *tos_look; struct fttag_any_look *any_look; struct ip_prefix ipp; struct radix_node_head *rhead; u_int32 tag, hash, ipaddr; u_int16 as, port; u_int8 tos; int sflag, new; char *c, *match; if (!lp->cur_action->type) { fterr_warnx("%s line %d: Must set type first.", lp->fname, lp->lineno); return -1; } bzero(&sock1, sizeof sock1); bzero(&sock2, sizeof sock2); sock1.sin_family = AF_INET; sock1.sin_len = sizeof (struct radix_sockaddr_in); sock2.sin_family = AF_INET; sock2.sin_len = sizeof (struct radix_sockaddr_in); as_look = lp->cur_action->look; nh_look = lp->cur_action->look; prefix_look = lp->cur_action->look; port_look = lp->cur_action->look; tos_look = lp->cur_action->look; any_look = lp->cur_action->look; NEXT_WORD(&lp->buf, c); if (!c) { fterr_warnx("%s line %d: Expecting match data.", lp->fname, lp->lineno); return -1; } match = c; NEXT_WORD(&lp->buf, c); if (!c) { fterr_warnx("%s line %d: Expecting [set|or]-[src|dst].", lp->fname, lp->lineno); return -1; } if (!strcasecmp(c, "set-src")) sflag = FT_TAG_SET_SRC_TAG; else if (!strcasecmp(c, "set-dst")) sflag = FT_TAG_SET_DST_TAG; else if (!strcasecmp(c, "or-src")) sflag = FT_TAG_OR_SRC_TAG; else if (!strcasecmp(c, "or-dst")) sflag = FT_TAG_OR_DST_TAG; else { fterr_warnx("%s line %d: Expecting [set|or]-[src|dst].", lp->fname, lp->lineno); return -1; } NEXT_WORD(&lp->buf, c); if (!c) { fterr_warnx("%s line %d: Expecting set data.", lp->fname, lp->lineno); return -1; } tag = strtoul(c, (char **)0L, 0); if (lp->cur_action->type & FT_TAG_TYPE_MATCH_AS) { as = atoi(match); if (as_look->set_flags_lookup[as] & sflag) { fterr_warnx("%s line %d: Only one match.", lp->fname, lp->lineno); return -1; } as_look->set_flags_lookup[as] |= sflag; if (sflag & FT_TAG_SET_SRC_TAG) as_look->src_tag_lookup[as] = tag; if (sflag & FT_TAG_OR_SRC_TAG) as_look->src_tag_lookup[as] |= tag; if (sflag & FT_TAG_SET_DST_TAG) as_look->dst_tag_lookup[as] = tag; if (sflag & FT_TAG_OR_DST_TAG) as_look->dst_tag_lookup[as] |= tag; } else if (lp->cur_action->type & (FT_TAG_TYPE_MATCH_TCP_PORT|FT_TAG_TYPE_MATCH_UDP_PORT)) { port = atoi(match); if (port_look->set_flags_lookup[port] & sflag) { fterr_warnx("%s line %d: Only one match.", lp->fname, lp->lineno); return -1; } port_look->set_flags_lookup[port] |= sflag; if (sflag & FT_TAG_SET_SRC_TAG) port_look->src_tag_lookup[port] = tag; if (sflag & FT_TAG_OR_SRC_TAG) port_look->src_tag_lookup[port] |= tag; if (sflag & FT_TAG_SET_DST_TAG) port_look->dst_tag_lookup[port] = tag; if (sflag & FT_TAG_OR_DST_TAG) port_look->dst_tag_lookup[port] |= tag; } else if (lp->cur_action->type & FT_TAG_TYPE_MATCH_TOS) { tos = atoi(match); if (tos_look->set_flags_lookup[tos] & sflag) { fterr_warnx("%s line %d: Only one match.", lp->fname, lp->lineno); return -1; } tos_look->set_flags_lookup[tos] |= sflag; if (sflag & FT_TAG_SET_SRC_TAG) tos_look->src_tag_lookup[tos] = tag; if (sflag & FT_TAG_OR_SRC_TAG) tos_look->src_tag_lookup[tos] |= tag; if (sflag & FT_TAG_SET_DST_TAG) tos_look->dst_tag_lookup[tos] = tag; if (sflag & FT_TAG_OR_DST_TAG) tos_look->dst_tag_lookup[tos] |= tag; } else if (lp->cur_action->type & FT_TAG_TYPE_MATCH_ANY) { if (strcasecmp(match, "any")) { fterr_warnx("%s line %d: Match must be any.", lp->fname, lp->lineno); return -1; } if (any_look->set_flags & sflag) { fterr_warnx("%s line %d: Only one match.", lp->fname, lp->lineno); return -1; } any_look->set_flags |= sflag; if (sflag & FT_TAG_SET_SRC_TAG) any_look->src_tag = tag; if (sflag & FT_TAG_OR_SRC_TAG) any_look->src_tag |= tag; if (sflag & FT_TAG_SET_DST_TAG) any_look->dst_tag = tag; if (sflag & FT_TAG_OR_DST_TAG) any_look->dst_tag |= tag; } else if (lp->cur_action->type & FT_TAG_TYPE_MATCH_PREFIX) { ipp = scan_ip_prefix(match); sock1.sin_addr.s_addr = ipp.addr; sock2.sin_addr.s_addr = (!ipp.len) ? 0 : mask_lookup[ipp.len]; rhead = lp->cur_action->look; /* try to retrieve from trie */ prefix_look = (struct fttag_prefix_look*)rhead->rnh_lookup(&sock1, &sock2, rhead); new = 1; /* if it exists, make sure not a duplicate set */ if (prefix_look && (prefix_look->addr.sin_addr.s_addr == ipp.addr) && (prefix_look->masklen == ipp.len)) { /* if the set is invalid fail, else update the record and return */ if (prefix_look->set_flags & sflag) { fterr_warnx("%s line %d: Only one match.", lp->fname, lp->lineno); return -1; } else { new = 0; } } /* allocate a new prefix lookup */ if (new) { if (!(prefix_look = (struct fttag_prefix_look*)malloc(sizeof (struct fttag_prefix_look)))) { fterr_warn("malloc(prefix_look)"); return -1; } bzero(prefix_look, sizeof *prefix_look); prefix_look->rt_nodes->rn_key = (caddr_t)&prefix_look->addr; prefix_look->addr.sin_addr.s_addr = ipp.addr; prefix_look->addr.sin_len = sizeof (struct radix_sockaddr_in); prefix_look->addr.sin_family = AF_INET; sock1.sin_addr.s_addr = (!ipp.len) ? 0 : mask_lookup[ipp.len]; prefix_look->masklen = ipp.len; /* add it to the trie */ if (!rhead->rnh_addaddr(&prefix_look->addr, &sock1, rhead, prefix_look->rt_nodes)) { free(prefix_look); fterr_warnx("rnh_addaddr(): failed for %s",match); return -1; } } /* new */ /* finish filling in */ prefix_look->set_flags |= sflag; if (sflag & FT_TAG_SET_SRC_TAG) prefix_look->src_tag = tag; if (sflag & FT_TAG_OR_SRC_TAG) prefix_look->src_tag |= tag; if (sflag & FT_TAG_SET_DST_TAG) prefix_look->dst_tag = tag; if (sflag & FT_TAG_OR_DST_TAG) prefix_look->dst_tag |= tag; } else if (lp->cur_action->type & FT_TAG_TYPE_MATCH_NEXTHOP) { ipaddr = scan_ip(match); hash = (ipaddr>>16) ^ (ipaddr & 0xFFFF); hash = (hash>>8) ^ (hash & 0xFF); nh_look = ftchash_lookup(lp->cur_action->look, &ipaddr, hash); new = 1; /* if it exists, make sure not a duplicate set */ if (nh_look) { /* if the set is invalid fail, else update the record and return */ if (nh_look->set_flags & sflag) { fterr_warnx("%s line %d: Only one match.", lp->fname, lp->lineno); return -1; } else { new = 0; } } if (new) { bzero(&nh_look2, sizeof nh_look2); nh_look2.addr = ipaddr; if (!(nh_look = ftchash_update(lp->cur_action->look, &nh_look2, hash))) { fterr_warnx("ftch_update(): failed"); return -1; } } /* finish filling in fields */ nh_look->set_flags |= sflag; if (sflag & FT_TAG_SET_SRC_TAG) nh_look->src_tag = tag; if (sflag & FT_TAG_OR_SRC_TAG) nh_look->src_tag |= tag; if (sflag & FT_TAG_SET_DST_TAG) nh_look->dst_tag = tag; if (sflag & FT_TAG_OR_DST_TAG) nh_look->dst_tag |= tag; } return 0;} /* parse_action_match *//* * function: parse_def * * process the 'definition' line. Each definition has a unique name which * is added to the fttag->defs linked list. The current definition is * updated in lp. * * returns: 0 ok * <0 fail */int parse_def(struct line_parser *lp, struct fttag *fttag){ char *c; struct fttag_def *ftd; NEXT_WORD(&lp->buf, c); if (!c) { fterr_warnx("%s line %d: Expecting name.", lp->fname, lp->lineno); return -1; } /* check if it exists */ FT_SLIST_FOREACH(ftd, &fttag->defs, chain) { if (!strcasecmp(c, ftd->name)) { fterr_warnx("%s line %d: Name (%s) previously defined.", lp->fname, lp->lineno, c); return -1; } } /* no, add a new entry to the list */ if (!(ftd = (struct fttag_def*)malloc(sizeof (struct fttag_def)))) { fterr_warn("malloc()"); return -1; } bzero(ftd, sizeof *ftd); FT_STAILQ_INIT(&ftd->terms); if (!(ftd->name = (char*)malloc(strlen(c)+1))) { fterr_warn("malloc()"); free(ftd); return -1; } strcpy(ftd->name, c); FT_SLIST_INSERT_HEAD(&fttag->defs, ftd, chain); lp->state = PARSE_STATE_DEFINITION; lp->cur_def = ftd; return 0;} /* parse_def *//* * function: parse_def_term * * process the term line. Each definition has a list of terms, the * terms have a common input, output, and exporter IP filter and * may have one or more actions. Without an action a term has * no purpose. * * returns: 0 ok * <0 fail */int parse_def_term(struct line_parser *lp, struct fttag *fttag){ struct fttag_def_term *ftdt; if (!lp->cur_def) { fterr_warnx("%s line %d: Must set name first.", lp->fname, lp->lineno); return -1; } /* no, add a new term entry to this definition */ if (!(ftdt = (struct fttag_def_term*)malloc(sizeof *ftdt))) { fterr_warn("malloc()"); return -1; } bzero(ftdt, sizeof *ftdt); FT_STAILQ_INIT(&ftdt->actions); FT_STAILQ_INSERT_TAIL(&lp->cur_def->terms, ftdt, chain); lp->cur_def_term = ftdt; return 0;} /* parse_def_term *//* * function: parse_def_exporter * * process the 'exporter' line. * * returns: 0 ok * <0 fail */int parse_def_exporter(struct line_parser *lp, struct fttag *fttag){ char *c; if (!lp->cur_def_term) { fterr_warnx("%s line %d: Must start term.", lp->fname, lp->lineno); return -1; } NEXT_WORD(&lp->buf, c); if (!c) { fterr_warnx("%s line %d: Expecting exporter.", lp->fname, lp->lineno); return -1; } if (lp->cur_def_term->flags & FT_TAG_DEF_FILTER_EXPORTER) { fterr_warnx("%s line %d: Exporter previously defined.", lp->fname, lp->lineno); return -1; } lp->cur_def_term->exporter_ip = scan_ip(c); lp->cur_def_term->flags |= FT_TAG_DEF_FILTER_EXPORTER; return 0;} /* parse_def_exporter *//* * function: parse_def_input_filter * * process the 'input-filter' line. * * returns: 0 ok * <0 fail */int parse_def_input_filter(struct line_parser *lp, struct fttag *fttag){ char *c; if (!lp->cur_def_term) { fterr_warnx("%s line %d: Must start term.", lp->fname, lp->lineno); return -1; } NEXT_WORD(&lp->buf, c); if (!c) { fterr_warnx("%s line %d: Expecting filter list.", lp->fname, lp->lineno); return -1; } if (lp->cur_def_term->flags & FT_TAG_DEF_FILTER_INPUT) { fterr_warnx("%s line %d: Input filter previously defined.", lp->fname, lp->lineno); return -1; } if (load_lookup(c, 65536, lp->cur_def_term->in_tbl)) { fterr_warnx("load_lookup(): failed"); return -1; } lp->cur_def_term->flags |= FT_TAG_DEF_FILTER_INPUT; return 0;} /* parse_def_input_filter *//* * function: parse_def_output_filter * * process the 'output-filter' line. * * returns: 0 ok * <0 fail */int parse_def_output_filter(struct line_parser *lp, struct fttag *fttag){ char *c; if (!lp->cur_def_term) { fterr_warnx("%s line %d: Must start term.", lp->fname, lp->lineno); return -1; } NEXT_WORD(&lp->buf, c); if (!c) { fterr_warnx("%s line %d: Expecting filter list.", lp->fname, lp->lineno); return -1; } if (lp->cur_def_term->flags & FT_TAG_DEF_FILTER_OUTPUT) { fterr_warnx("%s line %d: Output filter previously defined.", lp->fname, lp->lineno); return -1; } if (load_lookup(c, 65536, lp->cur_def_term->out_tbl)) { fterr_warnx("load_lookup(): failed"); return -1; } lp->cur_def_term->flags |= FT_TAG_DEF_FILTER_OUTPUT; return 0;} /* parse_def_output_filter *//* * function: parse_def_action * * foreach action listed, add it to a linked list of actions for the * definition. Note resolve_actions() must be called before the actions * are valid. * * returns: 0 ok * <0 fail */int parse_def_action(struct line_parser *lp, struct fttag *fttag){ struct fttag_def_term_actions *ftdta; char *c; if (!lp->cur_def_term) { fterr_warnx("%s line %d: Must start term.", lp->fname, lp->lineno); return -1; } NEXT_WORD(&lp->buf, c); if (!c) { fterr_warnx("%s line %d: Expecting action.", lp->fname, lp->lineno); return -1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -