libxt_TCPMSS.c revision d09b6d591ca7d7d7575cb6aa20384c9830f777ab
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
76	return 1;
77}
78
79static int TCPMSS_parse(int c, char **argv, int invert, unsigned int *flags,
80                        const void *entry, struct xt_entry_target **target)
81{
82	return __TCPMSS_parse(c, argv, invert, flags, entry, target, 40);
83}
84
85static int TCPMSS_parse6(int c, char **argv, int invert, unsigned int *flags,
86                         const void *entry, struct xt_entry_target **target)
87{
88	return __TCPMSS_parse(c, argv, invert, flags, entry, target, 60);
89}
90
91static void TCPMSS_check(unsigned int flags)
92{
93	if (!flags)
94		xtables_error(PARAMETER_PROBLEM,
95		           "TCPMSS target: At least one parameter is required");
96}
97
98static void TCPMSS_print(const void *ip, const struct xt_entry_target *target,
99                         int numeric)
100{
101	const struct xt_tcpmss_info *mssinfo =
102		(const struct xt_tcpmss_info *)target->data;
103	if(mssinfo->mss == XT_TCPMSS_CLAMP_PMTU)
104		printf("TCPMSS clamp to PMTU ");
105	else
106		printf("TCPMSS set %u ", mssinfo->mss);
107}
108
109static void TCPMSS_save(const void *ip, const struct xt_entry_target *target)
110{
111	const struct xt_tcpmss_info *mssinfo =
112		(const struct xt_tcpmss_info *)target->data;
113
114	if(mssinfo->mss == XT_TCPMSS_CLAMP_PMTU)
115		printf("--clamp-mss-to-pmtu ");
116	else
117		printf("--set-mss %u ", mssinfo->mss);
118}
119
120static struct xtables_target tcpmss_target = {
121	.family		= NFPROTO_IPV4,
122	.name		= "TCPMSS",
123	.version	= XTABLES_VERSION,
124	.size		= XT_ALIGN(sizeof(struct xt_tcpmss_info)),
125	.userspacesize	= XT_ALIGN(sizeof(struct xt_tcpmss_info)),
126	.help		= TCPMSS_help,
127	.parse		= TCPMSS_parse,
128	.final_check	= TCPMSS_check,
129	.print		= TCPMSS_print,
130	.save		= TCPMSS_save,
131	.extra_opts	= TCPMSS_opts,
132};
133
134static struct xtables_target tcpmss_target6 = {
135	.family		= NFPROTO_IPV6,
136	.name		= "TCPMSS",
137	.version	= XTABLES_VERSION,
138	.size		= XT_ALIGN(sizeof(struct xt_tcpmss_info)),
139	.userspacesize	= XT_ALIGN(sizeof(struct xt_tcpmss_info)),
140	.help		= TCPMSS_help6,
141	.parse		= TCPMSS_parse6,
142	.final_check	= TCPMSS_check,
143	.print		= TCPMSS_print,
144	.save		= TCPMSS_save,
145	.extra_opts	= TCPMSS_opts,
146};
147
148void _init(void)
149{
150	xtables_register_target(&tcpmss_target);
151	xtables_register_target(&tcpmss_target6);
152}
153