/*
* 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);
}