7c249152c9303f10a3ba91dc6e42cdc754fda8b8
[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>\n"
28 "  --hl-dec value               Decrement HL by <value>\n"
29 "  --hl-inc value               Increment HL by <value>\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         u_int8_t 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         value = atoi(optarg);
54
55         switch (c) {
56
57                 case '1':
58                         info->mode = IP6T_HL_SET;
59                         break;
60
61                 case '2':
62                         if (value == 0) {
63                                 exit_error(PARAMETER_PROBLEM,
64                                         "HL: decreasing by 0?");
65                         }
66
67                         info->mode = IP6T_HL_DEC;
68                         break;
69
70                 case '3':
71                         if (value == 0) {
72                                 exit_error(PARAMETER_PROBLEM,
73                                         "HL: increasing by 0?");
74                         }
75
76                         info->mode = IP6T_HL_INC;
77                         break;
78
79                 default:
80                         return 0;
81
82         }
83         
84         info->hop_limit = value;
85         *flags |= IP6T_HL_USED;
86
87         return 1;
88 }
89
90 static void final_check(unsigned int flags)
91 {
92         if (!(flags & IP6T_HL_USED))
93                 exit_error(PARAMETER_PROBLEM,
94                                 "HL: You must specify an action");
95 }
96
97 static void save(const struct ip6t_ip6 *ip,
98                 const struct ip6t_entry_target *target)
99 {
100         const struct ip6t_HL_info *info = 
101                 (struct ip6t_HL_info *) target->data;
102
103         switch (info->mode) {
104                 case IP6T_HL_SET:
105                         printf("--hl-set ");
106                         break;
107                 case IP6T_HL_DEC:
108                         printf("--hl-dec ");
109                         break;
110
111                 case IP6T_HL_INC:
112                         printf("--hl-inc ");
113                         break;
114         }
115         printf("%u ", info->hop_limit);
116 }
117
118 static void print(const struct ip6t_ip6 *ip,
119                 const struct ip6t_entry_target *target, int numeric)
120 {
121         const struct ip6t_HL_info *info =
122                 (struct ip6t_HL_info *) target->data;
123
124         printf("HL ");
125         switch (info->mode) {
126                 case IP6T_HL_SET:
127                         printf("set to ");
128                         break;
129                 case IP6T_HL_DEC:
130                         printf("decrement by ");
131                         break;
132                 case IP6T_HL_INC:
133                         printf("increment by ");
134                         break;
135         }
136         printf("%u ", info->hop_limit);
137 }
138
139 static struct option opts[] = {
140         { "hl-set", 1, 0, '1' },
141         { "hl-dec", 1, 0, '2' },
142         { "hl-inc", 1, 0, '3' },
143         { 0 }
144 };
145
146 static
147 struct ip6tables_target HL = { NULL, 
148         "HL",
149         IPTABLES_VERSION,
150         IP6T_ALIGN(sizeof(struct ip6t_HL_info)),
151         IP6T_ALIGN(sizeof(struct ip6t_HL_info)),
152         &help,
153         &init,
154         &parse,
155         &final_check,
156         &print,
157         &save,
158         opts 
159 };
160
161 void _init(void)
162 {
163         register_target6(&HL);
164 }