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