📄 fttag.c
字号:
/* add a new entry to the list */ if (!(ftdta = (struct fttag_def_term_actions*)malloc(sizeof *ftdta))) { fterr_warn("malloc()"); return -1; } bzero(ftdta, sizeof *ftdta); ftdta->name = c; FT_STAILQ_INSERT_TAIL(&lp->cur_def_term->actions, ftdta, chain); /* resolve the ftdta->action later in resolve_actions */ return 0;} /* parse_def_action *//* * function: resolve_actions * * The parser points to the name of the action in the definition to allow * for definitions to be defined before actions in the config file. This * fixes the pointers so the definitions point to the actions * * returns: 0 ok * <0 fail (an action could not be resolved) */int resolve_actions(struct fttag *fttag){ struct fttag_def *ftd; struct fttag_def_term *ftdt; struct fttag_def_term_actions *ftdta; struct fttag_action *fta; int i, found; /* foreach definition */ FT_SLIST_FOREACH(ftd, &fttag->defs, chain) { /* foreach term in the definition */ FT_STAILQ_FOREACH(ftdt, &ftd->terms, chain) { /* * pre-init filter to all 1's to minimize test in eval later */ if (!(ftdt->flags & FT_TAG_DEF_FILTER_INPUT)) for (i = 0; i < 65536; ++i) ftdt->in_tbl[i] = 1; if (!(ftdt->flags & FT_TAG_DEF_FILTER_OUTPUT)) for (i = 0; i < 65536; ++i) ftdt->out_tbl[i] = 1; /* foreach action in the term */ FT_STAILQ_FOREACH(ftdta, &ftdt->actions, chain) { found = 0; /* foreach action */ FT_SLIST_FOREACH(fta, &fttag->actions, chain) { if (!(strcasecmp(fta->name, ftdta->name))) { ftdta->action = fta; found = 1; break; } } } if (!found) { fterr_warnx("Unable to resolve action \"%s\" in tag-definition \"%s\".", ftdta->name, ftd->name); return -1; } } } return 0;} /* resolve actions *//* * function: fttag_free * * free resources allocated by fttag_load() * */void fttag_free(struct fttag *fttag){ struct fttag_action *fta; struct fttag_def *ftd; struct fttag_def_term *ftdt; struct fttag_def_term_actions *ftdta; /* foreach action, remove the action and associated storge */ while (!FT_SLIST_EMPTY(&fttag->actions)) { fta = FT_SLIST_FIRST(&fttag->actions); FT_SLIST_REMOVE_HEAD(&fttag->actions, chain); if (fta->type & FT_TAG_TYPE_MATCH_AS) free(fta->look); else if (fta->type & FT_TAG_TYPE_MATCH_NEXTHOP) ftchash_free(fta->look); else if (fta->type & FT_TAG_TYPE_MATCH_PREFIX) { rhead = fta->look; rhead->rnh_walktree(rhead, walk_free, 0); } free(fta->name); free(fta); } /* while */ /* foreach definition, remove the definition and associated storage */ while (!FT_SLIST_EMPTY(&fttag->defs)) { ftd = FT_SLIST_FIRST(&fttag->defs); FT_SLIST_REMOVE_HEAD(&fttag->defs, chain); /* foreach term in the definition */ while (!FT_STAILQ_EMPTY(&ftd->terms)) { ftdt = FT_STAILQ_FIRST(&ftd->terms); while (!FT_STAILQ_EMPTY(&ftdt->actions)) { ftdta = FT_STAILQ_FIRST(&ftdt->actions); FT_STAILQ_REMOVE_HEAD(&ftdt->actions, chain); free(ftdta); } FT_STAILQ_REMOVE_HEAD(&ftd->terms, chain); free (ftdt); } free(ftd->name); free(ftd); } /* while */} /* fttag_free *//* * function: fttag_def_eval * * perform tag actions on a flow * * run down each term in the definition * evaluate the filter, if okay * run every action * * the filter is activated by * FT_TAG_DEF_FILTER_INPUT - check input * FT_TAG_DEF_FILTER_OUTPUT check output * FT_TAG_DEF_FILTER_EXPORTER check exporter * * * returns 0 */inline int fttag_def_eval(struct fttag_def *ftd, struct fts3rec_v1005 *rec){ struct fttag_def_term *ftdt; struct fttag_def_term_actions *ftdta; struct fttag_action *fta; /* foreach term in the definition */ FT_STAILQ_FOREACH(ftdt, &ftd->terms, chain) { /* in_tbl is preloaded with "permit any" so don't check the flags bit */ if (!ftdt->in_tbl[rec->input]) continue; /* out_tbl is preloaded with "permit any" so don't check the flags bit */ if (!ftdt->out_tbl[rec->output]) continue; if (ftdt->flags & FT_TAG_DEF_FILTER_EXPORTER) if (ftdt->exporter_ip != rec->exaddr) continue; /* for every action chained to this term */ FT_STAILQ_FOREACH(ftdta, &ftdt->actions, chain) { /* the action */ fta = ftdta->action; /* based on the type do the action if a match is made */ fta->eval(fta, rec); } /* foreach action references by the term */ } /* foreach term */ return 0;} /* fttag_def_eval */inline void eval_match_src_as(struct fttag_action *fta, struct fts3rec_v1005 *rec){ struct fttag_as_look *as_look; u_int16 set_tmp; as_look = fta->look; set_tmp = as_look->set_flags_lookup[rec->src_as]; if (set_tmp & FT_TAG_SET_DST_TAG) rec->dst_tag = as_look->dst_tag_lookup[rec->src_as]; else if (set_tmp & FT_TAG_OR_DST_TAG) rec->dst_tag |= as_look->dst_tag_lookup[rec->src_as]; if (set_tmp & FT_TAG_SET_SRC_TAG) rec->src_tag = as_look->src_tag_lookup[rec->src_as]; if (set_tmp & FT_TAG_OR_SRC_TAG) rec->src_tag |= as_look->src_tag_lookup[rec->src_as];} /* eval_match_src_as */inline void eval_match_dst_as(struct fttag_action *fta, struct fts3rec_v1005 *rec){ struct fttag_as_look *as_look; u_int16 set_tmp; as_look = fta->look; set_tmp = as_look->set_flags_lookup[rec->dst_as]; if (set_tmp & FT_TAG_SET_DST_TAG) rec->dst_tag = as_look->dst_tag_lookup[rec->dst_as]; else if (set_tmp & FT_TAG_OR_DST_TAG) rec->dst_tag |= as_look->dst_tag_lookup[rec->dst_as]; if (set_tmp & FT_TAG_SET_SRC_TAG) rec->src_tag = as_look->src_tag_lookup[rec->dst_as]; if (set_tmp & FT_TAG_OR_SRC_TAG) rec->src_tag |= as_look->src_tag_lookup[rec->dst_as];} /* eval_match_dst_as */inline void eval_match_src_prefix(struct fttag_action *fta, struct fts3rec_v1005 *rec){ struct radix_sockaddr_in dst_sock; struct fttag_prefix_look *prefix_look; struct radix_node_head *rhead; u_int16 set_tmp; rhead = fta->look; dst_sock.sin_addr.s_addr = rec->srcaddr; dst_sock.sin_len = sizeof (struct radix_sockaddr_in); dst_sock.sin_family = AF_INET; prefix_look = (struct fttag_prefix_look *) rhead->rnh_matchaddr(&dst_sock, rhead); if (prefix_look) { set_tmp = prefix_look->set_flags; if (set_tmp & FT_TAG_SET_DST_TAG) rec->dst_tag = prefix_look->dst_tag; else if (set_tmp & FT_TAG_OR_DST_TAG) rec->dst_tag |= prefix_look->dst_tag; if (set_tmp & FT_TAG_SET_SRC_TAG) rec->src_tag = prefix_look->src_tag; else if (set_tmp & FT_TAG_OR_SRC_TAG) rec->src_tag |= prefix_look->src_tag; }} /* eval_match_src_prefix */inline void eval_match_dst_prefix(struct fttag_action *fta, struct fts3rec_v1005 *rec){ struct radix_sockaddr_in dst_sock; struct fttag_prefix_look *prefix_look; struct radix_node_head *rhead; u_int16 set_tmp; rhead = fta->look; dst_sock.sin_addr.s_addr = rec->dstaddr; dst_sock.sin_len = sizeof (struct radix_sockaddr_in); dst_sock.sin_family = AF_INET; prefix_look = (struct fttag_prefix_look *) rhead->rnh_matchaddr(&dst_sock, rhead); if (prefix_look) { set_tmp = prefix_look->set_flags; if (set_tmp & FT_TAG_SET_DST_TAG) rec->dst_tag = prefix_look->dst_tag; else if (set_tmp & FT_TAG_OR_DST_TAG) rec->dst_tag |= prefix_look->dst_tag; if (set_tmp & FT_TAG_SET_SRC_TAG) rec->src_tag = prefix_look->src_tag; else if (set_tmp & FT_TAG_OR_SRC_TAG) rec->src_tag |= prefix_look->src_tag; }} /* eval_match_dst_prefix */inline void eval_match_nexthop(struct fttag_action *fta, struct fts3rec_v1005 *rec){ struct ftchash *ftch; u_int32 hash, ipaddr; struct fttag_next_hop_look *nh_look; u_int16 set_tmp; ftch = fta->look; ipaddr = rec->nexthop; hash = (ipaddr>>16) ^ (ipaddr & 0xFFFF); hash = (hash>>8) ^ (hash & 0xFF); /* lookup next hop */ nh_look = ftchash_lookup(ftch, &ipaddr, hash); if (nh_look) { set_tmp = nh_look->set_flags; if (set_tmp & FT_TAG_SET_DST_TAG) rec->dst_tag = nh_look->dst_tag; else if (set_tmp & FT_TAG_OR_DST_TAG) rec->dst_tag |= nh_look->dst_tag; if (set_tmp & FT_TAG_SET_SRC_TAG) rec->src_tag = nh_look->src_tag; else if (set_tmp & FT_TAG_OR_SRC_TAG) rec->src_tag |= nh_look->src_tag; }} /* eval_match_nexthop */inline void eval_match_prefix(struct fttag_action *fta, struct fts3rec_v1005 *rec){ eval_match_src_prefix(fta, rec); eval_match_dst_prefix(fta, rec);} /* eval_match_prefix */inline void eval_match_as(struct fttag_action *fta, struct fts3rec_v1005 *rec){ eval_match_src_as(fta, rec); eval_match_dst_as(fta, rec);} /* eval_match_as */inline void eval_match_tcp_src_port(struct fttag_action *fta, struct fts3rec_v1005 *rec){ struct fttag_port_look *port_look; u_int16 set_tmp; port_look = fta->look; /* only TCP here */ if (rec->prot != 6) return; set_tmp = port_look->set_flags_lookup[rec->srcport]; if (set_tmp & FT_TAG_SET_DST_TAG) rec->dst_tag = port_look->dst_tag_lookup[rec->srcport]; else if (set_tmp & FT_TAG_OR_DST_TAG) rec->dst_tag |= port_look->dst_tag_lookup[rec->srcport]; if (set_tmp & FT_TAG_SET_SRC_TAG) rec->src_tag = port_look->src_tag_lookup[rec->srcport]; if (set_tmp & FT_TAG_OR_SRC_TAG) rec->src_tag |= port_look->src_tag_lookup[rec->srcport];} /* eval_match_tcp_src_port */inline void eval_match_tcp_dst_port(struct fttag_action *fta, struct fts3rec_v1005 *rec){ struct fttag_port_look *port_look; u_int16 set_tmp; port_look = fta->look; /* only TCP here */ if (rec->prot != 6) return; set_tmp = port_look->set_flags_lookup[rec->dstport]; if (set_tmp & FT_TAG_SET_DST_TAG) rec->dst_tag = port_look->dst_tag_lookup[rec->dstport]; else if (set_tmp & FT_TAG_OR_DST_TAG) rec->dst_tag |= port_look->dst_tag_lookup[rec->dstport]; if (set_tmp & FT_TAG_SET_SRC_TAG) rec->src_tag = port_look->src_tag_lookup[rec->dstport]; if (set_tmp & FT_TAG_OR_SRC_TAG) rec->src_tag |= port_look->src_tag_lookup[rec->dstport];} /* eval_match_tcp_dst_port */inline void eval_match_udp_src_port(struct fttag_action *fta, struct fts3rec_v1005 *rec){ struct fttag_port_look *port_look; u_int16 set_tmp; port_look = fta->look; /* only UDP here */ if (rec->prot != 17) return; set_tmp = port_look->set_flags_lookup[rec->srcport]; if (set_tmp & FT_TAG_SET_DST_TAG) rec->dst_tag = port_look->dst_tag_lookup[rec->srcport]; else if (set_tmp & FT_TAG_OR_DST_TAG) rec->dst_tag |= port_look->dst_tag_lookup[rec->srcport]; if (set_tmp & FT_TAG_SET_SRC_TAG) rec->src_tag = port_look->src_tag_lookup[rec->srcport]; if (set_tmp & FT_TAG_OR_SRC_TAG) rec->src_tag |= port_look->src_tag_lookup[rec->srcport];} /* eval_match_udp_src_port */inline void eval_match_udp_dst_port(struct fttag_action *fta, struct fts3rec_v1005 *rec){ struct fttag_port_look *port_look; u_int16 set_tmp; port_look = fta->look; /* only UDP here */ if (rec->prot != 17) return; set_tmp = port_look->set_flags_lookup[rec->dstport]; if (set_tmp & FT_TAG_SET_DST_TAG) rec->dst_tag = port_look->dst_tag_lookup[rec->dstport]; else if (set_tmp & FT_TAG_OR_DST_TAG) rec->dst_tag |= port_look->dst_tag_lookup[rec->dstport]; if (set_tmp & FT_TAG_SET_SRC_TAG) rec->src_tag = port_look->src_tag_lookup[rec->dstport]; if (set_tmp & FT_TAG_OR_SRC_TAG) rec->src_tag |= port_look->src_tag_lookup[rec->dstport];} /* eval_match_udp_dst_port */inline void eval_match_tcp_port(struct fttag_action *fta, struct fts3rec_v1005 *rec){ eval_match_tcp_src_port(fta, rec); eval_match_tcp_dst_port(fta, rec);} /* eval_match_tcp_port */inline void eval_match_udp_port(struct fttag_action *fta, struct fts3rec_v1005 *rec){ eval_match_udp_src_port(fta, rec); eval_match_udp_dst_port(fta, rec);} /* eval_match_udp_port */inline void eval_match_tos(struct fttag_action *fta, struct fts3rec_v1005 *rec){ struct fttag_tos_look *tos_look; u_int16 set_tmp; tos_look = fta->look; set_tmp = tos_look->set_flags_lookup[rec->tos]; if (set_tmp & FT_TAG_SET_DST_TAG) rec->dst_tag = tos_look->dst_tag_lookup[rec->tos]; else if (set_tmp & FT_TAG_OR_DST_TAG) rec->dst_tag |= tos_look->dst_tag_lookup[rec->tos]; if (set_tmp & FT_TAG_SET_SRC_TAG) rec->src_tag = tos_look->src_tag_lookup[rec->tos]; if (set_tmp & FT_TAG_OR_SRC_TAG) rec->src_tag |= tos_look->src_tag_lookup[rec->tos];} /* eval_match_tos */inline void eval_match_any(struct fttag_action *fta, struct fts3rec_v1005 *rec){ struct fttag_any_look *any_look; u_int16 set_tmp; any_look = fta->look; set_tmp = any_look->set_flags; if (set_tmp & FT_TAG_SET_DST_TAG) rec->dst_tag = any_look->dst_tag; else if (set_tmp & FT_TAG_OR_DST_TAG) rec->dst_tag |= any_look->dst_tag; if (set_tmp & FT_TAG_SET_SRC_TAG) rec->src_tag = any_look->src_tag; if (set_tmp & FT_TAG_OR_SRC_TAG) rec->src_tag |= any_look->src_tag;} /* eval_match_any */static int walk_free(struct radix_node *rn, struct walkarg *UNUSED){ struct fttag_prefix_look *r; struct radix_sockaddr_in sock1, sock2; r = (struct fttag_prefix_look*)rn; bzero(&sock1, sizeof sock1); bzero(&sock2, sizeof sock2); sock1.sin_addr.s_addr = r->addr.sin_addr.s_addr; sock1.sin_len = sizeof sock1; sock1.sin_family = AF_INET; sock2.sin_addr.s_addr = (!r->masklen) ? 0: mask_lookup[r->masklen]; sock2.sin_len = sizeof sock2; sock2.sin_family = AF_INET; if (r != (struct fttag_prefix_look*)rhead->rnh_deladdr(&sock1, &sock2, rhead)) fterr_errx(1, "rn_deladdr(): failed."); else free(r); return 0;} /* walk_free */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -