/** * QUERY. * */ static query_state query_process_query(query_type* q, ldns_rr_type qtype, engine_type* engine) { dnsout_type* dnsout = NULL; if (!q || !q->zone) { return QUERY_DISCARDED; } ods_log_assert(q->zone->name); ods_log_debug("[%s] incoming query qtype=%s for zone %s", query_str, rrset_type2str(qtype), q->zone->name); /* sanity checks */ if (buffer_pkt_qdcount(q->buffer) != 1 || buffer_pkt_tc(q->buffer)) { buffer_pkt_set_flags(q->buffer, 0); return query_formerr(q); } if (buffer_pkt_ancount(q->buffer) != 0 || (qtype != LDNS_RR_TYPE_IXFR && buffer_pkt_nscount(q->buffer) != 0)) { buffer_pkt_set_flags(q->buffer, 0); return query_formerr(q); } /* acl */ if (!q->zone->adoutbound || q->zone->adoutbound->type != ADAPTER_DNS) { ods_log_error("[%s] zone %s is not configured to have output dns " "adapter", query_str, q->zone->name); return query_refused(q); } ods_log_assert(q->zone->adoutbound->config); dnsout = (dnsout_type*) q->zone->adoutbound->config; /* acl also in use for soa and other queries */ if (!acl_find(dnsout->provide_xfr, &q->addr, q->tsig_rr)) { return query_refused(q); } /* ixfr? */ if (qtype == LDNS_RR_TYPE_IXFR) { if (query_process_ixfr(q) != QUERY_PROCESSED) { buffer_pkt_set_flags(q->buffer, 0); return query_formerr(q); } query_prepare(q); ods_log_assert(q->zone->name); ods_log_debug("[%s] incoming ixfr request serial=%u for zone %s", query_str, q->serial, q->zone->name); return ixfr(q, engine); } query_prepare(q); /* axfr? */ if (qtype == LDNS_RR_TYPE_AXFR) { ods_log_assert(q->zone->name); ods_log_debug("[%s] incoming axfr request for zone %s", query_str, q->zone->name); return axfr(q, engine); } /* (soa) query */ return query_response(q, qtype); }
// standard ACL int cliAclIcmpCmd(CliMode mode, int argc, char **argv) { char *data = (char *) pktout + sizeof(RcpPkt); *data = '\0'; // // store incoming data in a temporary structure // RcpAclIcmp in; memset(&in, 0, sizeof(RcpAclIcmp)); // no form int noform = 0; int index = 1; if (strcmp(argv[0], "no") == 0) { noform = 1; index++; } // list number uint8_t list_number = atoi(argv[index++]); // action uint8_t action; if (strcmp(argv[index++], "deny") == 0) action = RCPACL_ACTION_DENY; else action = RCPACL_ACTION_PERMIT; // mac address uint8_t mac[6]; if (atomac(argv[index], mac) == 0) { memcpy(in.mac, mac, 6); index++; } else // skip "icmp" index++; // source address if (strcmp(argv[index], "any") == 0) ; else { uint32_t ip; uint32_t mask; if (atocidr(argv[index], &ip, &mask)) { sprintf(data, "Error: invalid source IP address\n"); return RCPERR; } uint8_t mask_bits = mask2bits(mask); in.ip = ip; in.mask_bits = mask_bits; } index++; // destination address/output interface if (strcmp(argv[index], "any") == 0) ; else { uint32_t ip; uint32_t mask; if (atocidr(argv[index], &ip, &mask)) { sprintf(data, "Error: invalid destination IP address\n"); return RCPERR; } uint8_t mask_bits = mask2bits(mask); in.dest_ip = ip; in.dest_mask_bits = mask_bits; } index++; // icmp type if ((argc - 1) == index) in.icmp_type = atoi(argv[index]); // // process acl // // find if this is an existing acl RcpAcl *found = acl_find(&in, RCP_ACL_TYPE_ICMP, action, list_number); // process command if (noform) { if (found == NULL) return 0; // remove acl found->valid = 0; } else { // already there? if (found != NULL) return 0; // allocate new acl RcpAcl *newacl = acl_find_empty(); if (newacl == NULL) { strcpy(data, "Error: cannot configure ACL entry, limit reached"); return RCPERR; } // copy the data memcpy(&newacl->u.icmp, &in, sizeof(RcpAclIcmp)); newacl->valid = 1; newacl->type = RCP_ACL_TYPE_ICMP; newacl->action = action; newacl->list_number = list_number; } // trigger netfilter configuration update netfilter_update = 2; return 0; }
// extended ACL int cliAclCmd(CliMode mode, int argc, char **argv) { char *data = (char *) pktout + sizeof(RcpPkt); *data = '\0'; // // store incoming data in a temporary structure // RcpAclExtended in; memset(&in, 0, sizeof(RcpAclExtended)); // no form int noform = 0; int index = 1; if (strcmp(argv[0], "no") == 0) { noform = 1; index++; } // list number uint8_t list_number = atoi(argv[index++]); // action uint8_t action; if (strcmp(argv[index++], "deny") == 0) action = RCPACL_ACTION_DENY; else action = RCPACL_ACTION_PERMIT; // mac address uint8_t mac[6]; if (atomac(argv[index], mac) == 0) { memcpy(in.mac, mac, 6); index++; } // protocol if (isnum(argv[index])) in.protocol = atoi(argv[index++]); else if (strcmp(argv[index], "tcp") == 0) { in.protocol = RCPACL_PROTOCOL_TCP; index++; } else if (strcmp(argv[index], "udp") == 0) { in.protocol = RCPACL_PROTOCOL_UDP; index++; } else in.protocol = RCPACL_PROTOCOL_ANY; // source address if (strcmp(argv[index], "any") == 0) ; else { uint32_t ip; uint32_t mask; if (atocidr(argv[index], &ip, &mask)) { sprintf(data, "Error: invalid source IP address\n"); return RCPERR; } uint8_t mask_bits = mask2bits(mask); in.ip = ip; in.mask_bits = mask_bits; } index++; // source port if (isnum(argv[index])) in.port = atoi(argv[index++]); // destination address/output interface if (strcmp(argv[index], "any") == 0) ; else if (strcmp(argv[index], "out-interface") == 0) { strncpy(in.out_interface, argv[index + 1], RCP_MAX_IF_NAME); index++; } else { uint32_t ip; uint32_t mask; if (atocidr(argv[index], &ip, &mask)) { sprintf(data, "Error: invalid destination IP address\n"); return RCPERR; } uint8_t mask_bits = mask2bits(mask); in.dest_ip = ip; in.dest_mask_bits = mask_bits; } index++; // destination port if (index < argc && isnum(argv[index])) in.dest_port = atoi(argv[index++]); // connection state if (index < argc) { // parsing char *str = argv[index]; char *ptr = strtok(str, ","); in.constate = 0; while(ptr != NULL) { if (strcmp(ptr, "new") == 0) in.constate |= RCP_ACL_CONSTATE_NEW; else if (strcmp(ptr, "established") == 0) in.constate |= RCP_ACL_CONSTATE_ESTABLISHED; else if (strcmp(ptr, "related") == 0) in.constate |= RCP_ACL_CONSTATE_RELATED; else if (strcmp(ptr, "invalid") == 0) in.constate |= RCP_ACL_CONSTATE_INVALID; else { sprintf(data, "Error: invalid connecton state\n"); return RCPERR; } ptr = strtok(NULL, ","); } } // this should be the last one, argv was modified by strtok // // process acl // // find if this is an existing acl RcpAcl *found = acl_find(&in, RCP_ACL_TYPE_EXTENDED, action, list_number); // process command if (noform) { if (found == NULL) return 0; // remove acl found->valid = 0; } else { // already there? if (found != NULL) return 0; // allocate new acl RcpAcl *newacl = acl_find_empty(); if (newacl == NULL) { strcpy(data, "Error: cannot configure ACL entry, limit reached"); return RCPERR; } // copy the data memcpy(&newacl->u.extended, &in, sizeof(RcpAclExtended)); newacl->valid = 1; newacl->type = RCP_ACL_TYPE_EXTENDED; newacl->action = action; newacl->list_number = list_number; } // trigger netfilter configuration update netfilter_update = 2; return 0; }
/** * NOTIFY. * */ static query_state query_process_notify(query_type* q, ldns_rr_type qtype, void* engine) { engine_type* e = (engine_type*) engine; dnsin_type* dnsin = NULL; uint16_t count = 0; uint16_t rrcount = 0; uint32_t serial = 0; size_t pos = 0; char address[128]; if (!e || !q || !q->zone) { return QUERY_DISCARDED; } ods_log_assert(e->dnshandler); ods_log_assert(q->zone->name); ods_log_debug("[%s] incoming notify for zone %s", query_str, q->zone->name); if (buffer_pkt_rcode(q->buffer) != LDNS_RCODE_NOERROR || buffer_pkt_qr(q->buffer) || !buffer_pkt_aa(q->buffer) || buffer_pkt_tc(q->buffer) || buffer_pkt_rd(q->buffer) || buffer_pkt_ra(q->buffer) || buffer_pkt_ad(q->buffer) || buffer_pkt_cd(q->buffer) || buffer_pkt_qdcount(q->buffer) != 1 || buffer_pkt_ancount(q->buffer) > 1 || qtype != LDNS_RR_TYPE_SOA) { return query_formerr(q); } if (!q->zone->adinbound || q->zone->adinbound->type != ADAPTER_DNS) { ods_log_error("[%s] zone %s is not configured to have input dns " "adapter", query_str, q->zone->name); return query_notauth(q); } ods_log_assert(q->zone->adinbound->config); dnsin = (dnsin_type*) q->zone->adinbound->config; if (!acl_find(dnsin->allow_notify, &q->addr, q->tsig_rr)) { if (addr2ip(q->addr, address, sizeof(address))) { ods_log_info("[%s] unauthorized notify for zone %s from client %s: " "no acl matches", query_str, q->zone->name, address); } else { ods_log_info("[%s] unauthorized notify for zone %s from unknown " "client: no acl matches", query_str, q->zone->name); } return query_notauth(q); } ods_log_assert(q->zone->xfrd); /* skip header and question section */ buffer_skip(q->buffer, BUFFER_PKT_HEADER_SIZE); count = buffer_pkt_qdcount(q->buffer); for (rrcount = 0; rrcount < count; rrcount++) { if (!buffer_skip_rr(q->buffer, 1)) { ods_log_error("[%s] dropped packet: zone %s received bad notify " "(bad question section)", query_str, q->zone->name); return QUERY_DISCARDED; } } pos = buffer_position(q->buffer); /* examine answer section */ count = buffer_pkt_ancount(q->buffer); if (count) { if (!buffer_skip_dname(q->buffer) || !query_parse_soa(q->buffer, &serial)) { ods_log_error("[%s] dropped packet: zone %s received bad notify " "(bad soa in answer section)", query_str, q->zone->name); return QUERY_DISCARDED; } lock_basic_lock(&q->zone->xfrd->serial_lock); q->zone->xfrd->serial_notify = serial; q->zone->xfrd->serial_notify_acquired = time_now(); if (!util_serial_gt(q->zone->xfrd->serial_notify, q->zone->xfrd->serial_disk)) { ods_log_debug("[%s] ignore notify: already got zone %s serial " "%u on disk", query_str, q->zone->name, q->zone->xfrd->serial_notify); lock_basic_unlock(&q->zone->xfrd->serial_lock); goto send_notify_ok; } lock_basic_unlock(&q->zone->xfrd->serial_lock); } else { lock_basic_lock(&q->zone->xfrd->serial_lock); q->zone->xfrd->serial_notify = 0; q->zone->xfrd->serial_notify_acquired = 0; lock_basic_unlock(&q->zone->xfrd->serial_lock); } /* forward notify to xfrd */ xfrd_set_timer_now(q->zone->xfrd); dnshandler_fwd_notify(e->dnshandler, buffer_begin(q->buffer), buffer_remaining(q->buffer)); send_notify_ok: /* send notify ok */ buffer_pkt_set_qr(q->buffer); buffer_pkt_set_aa(q->buffer); buffer_pkt_set_ancount(q->buffer, 0); buffer_clear(q->buffer); /* lim = pos, pos = 0; */ buffer_set_position(q->buffer, pos); buffer_set_limit(q->buffer, buffer_capacity(q->buffer)); q->reserved_space = edns_rr_reserved_space(q->edns_rr); q->reserved_space += tsig_rr_reserved_space(q->tsig_rr); return QUERY_PROCESSED; }
int main(int argc, char **argv) { struct fts3rec_all cur; struct fts3rec_offsets fo; struct ftio ftio_in, ftio_out; struct ftset ftset; struct ftver ftv; struct ftprof ftp; uint32_t time_start, time_end, exaddr; int i, ret; char *acl_fname, *acl_std_src_name, *acl_std_dst_name; char *acl_std_nexthop_name; char *acl_ext_name, *str, *strm; int acl_std_src_index, acl_std_src_index2; int acl_std_dst_index, acl_std_dst_index2; int acl_std_nexthop_index, acl_std_nexthop_index2; int acl_ext_index, acl_ext_index2; struct acl_ip_ext_entry tmp_ext; int keep_input_time; int filter_input, filter_output, filter_srcport, filter_dstport; int filter_prot, filter_srcas, filter_dstas, filter_tos, filter_tcp_flags; int filter_exaddr; char in_tbl[65536], out_tbl[65536], src_tbl[65536], dst_tbl[65536]; char srcas_tbl[65536], dstas_tbl[65536], tos_tbl[65536]; char tcp_flags_tbl[65536]; char prot_tbl[256]; u_char tos_mask, tos, tcp_flags_mask, tcp_flags; uint64_t total_flows, xflag; char *rec; int first_match = 0; /* init fterr */ fterr_setid(argv[0]); bzero(&ftv, sizeof ftv); /* defaults + no compression */ ftset_init(&ftset, 0); /* init */ bzero(&acl_list, sizeof acl_list); acl_fname = acl_std_src_name = acl_std_dst_name = (char*)0L; acl_std_nexthop_name = (char*)0L; acl_ext_name = (char*)0L; acl_std_src_index = acl_std_dst_index = -1; acl_std_nexthop_index = -1; acl_ext_index = -1; bzero(&tmp_ext, sizeof tmp_ext); total_flows = 0; tos_mask = 0xff; tcp_flags_mask = 0xff; keep_input_time = 0; filter_input = filter_output = filter_srcport = filter_dstport = 0; filter_prot = filter_srcas = filter_dstas = filter_tos = filter_exaddr = 0; filter_tcp_flags = 0; while ((i = getopt(argc, argv, "a:A:b:C:d:D:e:E:f:i:I:kop:P:r:S:t:T:x:z:")) != -1) switch (i) { case 'a': /* src AS filter list */ if (load_lookup(optarg, 65536, srcas_tbl)) fterr_errx(1, "load_lookup(): failed"); filter_srcas = 1; break; case 'A': /* dst AS filter list */ if (load_lookup(optarg, 65536, dstas_tbl)) fterr_errx(1, "load_lookup(): failed"); filter_dstas = 1; break; case 'b': /* output byte order */ if (!strcasecmp(optarg, "little")) ftset.byte_order = FT_HEADER_LITTLE_ENDIAN; else if (!strcasecmp(optarg, "big")) ftset.byte_order = FT_HEADER_BIG_ENDIAN; else fterr_errx(1, "expecting \"big\" or \"little\""); break; case 'C': /* comment field */ ftset.comments = optarg; break; case 'D': /* dst ip standard access list filter */ acl_std_dst_name = optarg; break; case 'd': /* debug */ debug = atoi(optarg); break; case 'e': /* export IP address */ filter_exaddr = 1; exaddr = scan_ip(optarg); break; case 'E': /* extended access list filter */ acl_ext_name = optarg; break; case 'f': /* acl file name */ acl_fname = optarg; break; case 'i': /* input filter interface list */ if (load_lookup(optarg, 65536, in_tbl)) fterr_errx(1, "load_lookup(): failed"); filter_input = 1; break; case 'I': /* output filter interface list */ if (load_lookup(optarg, 65536, out_tbl)) fterr_errx(1, "load_lookup(): failed"); filter_output = 1; break; case 'k': /* keep the start/end time from the input */ keep_input_time = 1; break; case 'o': /* do logical OR between different statements (first match) */ first_match = 1; break; case 'P': /* filter dstport */ if (load_lookup(optarg, 65536, dst_tbl)) fterr_errx(1, "load_lookup(): failed"); filter_dstport = 1; break; case 'p': /* filter srcport */ if (load_lookup(optarg, 65536, src_tbl)) fterr_errx(1, "load_lookup(): failed"); filter_srcport = 1; break; case 'r': /* filter protocol */ if (load_lookup(optarg, 256, prot_tbl)) fterr_errx(1, "load_lookup(): failed"); filter_prot = 1; break; case 'S': /* src ip standard access list filter */ acl_std_src_name = optarg; break; case 't': /* ToS Filter */ if (!(str = malloc(strlen(optarg+1)))) fterr_err(1, "malloc()"); strcpy(str, optarg); /* search for mask option */ if ((strm = index(str, '/'))) { ++strm; tos_mask = (u_char)strtol(strm, (char**)0L, 0); --strm; *strm = 0; } if (load_lookup(str, 65536, tos_tbl)) { free(str); fterr_errx(1, "load_lookup(): failed"); } free(str); filter_tos = 1; break; case 'T': /* tcp flags filter */ if (!(str = malloc(strlen(optarg+1)))) fterr_err(1, "malloc()"); strcpy(str, optarg); /* search for mask option */ if ((strm = index(str, '/'))) { ++strm; tcp_flags_mask = (u_char)strtol(strm, (char**)0L, 0); --strm; *strm = 0; } if (load_lookup(str, 65536, tcp_flags_tbl)) { free(str); fterr_errx(1, "load_lookup(): failed"); } free(str); filter_tcp_flags = 1; break; case 'x': /* nexthop ip standard access list filter */ acl_std_nexthop_name = optarg; break; case 'h': /* help */ case '?': usage(); exit (0); break; case 'z': /* compress level */ ftset.z_level = atoi(optarg); if ((ftset.z_level < 0) || (ftset.z_level > 9)) fterr_errx(1, "Compression level must be between 0 and 9"); break; default: usage(); exit (1); break; } /* switch */ if (argc - optind) fterr_errx(1, "Extra arguments starting with %s.", argv[optind]); /* input from stdin */ if (ftio_init(&ftio_in, 0, FT_IO_FLAG_READ) < 0) fterr_errx(1, "ftio_init(): failed"); ftio_get_ver(&ftio_in, &ftv); ftv.s_version = FT_IO_SVERSION; xflag = 0; if (filter_input) xflag |= FT_XFIELD_INPUT; if (filter_output) xflag |= FT_XFIELD_OUTPUT; if (filter_srcport) xflag |= FT_XFIELD_SRCPORT; if (filter_dstport) xflag |= FT_XFIELD_DSTPORT; if (filter_exaddr) xflag |= FT_XFIELD_EXADDR; if (filter_prot) xflag |= FT_XFIELD_PROT; if (filter_srcas) xflag |= FT_XFIELD_SRC_AS; if (filter_dstas) xflag |= FT_XFIELD_DST_AS; if (filter_tos) xflag |= FT_XFIELD_TOS; if (filter_tcp_flags) xflag |= FT_XFIELD_TCP_FLAGS; if (acl_std_nexthop_name) xflag |= FT_XFIELD_NEXTHOP; if (acl_std_src_name) xflag |= FT_XFIELD_SRCADDR; if (acl_std_dst_name) xflag |= FT_XFIELD_DSTADDR; if (acl_ext_name) xflag |= (FT_XFIELD_SRCADDR | FT_XFIELD_DSTADDR); if (ftio_check_xfield(&ftio_in, xflag)) { fterr_warnx("Flow record missing required field for format."); exit (1); } fts3rec_compute_offsets(&fo, &ftv); /* output to stdout */ if (ftio_init(&ftio_out, 1, FT_IO_FLAG_WRITE | ((ftset.z_level) ? FT_IO_FLAG_ZINIT : 0) ) < 0) fterr_errx(1, "ftio_init(): failed"); /* preserve start/end time from input stream? */ if (keep_input_time) { time_start = ftio_get_cap_start(&ftio_in); time_end = ftio_get_cap_end(&ftio_in); if (time_start && time_end) { ftio_set_preloaded(&ftio_out, 1); ftio_set_cap_time(&ftio_out, time_start, time_end); } } /* keep_input_time */ ftio_set_comment(&ftio_out, ftset.comments); ftio_set_byte_order(&ftio_out, ftset.byte_order); ftio_set_z_level(&ftio_out, ftset.z_level); ftio_set_streaming(&ftio_out, 1); ftio_set_debug(&ftio_out, debug); if (ftio_set_ver(&ftio_out, &ftv) < 0) fterr_errx(1, "ftio_set_ver(): failed"); /* * load acl's * XXX add fname check and close */ if ((yyin = fopen(acl_fname ? acl_fname : "flow.acl", "r"))) while (!feof(yyin)) yyparse(); /* * normalize masks */ /* XXX TODO */ if (debug > 5) acl_dump(acl_list); if (acl_std_src_name) { if ((acl_std_src_index = acl_find(acl_list, acl_std_src_name)) == -1) fterr_errx(1, "Couldn't find list %s\n", acl_std_src_name); acl_std_src_index2 = acl_list.names[acl_std_src_index].num; } if (acl_std_dst_name) { if ((acl_std_dst_index = acl_find(acl_list, acl_std_dst_name)) == -1) fterr_errx(1, "Couldn't find list %s\n", acl_std_dst_name); acl_std_dst_index2 = acl_list.names[acl_std_dst_index].num; } if (acl_ext_name) { if ((acl_ext_index = acl_find(acl_list, acl_ext_name)) == -1) fterr_errx(1, "Couldn't find list %s\n", acl_ext_name); acl_ext_index2 = acl_list.names[acl_ext_index].num; } if (acl_std_nexthop_name) { if ((acl_std_nexthop_index = acl_find(acl_list, acl_std_nexthop_name)) == -1) fterr_errx(1, "Couldn't find list %s\n", acl_std_nexthop_name); acl_std_nexthop_index2 = acl_list.names[acl_std_nexthop_index].num; } /* header first */ if (ftio_write_header(&ftio_out) < 0) fterr_errx(1, "ftio_write_header(): failed"); /* profile */ ftprof_start (&ftp); /* grab 1 flow */ while ((rec = ftio_read(&ftio_in))) { cur.srcaddr = ((uint32_t*)(rec+fo.srcaddr)); cur.dstaddr = ((uint32_t*)(rec+fo.dstaddr)); cur.exaddr = ((uint32_t*)(rec+fo.exaddr)); cur.nexthop = ((uint32_t*)(rec+fo.nexthop)); cur.input = ((uint16_t*)(rec+fo.input)); cur.output = ((uint16_t*)(rec+fo.output)); cur.srcport = ((uint16_t*)(rec+fo.srcport)); cur.dstport = ((uint16_t*)(rec+fo.dstport)); cur.src_as = ((uint16_t*)(rec+fo.src_as)); cur.dst_as = ((uint16_t*)(rec+fo.dst_as)); cur.prot = ((uint8_t*)(rec+fo.prot)); cur.tcp_flags = ((uint8_t*)(rec+fo.tcp_flags)); cur.tos = ((uint8_t*)(rec+fo.tos)); ++ total_flows; /* filter on input interface */ if (filter_input) { if (!in_tbl[*cur.input]) { if (!first_match) continue; } else if (first_match) { goto found; } } /* filter on output interface */ if (filter_output) { if (!out_tbl[*cur.output]) { if (!first_match) continue; } else if (first_match) { goto found; } } /* filter on src port */ if (filter_srcport) { if (!src_tbl[*cur.srcport]) { if (!first_match) continue; } else if (first_match) { goto found; } } /* filter on dst port */ if (filter_dstport) { if (!dst_tbl[*cur.dstport]) { if (!first_match) continue; } else if (first_match) { goto found; } } /* filter on exporter addr */ if (filter_exaddr) { if (*cur.exaddr != exaddr) { if (!first_match) continue; } else if (first_match) { goto found; } } /* filter on protocol */ if (filter_prot) { if (!prot_tbl[*cur.prot]) { if (!first_match) continue; } else if (first_match) { goto found; } } /* filter on ToS */ if (filter_tos) { tos = *cur.tos & tos_mask; if (!tos_tbl[tos]) { if (!first_match) continue; } else if (first_match) { goto found; } } /* filter on tcp_flags */ if (filter_tcp_flags && (*cur.prot == IPPROTO_TCP)) { tcp_flags = *cur.tcp_flags & tcp_flags_mask; if (!tcp_flags_tbl[tcp_flags]) { if (!first_match) continue; } else if (first_match) { goto found; } } if (filter_srcas) { if (!srcas_tbl[*cur.src_as]) { if (!first_match) continue; } else if (first_match) { goto found; } } /* filter on src AS */ if (filter_dstas) { if (!dstas_tbl[*cur.dst_as]) { if (!first_match) continue; } else if (first_match) { goto found; } } /* eval flow nexthop addr and nexthop standard acl */ if (acl_std_nexthop_index != -1) { ret = acl_eval_std(acl_list, acl_std_nexthop_index2, *cur.nexthop); if (ret == 1) { if (!first_match) continue; } else if (first_match) { goto found; } } /* eval flow src addr and source standard acl */ if (acl_std_src_index != -1) { ret = acl_eval_std(acl_list, acl_std_src_index2, *cur.srcaddr); if (ret == 1) { if (!first_match) continue; } else if (first_match) { goto found; } } /* eval flow dst addr and destination standard acl */ if (acl_std_dst_index != -1) { ret = acl_eval_std(acl_list, acl_std_dst_index2, *cur.dstaddr); if (ret == 1) { if (!first_match) continue; } else if (first_match) { goto found; } } /* eval flow and extended acl */ if (acl_ext_index != -1) { tmp_ext.protocol = *cur.prot; tmp_ext.tos = *cur.tos; /* XXX */ tmp_ext.type = 0; tmp_ext.type_code = 0; tmp_ext.message = 0; tmp_ext.src_addr = *cur.srcaddr; tmp_ext.src_port = *cur.srcport; tmp_ext.dst_addr = *cur.dstaddr; tmp_ext.dst_port = *cur.dstport; ret = acl_eval_ext(acl_list, acl_ext_index2, tmp_ext); if (ret == 1) { if (!first_match) continue; } else if (first_match) { goto found; } } if (first_match) /* No matches yet? next try.. */ continue; /* * made it by the filters, write it */ found: if (ftio_write(&ftio_out, rec) < 0) fterr_errx(1, "ftio_write(): failed"); } /* while more flows to read */ if (ftio_close(&ftio_in) < 0) fterr_errx(1, "ftio_close(): failed"); if (ftio_close(&ftio_out) < 0) fterr_errx(1, "ftio_close(): failed"); if (debug > 0) { ftprof_end (&ftp, total_flows); ftprof_print(&ftp, argv[0], stderr); } if (debug > 1) { acl_dump_std(acl_list, acl_std_src_index); acl_dump_std(acl_list, acl_std_dst_index); acl_dump_std(acl_list, acl_std_nexthop_index); } return 0; } /* main */