GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / net / ipv4 / netfilter / ipt_web.c
blob8379987d31815cd5ebb8756ffc233fe5552a9b1e
1 /*
3 web (experimental)
4 HTTP client request match
5 Copyright (C) 2006 Jonathan Zarate
7 Licensed under GNU GPL v2 or later.
9 */
10 #include <linux/module.h>
11 #include <linux/skbuff.h>
12 #include <linux/version.h>
13 #include <linux/ip.h>
14 #include <linux/tcp.h>
15 #include <net/sock.h>
16 #include <linux/netfilter_ipv4/ip_tables.h>
17 #include <linux/netfilter_ipv4/ipt_web.h>
19 MODULE_AUTHOR("Jonathan Zarate");
20 MODULE_DESCRIPTION("HTTP client request match (experimental)");
21 MODULE_LICENSE("GPL");
23 #define LOG(...) do { } while (0);
25 static int find(const char *data, const char *tail, const char *text)
27 int n, o;
28 int dlen;
29 const char *p, *e;
31 while ((data < tail) && (*data == ' ')) ++data;
32 while ((tail > data) && (*(tail - 1) == ' ')) --tail;
34 dlen = tail - data;
36 // 012345
37 // text
38 // ^text
39 // text$
40 // ^text$
41 // 012345
43 while (*text) {
44 n = o = strlen(text);
45 if (*text == '^') {
46 --n;
47 if (*(text + n) == '$') {
48 // exact
49 --n;
50 if ((dlen == n) && (memcmp(data, text + 1, n) == 0)) {
51 LOG(KERN_INFO "matched %s\n", text);
52 return 1;
55 else {
56 // begins with
57 if ((dlen >= n) && (memcmp(data, text + 1, n) == 0)) {
58 LOG(KERN_INFO "matched %s\n", text);
59 return 1;
63 else if (*(text + n - 1) == '$') {
64 // ends with
65 --n;
66 if (memcmp(tail - n, text, n) == 0) {
67 LOG(KERN_INFO "matched %s\n", text);
68 return 1;
71 else {
72 // contains
73 p = data;
74 e = tail - n;
75 while (p <= e) {
76 if (memcmp(p, text, n) == 0) {
77 LOG(KERN_INFO "matched %s\n", text);
78 return 1;
80 ++p;
84 text += o + 1;
86 return 0;
89 static inline const char *findend(const char *data, const char *tail, int min)
91 int n = tail - data;
92 if (n >= min) {
93 while (data < tail) {
94 if (*data == '\r') return data;
95 ++data;
98 return NULL;
102 static bool
103 match(const struct sk_buff *skb, struct xt_action_param *par)
105 const struct ipt_web_info *info = par->matchinfo;
106 const int offset = par->fragoff;
107 const struct iphdr *iph = ip_hdr(skb);
108 const struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
109 const char *data;
110 const char *tail;
111 const char *p, *q;
112 int doff, dlen;
113 __u32 sig;
115 if (offset != 0) return info->invert;
117 doff = (tcph->doff * 4);
118 data = (void *)tcph + doff;
119 dlen = ntohs(ip_hdr(skb)->tot_len);
121 // POST / HTTP/1.0$$$$
122 // GET / HTTP/1.0$$$$
123 // 1234567890123456789
124 if (dlen < 18) return info->invert;
126 // "GET " or "POST"
127 sig = *(__u32 *)data;
128 if ((sig != __constant_htonl(0x47455420)) && (sig != __constant_htonl(0x504f5354))) {
129 return info->invert;
132 tail = data + dlen;
133 if (dlen > 1024) {
134 dlen = 1024;
135 tail = data + 1024;
138 // POST / HTTP/1.0$$$$
139 // GET / HTTP/1.0$$$$ -- minimum
140 // 0123456789012345678
141 // 9876543210
142 if (((p = findend(data + 14, tail, 18)) == NULL) || (memcmp(p - 9, " HTTP/", 6) != 0))
143 return info->invert;
145 switch (info->mode) {
146 case IPT_WEB_HTTP:
147 return !info->invert;
148 case IPT_WEB_HORE:
149 // entire request line, else host line
150 if (find(data + 4, p - 9, info->text)) return !info->invert;
151 break;
152 case IPT_WEB_PATH:
153 // left side of '?' or entire line
154 q = data += 4;
155 p -= 9;
156 while ((q < p) && (*q != '?')) ++q;
157 return find(data, q, info->text) ^ info->invert;
158 case IPT_WEB_QUERY:
159 // right side of '?' or none
160 q = data + 4;
161 p -= 9;
162 while ((q < p) && (*q != '?')) ++q;
163 if (q >= p) return info->invert;
164 return find(q + 1, p, info->text) ^ info->invert;
165 case IPT_WEB_RURI:
166 // entire request line
167 return find(data + 4, p - 9, info->text) ^ info->invert;
168 default:
169 // shutup compiler
170 break;
173 // else, IPT_WEB_HOST
175 while (1) {
176 data = p + 2; // skip previous \r\n
177 p = findend(data, tail, 8); // p = current line's \r
178 if (p == NULL) return 0;
180 if (memcmp(data, "Host: ", 6) == 0)
181 return find(data + 6, p, info->text) ^ info->invert;
184 return !info->invert;
187 static int
188 checkentry(const struct xt_mtchk_param *par)
190 return 0;
193 static struct xt_match web_match = {
194 .name = "web",
195 .family = AF_INET,
196 .match = &match,
197 .matchsize = sizeof(struct ipt_web_info),
198 .checkentry = &checkentry,
199 .destroy = NULL,
200 .me = THIS_MODULE
203 static int __init init(void)
205 return xt_register_match(&web_match);
208 static void __exit fini(void)
210 xt_unregister_match(&web_match);
213 module_init(init);
214 module_exit(fini);