1 /* Shared library add-on to iptables to add string matching support.
3 * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
6 * 27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
7 * Changed --tos to --string in save(). Also
8 * updated to work with slightly modified
19 #include <linux/netfilter_ipv4/ipt_string.h>
22 /* Function which prints out usage message. */
27 "STRING match v%s options:\n"
28 "--string [!] string Match a string in a packet\n"
29 "--hex-string [!] string Match a hex string in a packet\n",
34 static struct option opts[] = {
35 { .name = "string", .has_arg = 1, .flag = 0, .val = '1' },
36 { .name = "hex-string", .has_arg = 1, .flag = 0, .val = '2' },
41 /* Initialize the match. */
43 init(struct ipt_entry_match *m, unsigned int *nfcache)
45 *nfcache |= NFC_UNKNOWN;
50 parse_string(const unsigned char *s, struct ipt_string_info *info)
52 if (strlen(s) <= BM_MAX_NLEN) strcpy(info->string, s);
53 else exit_error(PARAMETER_PROBLEM, "STRING too long `%s'", s);
58 parse_hex_string(const unsigned char *s, struct ipt_string_info *info)
60 int i=0, slen, sindex=0, schar;
61 short hex_f = 0, literal_f = 0;
67 exit_error(PARAMETER_PROBLEM,
68 "STRING must contain at least one char");
72 if (s[i] == '\\' && !hex_f) {
74 } else if (s[i] == '\\') {
75 exit_error(PARAMETER_PROBLEM,
76 "Cannot include literals in hex data");
77 } else if (s[i] == '|') {
85 i++; /* advance to the next character */
90 exit_error(PARAMETER_PROBLEM,
91 "Bad literal placement at end of string");
93 info->string[sindex] = s[i+1];
94 i += 2; /* skip over literal char */
98 exit_error(PARAMETER_PROBLEM,
99 "Odd number of hex digits");
102 /* must end with a "|" */
103 exit_error(PARAMETER_PROBLEM, "Invalid hex block");
105 if (! isxdigit(s[i])) /* check for valid hex char */
106 exit_error(PARAMETER_PROBLEM, "Invalid hex char `%c'", s[i]);
107 if (! isxdigit(s[i+1])) /* check for valid hex char */
108 exit_error(PARAMETER_PROBLEM, "Invalid hex char `%c'", s[i+1]);
112 if (! sscanf(hextmp, "%x", &schar))
113 exit_error(PARAMETER_PROBLEM,
114 "Invalid hex char `%c'", s[i]);
115 info->string[sindex] = (char) schar;
117 i += 3; /* spaces included in the hex block */
120 } else { /* the char is not part of hex data, so just copy */
121 info->string[sindex] = s[i];
124 if (sindex > BM_MAX_NLEN)
125 exit_error(PARAMETER_PROBLEM, "STRING too long `%s'", s);
132 /* Function which parses command options; returns true if it
135 parse(int c, char **argv, int invert, unsigned int *flags,
136 const struct ipt_entry *entry,
137 unsigned int *nfcache,
138 struct ipt_entry_match **match)
140 struct ipt_string_info *stringinfo = (struct ipt_string_info *)(*match)->data;
145 exit_error(PARAMETER_PROBLEM,
146 "Can't specify multiple strings");
148 check_inverse(optarg, &invert, &optind, 0);
149 parse_string(argv[optind-1], stringinfo);
151 stringinfo->invert = 1;
152 stringinfo->len=strlen((char *)&stringinfo->string);
158 exit_error(PARAMETER_PROBLEM,
159 "Can't specify multiple strings");
161 check_inverse(optarg, &invert, &optind, 0);
162 parse_hex_string(argv[optind-1], stringinfo); /* sets length */
164 stringinfo->invert = 1;
175 /* Final check; must have specified --string. */
177 final_check(unsigned int flags)
180 exit_error(PARAMETER_PROBLEM,
181 "STRING match: You must specify `--string'");
185 /* Prints out the matchinfo. */
187 print(const struct ipt_ip *ip,
188 const struct ipt_entry_match *match,
191 const struct ipt_string_info *info =
192 (const struct ipt_string_info*) match->data;
194 printf("STRING match %s%s ", (info->invert) ? "!" : "", info->string);
198 /* Saves the union ipt_matchinfo in parseable form to stdout. */
200 save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
202 const struct ipt_string_info *info =
203 (const struct ipt_string_info*) match->data;
205 printf("--string %s%s ", (info->invert) ? "! ": "", info->string);
209 static struct iptables_match string = {
211 .version = IPTABLES_VERSION,
212 .size = IPT_ALIGN(sizeof(struct ipt_string_info)),
213 .userspacesize = IPT_ALIGN(sizeof(struct ipt_string_info)),
217 .final_check = &final_check,
226 register_match(&string);