Home | History | Annotate | Download | only in extensions
      1 #include <stdbool.h>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <xtables.h>
      5 #include <linux/netfilter/xt_recent.h>
      6 
      7 enum {
      8 	O_SET = 0,
      9 	O_RCHECK,
     10 	O_UPDATE,
     11 	O_REMOVE,
     12 	O_SECONDS,
     13 	O_HITCOUNT,
     14 	O_RTTL,
     15 	O_NAME,
     16 	O_RSOURCE,
     17 	O_RDEST,
     18 	F_SET    = 1 << O_SET,
     19 	F_RCHECK = 1 << O_RCHECK,
     20 	F_UPDATE = 1 << O_UPDATE,
     21 	F_REMOVE = 1 << O_REMOVE,
     22 	F_ANY_OP = F_SET | F_RCHECK | F_UPDATE | F_REMOVE,
     23 };
     24 
     25 #define s struct xt_recent_mtinfo
     26 static const struct xt_option_entry recent_opts[] = {
     27 	{.name = "set", .id = O_SET, .type = XTTYPE_NONE,
     28 	 .excl = F_ANY_OP, .flags = XTOPT_INVERT},
     29 	{.name = "rcheck", .id = O_RCHECK, .type = XTTYPE_NONE,
     30 	 .excl = F_ANY_OP, .flags = XTOPT_INVERT},
     31 	{.name = "update", .id = O_UPDATE, .type = XTTYPE_NONE,
     32 	 .excl = F_ANY_OP, .flags = XTOPT_INVERT},
     33 	{.name = "remove", .id = O_REMOVE, .type = XTTYPE_NONE,
     34 	 .excl = F_ANY_OP, .flags = XTOPT_INVERT},
     35 	{.name = "seconds", .id = O_SECONDS, .type = XTTYPE_UINT32,
     36 	 .flags = XTOPT_PUT, XTOPT_POINTER(s, seconds)},
     37 	{.name = "hitcount", .id = O_HITCOUNT, .type = XTTYPE_UINT32,
     38 	 .flags = XTOPT_PUT, XTOPT_POINTER(s, hit_count)},
     39 	{.name = "rttl", .id = O_RTTL, .type = XTTYPE_NONE,
     40 	 .excl = F_SET | F_REMOVE},
     41 	{.name = "name", .id = O_NAME, .type = XTTYPE_STRING,
     42 	 .flags = XTOPT_PUT, XTOPT_POINTER(s, name)},
     43 	{.name = "rsource", .id = O_RSOURCE, .type = XTTYPE_NONE},
     44 	{.name = "rdest", .id = O_RDEST, .type = XTTYPE_NONE},
     45 	XTOPT_TABLEEND,
     46 };
     47 #undef s
     48 
     49 static void recent_help(void)
     50 {
     51 	printf(
     52 "recent match options:\n"
     53 "[!] --set                       Add source address to list, always matches.\n"
     54 "[!] --rcheck                    Match if source address in list.\n"
     55 "[!] --update                    Match if source address in list, also update last-seen time.\n"
     56 "[!] --remove                    Match if source address in list, also removes that address from list.\n"
     57 "    --seconds seconds           For check and update commands above.\n"
     58 "                                Specifies that the match will only occur if source address last seen within\n"
     59 "                                the last 'seconds' seconds.\n"
     60 "    --hitcount hits             For check and update commands above.\n"
     61 "                                Specifies that the match will only occur if source address seen hits times.\n"
     62 "                                May be used in conjunction with the seconds option.\n"
     63 "    --rttl                      For check and update commands above.\n"
     64 "                                Specifies that the match will only occur if the source address and the TTL\n"
     65 "                                match between this packet and the one which was set.\n"
     66 "                                Useful if you have problems with people spoofing their source address in order\n"
     67 "                                to DoS you via this module.\n"
     68 "    --name name                 Name of the recent list to be used.  DEFAULT used if none given.\n"
     69 "    --rsource                   Match/Save the source address of each packet in the recent list table (default).\n"
     70 "    --rdest                     Match/Save the destination address of each packet in the recent list table.\n"
     71 "xt_recent by: Stephen Frost <sfrost (at) snowman.net>.  http://snowman.net/projects/ipt_recent/\n");
     72 }
     73 
     74 static void recent_init(struct xt_entry_match *match)
     75 {
     76 	struct xt_recent_mtinfo *info = (void *)(match)->data;
     77 
     78 	strncpy(info->name,"DEFAULT", XT_RECENT_NAME_LEN);
     79 	/* even though XT_RECENT_NAME_LEN is currently defined as 200,
     80 	 * better be safe, than sorry */
     81 	info->name[XT_RECENT_NAME_LEN-1] = '\0';
     82 	info->side = XT_RECENT_SOURCE;
     83 }
     84 
     85 static void recent_parse(struct xt_option_call *cb)
     86 {
     87 	struct xt_recent_mtinfo *info = cb->data;
     88 
     89 	xtables_option_parse(cb);
     90 	switch (cb->entry->id) {
     91 	case O_SET:
     92 		info->check_set |= XT_RECENT_SET;
     93 		if (cb->invert)
     94 			info->invert = true;
     95 		break;
     96 	case O_RCHECK:
     97 		info->check_set |= XT_RECENT_CHECK;
     98 		if (cb->invert)
     99 			info->invert = true;
    100 		break;
    101 	case O_UPDATE:
    102 		info->check_set |= XT_RECENT_UPDATE;
    103 		if (cb->invert)
    104 			info->invert = true;
    105 		break;
    106 	case O_REMOVE:
    107 		info->check_set |= XT_RECENT_REMOVE;
    108 		if (cb->invert)
    109 			info->invert = true;
    110 		break;
    111 	case O_RTTL:
    112 		info->check_set |= XT_RECENT_TTL;
    113 		break;
    114 	case O_RSOURCE:
    115 		info->side = XT_RECENT_SOURCE;
    116 		break;
    117 	case O_RDEST:
    118 		info->side = XT_RECENT_DEST;
    119 		break;
    120 	}
    121 }
    122 
    123 static void recent_check(struct xt_fcheck_call *cb)
    124 {
    125 	if (!(cb->xflags & F_ANY_OP))
    126 		xtables_error(PARAMETER_PROBLEM,
    127 			"recent: you must specify one of `--set', `--rcheck' "
    128 			"`--update' or `--remove'");
    129 }
    130 
    131 static void recent_print(const void *ip, const struct xt_entry_match *match,
    132                          int numeric)
    133 {
    134 	const struct xt_recent_mtinfo *info = (const void *)match->data;
    135 
    136 	if (info->invert)
    137 		printf(" !");
    138 
    139 	printf(" recent:");
    140 	if (info->check_set & XT_RECENT_SET)
    141 		printf(" SET");
    142 	if (info->check_set & XT_RECENT_CHECK)
    143 		printf(" CHECK");
    144 	if (info->check_set & XT_RECENT_UPDATE)
    145 		printf(" UPDATE");
    146 	if (info->check_set & XT_RECENT_REMOVE)
    147 		printf(" REMOVE");
    148 	if(info->seconds) printf(" seconds: %d", info->seconds);
    149 	if(info->hit_count) printf(" hit_count: %d", info->hit_count);
    150 	if (info->check_set & XT_RECENT_TTL)
    151 		printf(" TTL-Match");
    152 	if(info->name) printf(" name: %s", info->name);
    153 	if (info->side == XT_RECENT_SOURCE)
    154 		printf(" side: source");
    155 	if (info->side == XT_RECENT_DEST)
    156 		printf(" side: dest");
    157 }
    158 
    159 static void recent_save(const void *ip, const struct xt_entry_match *match)
    160 {
    161 	const struct xt_recent_mtinfo *info = (const void *)match->data;
    162 
    163 	if (info->invert)
    164 		printf(" !");
    165 
    166 	if (info->check_set & XT_RECENT_SET)
    167 		printf(" --set");
    168 	if (info->check_set & XT_RECENT_CHECK)
    169 		printf(" --rcheck");
    170 	if (info->check_set & XT_RECENT_UPDATE)
    171 		printf(" --update");
    172 	if (info->check_set & XT_RECENT_REMOVE)
    173 		printf(" --remove");
    174 	if(info->seconds) printf(" --seconds %d", info->seconds);
    175 	if(info->hit_count) printf(" --hitcount %d", info->hit_count);
    176 	if (info->check_set & XT_RECENT_TTL)
    177 		printf(" --rttl");
    178 	if(info->name) printf(" --name %s",info->name);
    179 	if (info->side == XT_RECENT_SOURCE)
    180 		printf(" --rsource");
    181 	if (info->side == XT_RECENT_DEST)
    182 		printf(" --rdest");
    183 }
    184 
    185 static struct xtables_match recent_mt_reg = {
    186 	.name          = "recent",
    187 	.version       = XTABLES_VERSION,
    188 	.family        = NFPROTO_UNSPEC,
    189 	.size          = XT_ALIGN(sizeof(struct xt_recent_mtinfo)),
    190 	.userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo)),
    191 	.help          = recent_help,
    192 	.init          = recent_init,
    193 	.x6_parse      = recent_parse,
    194 	.x6_fcheck     = recent_check,
    195 	.print         = recent_print,
    196 	.save          = recent_save,
    197 	.x6_options    = recent_opts,
    198 };
    199 
    200 void _init(void)
    201 {
    202 	xtables_register_match(&recent_mt_reg);
    203 }
    204