blob: 3fc747d871a02ec286361a1eb14ae38e6c8aa22c [file] [log] [blame]
Marc Bouchere6869a82000-03-20 06:03:29 +00001#include <stdio.h>
Marc Bouchere6869a82000-03-20 06:03:29 +00002#include <string.h>
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +00003#include <xtables.h>
Patrick McHardy40d54752007-04-18 07:00:36 +00004#include <linux/netfilter/nf_conntrack_common.h>
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +00005#include <linux/netfilter/xt_state.h>
Marc Bouchere6869a82000-03-20 06:03:29 +00006
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +00007#ifndef XT_STATE_UNTRACKED
8#define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
Harald Welte4dc734c2003-10-07 18:55:13 +00009#endif
10
Jan Engelhardt72ef3d32011-03-02 22:52:04 +010011enum {
12 O_STATE = 0,
13};
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
Jan Engelhardt72ef3d32011-03-02 22:52:04 +010024static const struct xt_option_entry state_opts[] = {
25 {.name = "state", .id = O_STATE, .type = XTTYPE_STRING,
26 .flags = XTOPT_MAND},
27 XTOPT_TABLEEND,
Marc Bouchere6869a82000-03-20 06:03:29 +000028};
29
Marc Bouchere6869a82000-03-20 06:03:29 +000030static int
Jan Engelhardtdbb77542008-02-11 00:33:30 +010031state_parse_state(const char *state, size_t len, struct xt_state_info *sinfo)
Marc Bouchere6869a82000-03-20 06:03:29 +000032{
Jan Engelhardtdbb77542008-02-11 00:33:30 +010033 if (strncasecmp(state, "INVALID", len) == 0)
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +000034 sinfo->statemask |= XT_STATE_INVALID;
Jan Engelhardtdbb77542008-02-11 00:33:30 +010035 else if (strncasecmp(state, "NEW", len) == 0)
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +000036 sinfo->statemask |= XT_STATE_BIT(IP_CT_NEW);
Jan Engelhardtdbb77542008-02-11 00:33:30 +010037 else if (strncasecmp(state, "ESTABLISHED", len) == 0)
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +000038 sinfo->statemask |= XT_STATE_BIT(IP_CT_ESTABLISHED);
Jan Engelhardtdbb77542008-02-11 00:33:30 +010039 else if (strncasecmp(state, "RELATED", len) == 0)
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +000040 sinfo->statemask |= XT_STATE_BIT(IP_CT_RELATED);
Jan Engelhardtdbb77542008-02-11 00:33:30 +010041 else if (strncasecmp(state, "UNTRACKED", len) == 0)
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +000042 sinfo->statemask |= XT_STATE_UNTRACKED;
Marc Bouchere6869a82000-03-20 06:03:29 +000043 else
44 return 0;
45 return 1;
46}
47
48static void
László Attila Tóth72118882007-10-08 05:12:42 +000049state_parse_states(const char *arg, struct xt_state_info *sinfo)
Marc Bouchere6869a82000-03-20 06:03:29 +000050{
51 const char *comma;
52
53 while ((comma = strchr(arg, ',')) != NULL) {
László Attila Tóth72118882007-10-08 05:12:42 +000054 if (comma == arg || !state_parse_state(arg, comma-arg, sinfo))
Jan Engelhardt1829ed42009-02-21 03:29:44 +010055 xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg);
Marc Bouchere6869a82000-03-20 06:03:29 +000056 arg = comma+1;
57 }
Pablo Neira Ayuso0ec8c0f2008-11-19 19:01:26 +010058 if (!*arg)
Jan Engelhardt1829ed42009-02-21 03:29:44 +010059 xtables_error(PARAMETER_PROBLEM, "\"--state\" requires a list of "
Pablo Neira Ayuso0ec8c0f2008-11-19 19:01:26 +010060 "states with no spaces, e.g. "
61 "ESTABLISHED,RELATED");
László Attila Tóth72118882007-10-08 05:12:42 +000062 if (strlen(arg) == 0 || !state_parse_state(arg, strlen(arg), sinfo))
Jan Engelhardt1829ed42009-02-21 03:29:44 +010063 xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg);
Marc Bouchere6869a82000-03-20 06:03:29 +000064}
65
Jan Engelhardt72ef3d32011-03-02 22:52:04 +010066static void state_parse(struct xt_option_call *cb)
Marc Bouchere6869a82000-03-20 06:03:29 +000067{
Jan Engelhardt72ef3d32011-03-02 22:52:04 +010068 struct xt_state_info *sinfo = cb->data;
Marc Bouchere6869a82000-03-20 06:03:29 +000069
Jan Engelhardt72ef3d32011-03-02 22:52:04 +010070 xtables_option_parse(cb);
71 state_parse_states(cb->arg, sinfo);
72 if (cb->invert)
73 sinfo->statemask = ~sinfo->statemask;
Marc Bouchere6869a82000-03-20 06:03:29 +000074}
75
László Attila Tóth72118882007-10-08 05:12:42 +000076static void state_print_state(unsigned int statemask)
Marc Bouchere6869a82000-03-20 06:03:29 +000077{
78 const char *sep = "";
79
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +000080 if (statemask & XT_STATE_INVALID) {
Marc Bouchere6869a82000-03-20 06:03:29 +000081 printf("%sINVALID", sep);
82 sep = ",";
83 }
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +000084 if (statemask & XT_STATE_BIT(IP_CT_NEW)) {
Marc Bouchere6869a82000-03-20 06:03:29 +000085 printf("%sNEW", sep);
86 sep = ",";
87 }
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +000088 if (statemask & XT_STATE_BIT(IP_CT_RELATED)) {
Marc Bouchere6869a82000-03-20 06:03:29 +000089 printf("%sRELATED", sep);
90 sep = ",";
91 }
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +000092 if (statemask & XT_STATE_BIT(IP_CT_ESTABLISHED)) {
Marc Bouchere6869a82000-03-20 06:03:29 +000093 printf("%sESTABLISHED", sep);
94 sep = ",";
95 }
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +000096 if (statemask & XT_STATE_UNTRACKED) {
Harald Welte4dc734c2003-10-07 18:55:13 +000097 printf("%sUNTRACKED", sep);
98 sep = ",";
99 }
Marc Bouchere6869a82000-03-20 06:03:29 +0000100}
101
Marc Bouchere6869a82000-03-20 06:03:29 +0000102static void
László Attila Tóth72118882007-10-08 05:12:42 +0000103state_print(const void *ip,
Yasuyuki KOZAKAI193df8e2007-07-24 05:57:28 +0000104 const struct xt_entry_match *match,
Marc Bouchere6869a82000-03-20 06:03:29 +0000105 int numeric)
106{
Jan Engelhardt69f564e2009-05-26 13:14:06 +0200107 const struct xt_state_info *sinfo = (const void *)match->data;
Marc Bouchere6869a82000-03-20 06:03:29 +0000108
Jan Engelhardt73866352010-12-18 02:04:59 +0100109 printf(" state ");
László Attila Tóth72118882007-10-08 05:12:42 +0000110 state_print_state(sinfo->statemask);
Marc Bouchere6869a82000-03-20 06:03:29 +0000111}
112
László Attila Tóth72118882007-10-08 05:12:42 +0000113static void state_save(const void *ip, const struct xt_entry_match *match)
Marc Bouchere6869a82000-03-20 06:03:29 +0000114{
Jan Engelhardt69f564e2009-05-26 13:14:06 +0200115 const struct xt_state_info *sinfo = (const void *)match->data;
Marc Bouchere6869a82000-03-20 06:03:29 +0000116
Jan Engelhardt73866352010-12-18 02:04:59 +0100117 printf(" --state ");
László Attila Tóth72118882007-10-08 05:12:42 +0000118 state_print_state(sinfo->statemask);
Marc Bouchere6869a82000-03-20 06:03:29 +0000119}
120
László Attila Tóth72118882007-10-08 05:12:42 +0000121static struct xtables_match state_match = {
Jan Engelhardtc5e85732009-06-12 20:55:44 +0200122 .family = NFPROTO_UNSPEC,
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +0000123 .name = "state",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200124 .version = XTABLES_VERSION,
Yasuyuki KOZAKAI1ff0b8d2007-08-04 08:09:51 +0000125 .size = XT_ALIGN(sizeof(struct xt_state_info)),
126 .userspacesize = XT_ALIGN(sizeof(struct xt_state_info)),
László Attila Tóth72118882007-10-08 05:12:42 +0000127 .help = state_help,
László Attila Tóth72118882007-10-08 05:12:42 +0000128 .print = state_print,
129 .save = state_save,
Jan Engelhardt72ef3d32011-03-02 22:52:04 +0100130 .x6_parse = state_parse,
131 .x6_options = state_opts,
Marc Bouchere6869a82000-03-20 06:03:29 +0000132};
133
134void _init(void)
135{
László Attila Tóth72118882007-10-08 05:12:42 +0000136 xtables_register_match(&state_match);
Marc Bouchere6869a82000-03-20 06:03:29 +0000137}