blob: e08be4890459e83bd130ca10823b41f5e50d6139 [file] [log] [blame]
Rusty Russell2ce6ec62000-08-30 05:49:06 +00001/* Shared library add-on to iptables to add tcp MSS matching support. */
2#include <stdio.h>
3#include <netdb.h>
4#include <string.h>
5#include <stdlib.h>
6#include <getopt.h>
7
Yasuyuki KOZAKAI7999bd32007-07-24 06:57:56 +00008#include <xtables.h>
9#include <linux/netfilter/xt_tcpmss.h>
Rusty Russell2ce6ec62000-08-30 05:49:06 +000010
11/* Function which prints out usage message. */
Jan Engelhardt181dead2007-10-04 16:27:07 +000012static void tcpmss_help(void)
Rusty Russell2ce6ec62000-08-30 05:49:06 +000013{
14 printf(
15"tcpmss match v%s options:\n"
16"[!] --mss value[:value] Match TCP MSS range.\n"
17" (only valid for TCP SYN or SYN/ACK packets)\n",
Harald Welte80fe35d2002-05-29 13:08:15 +000018IPTABLES_VERSION);
Rusty Russell2ce6ec62000-08-30 05:49:06 +000019}
20
Jan Engelhardt181dead2007-10-04 16:27:07 +000021static const struct option tcpmss_opts[] = {
Patrick McHardy500f4832007-09-08 15:59:04 +000022 { "mss", 1, NULL, '1' },
23 { }
Rusty Russell2ce6ec62000-08-30 05:49:06 +000024};
25
Rusty Russell2ce6ec62000-08-30 05:49:06 +000026static u_int16_t
27parse_tcp_mssvalue(const char *mssvalue)
28{
Harald Welteb4719762001-07-23 02:14:22 +000029 unsigned int mssvaluenum;
Rusty Russell2ce6ec62000-08-30 05:49:06 +000030
Harald Welteb4719762001-07-23 02:14:22 +000031 if (string_to_number(mssvalue, 0, 65535, &mssvaluenum) != -1)
Rusty Russell2ce6ec62000-08-30 05:49:06 +000032 return (u_int16_t)mssvaluenum;
33
34 exit_error(PARAMETER_PROBLEM,
35 "Invalid mss `%s' specified", mssvalue);
36}
37
38static void
39parse_tcp_mssvalues(const char *mssvaluestring,
40 u_int16_t *mss_min, u_int16_t *mss_max)
41{
42 char *buffer;
43 char *cp;
44
45 buffer = strdup(mssvaluestring);
46 if ((cp = strchr(buffer, ':')) == NULL)
Rusty Russelld4a8b282000-08-31 11:22:14 +000047 *mss_min = *mss_max = parse_tcp_mssvalue(buffer);
Rusty Russell2ce6ec62000-08-30 05:49:06 +000048 else {
49 *cp = '\0';
50 cp++;
51
Rusty Russelld4a8b282000-08-31 11:22:14 +000052 *mss_min = buffer[0] ? parse_tcp_mssvalue(buffer) : 0;
53 *mss_max = cp[0] ? parse_tcp_mssvalue(cp) : 0xFFFF;
Rusty Russell2ce6ec62000-08-30 05:49:06 +000054 }
55 free(buffer);
56}
57
58/* Function which parses command options; returns true if it
59 ate an option */
60static int
Jan Engelhardt181dead2007-10-04 16:27:07 +000061tcpmss_parse(int c, char **argv, int invert, unsigned int *flags,
62 const void *entry, struct xt_entry_match **match)
Rusty Russell2ce6ec62000-08-30 05:49:06 +000063{
Yasuyuki KOZAKAI7999bd32007-07-24 06:57:56 +000064 struct xt_tcpmss_match_info *mssinfo =
65 (struct xt_tcpmss_match_info *)(*match)->data;
Rusty Russell2ce6ec62000-08-30 05:49:06 +000066
67 switch (c) {
68 case '1':
69 if (*flags)
70 exit_error(PARAMETER_PROBLEM,
71 "Only one `--mss' allowed");
Harald Welteb77f1da2002-03-14 11:35:58 +000072 check_inverse(optarg, &invert, &optind, 0);
Rusty Russell2ce6ec62000-08-30 05:49:06 +000073 parse_tcp_mssvalues(argv[optind-1],
74 &mssinfo->mss_min, &mssinfo->mss_max);
75 if (invert)
76 mssinfo->invert = 1;
77 *flags = 1;
78 break;
79 default:
80 return 0;
81 }
82 return 1;
83}
84
85static void
86print_tcpmss(u_int16_t mss_min, u_int16_t mss_max, int invert, int numeric)
87{
88 if (invert)
89 printf("! ");
90
91 if (mss_min == mss_max)
Harald Weltea713ce02002-09-05 09:51:22 +000092 printf("%u ", mss_min);
Rusty Russell2ce6ec62000-08-30 05:49:06 +000093 else
Harald Weltea713ce02002-09-05 09:51:22 +000094 printf("%u:%u ", mss_min, mss_max);
Rusty Russell2ce6ec62000-08-30 05:49:06 +000095}
96
97/* Final check; must have specified --mss. */
Jan Engelhardt181dead2007-10-04 16:27:07 +000098static void tcpmss_check(unsigned int flags)
Rusty Russell2ce6ec62000-08-30 05:49:06 +000099{
100 if (!flags)
101 exit_error(PARAMETER_PROBLEM,
102 "tcpmss match: You must specify `--mss'");
103}
104
105/* Prints out the matchinfo. */
106static void
Jan Engelhardt181dead2007-10-04 16:27:07 +0000107tcpmss_print(const void *ip, const struct xt_entry_match *match, int numeric)
Rusty Russell2ce6ec62000-08-30 05:49:06 +0000108{
Yasuyuki KOZAKAI7999bd32007-07-24 06:57:56 +0000109 const struct xt_tcpmss_match_info *mssinfo =
110 (const struct xt_tcpmss_match_info *)match->data;
Rusty Russell2ce6ec62000-08-30 05:49:06 +0000111
112 printf("tcpmss match ");
Rusty Russelld4a8b282000-08-31 11:22:14 +0000113 print_tcpmss(mssinfo->mss_min, mssinfo->mss_max,
114 mssinfo->invert, numeric);
Rusty Russell2ce6ec62000-08-30 05:49:06 +0000115}
116
117/* Saves the union ipt_matchinfo in parsable form to stdout. */
Jan Engelhardt181dead2007-10-04 16:27:07 +0000118static void tcpmss_save(const void *ip, const struct xt_entry_match *match)
Rusty Russell2ce6ec62000-08-30 05:49:06 +0000119{
Yasuyuki KOZAKAI7999bd32007-07-24 06:57:56 +0000120 const struct xt_tcpmss_match_info *mssinfo =
121 (const struct xt_tcpmss_match_info *)match->data;
Rusty Russell2ce6ec62000-08-30 05:49:06 +0000122
123 printf("--mss ");
Rusty Russelld4a8b282000-08-31 11:22:14 +0000124 print_tcpmss(mssinfo->mss_min, mssinfo->mss_max,
125 mssinfo->invert, 0);
Rusty Russell2ce6ec62000-08-30 05:49:06 +0000126}
127
Jan Engelhardt181dead2007-10-04 16:27:07 +0000128static struct xtables_match tcpmss_match = {
Yasuyuki KOZAKAI7999bd32007-07-24 06:57:56 +0000129 .family = AF_INET,
Pablo Neira8caee8b2004-12-28 13:11:59 +0000130 .name = "tcpmss",
131 .version = IPTABLES_VERSION,
Yasuyuki KOZAKAI7999bd32007-07-24 06:57:56 +0000132 .size = XT_ALIGN(sizeof(struct xt_tcpmss_match_info)),
133 .userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_match_info)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000134 .help = tcpmss_help,
135 .parse = tcpmss_parse,
136 .final_check = tcpmss_check,
137 .print = tcpmss_print,
138 .save = tcpmss_save,
139 .extra_opts = tcpmss_opts,
Yasuyuki KOZAKAI7999bd32007-07-24 06:57:56 +0000140};
141
Jan Engelhardt181dead2007-10-04 16:27:07 +0000142static struct xtables_match tcpmss_match6 = {
Yasuyuki KOZAKAI7999bd32007-07-24 06:57:56 +0000143 .family = AF_INET6,
144 .name = "tcpmss",
145 .version = IPTABLES_VERSION,
146 .size = XT_ALIGN(sizeof(struct xt_tcpmss_match_info)),
147 .userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_match_info)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000148 .help = tcpmss_help,
149 .parse = tcpmss_parse,
150 .final_check = tcpmss_check,
151 .print = tcpmss_print,
152 .save = tcpmss_save,
153 .extra_opts = tcpmss_opts,
Rusty Russell2ce6ec62000-08-30 05:49:06 +0000154};
155
156void _init(void)
157{
Jan Engelhardt181dead2007-10-04 16:27:07 +0000158 xtables_register_match(&tcpmss_match);
159 xtables_register_match(&tcpmss_match6);
Rusty Russell2ce6ec62000-08-30 05:49:06 +0000160}