100524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy/* ip6tables match extension for limiting packets per destination 200524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy * 300524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy * (C) 2003-2004 by Harald Welte <laforge@netfilter.org> 400524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy * 500524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy * Development of this code was funded by Astaro AG, http://www.astaro.com/ 600524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy * 700524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy * Based on ipt_limit.c by 881bd58838403fc8c4a63840f0af42deebe6d4a20Jan Engelhardt * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr> 981bd58838403fc8c4a63840f0af42deebe6d4a20Jan Engelhardt * Hervé Eychenne <rv@wallfire.org> 1000524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy * 1100524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy * Error corections by nmalykh@bilim.com (22.01.2005) 1200524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy */ 139921f2b9a241750e4730fc7d486687c6a32779f4Jan Engelhardt#define _BSD_SOURCE 1 149921f2b9a241750e4730fc7d486687c6a32779f4Jan Engelhardt#define _ISOC99_SOURCE 1 159d69da4bdb1d546218d168b72f12ac8aa042e3d8Jan Engelhardt#include <math.h> 169a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt#include <stdbool.h> 17ef18e8147903885708d1c264904129af4fb636d6Jan Engelhardt#include <stdint.h> 1800524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy#include <stdio.h> 1900524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy#include <string.h> 2000524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy#include <stdlib.h> 21d62a9db1295608ef98394b830703389973346716Yasuyuki KOZAKAI#include <xtables.h> 22d62a9db1295608ef98394b830703389973346716Yasuyuki KOZAKAI#include <linux/netfilter/x_tables.h> 2300524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy#include <linux/netfilter/xt_hashlimit.h> 2400524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 2500524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy#define XT_HASHLIMIT_BURST 5 26abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal#define XT_HASHLIMIT_BURST_MAX 10000 27abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 28abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal#define XT_HASHLIMIT_BYTE_EXPIRE 15 29abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal#define XT_HASHLIMIT_BYTE_EXPIRE_BURST 60 3000524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 3100524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy/* miliseconds */ 3200524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy#define XT_HASHLIMIT_GCINTERVAL 1000 3300524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 3468146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardtstruct hashlimit_mt_udata { 3568146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt uint32_t mult; 3668146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt}; 3768146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt 38181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void hashlimit_help(void) 3900524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy{ 4000524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy printf( 418b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"hashlimit match options:\n" 4200524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy"--hashlimit <avg> max average match rate\n" 4300524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy" [Packets per second unless followed by \n" 4400524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy" /sec /minute /hour /day postfixes]\n" 4500524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy"--hashlimit-mode <mode> mode is a comma-separated list of\n" 4600524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy" dstip,srcip,dstport,srcport\n" 4700524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy"--hashlimit-name <name> name for /proc/net/ipt_hashlimit/\n" 4800524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy"[--hashlimit-burst <num>] number to match in a burst, default %u\n" 4900524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy"[--hashlimit-htable-size <num>] number of hashtable buckets\n" 5000524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy"[--hashlimit-htable-max <num>] number of hashtable entries\n" 5100524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy"[--hashlimit-htable-gcinterval] interval between garbage collection runs\n" 528b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"[--hashlimit-htable-expire] after which time are idle entries expired?\n", 538b7c64d6ba156a99008fcd810cba874c73294333Jan EngelhardtXT_HASHLIMIT_BURST); 5400524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy} 5500524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 56fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardtenum { 57fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt O_UPTO = 0, 58fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt O_ABOVE, 59fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt O_LIMIT, 60fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt O_MODE, 61fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt O_SRCMASK, 62fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt O_DSTMASK, 63fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt O_NAME, 64fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt O_BURST, 65fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt O_HTABLE_SIZE, 66fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt O_HTABLE_MAX, 67fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt O_HTABLE_GCINT, 68fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt O_HTABLE_EXPIRE, 69abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal F_BURST = 1 << O_BURST, 7068146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt F_UPTO = 1 << O_UPTO, 7168146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt F_ABOVE = 1 << O_ABOVE, 7268146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt F_HTABLE_EXPIRE = 1 << O_HTABLE_EXPIRE, 73fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt}; 74fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt 759a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardtstatic void hashlimit_mt_help(void) 769a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt{ 779a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt printf( 789a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt"hashlimit match options:\n" 799a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt" --hashlimit-upto <avg> max average match rate\n" 809a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt" [Packets per second unless followed by \n" 819a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt" /sec /minute /hour /day postfixes]\n" 829a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt" --hashlimit-above <avg> min average match rate\n" 839a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt" --hashlimit-mode <mode> mode is a comma-separated list of\n" 849a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt" dstip,srcip,dstport,srcport (or none)\n" 859a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt" --hashlimit-srcmask <length> source address grouping prefix length\n" 869a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt" --hashlimit-dstmask <length> destination address grouping prefix length\n" 879a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt" --hashlimit-name <name> name for /proc/net/ipt_hashlimit\n" 889a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt" --hashlimit-burst <num> number to match in a burst, default %u\n" 899a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt" --hashlimit-htable-size <num> number of hashtable buckets\n" 909a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt" --hashlimit-htable-max <num> number of hashtable entries\n" 919a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt" --hashlimit-htable-gcinterval interval between garbage collection runs\n" 929a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt" --hashlimit-htable-expire after which time are idle entries expired?\n" 939a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt"\n", XT_HASHLIMIT_BURST); 949a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt} 959a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 96fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt#define s struct xt_hashlimit_info 97fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardtstatic const struct xt_option_entry hashlimit_opts[] = { 98fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE, 99de1f06dca906bfcb82d7c7c2d555fbf3229d12b6Jan Engelhardt .type = XTTYPE_STRING}, 100fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_UINT32, 101abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal .min = 1, .max = XT_HASHLIMIT_BURST_MAX, .flags = XTOPT_PUT, 102fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt XTOPT_POINTER(s, cfg.burst)}, 103fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE, 104fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .type = XTTYPE_UINT32, .flags = XTOPT_PUT, 105fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt XTOPT_POINTER(s, cfg.size)}, 106fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit-htable-max", .id = O_HTABLE_MAX, 107fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .type = XTTYPE_UINT32, .flags = XTOPT_PUT, 108fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt XTOPT_POINTER(s, cfg.max)}, 109fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit-htable-gcinterval", .id = O_HTABLE_GCINT, 110fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .type = XTTYPE_UINT32, .flags = XTOPT_PUT, 111fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt XTOPT_POINTER(s, cfg.gc_interval)}, 112fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit-htable-expire", .id = O_HTABLE_EXPIRE, 113fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .type = XTTYPE_UINT32, .flags = XTOPT_PUT, 114fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt XTOPT_POINTER(s, cfg.expire)}, 115fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit-mode", .id = O_MODE, .type = XTTYPE_STRING, 116fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .flags = XTOPT_MAND}, 117fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit-name", .id = O_NAME, .type = XTTYPE_STRING, 118fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name), .min = 1}, 119fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt XTOPT_TABLEEND, 12000524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy}; 121fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt#undef s 122fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt 123fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt#define s struct xt_hashlimit_mtinfo1 124fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardtstatic const struct xt_option_entry hashlimit_mt_opts[] = { 125fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit-upto", .id = O_UPTO, .excl = F_ABOVE, 126fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, 127fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit-above", .id = O_ABOVE, .excl = F_UPTO, 128fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, 129fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE, 130fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, /* old name */ 131fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit-srcmask", .id = O_SRCMASK, .type = XTTYPE_PLEN}, 132fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit-dstmask", .id = O_DSTMASK, .type = XTTYPE_PLEN}, 133abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal {.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_STRING}, 134fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE, 135fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .type = XTTYPE_UINT32, .flags = XTOPT_PUT, 136fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt XTOPT_POINTER(s, cfg.size)}, 137fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit-htable-max", .id = O_HTABLE_MAX, 138fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .type = XTTYPE_UINT32, .flags = XTOPT_PUT, 139fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt XTOPT_POINTER(s, cfg.max)}, 140fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit-htable-gcinterval", .id = O_HTABLE_GCINT, 141fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .type = XTTYPE_UINT32, .flags = XTOPT_PUT, 142fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt XTOPT_POINTER(s, cfg.gc_interval)}, 143fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit-htable-expire", .id = O_HTABLE_EXPIRE, 144fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .type = XTTYPE_UINT32, .flags = XTOPT_PUT, 145fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt XTOPT_POINTER(s, cfg.expire)}, 146fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit-mode", .id = O_MODE, .type = XTTYPE_STRING}, 147fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt {.name = "hashlimit-name", .id = O_NAME, .type = XTTYPE_STRING, 148fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name), .min = 1}, 149fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt XTOPT_TABLEEND, 1509a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt}; 151fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt#undef s 1529a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 153abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphalstatic uint32_t cost_to_bytes(uint32_t cost) 154abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal{ 155abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal uint32_t r; 156abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 157abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal r = cost ? UINT32_MAX / cost : UINT32_MAX; 158abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal r = (r - 1) << XT_HASHLIMIT_BYTE_SHIFT; 159abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal return r; 160abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal} 161abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 162abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphalstatic uint64_t bytes_to_cost(uint32_t bytes) 163abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal{ 164abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal uint32_t r = bytes >> XT_HASHLIMIT_BYTE_SHIFT; 165abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal return UINT32_MAX / (r+1); 166abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal} 167abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 168abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphalstatic uint32_t get_factor(int chr) 169abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal{ 170abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal switch (chr) { 171abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal case 'm': return 1024 * 1024; 172abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal case 'k': return 1024; 173abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal } 174abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal return 1; 175abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal} 176abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 177abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphalstatic void burst_error(void) 178abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal{ 179abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal xtables_error(PARAMETER_PROBLEM, "bad value for option " 180abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal "\"--hashlimit-burst\", or out of range (1-%u).", XT_HASHLIMIT_BURST_MAX); 181abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal} 182abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 183abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphalstatic uint32_t parse_burst(const char *burst, struct xt_hashlimit_mtinfo1 *info) 184abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal{ 185abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal uintmax_t v; 186abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal char *end; 187abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 188abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal if (!xtables_strtoul(burst, &end, &v, 1, UINT32_MAX) || 189abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal (*end == 0 && v > XT_HASHLIMIT_BURST_MAX)) 190abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal burst_error(); 191abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 192abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal v *= get_factor(*end); 193abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal if (v > UINT32_MAX) 194abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal xtables_error(PARAMETER_PROBLEM, "bad value for option " 195abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal "\"--hashlimit-burst\", value \"%s\" too large " 196abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal "(max %umb).", burst, UINT32_MAX/1024/1024); 197abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal return v; 198abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal} 199abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 200abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphalstatic bool parse_bytes(const char *rate, uint32_t *val, struct hashlimit_mt_udata *ud) 201abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal{ 202abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal unsigned int factor = 1; 203abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal uint64_t tmp; 204abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal int r; 205abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal const char *mode = strstr(rate, "b/s"); 206abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal if (!mode || mode == rate) 207abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal return false; 208abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 209abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal mode--; 210abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal r = atoi(rate); 211abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal if (r == 0) 212abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal return false; 213abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 214abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal factor = get_factor(*mode); 215abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal tmp = (uint64_t) r * factor; 216abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal if (tmp > UINT32_MAX) 217abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal xtables_error(PARAMETER_PROBLEM, 218abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal "Rate value too large \"%llu\" (max %u)\n", 219abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal (unsigned long long)tmp, UINT32_MAX); 220abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 221abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal *val = bytes_to_cost(tmp); 222abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal if (*val == 0) 223abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal xtables_error(PARAMETER_PROBLEM, "Rate too high \"%s\"\n", rate); 224abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 225abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal ud->mult = XT_HASHLIMIT_BYTE_EXPIRE; 226abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal return true; 227abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal} 228abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 22900524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardystatic 23068146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardtint parse_rate(const char *rate, uint32_t *val, struct hashlimit_mt_udata *ud) 23100524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy{ 23200524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy const char *delim; 2337ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardt uint32_t r; 23400524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 23568146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt ud->mult = 1; /* Seconds by default. */ 23600524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy delim = strchr(rate, '/'); 23700524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy if (delim) { 23800524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy if (strlen(delim+1) == 0) 23900524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy return 0; 24000524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 24100524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0) 24268146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt ud->mult = 1; 24300524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0) 24468146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt ud->mult = 60; 24500524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0) 24668146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt ud->mult = 60*60; 24700524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0) 24868146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt ud->mult = 24*60*60; 24900524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy else 25000524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy return 0; 25100524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy } 25200524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy r = atoi(rate); 25300524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy if (!r) 25400524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy return 0; 25500524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 25668146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt *val = XT_HASHLIMIT_SCALE * ud->mult / r; 2579d69da4bdb1d546218d168b72f12ac8aa042e3d8Jan Engelhardt if (*val == 0) 2589d69da4bdb1d546218d168b72f12ac8aa042e3d8Jan Engelhardt /* 2599d69da4bdb1d546218d168b72f12ac8aa042e3d8Jan Engelhardt * The rate maps to infinity. (1/day is the minimum they can 2609d69da4bdb1d546218d168b72f12ac8aa042e3d8Jan Engelhardt * specify, so we are ok at that end). 2619d69da4bdb1d546218d168b72f12ac8aa042e3d8Jan Engelhardt */ 2629d69da4bdb1d546218d168b72f12ac8aa042e3d8Jan Engelhardt xtables_error(PARAMETER_PROBLEM, "Rate too fast \"%s\"\n", rate); 26300524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy return 1; 26400524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy} 26500524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 266181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void hashlimit_init(struct xt_entry_match *m) 26700524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy{ 26800524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy struct xt_hashlimit_info *r = (struct xt_hashlimit_info *)m->data; 26900524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 27000524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy r->cfg.burst = XT_HASHLIMIT_BURST; 27100524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy r->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL; 27200524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 27300524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy} 27400524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 2759a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardtstatic void hashlimit_mt4_init(struct xt_entry_match *match) 2769a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt{ 2779a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt struct xt_hashlimit_mtinfo1 *info = (void *)match->data; 2789a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 2799a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt info->cfg.mode = 0; 2809a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt info->cfg.burst = XT_HASHLIMIT_BURST; 2819a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt info->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL; 2829a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt info->cfg.srcmask = 32; 2839a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt info->cfg.dstmask = 32; 2849a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt} 2859a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 2869a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardtstatic void hashlimit_mt6_init(struct xt_entry_match *match) 2879a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt{ 2889a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt struct xt_hashlimit_mtinfo1 *info = (void *)match->data; 2899a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 2909a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt info->cfg.mode = 0; 2919a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt info->cfg.burst = XT_HASHLIMIT_BURST; 2929a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt info->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL; 2939a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt info->cfg.srcmask = 128; 2949a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt info->cfg.dstmask = 128; 2959a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt} 29600524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 29700524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy/* Parse a 'mode' parameter into the required bitmask */ 298fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardtstatic int parse_mode(uint32_t *mode, const char *option_arg) 29900524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy{ 30000524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy char *tok; 301dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt char *arg = strdup(option_arg); 30200524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 30300524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy if (!arg) 30400524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy return -1; 30500524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 30600524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy for (tok = strtok(arg, ",|"); 30700524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy tok; 30800524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy tok = strtok(NULL, ",|")) { 30900524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy if (!strcmp(tok, "dstip")) 3109a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt *mode |= XT_HASHLIMIT_HASH_DIP; 31100524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy else if (!strcmp(tok, "srcip")) 3129a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt *mode |= XT_HASHLIMIT_HASH_SIP; 31300524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy else if (!strcmp(tok, "srcport")) 3149a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt *mode |= XT_HASHLIMIT_HASH_SPT; 31500524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy else if (!strcmp(tok, "dstport")) 3169a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt *mode |= XT_HASHLIMIT_HASH_DPT; 31700524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy else { 31800524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy free(arg); 31900524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy return -1; 32000524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy } 32100524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy } 32200524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy free(arg); 32300524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy return 0; 32400524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy} 32500524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 326fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardtstatic void hashlimit_parse(struct xt_option_call *cb) 32700524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy{ 328fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt struct xt_hashlimit_info *info = cb->data; 32900524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 330fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt xtables_option_parse(cb); 331fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt switch (cb->entry->id) { 332fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt case O_UPTO: 33368146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata)) 334fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt xtables_param_act(XTF_BAD_VALUE, "hashlimit", 335fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt "--hashlimit-upto", cb->arg); 33600524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy break; 337fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt case O_MODE: 338fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt if (parse_mode(&info->cfg.mode, cb->arg) < 0) 339fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt xtables_param_act(XTF_BAD_VALUE, "hashlimit", 340fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt "--hashlimit-mode", cb->arg); 34100524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy break; 34200524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy } 34300524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy} 34400524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 345fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardtstatic void hashlimit_mt_parse(struct xt_option_call *cb) 3469a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt{ 347fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt struct xt_hashlimit_mtinfo1 *info = cb->data; 3489a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 349fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt xtables_option_parse(cb); 350fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt switch (cb->entry->id) { 351abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal case O_BURST: 352abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal info->cfg.burst = parse_burst(cb->arg, info); 353abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal break; 354fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt case O_UPTO: 355fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt if (cb->invert) 3569a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt info->cfg.mode |= XT_HASHLIMIT_INVERT; 357abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata)) 358abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal info->cfg.mode |= XT_HASHLIMIT_BYTES; 359abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata)) 360a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt xtables_param_act(XTF_BAD_VALUE, "hashlimit", 361fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt "--hashlimit-upto", cb->arg); 362fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt break; 363fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt case O_ABOVE: 364fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt if (!cb->invert) 3659a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt info->cfg.mode |= XT_HASHLIMIT_INVERT; 366abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata)) 367abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal info->cfg.mode |= XT_HASHLIMIT_BYTES; 368abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata)) 369a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt xtables_param_act(XTF_BAD_VALUE, "hashlimit", 370fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt "--hashlimit-above", cb->arg); 371fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt break; 372fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt case O_MODE: 373fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt if (parse_mode(&info->cfg.mode, cb->arg) < 0) 374a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt xtables_param_act(XTF_BAD_VALUE, "hashlimit", 375fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt "--hashlimit-mode", cb->arg); 376fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt break; 377fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt case O_SRCMASK: 378fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt info->cfg.srcmask = cb->val.hlen; 379fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt break; 380fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt case O_DSTMASK: 381fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt info->cfg.dstmask = cb->val.hlen; 382fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt break; 3839a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt } 3849a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt} 3859a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 386fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardtstatic void hashlimit_check(struct xt_fcheck_call *cb) 38700524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy{ 38868146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt const struct hashlimit_mt_udata *udata = cb->udata; 38968146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt struct xt_hashlimit_info *info = cb->data; 39068146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt 391fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt if (!(cb->xflags & (F_UPTO | F_ABOVE))) 3921829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 39300524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy "You have to specify --hashlimit"); 39468146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt if (!(cb->xflags & F_HTABLE_EXPIRE)) 395c148c4ad2e28b94125c0c9954a887f0a473d598bJan Engelhardt info->cfg.expire = udata->mult * 1000; /* from s to msec */ 39668146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt} 39768146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt 39868146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardtstatic void hashlimit_mt_check(struct xt_fcheck_call *cb) 39968146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt{ 40068146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt const struct hashlimit_mt_udata *udata = cb->udata; 40168146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt struct xt_hashlimit_mtinfo1 *info = cb->data; 40268146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt 40368146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt if (!(cb->xflags & (F_UPTO | F_ABOVE))) 40468146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt xtables_error(PARAMETER_PROBLEM, 40568146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt "You have to specify --hashlimit"); 40668146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt if (!(cb->xflags & F_HTABLE_EXPIRE)) 407c148c4ad2e28b94125c0c9954a887f0a473d598bJan Engelhardt info->cfg.expire = udata->mult * 1000; /* from s to msec */ 408abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 409abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal if (info->cfg.mode & XT_HASHLIMIT_BYTES) { 410abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal uint32_t burst = 0; 411abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal if (cb->xflags & F_BURST) { 412abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal if (info->cfg.burst < cost_to_bytes(info->cfg.avg)) 413abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal xtables_error(PARAMETER_PROBLEM, 414abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal "burst cannot be smaller than %ub", cost_to_bytes(info->cfg.avg)); 415abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 416abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal burst = info->cfg.burst; 417abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal burst /= cost_to_bytes(info->cfg.avg); 418abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal if (info->cfg.burst % cost_to_bytes(info->cfg.avg)) 419abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal burst++; 420abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal if (!(cb->xflags & F_HTABLE_EXPIRE)) 421abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal info->cfg.expire = XT_HASHLIMIT_BYTE_EXPIRE_BURST * 1000; 422abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal } 423abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal info->cfg.burst = burst; 424abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal } else if (info->cfg.burst > XT_HASHLIMIT_BURST_MAX) 425abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal burst_error(); 4269a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt} 4279a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 4280e2abed11985e16215559cefd90625f99317b96cJan Engelhardtstatic const struct rates 42900524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy{ 43000524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy const char *name; 4317ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardt uint32_t mult; 43200524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy} rates[] = { { "day", XT_HASHLIMIT_SCALE*24*60*60 }, 43300524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy { "hour", XT_HASHLIMIT_SCALE*60*60 }, 43400524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy { "min", XT_HASHLIMIT_SCALE*60 }, 43500524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy { "sec", XT_HASHLIMIT_SCALE } }; 43600524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 4374a56bcbd49ef20a0203017c15ab1cec9bb140d1aJan Engelhardtstatic uint32_t print_rate(uint32_t period) 43800524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy{ 43900524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy unsigned int i; 44000524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 4419d69da4bdb1d546218d168b72f12ac8aa042e3d8Jan Engelhardt if (period == 0) { 4429d69da4bdb1d546218d168b72f12ac8aa042e3d8Jan Engelhardt printf(" %f", INFINITY); 4439d69da4bdb1d546218d168b72f12ac8aa042e3d8Jan Engelhardt return 0; 4449d69da4bdb1d546218d168b72f12ac8aa042e3d8Jan Engelhardt } 4459d69da4bdb1d546218d168b72f12ac8aa042e3d8Jan Engelhardt 4462c69b55e55f2efc5a334b87ccdceaa9de0ecb658Jan Engelhardt for (i = 1; i < ARRAY_SIZE(rates); ++i) 44700524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy if (period > rates[i].mult 44800524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy || rates[i].mult/period < rates[i].mult%period) 44900524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy break; 45000524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 45173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" %u/%s", rates[i-1].mult / period, rates[i-1].name); 4524a56bcbd49ef20a0203017c15ab1cec9bb140d1aJan Engelhardt /* return in msec */ 4534a56bcbd49ef20a0203017c15ab1cec9bb140d1aJan Engelhardt return rates[i-1].mult / XT_HASHLIMIT_SCALE * 1000; 45400524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy} 45500524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 456abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphalstatic const struct { 457abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal const char *name; 458abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal uint32_t thresh; 459abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal} units[] = { 460abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal { "m", 1024 * 1024 }, 461abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal { "k", 1024 }, 462abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal { "", 1 }, 463abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal}; 464abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 465abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphalstatic uint32_t print_bytes(uint32_t avg, uint32_t burst, const char *prefix) 466abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal{ 467abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal unsigned int i; 468abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal unsigned long long r; 469abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 470abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal r = cost_to_bytes(avg); 471abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 472abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal for (i = 0; i < ARRAY_SIZE(units) -1; ++i) 473abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal if (r >= units[i].thresh && 474abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal bytes_to_cost(r & ~(units[i].thresh - 1)) == avg) 475abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal break; 476abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal printf(" %llu%sb/s", r/units[i].thresh, units[i].name); 477abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 478abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal if (burst == 0) 479abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal return XT_HASHLIMIT_BYTE_EXPIRE * 1000; 480abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 481abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal r *= burst; 482abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal printf(" %s", prefix); 483abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal for (i = 0; i < ARRAY_SIZE(units) -1; ++i) 484abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal if (r >= units[i].thresh) 485abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal break; 486abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 487abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal printf("burst %llu%sb", r / units[i].thresh, units[i].name); 488abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal return XT_HASHLIMIT_BYTE_EXPIRE_BURST * 1000; 489abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal} 490abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 4919a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardtstatic void print_mode(unsigned int mode, char separator) 49200524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy{ 4939a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt bool prevmode = false; 49400524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 49573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt putchar(' '); 4969a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt if (mode & XT_HASHLIMIT_HASH_SIP) { 49700524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy fputs("srcip", stdout); 49800524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy prevmode = 1; 49900524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy } 5009a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt if (mode & XT_HASHLIMIT_HASH_SPT) { 50100524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy if (prevmode) 50200524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy putchar(separator); 50300524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy fputs("srcport", stdout); 50400524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy prevmode = 1; 50500524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy } 5069a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt if (mode & XT_HASHLIMIT_HASH_DIP) { 50700524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy if (prevmode) 50800524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy putchar(separator); 50900524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy fputs("dstip", stdout); 51000524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy prevmode = 1; 51100524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy } 5129a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt if (mode & XT_HASHLIMIT_HASH_DPT) { 51300524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy if (prevmode) 51400524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy putchar(separator); 51500524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy fputs("dstport", stdout); 51600524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy } 51700524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy} 51800524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 519181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void hashlimit_print(const void *ip, 520181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt const struct xt_entry_match *match, int numeric) 52100524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy{ 52269f564e3890976461de0016cd81171ff8bfa8353Jan Engelhardt const struct xt_hashlimit_info *r = (const void *)match->data; 5234a56bcbd49ef20a0203017c15ab1cec9bb140d1aJan Engelhardt uint32_t quantum; 5244a56bcbd49ef20a0203017c15ab1cec9bb140d1aJan Engelhardt 5254a56bcbd49ef20a0203017c15ab1cec9bb140d1aJan Engelhardt fputs(" limit: avg", stdout); 5264a56bcbd49ef20a0203017c15ab1cec9bb140d1aJan Engelhardt quantum = print_rate(r->cfg.avg); 52773866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" burst %u", r->cfg.burst); 52873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt fputs(" mode", stdout); 5299a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt print_mode(r->cfg.mode, '-'); 53000524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy if (r->cfg.size) 53173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" htable-size %u", r->cfg.size); 53200524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy if (r->cfg.max) 53373866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" htable-max %u", r->cfg.max); 53400524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy if (r->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL) 53573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" htable-gcinterval %u", r->cfg.gc_interval); 5364a56bcbd49ef20a0203017c15ab1cec9bb140d1aJan Engelhardt if (r->cfg.expire != quantum) 53773866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" htable-expire %u", r->cfg.expire); 53800524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy} 53900524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 5409a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardtstatic void 5419a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardthashlimit_mt_print(const struct xt_hashlimit_mtinfo1 *info, unsigned int dmask) 5429a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt{ 5434a56bcbd49ef20a0203017c15ab1cec9bb140d1aJan Engelhardt uint32_t quantum; 5444a56bcbd49ef20a0203017c15ab1cec9bb140d1aJan Engelhardt 5459a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt if (info->cfg.mode & XT_HASHLIMIT_INVERT) 54673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt fputs(" limit: above", stdout); 5479a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt else 54873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt fputs(" limit: up to", stdout); 549abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 550abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal if (info->cfg.mode & XT_HASHLIMIT_BYTES) { 551abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal quantum = print_bytes(info->cfg.avg, info->cfg.burst, ""); 552abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal } else { 553abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal quantum = print_rate(info->cfg.avg); 554abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal printf(" burst %u", info->cfg.burst); 555abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal } 5569a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt if (info->cfg.mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT | 5579a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) { 55873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt fputs(" mode", stdout); 5599a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt print_mode(info->cfg.mode, '-'); 5609a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt } 5619a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt if (info->cfg.size != 0) 56273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" htable-size %u", info->cfg.size); 5639a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt if (info->cfg.max != 0) 56473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" htable-max %u", info->cfg.max); 5659a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt if (info->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL) 56673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" htable-gcinterval %u", info->cfg.gc_interval); 5674a56bcbd49ef20a0203017c15ab1cec9bb140d1aJan Engelhardt if (info->cfg.expire != quantum) 56873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" htable-expire %u", info->cfg.expire); 5699a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 5709a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt if (info->cfg.srcmask != dmask) 57173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" srcmask %u", info->cfg.srcmask); 5729a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt if (info->cfg.dstmask != dmask) 57373866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" dstmask %u", info->cfg.dstmask); 5749a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt} 5759a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 5769a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardtstatic void 5779a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardthashlimit_mt4_print(const void *ip, const struct xt_entry_match *match, 5789a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt int numeric) 5799a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt{ 5809a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data; 5819a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 5829a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt hashlimit_mt_print(info, 32); 5839a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt} 5849a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 5859a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardtstatic void 5869a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardthashlimit_mt6_print(const void *ip, const struct xt_entry_match *match, 5879a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt int numeric) 5889a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt{ 5899a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data; 5909a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 5919a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt hashlimit_mt_print(info, 128); 5929a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt} 5939a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 594181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void hashlimit_save(const void *ip, const struct xt_entry_match *match) 59500524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy{ 59669f564e3890976461de0016cd81171ff8bfa8353Jan Engelhardt const struct xt_hashlimit_info *r = (const void *)match->data; 5974a56bcbd49ef20a0203017c15ab1cec9bb140d1aJan Engelhardt uint32_t quantum; 59800524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 5994a56bcbd49ef20a0203017c15ab1cec9bb140d1aJan Engelhardt fputs(" --hashlimit", stdout); 6004a56bcbd49ef20a0203017c15ab1cec9bb140d1aJan Engelhardt quantum = print_rate(r->cfg.avg); 60173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --hashlimit-burst %u", r->cfg.burst); 60200524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 60373866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt fputs(" --hashlimit-mode", stdout); 6049a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt print_mode(r->cfg.mode, ','); 605abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 60673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --hashlimit-name %s", r->name); 60700524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 60800524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy if (r->cfg.size) 60973866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --hashlimit-htable-size %u", r->cfg.size); 61000524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy if (r->cfg.max) 61173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --hashlimit-htable-max %u", r->cfg.max); 61200524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy if (r->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL) 61373866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --hashlimit-htable-gcinterval %u", r->cfg.gc_interval); 6144a56bcbd49ef20a0203017c15ab1cec9bb140d1aJan Engelhardt if (r->cfg.expire != quantum) 61573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --hashlimit-htable-expire %u", r->cfg.expire); 61600524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy} 61700524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy 6189a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardtstatic void 6199a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardthashlimit_mt_save(const struct xt_hashlimit_mtinfo1 *info, unsigned int dmask) 6209a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt{ 6214a56bcbd49ef20a0203017c15ab1cec9bb140d1aJan Engelhardt uint32_t quantum; 6224a56bcbd49ef20a0203017c15ab1cec9bb140d1aJan Engelhardt 6239a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt if (info->cfg.mode & XT_HASHLIMIT_INVERT) 62473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt fputs(" --hashlimit-above", stdout); 6259a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt else 62673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt fputs(" --hashlimit-upto", stdout); 627abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal 628abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal if (info->cfg.mode & XT_HASHLIMIT_BYTES) { 629abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal quantum = print_bytes(info->cfg.avg, info->cfg.burst, "--hashlimit-"); 630abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal } else { 631abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal quantum = print_rate(info->cfg.avg); 632abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal printf(" --hashlimit-burst %u", info->cfg.burst); 633abdef13f36b63758f8775eb86febd96bf062df6fFlorian Westphal } 6349a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 6359a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt if (info->cfg.mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT | 6369a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) { 63773866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt fputs(" --hashlimit-mode", stdout); 6389a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt print_mode(info->cfg.mode, ','); 6399a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt } 6409a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 64173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --hashlimit-name %s", info->name); 6429a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 6439a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt if (info->cfg.size != 0) 64473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --hashlimit-htable-size %u", info->cfg.size); 6459a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt if (info->cfg.max != 0) 64673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --hashlimit-htable-max %u", info->cfg.max); 6479a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt if (info->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL) 64873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --hashlimit-htable-gcinterval %u", info->cfg.gc_interval); 6494a56bcbd49ef20a0203017c15ab1cec9bb140d1aJan Engelhardt if (info->cfg.expire != quantum) 65073866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --hashlimit-htable-expire %u", info->cfg.expire); 6519a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 6529a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt if (info->cfg.srcmask != dmask) 65373866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --hashlimit-srcmask %u", info->cfg.srcmask); 6549a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt if (info->cfg.dstmask != dmask) 65573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --hashlimit-dstmask %u", info->cfg.dstmask); 6569a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt} 6579a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 6589a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardtstatic void 6599a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardthashlimit_mt4_save(const void *ip, const struct xt_entry_match *match) 6609a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt{ 6619a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data; 6629a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 6639a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt hashlimit_mt_save(info, 32); 6649a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt} 6659a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 6669a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardtstatic void 6679a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardthashlimit_mt6_save(const void *ip, const struct xt_entry_match *match) 6689a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt{ 6699a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data; 6709a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 6719a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt hashlimit_mt_save(info, 128); 6729a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt} 6739a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 674f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardtstatic struct xtables_match hashlimit_mt_reg[] = { 675f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt { 676f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .family = NFPROTO_UNSPEC, 677f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .name = "hashlimit", 678f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .version = XTABLES_VERSION, 679f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .revision = 0, 680f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .size = XT_ALIGN(sizeof(struct xt_hashlimit_info)), 681f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .userspacesize = offsetof(struct xt_hashlimit_info, hinfo), 682f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .help = hashlimit_help, 683f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .init = hashlimit_init, 684fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .x6_parse = hashlimit_parse, 685fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .x6_fcheck = hashlimit_check, 686f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .print = hashlimit_print, 687f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .save = hashlimit_save, 688de1f06dca906bfcb82d7c7c2d555fbf3229d12b6Jan Engelhardt .x6_options = hashlimit_opts, 68968146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt .udata_size = sizeof(struct hashlimit_mt_udata), 690f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt }, 691f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt { 692f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .version = XTABLES_VERSION, 693f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .name = "hashlimit", 694f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .revision = 1, 695f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .family = NFPROTO_IPV4, 696f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .size = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo1)), 697f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo), 698f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .help = hashlimit_mt_help, 699f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .init = hashlimit_mt4_init, 700fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .x6_parse = hashlimit_mt_parse, 70168146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt .x6_fcheck = hashlimit_mt_check, 702f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .print = hashlimit_mt4_print, 703f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .save = hashlimit_mt4_save, 704fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .x6_options = hashlimit_mt_opts, 70568146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt .udata_size = sizeof(struct hashlimit_mt_udata), 706f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt }, 707f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt { 708f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .version = XTABLES_VERSION, 709f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .name = "hashlimit", 710f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .revision = 1, 711f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .family = NFPROTO_IPV6, 712f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .size = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo1)), 713f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo), 714f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .help = hashlimit_mt_help, 715f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .init = hashlimit_mt6_init, 716fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .x6_parse = hashlimit_mt_parse, 71768146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt .x6_fcheck = hashlimit_mt_check, 718f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .print = hashlimit_mt6_print, 719f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .save = hashlimit_mt6_save, 720fe02f76e013941a7f65f57f297d3177bcfeb0623Jan Engelhardt .x6_options = hashlimit_mt_opts, 72168146dad91611bd8d6d12c8ba27219130d99607bJan Engelhardt .udata_size = sizeof(struct hashlimit_mt_udata), 722f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt }, 7239a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt}; 7249a8c77fc8df3155747c34dcea79b7834a2a9a40aJan Engelhardt 72500524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardyvoid _init(void) 72600524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy{ 727f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt xtables_register_matches(hashlimit_mt_reg, ARRAY_SIZE(hashlimit_mt_reg)); 72800524b27b5e442d27414cf48e0d6e6372b6113aePatrick McHardy} 729