blob: 66af518a2a8fe77a183b0b2e111d2bdfb7dcebc2 [file] [log] [blame]
Marc Bouchere6869a82000-03-20 06:03:29 +00001/* Shared library add-on to iptables to add state tracking support. */
2#include <stdio.h>
3#include <netdb.h>
4#include <string.h>
5#include <stdlib.h>
6#include <getopt.h>
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +00007#include <xtables.h>
Patrick McHardy40d54752007-04-18 07:00:36 +00008#include <linux/netfilter/nf_conntrack_common.h>
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +00009#include <linux/netfilter/xt_state.h>
Marc Bouchere6869a82000-03-20 06:03:29 +000010
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +000011#ifndef XT_STATE_UNTRACKED
12#define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
Harald Welte4dc734c2003-10-07 18:55:13 +000013#endif
14
Marc Bouchere6869a82000-03-20 06:03:29 +000015static void
László Attila Tóth72118882007-10-08 05:12:42 +000016state_help(void)
Marc Bouchere6869a82000-03-20 06:03:29 +000017{
18 printf(
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020019"state match options:\n"
Harald Welte4dc734c2003-10-07 18:55:13 +000020" [!] --state [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED][,...]\n"
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020021" State(s) to match\n");
Marc Bouchere6869a82000-03-20 06:03:29 +000022}
23
László Attila Tóth72118882007-10-08 05:12:42 +000024static const struct option state_opts[] = {
Patrick McHardy500f4832007-09-08 15:59:04 +000025 { "state", 1, NULL, '1' },
Max Kellermann9ee386a2008-01-29 13:48:05 +000026 { .name = NULL }
Marc Bouchere6869a82000-03-20 06:03:29 +000027};
28
Marc Bouchere6869a82000-03-20 06:03:29 +000029static int
Jan Engelhardtdbb77542008-02-11 00:33:30 +010030state_parse_state(const char *state, size_t len, struct xt_state_info *sinfo)
Marc Bouchere6869a82000-03-20 06:03:29 +000031{
Jan Engelhardtdbb77542008-02-11 00:33:30 +010032 if (strncasecmp(state, "INVALID", len) == 0)
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +000033 sinfo->statemask |= XT_STATE_INVALID;
Jan Engelhardtdbb77542008-02-11 00:33:30 +010034 else if (strncasecmp(state, "NEW", len) == 0)
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +000035 sinfo->statemask |= XT_STATE_BIT(IP_CT_NEW);
Jan Engelhardtdbb77542008-02-11 00:33:30 +010036 else if (strncasecmp(state, "ESTABLISHED", len) == 0)
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +000037 sinfo->statemask |= XT_STATE_BIT(IP_CT_ESTABLISHED);
Jan Engelhardtdbb77542008-02-11 00:33:30 +010038 else if (strncasecmp(state, "RELATED", len) == 0)
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +000039 sinfo->statemask |= XT_STATE_BIT(IP_CT_RELATED);
Jan Engelhardtdbb77542008-02-11 00:33:30 +010040 else if (strncasecmp(state, "UNTRACKED", len) == 0)
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +000041 sinfo->statemask |= XT_STATE_UNTRACKED;
Marc Bouchere6869a82000-03-20 06:03:29 +000042 else
43 return 0;
44 return 1;
45}
46
47static void
László Attila Tóth72118882007-10-08 05:12:42 +000048state_parse_states(const char *arg, struct xt_state_info *sinfo)
Marc Bouchere6869a82000-03-20 06:03:29 +000049{
50 const char *comma;
51
52 while ((comma = strchr(arg, ',')) != NULL) {
László Attila Tóth72118882007-10-08 05:12:42 +000053 if (comma == arg || !state_parse_state(arg, comma-arg, sinfo))
Marc Bouchere6869a82000-03-20 06:03:29 +000054 exit_error(PARAMETER_PROBLEM, "Bad state `%s'", arg);
55 arg = comma+1;
56 }
Pablo Neira Ayuso0ec8c0f2008-11-19 19:01:26 +010057 if (!*arg)
58 exit_error(PARAMETER_PROBLEM, "`--state' requires a list of "
59 "states with no spaces, e.g. "
60 "ESTABLISHED,RELATED");
László Attila Tóth72118882007-10-08 05:12:42 +000061 if (strlen(arg) == 0 || !state_parse_state(arg, strlen(arg), sinfo))
Marc Bouchere6869a82000-03-20 06:03:29 +000062 exit_error(PARAMETER_PROBLEM, "Bad state `%s'", arg);
63}
64
Marc Bouchere6869a82000-03-20 06:03:29 +000065static int
László Attila Tóth72118882007-10-08 05:12:42 +000066state_parse(int c, char **argv, int invert, unsigned int *flags,
Yasuyuki KOZAKAIc0a9ab92007-07-24 06:02:05 +000067 const void *entry,
Yasuyuki KOZAKAI193df8e2007-07-24 05:57:28 +000068 struct xt_entry_match **match)
Marc Bouchere6869a82000-03-20 06:03:29 +000069{
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +000070 struct xt_state_info *sinfo = (struct xt_state_info *)(*match)->data;
Marc Bouchere6869a82000-03-20 06:03:29 +000071
72 switch (c) {
73 case '1':
Harald Welteb77f1da2002-03-14 11:35:58 +000074 check_inverse(optarg, &invert, &optind, 0);
Marc Bouchere6869a82000-03-20 06:03:29 +000075
László Attila Tóth72118882007-10-08 05:12:42 +000076 state_parse_states(argv[optind-1], sinfo);
Marc Bouchere6869a82000-03-20 06:03:29 +000077 if (invert)
78 sinfo->statemask = ~sinfo->statemask;
79 *flags = 1;
80 break;
81
82 default:
83 return 0;
84 }
85
86 return 1;
87}
88
László Attila Tóth72118882007-10-08 05:12:42 +000089static void state_final_check(unsigned int flags)
Marc Bouchere6869a82000-03-20 06:03:29 +000090{
91 if (!flags)
92 exit_error(PARAMETER_PROBLEM, "You must specify `--state'");
93}
94
László Attila Tóth72118882007-10-08 05:12:42 +000095static void state_print_state(unsigned int statemask)
Marc Bouchere6869a82000-03-20 06:03:29 +000096{
97 const char *sep = "";
98
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +000099 if (statemask & XT_STATE_INVALID) {
Marc Bouchere6869a82000-03-20 06:03:29 +0000100 printf("%sINVALID", sep);
101 sep = ",";
102 }
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +0000103 if (statemask & XT_STATE_BIT(IP_CT_NEW)) {
Marc Bouchere6869a82000-03-20 06:03:29 +0000104 printf("%sNEW", sep);
105 sep = ",";
106 }
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +0000107 if (statemask & XT_STATE_BIT(IP_CT_RELATED)) {
Marc Bouchere6869a82000-03-20 06:03:29 +0000108 printf("%sRELATED", sep);
109 sep = ",";
110 }
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +0000111 if (statemask & XT_STATE_BIT(IP_CT_ESTABLISHED)) {
Marc Bouchere6869a82000-03-20 06:03:29 +0000112 printf("%sESTABLISHED", sep);
113 sep = ",";
114 }
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +0000115 if (statemask & XT_STATE_UNTRACKED) {
Harald Welte4dc734c2003-10-07 18:55:13 +0000116 printf("%sUNTRACKED", sep);
117 sep = ",";
118 }
Marc Bouchere6869a82000-03-20 06:03:29 +0000119 printf(" ");
120}
121
Marc Bouchere6869a82000-03-20 06:03:29 +0000122static void
László Attila Tóth72118882007-10-08 05:12:42 +0000123state_print(const void *ip,
Yasuyuki KOZAKAI193df8e2007-07-24 05:57:28 +0000124 const struct xt_entry_match *match,
Marc Bouchere6869a82000-03-20 06:03:29 +0000125 int numeric)
126{
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +0000127 struct xt_state_info *sinfo = (struct xt_state_info *)match->data;
Marc Bouchere6869a82000-03-20 06:03:29 +0000128
129 printf("state ");
László Attila Tóth72118882007-10-08 05:12:42 +0000130 state_print_state(sinfo->statemask);
Marc Bouchere6869a82000-03-20 06:03:29 +0000131}
132
László Attila Tóth72118882007-10-08 05:12:42 +0000133static void state_save(const void *ip, const struct xt_entry_match *match)
Marc Bouchere6869a82000-03-20 06:03:29 +0000134{
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +0000135 struct xt_state_info *sinfo = (struct xt_state_info *)match->data;
Marc Bouchere6869a82000-03-20 06:03:29 +0000136
137 printf("--state ");
László Attila Tóth72118882007-10-08 05:12:42 +0000138 state_print_state(sinfo->statemask);
Marc Bouchere6869a82000-03-20 06:03:29 +0000139}
140
László Attila Tóth72118882007-10-08 05:12:42 +0000141static struct xtables_match state_match = {
Jan Engelhardt03d99482008-11-18 12:27:54 +0100142 .family = NFPROTO_IPV4,
Pablo Neira8caee8b2004-12-28 13:11:59 +0000143 .name = "state",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200144 .version = XTABLES_VERSION,
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +0000145 .size = XT_ALIGN(sizeof(struct xt_state_info)),
146 .userspacesize = XT_ALIGN(sizeof(struct xt_state_info)),
László Attila Tóth72118882007-10-08 05:12:42 +0000147 .help = state_help,
148 .parse = state_parse,
149 .final_check = state_final_check,
150 .print = state_print,
151 .save = state_save,
152 .extra_opts = state_opts,
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +0000153};
154
László Attila Tóth72118882007-10-08 05:12:42 +0000155static struct xtables_match state_match6 = {
Jan Engelhardt03d99482008-11-18 12:27:54 +0100156 .family = NFPROTO_IPV6,
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +0000157 .name = "state",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200158 .version = XTABLES_VERSION,
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +0000159 .size = XT_ALIGN(sizeof(struct xt_state_info)),
160 .userspacesize = XT_ALIGN(sizeof(struct xt_state_info)),
László Attila Tóth72118882007-10-08 05:12:42 +0000161 .help = state_help,
162 .parse = state_parse,
163 .final_check = state_final_check,
164 .print = state_print,
165 .save = state_save,
166 .extra_opts = state_opts,
Marc Bouchere6869a82000-03-20 06:03:29 +0000167};
168
169void _init(void)
170{
László Attila Tóth72118882007-10-08 05:12:42 +0000171 xtables_register_match(&state_match);
172 xtables_register_match(&state_match6);
Marc Bouchere6869a82000-03-20 06:03:29 +0000173}