iptables-1.2.9-2.3.1.src.rpm
[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         *nfcache |= NFC_UNKNOWN;
56
57         /* We assign the average to be 50 which is our default value */
58         /* 50 * 2.55 = 128 */
59         randinfo->average = 128;
60 }
61
62 #define IP6T_RAND_OPT_AVERAGE   0x01
63
64 /* Function which parses command options; returns true if it
65    ate an option */
66 static int
67 parse(int c, char **argv, int invert, unsigned int *flags,
68       const struct ip6t_entry *entry,
69       unsigned int *nfcache,
70       struct ip6t_entry_match **match)
71 {
72         struct ip6t_rand_info *randinfo = (struct ip6t_rand_info *)(*match)->data;
73         unsigned int num;
74
75         switch (c) {
76         case '1':
77                 /* check for common mistakes... */
78                 if (invert)
79                         exit_error(PARAMETER_PROBLEM,
80                                    "Can't specify ! --average");
81                 if (*flags & IP6T_RAND_OPT_AVERAGE)
82                         exit_error(PARAMETER_PROBLEM,
83                                    "Can't specify --average twice");
84
85                 /* Remember, this function will interpret a leading 0 to be 
86                    Octal, a leading 0x to be hexdecimal... */
87                 if (string_to_number(optarg, 1, 99, &num) == -1 || num < 1)
88                         exit_error(PARAMETER_PROBLEM,
89                                    "bad --average `%s', must be between 1 and 99", optarg);
90
91                 /* assign the values */
92                 randinfo->average = (int)(num * 2.55);
93                 *flags |= IP6T_RAND_OPT_AVERAGE;
94                 break;
95         default:
96                 return 0;
97         }
98         return 1;
99 }
100
101 /* Final check; nothing. */
102 static void final_check(unsigned int flags)
103 {
104 }
105
106 /* Prints out the targinfo. */
107 static void
108 print(const struct ip6t_ip6 *ip,
109       const struct ip6t_entry_match *match,
110       int numeric)
111 {
112         const struct ip6t_rand_info *randinfo
113                 = (const struct ip6t_rand_info *)match->data;
114         div_t result = div((randinfo->average*100), 255);
115         if (result.rem > 127)  /* round up... */
116                 ++result.quot;
117
118         printf(" random %u%% ", result.quot);
119 }
120
121 /* Saves the union ip6t_targinfo in parsable form to stdout. */
122 static void
123 save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
124 {
125         const struct ip6t_rand_info *randinfo
126                 = (const struct ip6t_rand_info *)match->data;
127         div_t result = div((randinfo->average *100), 255);
128         if (result.rem > 127)  /* round up... */
129                 ++result.quot;
130
131         printf("--average %u ", result.quot);
132 }
133
134 struct ip6tables_match rand_match
135 = { NULL,
136     "random",
137     IPTABLES_VERSION,
138     IP6T_ALIGN(sizeof(struct ip6t_rand_info)),
139     IP6T_ALIGN(sizeof(struct ip6t_rand_info)),
140     &help,
141     &init,
142     &parse,
143     &final_check,
144     &print,
145     &save,
146     opts
147 };
148
149 void _init(void)
150 {
151         register_match6(&rand_match);
152 }