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
14struct mssinfo {
15	struct ipt_entry_target t;
16	struct ipt_tcpmss_info mss;
17};
18
19/* Function which prints out usage message. */
20static void
21help(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",
27IPTABLES_VERSION);
28}
29
30static 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. */
37static void
38init(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 */
44static int
45parse(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
81static void
82final_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. */
90static void
91print(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. */
104static void
105save(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
116static
117struct iptables_target mss
118= { NULL,
119    "TCPMSS",
120    IPTABLES_VERSION,
121    IPT_ALIGN(sizeof(struct ipt_tcpmss_info)),
122    IPT_ALIGN(sizeof(struct ipt_tcpmss_info)),
123    &help,
124    &init,
125    &parse,
126    &final_check,
127    &print,
128    &save,
129    opts
130};
131
132void _init(void)
133{
134	register_target(&mss);
135}
136