1/* 2 Shared library add-on to iptables to add match support for random match. 3 4 This file is distributed under the terms of the GNU General Public 5 License (GPL). Copies of the GPL can be obtained from: 6 ftp://prep.ai.mit.edu/pub/gnu/GPL 7 8 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial development. 9 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 port. 10*/ 11 12#include <stdio.h> 13#include <netdb.h> 14#include <string.h> 15#include <stdlib.h> 16#include <syslog.h> 17#include <getopt.h> 18#include <ip6tables.h> 19#include <linux/netfilter_ipv6/ip6_tables.h> 20#include <linux/netfilter_ipv6/ip6t_random.h> 21 22/** 23 * The kernel random routing returns numbers between 0 and 255. 24 * To ease the task of the user in choosing the probability 25 * of matching, we want him to be able to use percentages. 26 * Therefore we have to accept numbers in percentage here, 27 * turn them into number between 0 and 255 for the kernel module, 28 * and turn them back to percentages when we print/save 29 * the rule. 30 */ 31 32 33/* Function which prints out usage message. */ 34static void 35help(void) 36{ 37 printf( 38"random v%s options:\n" 39" [--average] percent The probability in percentage of the match\n" 40" If ommited, a probability of 50%% percent is set.\n" 41" Percentage must be within : 1 <= percent <= 99.\n\n", 42IPTABLES_VERSION); 43} 44 45static struct option opts[] = { 46 { "average", 1, 0, '1' }, 47 { 0 } 48}; 49 50/* Initialize the target. */ 51static void 52init(struct ip6t_entry_match *m, unsigned int *nfcache) 53{ 54 struct ip6t_rand_info *randinfo = (struct ip6t_rand_info *)(m)->data; 55 56 /* We assign the average to be 50 which is our default value */ 57 /* 50 * 2.55 = 128 */ 58 randinfo->average = 128; 59} 60 61#define IP6T_RAND_OPT_AVERAGE 0x01 62 63/* Function which parses command options; returns true if it 64 ate an option */ 65static int 66parse(int c, char **argv, int invert, unsigned int *flags, 67 const struct ip6t_entry *entry, 68 unsigned int *nfcache, 69 struct ip6t_entry_match **match) 70{ 71 struct ip6t_rand_info *randinfo = (struct ip6t_rand_info *)(*match)->data; 72 unsigned int num; 73 74 switch (c) { 75 case '1': 76 /* check for common mistakes... */ 77 if (invert) 78 exit_error(PARAMETER_PROBLEM, 79 "Can't specify ! --average"); 80 if (*flags & IP6T_RAND_OPT_AVERAGE) 81 exit_error(PARAMETER_PROBLEM, 82 "Can't specify --average twice"); 83 84 /* Remember, this function will interpret a leading 0 to be 85 Octal, a leading 0x to be hexdecimal... */ 86 if (string_to_number(optarg, 1, 99, &num) == -1 || num < 1) 87 exit_error(PARAMETER_PROBLEM, 88 "bad --average `%s', must be between 1 and 99", optarg); 89 90 /* assign the values */ 91 randinfo->average = (int)(num * 2.55); 92 *flags |= IP6T_RAND_OPT_AVERAGE; 93 break; 94 default: 95 return 0; 96 } 97 return 1; 98} 99 100/* Final check; nothing. */ 101static void final_check(unsigned int flags) 102{ 103} 104 105/* Prints out the targinfo. */ 106static void 107print(const struct ip6t_ip6 *ip, 108 const struct ip6t_entry_match *match, 109 int numeric) 110{ 111 const struct ip6t_rand_info *randinfo 112 = (const struct ip6t_rand_info *)match->data; 113 div_t result = div((randinfo->average*100), 255); 114 if (result.rem > 127) /* round up... */ 115 ++result.quot; 116 117 printf(" random %u%% ", result.quot); 118} 119 120/* Saves the union ip6t_targinfo in parsable form to stdout. */ 121static void 122save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match) 123{ 124 const struct ip6t_rand_info *randinfo 125 = (const struct ip6t_rand_info *)match->data; 126 div_t result = div((randinfo->average *100), 255); 127 if (result.rem > 127) /* round up... */ 128 ++result.quot; 129 130 printf("--average %u ", result.quot); 131} 132 133struct ip6tables_match rand_match = { 134 .name = "random", 135 .version = IPTABLES_VERSION, 136 .size = IP6T_ALIGN(sizeof(struct ip6t_rand_info)), 137 .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_rand_info)), 138 .help = &help, 139 .init = &init, 140 .parse = &parse, 141 .final_check = &final_check, 142 .print = &print, 143 .save = &save, 144 .extra_opts = opts, 145}; 146 147void _init(void) 148{ 149 register_match6(&rand_match); 150} 151