blob: b812b672c4d1dedfeab43d2211fbca1090f8bdd8 [file] [log] [blame]
Fabrice MARIE147a2be2001-05-02 15:45:57 +00001/* Shared library add-on to iptables to add packet length matching support. */
2#include <stdio.h>
3#include <netdb.h>
4#include <string.h>
5#include <stdlib.h>
6#include <getopt.h>
7
Yasuyuki KOZAKAI36087d92007-07-24 07:15:03 +00008#include <xtables.h>
9#include <linux/netfilter/xt_length.h>
Fabrice MARIE147a2be2001-05-02 15:45:57 +000010
11/* Function which prints out usage message. */
Jan Engelhardt181dead2007-10-04 16:27:07 +000012static void length_help(void)
Fabrice MARIE147a2be2001-05-02 15:45:57 +000013{
14 printf(
15"length v%s options:\n"
16"[!] --length length[:length] Match packet length against value or range\n"
17" of values (inclusive)\n",
Harald Welte80fe35d2002-05-29 13:08:15 +000018IPTABLES_VERSION);
Fabrice MARIE147a2be2001-05-02 15:45:57 +000019
20}
21
Jan Engelhardt181dead2007-10-04 16:27:07 +000022static const struct option length_opts[] = {
Patrick McHardy500f4832007-09-08 15:59:04 +000023 { "length", 1, NULL, '1' },
Max Kellermann9ee386a2008-01-29 13:48:05 +000024 { .name = NULL }
Fabrice MARIE147a2be2001-05-02 15:45:57 +000025};
26
Fabrice MARIE147a2be2001-05-02 15:45:57 +000027static u_int16_t
28parse_length(const char *s)
29{
Harald Welteb4719762001-07-23 02:14:22 +000030 unsigned int len;
Fabrice MARIE147a2be2001-05-02 15:45:57 +000031
Harald Welteb4719762001-07-23 02:14:22 +000032 if (string_to_number(s, 0, 0xFFFF, &len) == -1)
Fabrice MARIE147a2be2001-05-02 15:45:57 +000033 exit_error(PARAMETER_PROBLEM, "length invalid: `%s'\n", s);
34 else
35 return (u_int16_t )len;
36}
37
38/* If a single value is provided, min and max are both set to the value */
39static void
Yasuyuki KOZAKAI36087d92007-07-24 07:15:03 +000040parse_lengths(const char *s, struct xt_length_info *info)
Fabrice MARIE147a2be2001-05-02 15:45:57 +000041{
42 char *buffer;
43 char *cp;
44
45 buffer = strdup(s);
46 if ((cp = strchr(buffer, ':')) == NULL)
47 info->min = info->max = parse_length(buffer);
48 else {
49 *cp = '\0';
50 cp++;
51
52 info->min = buffer[0] ? parse_length(buffer) : 0;
53 info->max = cp[0] ? parse_length(cp) : 0xFFFF;
54 }
55 free(buffer);
56
57 if (info->min > info->max)
58 exit_error(PARAMETER_PROBLEM,
59 "length min. range value `%u' greater than max. "
60 "range value `%u'", info->min, info->max);
61
62}
63
64/* Function which parses command options; returns true if it
65 ate an option */
66static int
Jan Engelhardt181dead2007-10-04 16:27:07 +000067length_parse(int c, char **argv, int invert, unsigned int *flags,
68 const void *entry, struct xt_entry_match **match)
Fabrice MARIE147a2be2001-05-02 15:45:57 +000069{
Yasuyuki KOZAKAI36087d92007-07-24 07:15:03 +000070 struct xt_length_info *info = (struct xt_length_info *)(*match)->data;
Fabrice MARIE147a2be2001-05-02 15:45:57 +000071
72 switch (c) {
73 case '1':
74 if (*flags)
75 exit_error(PARAMETER_PROBLEM,
76 "length: `--length' may only be "
77 "specified once");
Harald Welteb77f1da2002-03-14 11:35:58 +000078 check_inverse(optarg, &invert, &optind, 0);
Fabrice MARIE147a2be2001-05-02 15:45:57 +000079 parse_lengths(argv[optind-1], info);
80 if (invert)
81 info->invert = 1;
82 *flags = 1;
83 break;
84
85 default:
86 return 0;
87 }
88 return 1;
89}
90
91/* Final check; must have specified --length. */
Jan Engelhardt181dead2007-10-04 16:27:07 +000092static void length_check(unsigned int flags)
Fabrice MARIE147a2be2001-05-02 15:45:57 +000093{
94 if (!flags)
95 exit_error(PARAMETER_PROBLEM,
96 "length: You must specify `--length'");
97}
98
99/* Common match printing code. */
100static void
Yasuyuki KOZAKAI36087d92007-07-24 07:15:03 +0000101print_length(struct xt_length_info *info)
Fabrice MARIE147a2be2001-05-02 15:45:57 +0000102{
103 if (info->invert)
Gerry Skerbitzc8c0f402002-12-05 20:37:22 +0000104 printf("! ");
Fabrice MARIE147a2be2001-05-02 15:45:57 +0000105
106 if (info->max == info->min)
107 printf("%u ", info->min);
108 else
109 printf("%u:%u ", info->min, info->max);
110}
111
112/* Prints out the matchinfo. */
113static void
Jan Engelhardt181dead2007-10-04 16:27:07 +0000114length_print(const void *ip, const struct xt_entry_match *match, int numeric)
Fabrice MARIE147a2be2001-05-02 15:45:57 +0000115{
116 printf("length ");
Yasuyuki KOZAKAI36087d92007-07-24 07:15:03 +0000117 print_length((struct xt_length_info *)match->data);
Fabrice MARIE147a2be2001-05-02 15:45:57 +0000118}
119
120/* Saves the union ipt_matchinfo in parsable form to stdout. */
Jan Engelhardt181dead2007-10-04 16:27:07 +0000121static void length_save(const void *ip, const struct xt_entry_match *match)
Fabrice MARIE147a2be2001-05-02 15:45:57 +0000122{
123 printf("--length ");
Yasuyuki KOZAKAI36087d92007-07-24 07:15:03 +0000124 print_length((struct xt_length_info *)match->data);
Fabrice MARIE147a2be2001-05-02 15:45:57 +0000125}
126
Jan Engelhardt181dead2007-10-04 16:27:07 +0000127static struct xtables_match length_match = {
Yasuyuki KOZAKAI36087d92007-07-24 07:15:03 +0000128 .family = AF_INET,
Pablo Neira8caee8b2004-12-28 13:11:59 +0000129 .name = "length",
130 .version = IPTABLES_VERSION,
Yasuyuki KOZAKAI36087d92007-07-24 07:15:03 +0000131 .size = XT_ALIGN(sizeof(struct xt_length_info)),
132 .userspacesize = XT_ALIGN(sizeof(struct xt_length_info)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000133 .help = length_help,
134 .parse = length_parse,
135 .final_check = length_check,
136 .print = length_print,
137 .save = length_save,
138 .extra_opts = length_opts,
Yasuyuki KOZAKAI36087d92007-07-24 07:15:03 +0000139};
140
Jan Engelhardt181dead2007-10-04 16:27:07 +0000141static struct xtables_match length_match6 = {
Yasuyuki KOZAKAI36087d92007-07-24 07:15:03 +0000142 .family = AF_INET6,
143 .name = "length",
144 .version = IPTABLES_VERSION,
145 .size = XT_ALIGN(sizeof(struct xt_length_info)),
146 .userspacesize = XT_ALIGN(sizeof(struct xt_length_info)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000147 .help = length_help,
148 .parse = length_parse,
149 .final_check = length_check,
150 .print = length_print,
151 .save = length_save,
152 .extra_opts = length_opts,
Fabrice MARIE147a2be2001-05-02 15:45:57 +0000153};
154
155void _init(void)
156{
Jan Engelhardt181dead2007-10-04 16:27:07 +0000157 xtables_register_match(&length_match);
158 xtables_register_match(&length_match6);
Fabrice MARIE147a2be2001-05-02 15:45:57 +0000159}