Home | History | Annotate | Download | only in extensions
      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <xtables.h>
      4 #include <linux/netfilter/nf_conntrack_common.h>
      5 #include <linux/netfilter/xt_state.h>
      6 
      7 #ifndef XT_STATE_UNTRACKED
      8 #define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
      9 #endif
     10 
     11 enum {
     12 	O_STATE = 0,
     13 };
     14 
     15 static void
     16 state_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 
     24 static const struct xt_option_entry state_opts[] = {
     25 	{.name = "state", .id = O_STATE, .type = XTTYPE_STRING,
     26 	 .flags = XTOPT_MAND},
     27 	XTOPT_TABLEEND,
     28 };
     29 
     30 static int
     31 state_parse_state(const char *state, size_t len, struct xt_state_info *sinfo)
     32 {
     33 	if (strncasecmp(state, "INVALID", len) == 0)
     34 		sinfo->statemask |= XT_STATE_INVALID;
     35 	else if (strncasecmp(state, "NEW", len) == 0)
     36 		sinfo->statemask |= XT_STATE_BIT(IP_CT_NEW);
     37 	else if (strncasecmp(state, "ESTABLISHED", len) == 0)
     38 		sinfo->statemask |= XT_STATE_BIT(IP_CT_ESTABLISHED);
     39 	else if (strncasecmp(state, "RELATED", len) == 0)
     40 		sinfo->statemask |= XT_STATE_BIT(IP_CT_RELATED);
     41 	else if (strncasecmp(state, "UNTRACKED", len) == 0)
     42 		sinfo->statemask |= XT_STATE_UNTRACKED;
     43 	else
     44 		return 0;
     45 	return 1;
     46 }
     47 
     48 static void
     49 state_parse_states(const char *arg, struct xt_state_info *sinfo)
     50 {
     51 	const char *comma;
     52 
     53 	while ((comma = strchr(arg, ',')) != NULL) {
     54 		if (comma == arg || !state_parse_state(arg, comma-arg, sinfo))
     55 			xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg);
     56 		arg = comma+1;
     57 	}
     58 	if (!*arg)
     59 		xtables_error(PARAMETER_PROBLEM, "\"--state\" requires a list of "
     60 					      "states with no spaces, e.g. "
     61 					      "ESTABLISHED,RELATED");
     62 	if (strlen(arg) == 0 || !state_parse_state(arg, strlen(arg), sinfo))
     63 		xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg);
     64 }
     65 
     66 static void state_parse(struct xt_option_call *cb)
     67 {
     68 	struct xt_state_info *sinfo = cb->data;
     69 
     70 	xtables_option_parse(cb);
     71 	state_parse_states(cb->arg, sinfo);
     72 	if (cb->invert)
     73 		sinfo->statemask = ~sinfo->statemask;
     74 }
     75 
     76 static void state_print_state(unsigned int statemask)
     77 {
     78 	const char *sep = "";
     79 
     80 	if (statemask & XT_STATE_INVALID) {
     81 		printf("%sINVALID", sep);
     82 		sep = ",";
     83 	}
     84 	if (statemask & XT_STATE_BIT(IP_CT_NEW)) {
     85 		printf("%sNEW", sep);
     86 		sep = ",";
     87 	}
     88 	if (statemask & XT_STATE_BIT(IP_CT_RELATED)) {
     89 		printf("%sRELATED", sep);
     90 		sep = ",";
     91 	}
     92 	if (statemask & XT_STATE_BIT(IP_CT_ESTABLISHED)) {
     93 		printf("%sESTABLISHED", sep);
     94 		sep = ",";
     95 	}
     96 	if (statemask & XT_STATE_UNTRACKED) {
     97 		printf("%sUNTRACKED", sep);
     98 		sep = ",";
     99 	}
    100 }
    101 
    102 static void
    103 state_print(const void *ip,
    104       const struct xt_entry_match *match,
    105       int numeric)
    106 {
    107 	const struct xt_state_info *sinfo = (const void *)match->data;
    108 
    109 	printf(" state ");
    110 	state_print_state(sinfo->statemask);
    111 }
    112 
    113 static void state_save(const void *ip, const struct xt_entry_match *match)
    114 {
    115 	const struct xt_state_info *sinfo = (const void *)match->data;
    116 
    117 	printf(" --state ");
    118 	state_print_state(sinfo->statemask);
    119 }
    120 
    121 static struct xtables_match state_match = {
    122 	.family		= NFPROTO_UNSPEC,
    123 	.name		= "state",
    124 	.version	= XTABLES_VERSION,
    125 	.size		= XT_ALIGN(sizeof(struct xt_state_info)),
    126 	.userspacesize	= XT_ALIGN(sizeof(struct xt_state_info)),
    127 	.help		= state_help,
    128 	.print		= state_print,
    129 	.save		= state_save,
    130 	.x6_parse	= state_parse,
    131 	.x6_options	= state_opts,
    132 };
    133 
    134 void _init(void)
    135 {
    136 	xtables_register_match(&state_match);
    137 }
    138