Tomato 1.28
[tomato.git] / release / src / router / iptables / extensions / libipt_web.c
blob05e744c74cb1b6e166fd8e24e6d1697c38205b4d
1 /*
3 web (experimental)
4 HTTP client match
5 Copyright (C) 2006 Jonathan Zarate
7 Licensed under GNU GPL v2 or later.
9 */
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdlib.h>
13 #include <getopt.h>
15 #include <iptables.h>
16 #include <linux/netfilter_ipv4/ipt_web.h>
19 #undef IPTABLES_SAVE
22 static void help(void)
24 printf(
25 "web match v0.01 (experimental)\n"
26 "Copyright (C) 2006 Jonathan Zarate\n"
27 "Options:\n"
28 "[!] --http (default) find an HTTP GET/POST request\n"
29 "[!] --host <text ...> find in host line\n"
30 "[!] --req <text ...> find in request\n"
31 "[!] --path <text ...> find in request path\n"
32 "[!] --query <text ...> find in request query\n"
33 "[!] --hore <text ...> find in host or request line\n"
34 " <text> can be:\n"
35 " text contains\n"
36 " ^text begins with\n"
37 " text$ ends with\n"
38 " ^text$ exact match\n");
41 static void init(struct ipt_entry_match *m, unsigned int *nfcache)
43 *nfcache |= NFC_UNKNOWN;
46 static struct option opts[] = {
47 { .name = "http", .has_arg = 0, .flag = 0, .val = '1' },
48 { .name = "host", .has_arg = 1, .flag = 0, .val = '2' },
49 { .name = "req", .has_arg = 1, .flag = 0, .val = '3' },
50 { .name = "path", .has_arg = 1, .flag = 0, .val = '4' },
51 { .name = "query", .has_arg = 1, .flag = 0, .val = '5' },
52 { .name = "hore", .has_arg = 1, .flag = 0, .val = '6' },
53 { .name = 0 }
56 static int parse(int c, char **argv, int invert, unsigned int *flags,
57 const struct ipt_entry *entry, unsigned int *nfcache,
58 struct ipt_entry_match **match)
60 const char *s;
61 char *e, *p;
62 int n;
63 struct ipt_web_info *info;
65 if ((c < '1') || (c > '6')) return 0;
67 if (*flags) exit_error(PARAMETER_PROBLEM, "Multiple modes are not supported");
68 *flags = 1;
70 info = (struct ipt_web_info *)(*match)->data;
71 switch (c) {
72 case '2':
73 info->mode = IPT_WEB_HOST;
74 break;
75 case '3':
76 info->mode = IPT_WEB_RURI;
77 break;
78 case '4':
79 info->mode = IPT_WEB_PATH;
80 break;
81 case '5':
82 info->mode = IPT_WEB_QUERY;
83 break;
84 case '6':
85 info->mode = IPT_WEB_HORE;
86 break;
87 default: // IPT_WEB_HTTP
88 return 1;
91 if (entry->ip.proto != IPPROTO_TCP) {
92 exit_error(PARAMETER_PROBLEM, "web match requires -p tcp");
95 check_inverse(optarg, &invert, &optind, 0);
96 if (invert) info->invert = 1;
98 // convert arg to text\0text\0\0
99 s = argv[optind - 1];
101 if ((p = malloc(strlen(s) + 2)) == NULL) {
102 exit_error(PARAMETER_PROBLEM, "Not enough memory");
105 e = p;
106 while (*s) {
107 while ((*s == ' ') || (*s == '\n') || (*s == '\t')) ++s;
108 if (*s == 0) break;
109 while ((*s != 0) && (*s != ' ') && (*s != '\n') && (*s != '\t')) {
110 *e++ = *s++;
112 *e++ = 0;
114 n = (e - p);
116 #if 0
117 *e = 0;
118 e = p;
119 while (*e) {
120 printf("[%s]\n", e);
121 e += strlen(e) + 1;
123 #endif
125 if (n <= 1) {
126 exit_error(PARAMETER_PROBLEM, "Text is too short");
128 if (n >= IPT_WEB_MAXTEXT) {
129 exit_error(PARAMETER_PROBLEM, "Text is too long");
131 memcpy(info->text, p, n);
132 memset(info->text + n, 0, IPT_WEB_MAXTEXT - n); // term, need to clear rest for ipt rule cmp
133 free(p);
134 return 1;
137 static void final_check(unsigned int flags)
141 static void print_match(const struct ipt_web_info *info)
143 const char *text;
145 if (info->invert) printf("! ");
147 switch (info->mode) {
148 case IPT_WEB_HOST:
149 printf("--host");
150 break;
151 case IPT_WEB_RURI:
152 printf("--req");
153 break;
154 case IPT_WEB_PATH:
155 printf("--path");
156 break;
157 case IPT_WEB_QUERY:
158 printf("--query");
159 break;
160 case IPT_WEB_HORE:
161 printf("--hore");
162 break;
163 default:
164 printf("--http");
165 return;
168 text = info->text;
169 printf(" \"");
170 while (*text) {
171 while (*text) {
172 if (*text == '"') printf("\\\"");
173 else putc(*text, stdout);
174 ++text;
176 ++text;
177 if (*text == 0) break;
178 putc(' ', stdout);
180 printf("\" ");
183 static void print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric)
185 printf("web ");
186 print_match((const struct ipt_web_info *)match->data);
189 static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
191 #ifdef IPTABLES_SAVE
192 print_match((const struct ipt_web_info *)match->data);
193 #endif
197 static struct iptables_match web_match = {
198 .name = "web",
199 .version = IPTABLES_VERSION,
200 .size = IPT_ALIGN(sizeof(struct ipt_web_info)),
201 .userspacesize = IPT_ALIGN(sizeof(struct ipt_web_info)),
202 .help = &help,
203 .init = &init,
204 .parse = &parse,
205 .final_check = &final_check,
206 .print = &print,
207 .save = &save,
208 .extra_opts = opts
211 void _init(void)
213 register_match(&web_match);