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*/ 10 11#include <stdio.h> 12#include <netdb.h> 13#include <string.h> 14#include <stdlib.h> 15#include <syslog.h> 16#include <getopt.h> 17#include <iptables.h> 18#include <linux/netfilter_ipv4/ip_tables.h> 19#include <linux/netfilter_ipv4/ipt_random.h> 20 21/** 22 * The kernel random routing returns numbers between 0 and 255. 23 * To ease the task of the user in choosing the probability 24 * of matching, we want him to be able to use percentages. 25 * Therefore we have to accept numbers in percentage here, 26 * turn them into number between 0 and 255 for the kernel module, 27 * and turn them back to percentages when we print/save 28 * the rule. 29 */ 30 31 32/* Function which prints out usage message. */ 33static void 34help(void) 35{ 36 printf( 37"random v%s options:\n" 38" [--average percent ] The probability in percentage of the match\n" 39" If ommited, a probability of 50%% percent is set.\n" 40" Percentage must be within : 1 <= percent <= 99.\n\n", 41IPTABLES_VERSION); 42} 43 44static struct option opts[] = { 45 { "average", 1, 0, '1' }, 46 { 0 } 47}; 48 49/* Initialize the target. */ 50static void 51init(struct ipt_entry_match *m, unsigned int *nfcache) 52{ 53 struct ipt_rand_info *randinfo = (struct ipt_rand_info *)(m)->data; 54 55 /* We assign the average to be 50 which is our default value */ 56 /* 50 * 2.55 = 128 */ 57 randinfo->average = 128; 58} 59 60#define IPT_RAND_OPT_AVERAGE 0x01 61 62/* Function which parses command options; returns true if it 63 ate an option */ 64static int 65parse(int c, char **argv, int invert, unsigned int *flags, 66 const struct ipt_entry *entry, 67 unsigned int *nfcache, 68 struct ipt_entry_match **match) 69{ 70 struct ipt_rand_info *randinfo = (struct ipt_rand_info *)(*match)->data; 71 unsigned int num; 72 73 switch (c) { 74 case '1': 75 /* check for common mistakes... */ 76 if (invert) 77 exit_error(PARAMETER_PROBLEM, 78 "Can't specify ! --average"); 79 if (*flags & IPT_RAND_OPT_AVERAGE) 80 exit_error(PARAMETER_PROBLEM, 81 "Can't specify --average twice"); 82 83 /* Remember, this function will interpret a leading 0 to be 84 Octal, a leading 0x to be hexdecimal... */ 85 if (string_to_number(optarg, 1, 99, &num) == -1 || num < 1) 86 exit_error(PARAMETER_PROBLEM, 87 "bad --average `%s', must be between 1 and 99", optarg); 88 89 /* assign the values */ 90 randinfo->average = (int)(num * 2.55); 91 *flags |= IPT_RAND_OPT_AVERAGE; 92 break; 93 default: 94 return 0; 95 } 96 return 1; 97} 98 99/* Final check; nothing. */ 100static void final_check(unsigned int flags) 101{ 102} 103 104/* Prints out the targinfo. */ 105static void 106print(const struct ipt_ip *ip, 107 const struct ipt_entry_match *match, 108 int numeric) 109{ 110 const struct ipt_rand_info *randinfo 111 = (const struct ipt_rand_info *)match->data; 112 div_t result = div((randinfo->average*100), 255); 113 if (result.rem > 127) /* round up... */ 114 ++result.quot; 115 116 printf(" random %u%% ", result.quot); 117} 118 119/* Saves the union ipt_targinfo in parsable form to stdout. */ 120static void 121save(const struct ipt_ip *ip, const struct ipt_entry_match *match) 122{ 123 const struct ipt_rand_info *randinfo 124 = (const struct ipt_rand_info *)match->data; 125 div_t result = div((randinfo->average *100), 255); 126 if (result.rem > 127) /* round up... */ 127 ++result.quot; 128 129 printf("--average %u ", result.quot); 130} 131 132struct iptables_match rand_match = { 133 .next = NULL, 134 .name = "random", 135 .version = IPTABLES_VERSION, 136 .size = IPT_ALIGN(sizeof(struct ipt_rand_info)), 137 .userspacesize = IPT_ALIGN(sizeof(struct ipt_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_match(&rand_match); 150} 151