| /* |
| * src/f_ct.c Conntrack Filter |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation version 2.1 |
| * of the License. |
| * |
| * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch> |
| * Copyright (c) 2007 Philip Craig <philipc@snapgear.com> |
| * Copyright (c) 2007 Secure Computing Corporation |
| */ |
| |
| static void get_filter(struct nfnl_ct *ct, int argc, char **argv, int idx) |
| { |
| struct nl_addr *a; |
| |
| while (argc > idx) { |
| if (arg_match("family")) { |
| if (argc > ++idx) { |
| int family = nl_str2af(argv[idx++]); |
| if (family == AF_UNSPEC) |
| goto err_invaf; |
| nfnl_ct_set_family(ct, family); |
| } |
| } else if (arg_match("proto")) { |
| if (argc > ++idx) { |
| int proto = nl_str2ip_proto(argv[idx++]); |
| if (proto < 0) |
| goto err_invproto; |
| nfnl_ct_set_proto(ct, proto); |
| } |
| } else if (arg_match("tcpstate")) { |
| if (argc > ++idx) { |
| int state = nfnl_ct_str2tcp_state(argv[idx++]); |
| if (state < 0) |
| goto err_invtcpstate; |
| nfnl_ct_set_tcp_state(ct, state); |
| } |
| } else if (arg_match("status")) { |
| if (argc > ++idx) { |
| int status = strtoul(argv[idx++], NULL, 0); |
| nfnl_ct_set_status(ct, status); |
| nfnl_ct_unset_status(ct, ~status); |
| } |
| } else if (arg_match("timeout")) { |
| if (argc > ++idx) |
| nfnl_ct_set_timeout(ct, strtoul(argv[idx++], NULL, 0)); |
| } else if (arg_match("mark")) { |
| if (argc > ++idx) |
| nfnl_ct_set_mark(ct, strtoul(argv[idx++], NULL, 0)); |
| } else if (arg_match("use")) { |
| if (argc > ++idx) |
| nfnl_ct_set_use(ct, strtoul(argv[idx++], NULL, 0)); |
| } else if (arg_match("id")) { |
| if (argc > ++idx) |
| nfnl_ct_set_id(ct, strtoul(argv[idx++], NULL, 0)); |
| } else if (arg_match("origsrc")) { |
| if (argc > ++idx) { |
| a = nl_addr_parse(argv[idx++], |
| nfnl_ct_get_family(ct)); |
| if (!a) |
| goto err_invaddr; |
| nfnl_ct_set_src(ct, 0, a); |
| nl_addr_put(a); |
| } |
| } else if (arg_match("origdst")) { |
| if (argc > ++idx) { |
| a = nl_addr_parse(argv[idx++], |
| nfnl_ct_get_family(ct)); |
| if (!a) |
| goto err_invaddr; |
| nfnl_ct_set_dst(ct, 0, a); |
| nl_addr_put(a); |
| } |
| } else if (arg_match("origsrcport")) { |
| if (argc > ++idx) |
| nfnl_ct_set_src_port(ct, 0, strtoul(argv[idx++], NULL, 0)); |
| } else if (arg_match("origdstport")) { |
| if (argc > ++idx) |
| nfnl_ct_set_dst_port(ct, 0, strtoul(argv[idx++], NULL, 0)); |
| } else if (arg_match("origicmpid")) { |
| if (argc > ++idx) |
| nfnl_ct_set_icmp_id(ct, 0, strtoul(argv[idx++], NULL, 0)); |
| } else if (arg_match("origicmptype")) { |
| if (argc > ++idx) |
| nfnl_ct_set_icmp_type(ct, 0, strtoul(argv[idx++], NULL, 0)); |
| } else if (arg_match("origicmpcode")) { |
| if (argc > ++idx) |
| nfnl_ct_set_icmp_code(ct, 0, strtoul(argv[idx++], NULL, 0)); |
| } else if (arg_match("origpackets")) { |
| if (argc > ++idx) |
| nfnl_ct_set_packets(ct, 0, strtoul(argv[idx++], NULL, 0)); |
| } else if (arg_match("origbytes")) { |
| if (argc > ++idx) |
| nfnl_ct_set_bytes(ct, 0, strtoul(argv[idx++], NULL, 0)); |
| } else if (arg_match("replysrc")) { |
| if (argc > ++idx) { |
| a = nl_addr_parse(argv[idx++], |
| nfnl_ct_get_family(ct)); |
| if (!a) |
| goto err_invaddr; |
| nfnl_ct_set_src(ct, 1, a); |
| nl_addr_put(a); |
| } |
| } else if (arg_match("replydst")) { |
| if (argc > ++idx) { |
| a = nl_addr_parse(argv[idx++], |
| nfnl_ct_get_family(ct)); |
| if (!a) |
| goto err_invaddr; |
| nfnl_ct_set_dst(ct, 1, a); |
| nl_addr_put(a); |
| } |
| } else if (arg_match("replysrcport")) { |
| if (argc > ++idx) |
| nfnl_ct_set_src_port(ct, 1, strtoul(argv[idx++], NULL, 0)); |
| } else if (arg_match("replydstport")) { |
| if (argc > ++idx) |
| nfnl_ct_set_dst_port(ct, 1, strtoul(argv[idx++], NULL, 0)); |
| } else if (arg_match("replyicmpid")) { |
| if (argc > ++idx) |
| nfnl_ct_set_icmp_id(ct, 1, strtoul(argv[idx++], NULL, 0)); |
| } else if (arg_match("replyicmptype")) { |
| if (argc > ++idx) |
| nfnl_ct_set_icmp_type(ct, 1, strtoul(argv[idx++], NULL, 0)); |
| } else if (arg_match("replyicmpcode")) { |
| if (argc > ++idx) |
| nfnl_ct_set_icmp_code(ct, 1, strtoul(argv[idx++], NULL, 0)); |
| } else if (arg_match("replypackets")) { |
| if (argc > ++idx) |
| nfnl_ct_set_packets(ct, 1, strtoul(argv[idx++], NULL, 0)); |
| } else if (arg_match("replybytes")) { |
| if (argc > ++idx) |
| nfnl_ct_set_bytes(ct, 1, strtoul(argv[idx++], NULL, 0)); |
| } |
| #define MSTATUS(STR, STATUS) \ |
| else if (!strcasecmp(argv[idx], STR)) { \ |
| nfnl_ct_set_status(ct, STATUS); idx++; } |
| #define MNOSTATUS(STR, STATUS) \ |
| else if (!strcasecmp(argv[idx], STR)) { \ |
| nfnl_ct_unset_status(ct, STATUS); idx++; } |
| |
| MSTATUS("replied", IPS_SEEN_REPLY) |
| MNOSTATUS("unreplied", IPS_SEEN_REPLY) |
| MSTATUS("assured", IPS_ASSURED) |
| MNOSTATUS("unassured", IPS_ASSURED) |
| #undef MSTATUS |
| #undef MNOSTATUS |
| else { |
| fprintf(stderr, "What is '%s'?\n", argv[idx]); |
| exit(1); |
| } |
| } |
| |
| return; |
| |
| err_invproto: |
| fprintf(stderr, "Invalid IP protocol \"%s\".\n", argv[idx-1]); |
| exit(1); |
| err_invtcpstate: |
| fprintf(stderr, "Invalid TCP state \"%s\".\n", argv[idx-1]); |
| exit(1); |
| err_invaf: |
| fprintf(stderr, "Invalid address family \"%s\"\n", argv[idx-1]); |
| exit(1); |
| err_invaddr: |
| fprintf(stderr, "Invalid address \"%s\": %s\n", argv[idx-1], nl_geterror()); |
| exit(1); |
| } |