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