iptables-1.3.2-20050720
[iptables.git] / extensions / libip6t_random.c
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. */
34 static void
35 help(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",
42 IPTABLES_VERSION);
43 }
44
45 static struct option opts[] = {
46         { "average", 1, 0, '1' },
47         { 0 }
48 };
49
50 /* Initialize the target. */
51 static void
52 init(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 */
65 static int
66 parse(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. */
101 static void final_check(unsigned int flags)
102 {
103 }
104
105 /* Prints out the targinfo. */
106 static void
107 print(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. */
121 static void
122 save(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
133 struct 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
147 void _init(void)
148 {
149         register_match6(&rand_match);
150 }