libxt_recent.c revision 79ddbf202a06e6f018e087a328c2ca91e65a8463
1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <stdbool.h> 2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <stdio.h> 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <string.h> 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <xtables.h> 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <linux/netfilter/xt_recent.h> 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)enum { 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) O_SET = 0, 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) O_RCHECK, 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) O_UPDATE, 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) O_REMOVE, 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch O_SECONDS, 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) O_REAP, 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch O_HITCOUNT, 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch O_RTTL, 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) O_NAME, 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch O_RSOURCE, 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch O_RDEST, 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) F_SET = 1 << O_SET, 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) F_RCHECK = 1 << O_RCHECK, 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) F_UPDATE = 1 << O_UPDATE, 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) F_REMOVE = 1 << O_REMOVE, 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) F_SECONDS = 1 << O_SECONDS, 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) F_ANY_OP = F_SET | F_RCHECK | F_UPDATE | F_REMOVE, 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}; 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define s struct xt_recent_mtinfo 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static const struct xt_option_entry recent_opts[] = { 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) {.name = "set", .id = O_SET, .type = XTTYPE_NONE, 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) .excl = F_ANY_OP, .flags = XTOPT_INVERT}, 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) {.name = "rcheck", .id = O_RCHECK, .type = XTTYPE_NONE, 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) .excl = F_ANY_OP, .flags = XTOPT_INVERT}, 33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) {.name = "update", .id = O_UPDATE, .type = XTTYPE_NONE, 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) .excl = F_ANY_OP, .flags = XTOPT_INVERT}, 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) {.name = "remove", .id = O_REMOVE, .type = XTTYPE_NONE, 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .excl = F_ANY_OP, .flags = XTOPT_INVERT}, 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {.name = "seconds", .id = O_SECONDS, .type = XTTYPE_UINT32, 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .flags = XTOPT_PUT, XTOPT_POINTER(s, seconds), .min = 1}, 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {.name = "reap", .id = O_REAP, .type = XTTYPE_NONE, 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .also = F_SECONDS }, 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {.name = "hitcount", .id = O_HITCOUNT, .type = XTTYPE_UINT32, 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .flags = XTOPT_PUT, XTOPT_POINTER(s, hit_count)}, 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {.name = "rttl", .id = O_RTTL, .type = XTTYPE_NONE, 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .excl = F_SET | F_REMOVE}, 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {.name = "name", .id = O_NAME, .type = XTTYPE_STRING, 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .flags = XTOPT_PUT, XTOPT_POINTER(s, name)}, 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {.name = "rsource", .id = O_RSOURCE, .type = XTTYPE_NONE}, 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {.name = "rdest", .id = O_RDEST, .type = XTTYPE_NONE}, 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) XTOPT_TABLEEND, 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}; 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#undef s 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static void recent_help(void) 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles){ 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) printf( 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)"recent match options:\n" 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)"[!] --set Add source address to list, always matches.\n" 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)"[!] --rcheck Match if source address in list.\n" 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)"[!] --update Match if source address in list, also update last-seen time.\n" 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)"[!] --remove Match if source address in list, also removes that address from list.\n" 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)" --seconds seconds For check and update commands above.\n" 620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch" Specifies that the match will only occur if source address last seen within\n" 630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch" the last 'seconds' seconds.\n" 640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch" --reap Purge entries older then 'seconds'.\n" 655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu" Can only be used in conjunction with the seconds option.\n" 660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch" --hitcount hits For check and update commands above.\n" 670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch" Specifies that the match will only occur if source address seen hits times.\n" 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)" May be used in conjunction with the seconds option.\n" 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch" --rttl For check and update commands above.\n" 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch" Specifies that the match will only occur if the source address and the TTL\n" 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)" match between this packet and the one which was set.\n" 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)" Useful if you have problems with people spoofing their source address in order\n" 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)" to DoS you via this module.\n" 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)" --name name Name of the recent list to be used. DEFAULT used if none given.\n" 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)" --rsource Match/Save the source address of each packet in the recent list table (default).\n" 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)" --rdest Match/Save the destination address of each packet in the recent list table.\n" 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)"xt_recent by: Stephen Frost <sfrost@snowman.net>. http://snowman.net/projects/ipt_recent/\n"); 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static void recent_init(struct xt_entry_match *match) 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{ 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct xt_recent_mtinfo *info = (void *)(match)->data; 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) strncpy(info->name,"DEFAULT", XT_RECENT_NAME_LEN); 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) /* even though XT_RECENT_NAME_LEN is currently defined as 200, 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * better be safe, than sorry */ 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) info->name[XT_RECENT_NAME_LEN-1] = '\0'; 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) info->side = XT_RECENT_SOURCE; 89c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 90c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 91c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic void recent_parse(struct xt_option_call *cb) 92c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch{ 93c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch struct xt_recent_mtinfo *info = cb->data; 94c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 95c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch xtables_option_parse(cb); 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) switch (cb->entry->id) { 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case O_SET: 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) info->check_set |= XT_RECENT_SET; 99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (cb->invert) 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) info->invert = true; 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case O_RCHECK: 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) info->check_set |= XT_RECENT_CHECK; 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (cb->invert) 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) info->invert = true; 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case O_UPDATE: 1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu info->check_set |= XT_RECENT_UPDATE; 1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (cb->invert) 1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu info->invert = true; 1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu break; 1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case O_REMOVE: 1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 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 struct xt_recent_mtinfo *info = cb->data; 135 136 if (!(cb->xflags & F_ANY_OP)) 137 xtables_error(PARAMETER_PROBLEM, 138 "recent: you must specify one of `--set', `--rcheck' " 139 "`--update' or `--remove'"); 140} 141 142static void recent_print(const void *ip, const struct xt_entry_match *match, 143 int numeric) 144{ 145 const struct xt_recent_mtinfo *info = (const void *)match->data; 146 147 if (info->invert) 148 printf(" !"); 149 150 printf(" recent:"); 151 if (info->check_set & XT_RECENT_SET) 152 printf(" SET"); 153 if (info->check_set & XT_RECENT_CHECK) 154 printf(" CHECK"); 155 if (info->check_set & XT_RECENT_UPDATE) 156 printf(" UPDATE"); 157 if (info->check_set & XT_RECENT_REMOVE) 158 printf(" REMOVE"); 159 if(info->seconds) printf(" seconds: %d", info->seconds); 160 if (info->check_set & XT_RECENT_REAP) 161 printf(" reap"); 162 if(info->hit_count) printf(" hit_count: %d", info->hit_count); 163 if (info->check_set & XT_RECENT_TTL) 164 printf(" TTL-Match"); 165 if(info->name) printf(" name: %s", info->name); 166 if (info->side == XT_RECENT_SOURCE) 167 printf(" side: source"); 168 if (info->side == XT_RECENT_DEST) 169 printf(" side: dest"); 170} 171 172static void recent_save(const void *ip, const struct xt_entry_match *match) 173{ 174 const struct xt_recent_mtinfo *info = (const void *)match->data; 175 176 if (info->invert) 177 printf(" !"); 178 179 if (info->check_set & XT_RECENT_SET) 180 printf(" --set"); 181 if (info->check_set & XT_RECENT_CHECK) 182 printf(" --rcheck"); 183 if (info->check_set & XT_RECENT_UPDATE) 184 printf(" --update"); 185 if (info->check_set & XT_RECENT_REMOVE) 186 printf(" --remove"); 187 if(info->seconds) printf(" --seconds %d", info->seconds); 188 if (info->check_set & XT_RECENT_REAP) 189 printf(" --reap"); 190 if(info->hit_count) printf(" --hitcount %d", info->hit_count); 191 if (info->check_set & XT_RECENT_TTL) 192 printf(" --rttl"); 193 if(info->name) printf(" --name %s",info->name); 194 if (info->side == XT_RECENT_SOURCE) 195 printf(" --rsource"); 196 if (info->side == XT_RECENT_DEST) 197 printf(" --rdest"); 198} 199 200static struct xtables_match recent_mt_reg = { 201 .name = "recent", 202 .version = XTABLES_VERSION, 203 .family = NFPROTO_UNSPEC, 204 .size = XT_ALIGN(sizeof(struct xt_recent_mtinfo)), 205 .userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo)), 206 .help = recent_help, 207 .init = recent_init, 208 .x6_parse = recent_parse, 209 .x6_fcheck = recent_check, 210 .print = recent_print, 211 .save = recent_save, 212 .x6_options = recent_opts, 213}; 214 215void _init(void) 216{ 217 xtables_register_match(&recent_mt_reg); 218} 219