/** * uses rbwalk to check to see if a given ip address of a given type in the * tree is inside any of the cidrdata */ static int tree_checkincidr(tcpr_data_tree_t *treeroot, tcpr_buildcidr_t * bcdata) { tcpr_tree_t *node = NULL; tcpprep_opt_t *options = tcpprep->options; RB_FOREACH(node, tcpr_data_tree_s, treeroot) { /* we only check types that are valid */ if (bcdata->type != DIR_ANY) /* don't check if we're adding ANY */ if (bcdata->type != node->type) /* no match, exit early */ return 0; /* * in cases of leaves and last visit add to cidrdata if * necessary */ if (node->family == AF_INET && check_ip_cidr(options->cidrdata, node->u.ip)) /* if we exist, abort */ return 1; if (node->family == AF_INET6 && check_ip6_cidr(options->cidrdata, &node->u.ip6)) return 1; } return 0; }
int process_xX_by_cidr_ipv6(int mode, tcpr_cidr_t * cidr, ipv6_hdr_t * ip6_hdr) { if (mode & xXExclude) { /* Exclude mode */ switch (mode ^ xXExclude) { case xXSource: /* note: check_ip_cidr() returns TCPR_DIR_C2S for true, TCPR_DIR_S2C for false * and NOT true/false or 1/0, etc! */ return check_ip6_cidr(cidr, &ip6_hdr->ip_src) ? DONT_SEND : SEND; break; case xXDest: return check_ip6_cidr(cidr, &ip6_hdr->ip_dst) ? DONT_SEND : SEND; case xXBoth: return (check_ip6_cidr(cidr, &ip6_hdr->ip_dst) && check_ip6_cidr(cidr, &ip6_hdr->ip_src) ) ? DONT_SEND : SEND; break; case xXEither: return (check_ip6_cidr(cidr, &ip6_hdr->ip_dst) || check_ip6_cidr(cidr, &ip6_hdr->ip_src) ) ? DONT_SEND : SEND; break; } } else { /* Include Mode */ switch (mode) { case xXSource: return check_ip6_cidr(cidr, &ip6_hdr->ip_src) ? SEND : DONT_SEND; break; case xXDest: return check_ip6_cidr(cidr, &ip6_hdr->ip_dst) ? SEND : DONT_SEND; break; case xXBoth: return (check_ip6_cidr(cidr, &ip6_hdr->ip_dst) && check_ip6_cidr(cidr, &ip6_hdr->ip_src) ) ? SEND : DONT_SEND; break; case xXEither: return (check_ip6_cidr(cidr, &ip6_hdr->ip_dst) || check_ip6_cidr(cidr, &ip6_hdr->ip_src) ) ? SEND : DONT_SEND; break; } } /* total failure */ if (mode &xXExclude) { warn("Unable to determine action in CIDR filter mode. Default: Don't Send."); return DONT_SEND; } else { warn("Unable to determine action in CIDR filter mode. Default: Send."); return SEND; } }
/** * used with rbwalk to walk a tree and generate cidr_t * cidrdata. * is smart enough to prevent dupes. void * arg is cast to bulidcidr_t */ void tree_buildcidr(tcpr_data_tree_t *treeroot, tcpr_buildcidr_t * bcdata) { tcpr_tree_t *node = NULL; tcpr_cidr_t *newcidr = NULL; unsigned long network = 0; struct tcpr_in6_addr network6; unsigned long mask = ~0; /* turn on all bits */ tcpprep_opt_t *options = tcpprep->options; int i, j, k; dbg(1, "Running: tree_buildcidr()"); RB_FOREACH(node, tcpr_data_tree_s, treeroot) { /* we only check types that are valid */ if (bcdata->type != DIR_ANY) /* don't check if we're adding ANY */ if (bcdata->type != node->type) /* no match, exit early */ return; /* * in cases of leaves and last visit add to cidrdata if * necessary. First check IPv4 */ dbgx(4, "Checking if %s exists in cidrdata...", get_addr2name4(node->u.ip, RESOLVE)); if (node->family == AF_INET) { if (! check_ip_cidr(options->cidrdata, node->u.ip)) { /* if we exist, abort */ dbgx(3, "Node %s doesn't exist... creating.", get_addr2name4(node->u.ip, RESOLVE)); newcidr = new_cidr(); newcidr->masklen = bcdata->masklen; network = node->u.ip & (mask << (32 - bcdata->masklen)); dbgx(3, "Using network: %s", get_addr2name4(network, RESOLVE)); newcidr->u.network = network; add_cidr(&options->cidrdata, &newcidr); } } /* Check IPv6 Address */ else if (node->family == AF_INET6) { if (! check_ip6_cidr(options->cidrdata, &node->u.ip6)) { /* if we exist, abort */ dbgx(3, "Node %s doesn't exist... creating.", get_addr2name6(&node->u.ip6, RESOLVE)); newcidr = new_cidr(); newcidr->masklen = bcdata->masklen; /* init each 4 quads to zero */ for (i = 0; i < 4; i++) network6.tcpr_s6_addr32[i] = 0; /* Build our mask */ j = bcdata->masklen / 8; for (i = 0; i < j; i++) network6.tcpr_s6_addr[i] = node->u.ip6.tcpr_s6_addr[i]; if ((k = bcdata->masklen % 8) != 0) { k = ~0 << (8 - k); network6.tcpr_s6_addr[j] = node->u.ip6.tcpr_s6_addr[i] & k; } dbgx(3, "Using network: %s", get_addr2name6(&network6, RESOLVE)); newcidr->u.network6 = network6; add_cidr(&options->cidrdata, &newcidr); } } } }