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