Sapan says vnet_tun is obsolete.
[iptables.git] / extensions / libxt_tcpmss.c
1 /* Shared library add-on to iptables to add tcp MSS 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_tcpmss.h>
10
11 /* Function which prints out usage message. */
12 static void tcpmss_help(void)
13 {
14         printf(
15 "tcpmss match options:\n"
16 "[!] --mss value[:value]        Match TCP MSS range.\n"
17 "                               (only valid for TCP SYN or SYN/ACK packets)\n");
18 }
19
20 static const struct option tcpmss_opts[] = {
21         { "mss", 1, NULL, '1' },
22         { .name = NULL }
23 };
24
25 static u_int16_t
26 parse_tcp_mssvalue(const char *mssvalue)
27 {
28         unsigned int mssvaluenum;
29
30         if (string_to_number(mssvalue, 0, 65535, &mssvaluenum) != -1)
31                 return (u_int16_t)mssvaluenum;
32
33         exit_error(PARAMETER_PROBLEM,
34                    "Invalid mss `%s' specified", mssvalue);
35 }
36
37 static void
38 parse_tcp_mssvalues(const char *mssvaluestring,
39                     u_int16_t *mss_min, u_int16_t *mss_max)
40 {
41         char *buffer;
42         char *cp;
43
44         buffer = strdup(mssvaluestring);
45         if ((cp = strchr(buffer, ':')) == NULL)
46                 *mss_min = *mss_max = parse_tcp_mssvalue(buffer);
47         else {
48                 *cp = '\0';
49                 cp++;
50
51                 *mss_min = buffer[0] ? parse_tcp_mssvalue(buffer) : 0;
52                 *mss_max = cp[0] ? parse_tcp_mssvalue(cp) : 0xFFFF;
53         }
54         free(buffer);
55 }
56
57 /* Function which parses command options; returns true if it
58    ate an option */
59 static int
60 tcpmss_parse(int c, char **argv, int invert, unsigned int *flags,
61              const void *entry, struct xt_entry_match **match)
62 {
63         struct xt_tcpmss_match_info *mssinfo =
64                 (struct xt_tcpmss_match_info *)(*match)->data;
65
66         switch (c) {
67         case '1':
68                 if (*flags)
69                         exit_error(PARAMETER_PROBLEM,
70                                    "Only one `--mss' allowed");
71                 check_inverse(optarg, &invert, &optind, 0);
72                 parse_tcp_mssvalues(argv[optind-1],
73                                     &mssinfo->mss_min, &mssinfo->mss_max);
74                 if (invert)
75                         mssinfo->invert = 1;
76                 *flags = 1;
77                 break;
78         default:
79                 return 0;
80         }
81         return 1;
82 }
83
84 static void
85 print_tcpmss(u_int16_t mss_min, u_int16_t mss_max, int invert, int numeric)
86 {
87         if (invert)
88                 printf("! ");
89
90         if (mss_min == mss_max)
91                 printf("%u ", mss_min);
92         else
93                 printf("%u:%u ", mss_min, mss_max);
94 }
95
96 /* Final check; must have specified --mss. */
97 static void tcpmss_check(unsigned int flags)
98 {
99         if (!flags)
100                 exit_error(PARAMETER_PROBLEM,
101                            "tcpmss match: You must specify `--mss'");
102 }
103
104 /* Prints out the matchinfo. */
105 static void
106 tcpmss_print(const void *ip, const struct xt_entry_match *match, int numeric)
107 {
108         const struct xt_tcpmss_match_info *mssinfo =
109                 (const struct xt_tcpmss_match_info *)match->data;
110
111         printf("tcpmss match ");
112         print_tcpmss(mssinfo->mss_min, mssinfo->mss_max,
113                      mssinfo->invert, numeric);
114 }
115
116 /* Saves the union ipt_matchinfo in parsable form to stdout. */
117 static void tcpmss_save(const void *ip, const struct xt_entry_match *match)
118 {
119         const struct xt_tcpmss_match_info *mssinfo =
120                 (const struct xt_tcpmss_match_info *)match->data;
121
122         printf("--mss ");
123         print_tcpmss(mssinfo->mss_min, mssinfo->mss_max,
124                      mssinfo->invert, 0);
125 }
126
127 static struct xtables_match tcpmss_match = {
128         .family         = AF_INET,
129         .name           = "tcpmss",
130         .version        = XTABLES_VERSION,
131         .size           = XT_ALIGN(sizeof(struct xt_tcpmss_match_info)),
132         .userspacesize  = XT_ALIGN(sizeof(struct xt_tcpmss_match_info)),
133         .help           = tcpmss_help,
134         .parse          = tcpmss_parse,
135         .final_check    = tcpmss_check,
136         .print          = tcpmss_print,
137         .save           = tcpmss_save,
138         .extra_opts     = tcpmss_opts,
139 };
140
141 static struct xtables_match tcpmss_match6 = {
142         .family         = AF_INET6,
143         .name           = "tcpmss",
144         .version        = XTABLES_VERSION,
145         .size           = XT_ALIGN(sizeof(struct xt_tcpmss_match_info)),
146         .userspacesize  = XT_ALIGN(sizeof(struct xt_tcpmss_match_info)),
147         .help           = tcpmss_help,
148         .parse          = tcpmss_parse,
149         .final_check    = tcpmss_check,
150         .print          = tcpmss_print,
151         .save           = tcpmss_save,
152         .extra_opts     = tcpmss_opts,
153 };
154
155 void _init(void)
156 {
157         xtables_register_match(&tcpmss_match);
158         xtables_register_match(&tcpmss_match6);
159 }