libxt_state.c revision 69f564e3890976461de0016cd81171ff8bfa8353
1/* 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> 7#include <xtables.h> 8#include <linux/netfilter/nf_conntrack_common.h> 9#include <linux/netfilter/xt_state.h> 10 11#ifndef XT_STATE_UNTRACKED 12#define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1)) 13#endif 14 15static void 16state_help(void) 17{ 18 printf( 19"state match options:\n" 20" [!] --state [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED][,...]\n" 21" State(s) to match\n"); 22} 23 24static const struct option state_opts[] = { 25 { "state", 1, NULL, '1' }, 26 { .name = NULL } 27}; 28 29static int 30state_parse_state(const char *state, size_t len, struct xt_state_info *sinfo) 31{ 32 if (strncasecmp(state, "INVALID", len) == 0) 33 sinfo->statemask |= XT_STATE_INVALID; 34 else if (strncasecmp(state, "NEW", len) == 0) 35 sinfo->statemask |= XT_STATE_BIT(IP_CT_NEW); 36 else if (strncasecmp(state, "ESTABLISHED", len) == 0) 37 sinfo->statemask |= XT_STATE_BIT(IP_CT_ESTABLISHED); 38 else if (strncasecmp(state, "RELATED", len) == 0) 39 sinfo->statemask |= XT_STATE_BIT(IP_CT_RELATED); 40 else if (strncasecmp(state, "UNTRACKED", len) == 0) 41 sinfo->statemask |= XT_STATE_UNTRACKED; 42 else 43 return 0; 44 return 1; 45} 46 47static void 48state_parse_states(const char *arg, struct xt_state_info *sinfo) 49{ 50 const char *comma; 51 52 while ((comma = strchr(arg, ',')) != NULL) { 53 if (comma == arg || !state_parse_state(arg, comma-arg, sinfo)) 54 xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg); 55 arg = comma+1; 56 } 57 if (!*arg) 58 xtables_error(PARAMETER_PROBLEM, "\"--state\" requires a list of " 59 "states with no spaces, e.g. " 60 "ESTABLISHED,RELATED"); 61 if (strlen(arg) == 0 || !state_parse_state(arg, strlen(arg), sinfo)) 62 xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg); 63} 64 65static int 66state_parse(int c, char **argv, int invert, unsigned int *flags, 67 const void *entry, 68 struct xt_entry_match **match) 69{ 70 struct xt_state_info *sinfo = (struct xt_state_info *)(*match)->data; 71 72 switch (c) { 73 case '1': 74 xtables_check_inverse(optarg, &invert, &optind, 0); 75 76 state_parse_states(argv[optind-1], sinfo); 77 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 89static void state_final_check(unsigned int flags) 90{ 91 if (!flags) 92 xtables_error(PARAMETER_PROBLEM, "You must specify \"--state\""); 93} 94 95static void state_print_state(unsigned int statemask) 96{ 97 const char *sep = ""; 98 99 if (statemask & XT_STATE_INVALID) { 100 printf("%sINVALID", sep); 101 sep = ","; 102 } 103 if (statemask & XT_STATE_BIT(IP_CT_NEW)) { 104 printf("%sNEW", sep); 105 sep = ","; 106 } 107 if (statemask & XT_STATE_BIT(IP_CT_RELATED)) { 108 printf("%sRELATED", sep); 109 sep = ","; 110 } 111 if (statemask & XT_STATE_BIT(IP_CT_ESTABLISHED)) { 112 printf("%sESTABLISHED", sep); 113 sep = ","; 114 } 115 if (statemask & XT_STATE_UNTRACKED) { 116 printf("%sUNTRACKED", sep); 117 sep = ","; 118 } 119 printf(" "); 120} 121 122static void 123state_print(const void *ip, 124 const struct xt_entry_match *match, 125 int numeric) 126{ 127 const struct xt_state_info *sinfo = (const void *)match->data; 128 129 printf("state "); 130 state_print_state(sinfo->statemask); 131} 132 133static void state_save(const void *ip, const struct xt_entry_match *match) 134{ 135 const struct xt_state_info *sinfo = (const void *)match->data; 136 137 printf("--state "); 138 state_print_state(sinfo->statemask); 139} 140 141static struct xtables_match state_match = { 142 .family = NFPROTO_IPV4, 143 .name = "state", 144 .version = XTABLES_VERSION, 145 .size = XT_ALIGN(sizeof(struct xt_state_info)), 146 .userspacesize = XT_ALIGN(sizeof(struct xt_state_info)), 147 .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, 153}; 154 155static struct xtables_match state_match6 = { 156 .family = NFPROTO_IPV6, 157 .name = "state", 158 .version = XTABLES_VERSION, 159 .size = XT_ALIGN(sizeof(struct xt_state_info)), 160 .userspacesize = XT_ALIGN(sizeof(struct xt_state_info)), 161 .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, 167}; 168 169void _init(void) 170{ 171 xtables_register_match(&state_match); 172 xtables_register_match(&state_match6); 173} 174