iptables-1.3.2-20050720
[iptables.git] / extensions / libip6t_hl.c
1 /*
2  * IPv6 Hop Limit matching module
3  * Maciej Soltysiak <solt@dns.toxicfilms.tv>
4  * Based on HW's ttl match
5  * This program is released under the terms of GNU GPL
6  * Cleanups by Stephane Ouellette <ouellettes@videotron.ca>
7  */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <getopt.h>
13 #include <ip6tables.h>
14
15 #include <linux/netfilter_ipv6/ip6_tables.h>
16 #include <linux/netfilter_ipv6/ip6t_hl.h>
17
18 static void help(void) 
19 {
20         printf(
21 "HL match v%s options:\n"
22 "  --hl-eq [!] value    Match hop limit value\n"
23 "  --hl-lt value        Match HL < value\n"
24 "  --hl-gt value        Match HL > value\n"
25 , IPTABLES_VERSION);
26 }
27
28 static int parse(int c, char **argv, int invert, unsigned int *flags,
29                 const struct ip6t_entry *entry, unsigned int *nfcache,
30                 struct ip6t_entry_match **match)
31 {
32         struct ip6t_hl_info *info = (struct ip6t_hl_info *) (*match)->data;
33         u_int8_t value;
34
35         check_inverse(optarg, &invert, &optind, 0);
36         value = atoi(argv[optind-1]);
37
38         if (*flags) 
39                 exit_error(PARAMETER_PROBLEM, 
40                                 "Can't specify HL option twice");
41
42         if (!optarg)
43                 exit_error(PARAMETER_PROBLEM,
44                                 "hl: You must specify a value");
45         switch (c) {
46                 case '2':
47                         if (invert)
48                                 info->mode = IP6T_HL_NE;
49                         else
50                                 info->mode = IP6T_HL_EQ;
51
52                         /* is 0 allowed? */
53                         info->hop_limit = value;
54                         *flags = 1;
55
56                         break;
57                 case '3':
58                         if (invert) 
59                                 exit_error(PARAMETER_PROBLEM,
60                                                 "hl: unexpected `!'");
61
62                         info->mode = IP6T_HL_LT;
63                         info->hop_limit = value;
64                         *flags = 1;
65
66                         break;
67                 case '4':
68                         if (invert)
69                                 exit_error(PARAMETER_PROBLEM,
70                                                 "hl: unexpected `!'");
71
72                         info->mode = IP6T_HL_GT;
73                         info->hop_limit = value;
74                         *flags = 1;
75
76                         break;
77                 default:
78                         return 0;
79         }
80
81         return 1;
82 }
83
84 static void final_check(unsigned int flags)
85 {
86         if (!flags) 
87                 exit_error(PARAMETER_PROBLEM,
88                         "HL match: You must specify one of "
89                         "`--hl-eq', `--hl-lt', `--hl-gt'");
90 }
91
92 static void print(const struct ip6t_ip6 *ip, 
93                 const struct ip6t_entry_match *match,
94                 int numeric)
95 {
96         static const char *op[] = {
97                 [IP6T_HL_EQ] = "==",
98                 [IP6T_HL_NE] = "!=",
99                 [IP6T_HL_LT] = "<",
100                 [IP6T_HL_GT] = ">" };
101
102         const struct ip6t_hl_info *info = 
103                 (struct ip6t_hl_info *) match->data;
104
105         printf("HL match HL %s %u ", op[info->mode], info->hop_limit);
106 }
107
108 static void save(const struct ip6t_ip6 *ip, 
109                 const struct ip6t_entry_match *match)
110 {
111         static const char *op[] = {
112                 [IP6T_HL_EQ] = "eq",
113                 [IP6T_HL_NE] = "eq !",
114                 [IP6T_HL_LT] = "lt",
115                 [IP6T_HL_GT] = "gt" };
116
117         const struct ip6t_hl_info *info =
118                 (struct ip6t_hl_info *) match->data;
119
120         printf("--hl-%s %u ", op[info->mode], info->hop_limit);
121 }
122
123 static struct option opts[] = {
124         { .name = "hl",    .has_arg = 1, .flag = 0, .val = '2' },
125         { .name = "hl-eq", .has_arg = 1, .flag = 0, .val = '2' },
126         { .name = "hl-lt", .has_arg = 1, .flag = 0, .val = '3' },
127         { .name = "hl-gt", .has_arg = 1, .flag = 0, .val = '4' },
128         { 0 }
129 };
130
131 static
132 struct ip6tables_match hl = {
133         .name          = "hl",
134         .version       = IPTABLES_VERSION,
135         .size          = IP6T_ALIGN(sizeof(struct ip6t_hl_info)),
136         .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_hl_info)),
137         .help          = &help,
138         .parse         = &parse,
139         .final_check   = &final_check,
140         .print         = &print,
141         .save          = &save,
142         .extra_opts    = opts
143 };
144
145
146 void _init(void) 
147 {
148         register_match6(&hl);
149 }