libxt_TCPMSS.c revision 932e648f38ac16b1ea14c1f66f23951388448c5a
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 <xtables.h>
11#include <linux/netfilter/x_tables.h>
12#include <linux/netfilter/xt_TCPMSS.h>
13
14struct mssinfo {
15	struct xt_entry_target t;
16	struct xt_tcpmss_info mss;
17};
18
19/* Function which prints out usage message. */
20static void __TCPMSS_help(int hdrsize)
21{
22	printf(
23"TCPMSS target v%s mutually-exclusive options:\n"
24"  --set-mss value               explicitly set MSS option to specified value\n"
25"  --clamp-mss-to-pmtu           automatically clamp MSS value to (path_MTU - %d)\n",
26IPTABLES_VERSION, hdrsize);
27}
28
29static void TCPMSS_help(void)
30{
31	__TCPMSS_help(40);
32}
33
34static void TCPMSS_help6(void)
35{
36	__TCPMSS_help(60);
37}
38
39static const struct option TCPMSS_opts[] = {
40	{ "set-mss", 1, NULL, '1' },
41	{ "clamp-mss-to-pmtu", 0, NULL, '2' },
42	{ }
43};
44
45/* Function which parses command options; returns true if it
46   ate an option */
47static int __TCPMSS_parse(int c, char **argv, int invert, unsigned int *flags,
48                          const void *entry, struct xt_entry_target **target,
49                          int hdrsize)
50{
51	struct xt_tcpmss_info *mssinfo
52		= (struct xt_tcpmss_info *)(*target)->data;
53
54	switch (c) {
55		unsigned int mssval;
56
57	case '1':
58		if (*flags)
59			exit_error(PARAMETER_PROBLEM,
60			           "TCPMSS target: Only one option may be specified");
61		if (string_to_number(optarg, 0, 65535 - hdrsize, &mssval) == -1)
62			exit_error(PARAMETER_PROBLEM, "Bad TCPMSS value `%s'", optarg);
63
64		mssinfo->mss = mssval;
65		*flags = 1;
66		break;
67
68	case '2':
69		if (*flags)
70			exit_error(PARAMETER_PROBLEM,
71			           "TCPMSS target: Only one option may be specified");
72		mssinfo->mss = XT_TCPMSS_CLAMP_PMTU;
73		*flags = 1;
74		break;
75
76	default:
77		return 0;
78	}
79
80	return 1;
81}
82
83static int TCPMSS_parse(int c, char **argv, int invert, unsigned int *flags,
84                        const void *entry, struct xt_entry_target **target)
85{
86	return __TCPMSS_parse(c, argv, invert, flags, entry, target, 40);
87}
88
89static int TCPMSS_parse6(int c, char **argv, int invert, unsigned int *flags,
90                         const void *entry, struct xt_entry_target **target)
91{
92	return __TCPMSS_parse(c, argv, invert, flags, entry, target, 60);
93}
94
95static void TCPMSS_check(unsigned int flags)
96{
97	if (!flags)
98		exit_error(PARAMETER_PROBLEM,
99		           "TCPMSS target: At least one parameter is required");
100}
101
102/* Prints out the targinfo. */
103static void TCPMSS_print(const void *ip, const struct xt_entry_target *target,
104                         int numeric)
105{
106	const struct xt_tcpmss_info *mssinfo =
107		(const struct xt_tcpmss_info *)target->data;
108	if(mssinfo->mss == XT_TCPMSS_CLAMP_PMTU)
109		printf("TCPMSS clamp to PMTU ");
110	else
111		printf("TCPMSS set %u ", mssinfo->mss);
112}
113
114/* Saves the union ipt_targinfo in parsable form to stdout. */
115static void TCPMSS_save(const void *ip, const struct xt_entry_target *target)
116{
117	const struct xt_tcpmss_info *mssinfo =
118		(const struct xt_tcpmss_info *)target->data;
119
120	if(mssinfo->mss == XT_TCPMSS_CLAMP_PMTU)
121		printf("--clamp-mss-to-pmtu ");
122	else
123		printf("--set-mss %u ", mssinfo->mss);
124}
125
126static struct xtables_target tcpmss_target = {
127	.family		= AF_INET,
128	.name		= "TCPMSS",
129	.version	= IPTABLES_VERSION,
130	.size		= XT_ALIGN(sizeof(struct xt_tcpmss_info)),
131	.userspacesize	= XT_ALIGN(sizeof(struct xt_tcpmss_info)),
132	.help		= TCPMSS_help,
133	.parse		= TCPMSS_parse,
134	.final_check	= TCPMSS_check,
135	.print		= TCPMSS_print,
136	.save		= TCPMSS_save,
137	.extra_opts	= TCPMSS_opts,
138};
139
140static struct xtables_target tcpmss_target6 = {
141	.family		= AF_INET6,
142	.name		= "TCPMSS",
143	.version	= IPTABLES_VERSION,
144	.size		= XT_ALIGN(sizeof(struct xt_tcpmss_info)),
145	.userspacesize	= XT_ALIGN(sizeof(struct xt_tcpmss_info)),
146	.help		= TCPMSS_help6,
147	.parse		= TCPMSS_parse6,
148	.final_check	= TCPMSS_check,
149	.print		= TCPMSS_print,
150	.save		= TCPMSS_save,
151	.extra_opts	= TCPMSS_opts,
152};
153
154void _init(void)
155{
156	xtables_register_target(&tcpmss_target);
157	xtables_register_target(&tcpmss_target6);
158}
159