This commit was manufactured by cvs2svn to create branch
[iptables.git] / extensions / libip6t_HL.c
1 /*
2  * IPv6 Hop Limit Target module
3  * Maciej Soltysiak <solt@dns.toxicfilms.tv>
4  * Based on HW's ttl target
5  * This program is distributed under the terms of GNU GPL
6  */
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <getopt.h>
12 #include <ip6tables.h>
13
14 #include <linux/netfilter_ipv6/ip6_tables.h>
15 #include <linux/netfilter_ipv6/ip6t_HL.h>
16
17 #define IP6T_HL_USED    1
18
19 static void init(struct ip6t_entry_target *t, unsigned int *nfcache) 
20 {
21 }
22
23 static void help(void) 
24 {
25         printf(
26 "HL target v%s options\n"
27 "  --hl-set value               Set HL to <value 0-255>\n"
28 "  --hl-dec value               Decrement HL by <value 1-255>\n"
29 "  --hl-inc value               Increment HL by <value 1-255>\n"
30 , IPTABLES_VERSION);
31 }
32
33 static int parse(int c, char **argv, int invert, unsigned int *flags,
34                 const struct ip6t_entry *entry,
35                 struct ip6t_entry_target **target)
36 {
37         struct ip6t_HL_info *info = (struct ip6t_HL_info *) (*target)->data;
38         unsigned int value;
39
40         if (*flags & IP6T_HL_USED) {
41                 exit_error(PARAMETER_PROBLEM, 
42                                 "Can't specify HL option twice");
43         }
44
45         if (!optarg) 
46                 exit_error(PARAMETER_PROBLEM, 
47                                 "HL: You must specify a value");
48
49         if (check_inverse(optarg, &invert, NULL, 0))
50                 exit_error(PARAMETER_PROBLEM,
51                                 "HL: unexpected `!'");
52         
53         if (string_to_number(optarg, 0, 255, &value) == -1)     
54                 exit_error(PARAMETER_PROBLEM,   
55                            "HL: Expected value between 0 and 255");
56
57         switch (c) {
58
59                 case '1':
60                         info->mode = IP6T_HL_SET;
61                         break;
62
63                 case '2':
64                         if (value == 0) {
65                                 exit_error(PARAMETER_PROBLEM,
66                                         "HL: decreasing by 0?");
67                         }
68
69                         info->mode = IP6T_HL_DEC;
70                         break;
71
72                 case '3':
73                         if (value == 0) {
74                                 exit_error(PARAMETER_PROBLEM,
75                                         "HL: increasing by 0?");
76                         }
77
78                         info->mode = IP6T_HL_INC;
79                         break;
80
81                 default:
82                         return 0;
83
84         }
85         
86         info->hop_limit = value;
87         *flags |= IP6T_HL_USED;
88
89         return 1;
90 }
91
92 static void final_check(unsigned int flags)
93 {
94         if (!(flags & IP6T_HL_USED))
95                 exit_error(PARAMETER_PROBLEM,
96                                 "HL: You must specify an action");
97 }
98
99 static void save(const struct ip6t_ip6 *ip,
100                 const struct ip6t_entry_target *target)
101 {
102         const struct ip6t_HL_info *info = 
103                 (struct ip6t_HL_info *) target->data;
104
105         switch (info->mode) {
106                 case IP6T_HL_SET:
107                         printf("--hl-set ");
108                         break;
109                 case IP6T_HL_DEC:
110                         printf("--hl-dec ");
111                         break;
112
113                 case IP6T_HL_INC:
114                         printf("--hl-inc ");
115                         break;
116         }
117         printf("%u ", info->hop_limit);
118 }
119
120 static void print(const struct ip6t_ip6 *ip,
121                 const struct ip6t_entry_target *target, int numeric)
122 {
123         const struct ip6t_HL_info *info =
124                 (struct ip6t_HL_info *) target->data;
125
126         printf("HL ");
127         switch (info->mode) {
128                 case IP6T_HL_SET:
129                         printf("set to ");
130                         break;
131                 case IP6T_HL_DEC:
132                         printf("decrement by ");
133                         break;
134                 case IP6T_HL_INC:
135                         printf("increment by ");
136                         break;
137         }
138         printf("%u ", info->hop_limit);
139 }
140
141 static struct option opts[] = {
142         { "hl-set", 1, 0, '1' },
143         { "hl-dec", 1, 0, '2' },
144         { "hl-inc", 1, 0, '3' },
145         { 0 }
146 };
147
148 static
149 struct ip6tables_target HL = { NULL, 
150         .name           = "HL",
151         .version        = IPTABLES_VERSION,
152         .size           = IP6T_ALIGN(sizeof(struct ip6t_HL_info)),
153         .userspacesize  = IP6T_ALIGN(sizeof(struct ip6t_HL_info)),
154         .help           = &help, 
155         .init           = &init,
156         .parse          = &parse,
157         .final_check    = &final_check,
158         .print          = &print,
159         .save           = &save,
160         .extra_opts     = opts 
161 };
162
163 void _init(void)
164 {
165         register_target6(&HL);
166 }