iptables-1.3.2-20050720
[iptables.git] / extensions / libipt_TCPMSS.c
1 /* Shared library add-on to iptables to add TCPMSS target support.
2  *
3  * Copyright (c) 2000 Marc Boucher
4 */
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <getopt.h>
9
10 #include <iptables.h>
11 #include <linux/netfilter_ipv4/ip_tables.h>
12 #include <linux/netfilter_ipv4/ipt_TCPMSS.h>
13
14 struct mssinfo {
15         struct ipt_entry_target t;
16         struct ipt_tcpmss_info mss;
17 };
18
19 /* Function which prints out usage message. */
20 static void
21 help(void)
22 {
23         printf(
24 "TCPMSS target v%s mutually-exclusive options:\n"
25 "  --set-mss value               explicitly set MSS option to specified value\n"
26 "  --clamp-mss-to-pmtu           automatically clamp MSS value to (path_MTU - 40)\n",
27 IPTABLES_VERSION);
28 }
29
30 static struct option opts[] = {
31         { "set-mss", 1, 0, '1' },
32         { "clamp-mss-to-pmtu", 0, 0, '2' },
33         { 0 }
34 };
35
36 /* Initialize the target. */
37 static void
38 init(struct ipt_entry_target *t, unsigned int *nfcache)
39 {
40 }
41
42 /* Function which parses command options; returns true if it
43    ate an option */
44 static int
45 parse(int c, char **argv, int invert, unsigned int *flags,
46       const struct ipt_entry *entry,
47       struct ipt_entry_target **target)
48 {
49         struct ipt_tcpmss_info *mssinfo
50                 = (struct ipt_tcpmss_info *)(*target)->data;
51
52         switch (c) {
53                 unsigned int mssval;
54
55         case '1':
56                 if (*flags)
57                         exit_error(PARAMETER_PROBLEM,
58                                    "TCPMSS target: Only one option may be specified");
59                 if (string_to_number(optarg, 0, 65535 - 40, &mssval) == -1)
60                         exit_error(PARAMETER_PROBLEM, "Bad TCPMSS value `%s'", optarg);
61                 
62                 mssinfo->mss = mssval;
63                 *flags = 1;
64                 break;
65
66         case '2':
67                 if (*flags)
68                         exit_error(PARAMETER_PROBLEM,
69                                    "TCPMSS target: Only one option may be specified");
70                 mssinfo->mss = IPT_TCPMSS_CLAMP_PMTU;
71                 *flags = 1;
72                 break;
73
74         default:
75                 return 0;
76         }
77
78         return 1;
79 }
80
81 static void
82 final_check(unsigned int flags)
83 {
84         if (!flags)
85                 exit_error(PARAMETER_PROBLEM,
86                            "TCPMSS target: At least one parameter is required");
87 }
88
89 /* Prints out the targinfo. */
90 static void
91 print(const struct ipt_ip *ip,
92       const struct ipt_entry_target *target,
93       int numeric)
94 {
95         const struct ipt_tcpmss_info *mssinfo =
96                 (const struct ipt_tcpmss_info *)target->data;
97         if(mssinfo->mss == IPT_TCPMSS_CLAMP_PMTU)
98                 printf("TCPMSS clamp to PMTU ");
99         else
100                 printf("TCPMSS set %u ", mssinfo->mss);
101 }
102
103 /* Saves the union ipt_targinfo in parsable form to stdout. */
104 static void
105 save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
106 {
107         const struct ipt_tcpmss_info *mssinfo =
108                 (const struct ipt_tcpmss_info *)target->data;
109
110         if(mssinfo->mss == IPT_TCPMSS_CLAMP_PMTU)
111                 printf("--clamp-mss-to-pmtu ");
112         else
113                 printf("--set-mss %u ", mssinfo->mss);
114 }
115
116 static struct iptables_target mss = {
117         .next           = NULL,
118         .name           = "TCPMSS",
119         .version        = IPTABLES_VERSION,
120         .size           = IPT_ALIGN(sizeof(struct ipt_tcpmss_info)),
121         .userspacesize  = IPT_ALIGN(sizeof(struct ipt_tcpmss_info)),
122         .help           = &help,
123         .init           = &init,
124         .parse          = &parse,
125         .final_check    = &final_check,
126         .print          = &print,
127         .save           = &save,
128         .extra_opts     = opts
129 };
130
131 void _init(void)
132 {
133         register_target(&mss);
134 }