Sapan says vnet_tun is obsolete.
[iptables.git] / extensions / libxt_length.c
1 /* Shared library add-on to iptables to add packet length matching support. */
2 #include <stdio.h>
3 #include <netdb.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <getopt.h>
7
8 #include <xtables.h>
9 #include <linux/netfilter/xt_length.h>
10
11 /* Function which prints out usage message. */
12 static void length_help(void)
13 {
14         printf(
15 "length match options:\n"
16 "[!] --length length[:length]    Match packet length against value or range\n"
17 "                                of values (inclusive)\n");
18 }
19   
20 static const struct option length_opts[] = {
21         { "length", 1, NULL, '1' },
22         { .name = NULL }
23 };
24
25 static u_int16_t
26 parse_length(const char *s)
27 {
28         unsigned int len;
29         
30         if (string_to_number(s, 0, 0xFFFF, &len) == -1)
31                 exit_error(PARAMETER_PROBLEM, "length invalid: `%s'\n", s);
32         else
33                 return (u_int16_t )len;
34 }
35
36 /* If a single value is provided, min and max are both set to the value */
37 static void
38 parse_lengths(const char *s, struct xt_length_info *info)
39 {
40         char *buffer;
41         char *cp;
42
43         buffer = strdup(s);
44         if ((cp = strchr(buffer, ':')) == NULL)
45                 info->min = info->max = parse_length(buffer);
46         else {
47                 *cp = '\0';
48                 cp++;
49
50                 info->min = buffer[0] ? parse_length(buffer) : 0;
51                 info->max = cp[0] ? parse_length(cp) : 0xFFFF;
52         }
53         free(buffer);
54         
55         if (info->min > info->max)
56                 exit_error(PARAMETER_PROBLEM,
57                            "length min. range value `%u' greater than max. "
58                            "range value `%u'", info->min, info->max);
59         
60 }
61
62 /* Function which parses command options; returns true if it
63    ate an option */
64 static int
65 length_parse(int c, char **argv, int invert, unsigned int *flags,
66              const void *entry, struct xt_entry_match **match)
67 {
68         struct xt_length_info *info = (struct xt_length_info *)(*match)->data;
69
70         switch (c) {
71                 case '1':
72                         if (*flags)
73                                 exit_error(PARAMETER_PROBLEM,
74                                            "length: `--length' may only be "
75                                            "specified once");
76                         check_inverse(optarg, &invert, &optind, 0);
77                         parse_lengths(argv[optind-1], info);
78                         if (invert)
79                                 info->invert = 1;
80                         *flags = 1;
81                         break;
82                         
83                 default:
84                         return 0;
85         }
86         return 1;
87 }
88
89 /* Final check; must have specified --length. */
90 static void length_check(unsigned int flags)
91 {
92         if (!flags)
93                 exit_error(PARAMETER_PROBLEM,
94                            "length: You must specify `--length'");
95 }
96
97 /* Common match printing code. */
98 static void
99 print_length(struct xt_length_info *info)
100 {
101         if (info->invert)
102                 printf("! ");
103         
104         if (info->max == info->min)
105                 printf("%u ", info->min);
106         else
107                 printf("%u:%u ", info->min, info->max);
108 }
109
110 /* Prints out the matchinfo. */
111 static void
112 length_print(const void *ip, const struct xt_entry_match *match, int numeric)
113 {
114         printf("length ");
115         print_length((struct xt_length_info *)match->data);
116 }
117
118 /* Saves the union ipt_matchinfo in parsable form to stdout. */
119 static void length_save(const void *ip, const struct xt_entry_match *match)
120 {
121         printf("--length ");
122         print_length((struct xt_length_info *)match->data);
123 }
124
125 static struct xtables_match length_match = {
126         .family         = AF_UNSPEC,
127         .name           = "length",
128         .version        = XTABLES_VERSION,
129         .size           = XT_ALIGN(sizeof(struct xt_length_info)),
130         .userspacesize  = XT_ALIGN(sizeof(struct xt_length_info)),
131         .help           = length_help,
132         .parse          = length_parse,
133         .final_check    = length_check,
134         .print          = length_print,
135         .save           = length_save,
136         .extra_opts     = length_opts,
137 };
138
139 void _init(void)
140 {
141         xtables_register_match(&length_match);
142 }