libxt_TCPMSS.c revision 32b8e61e4e5bd405d9ad07bf9468498dfbb19f9e
1/* Shared library add-on to iptables to add TCPMSS target support.
2 *
3 * Copyright (c) 2000 Marc Boucher
4*/
5#include <stdbool.h>
6#include <stdio.h>
7#include <string.h>
8#include <stdlib.h>
9#include <getopt.h>
10
11#include <xtables.h>
12#include <linux/netfilter/x_tables.h>
13#include <linux/netfilter/xt_TCPMSS.h>
14
15struct mssinfo {
16	struct xt_entry_target t;
17	struct xt_tcpmss_info mss;
18};
19
20static void __TCPMSS_help(int hdrsize)
21{
22	printf(
23"TCPMSS target 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",
26hdrsize);
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	{.name = "set-mss",           .has_arg = true,  .val = '1'},
41	{.name = "clamp-mss-to-pmtu", .has_arg = false, .val = '2'},
42	XT_GETOPT_TABLEEND,
43};
44
45static int __TCPMSS_parse(int c, char **argv, int invert, unsigned int *flags,
46                          const void *entry, struct xt_entry_target **target,
47                          int hdrsize)
48{
49	struct xt_tcpmss_info *mssinfo
50		= (struct xt_tcpmss_info *)(*target)->data;
51
52	switch (c) {
53		unsigned int mssval;
54
55	case '1':
56		if (*flags)
57			xtables_error(PARAMETER_PROBLEM,
58			           "TCPMSS target: Only one option may be specified");
59		if (!xtables_strtoui(optarg, NULL, &mssval,
60		    0, UINT16_MAX - hdrsize))
61			xtables_error(PARAMETER_PROBLEM, "Bad TCPMSS value \"%s\"", optarg);
62
63		mssinfo->mss = mssval;
64		*flags = 1;
65		break;
66
67	case '2':
68		if (*flags)
69			xtables_error(PARAMETER_PROBLEM,
70			           "TCPMSS target: Only one option may be specified");
71		mssinfo->mss = XT_TCPMSS_CLAMP_PMTU;
72		*flags = 1;
73		break;
74
75	default:
76		return 0;
77	}
78
79	return 1;
80}
81
82static int TCPMSS_parse(int c, char **argv, int invert, unsigned int *flags,
83                        const void *entry, struct xt_entry_target **target)
84{
85	return __TCPMSS_parse(c, argv, invert, flags, entry, target, 40);
86}
87
88static int TCPMSS_parse6(int c, char **argv, int invert, unsigned int *flags,
89                         const void *entry, struct xt_entry_target **target)
90{
91	return __TCPMSS_parse(c, argv, invert, flags, entry, target, 60);
92}
93
94static void TCPMSS_check(unsigned int flags)
95{
96	if (!flags)
97		xtables_error(PARAMETER_PROBLEM,
98		           "TCPMSS target: At least one parameter is required");
99}
100
101static void TCPMSS_print(const void *ip, const struct xt_entry_target *target,
102                         int numeric)
103{
104	const struct xt_tcpmss_info *mssinfo =
105		(const struct xt_tcpmss_info *)target->data;
106	if(mssinfo->mss == XT_TCPMSS_CLAMP_PMTU)
107		printf("TCPMSS clamp to PMTU ");
108	else
109		printf("TCPMSS set %u ", mssinfo->mss);
110}
111
112static void TCPMSS_save(const void *ip, const struct xt_entry_target *target)
113{
114	const struct xt_tcpmss_info *mssinfo =
115		(const struct xt_tcpmss_info *)target->data;
116
117	if(mssinfo->mss == XT_TCPMSS_CLAMP_PMTU)
118		printf("--clamp-mss-to-pmtu ");
119	else
120		printf("--set-mss %u ", mssinfo->mss);
121}
122
123static struct xtables_target tcpmss_target = {
124	.family		= NFPROTO_IPV4,
125	.name		= "TCPMSS",
126	.version	= XTABLES_VERSION,
127	.size		= XT_ALIGN(sizeof(struct xt_tcpmss_info)),
128	.userspacesize	= XT_ALIGN(sizeof(struct xt_tcpmss_info)),
129	.help		= TCPMSS_help,
130	.parse		= TCPMSS_parse,
131	.final_check	= TCPMSS_check,
132	.print		= TCPMSS_print,
133	.save		= TCPMSS_save,
134	.extra_opts	= TCPMSS_opts,
135};
136
137static struct xtables_target tcpmss_target6 = {
138	.family		= NFPROTO_IPV6,
139	.name		= "TCPMSS",
140	.version	= XTABLES_VERSION,
141	.size		= XT_ALIGN(sizeof(struct xt_tcpmss_info)),
142	.userspacesize	= XT_ALIGN(sizeof(struct xt_tcpmss_info)),
143	.help		= TCPMSS_help6,
144	.parse		= TCPMSS_parse6,
145	.final_check	= TCPMSS_check,
146	.print		= TCPMSS_print,
147	.save		= TCPMSS_save,
148	.extra_opts	= TCPMSS_opts,
149};
150
151void _init(void)
152{
153	xtables_register_target(&tcpmss_target);
154	xtables_register_target(&tcpmss_target6);
155}
156