4 HTTP client request match
5 Copyright (C) 2006 Jonathan Zarate
7 Licensed under GNU GPL v2 or later.
10 #include <linux/module.h>
11 #include <linux/skbuff.h>
13 #include <linux/netfilter_ipv4/ip_tables.h>
14 #include <linux/netfilter_ipv4/ipt_web.h>
16 MODULE_AUTHOR("Jonathan Zarate");
17 MODULE_DESCRIPTION("HTTP client request match (experimental)");
18 MODULE_LICENSE("GPL");
22 #define LOG(...) do { } while (0);
25 static int find(const char *data
, const char *tail
, const char *text
)
31 while ((data
< tail
) && (*data
== ' ')) ++data
;
32 while ((tail
> data
) && (*(tail
- 1) == ' ')) --tail
;
41 if (z
> dlen
) z
= dlen
;
44 LOG(KERN_INFO
"find in '%s'\n", tmp
);
59 if (*(text
+ n
) == '$') {
62 if ((dlen
== n
) && (memcmp(data
, text
+ 1, n
) == 0)) {
63 LOG(KERN_INFO
"matched %s\n", text
);
69 if ((dlen
>= n
) && (memcmp(data
, text
+ 1, n
) == 0)) {
70 LOG(KERN_INFO
"matched %s\n", text
);
75 else if (*(text
+ n
- 1) == '$') {
78 if (memcmp(tail
- n
, text
, n
) == 0) {
79 LOG(KERN_INFO
"matched %s\n", text
);
88 if (memcmp(p
, text
, n
) == 0) {
89 LOG(KERN_INFO
"matched %s\n", text
);
101 static inline const char *findend(const char *data
, const char *tail
, int min
)
105 while (data
< tail
) {
106 if (*data
== '\r') return data
;
113 static int match(const struct sk_buff
*skb
, const struct net_device
*in
, const struct net_device
*out
,
114 const void *matchinfo
, int offset
, const void *hdr
, u_int16_t datalen
, int *hotdrop
)
116 const struct ipt_web_info
*info
;
117 const struct tcphdr
*tcph
;
125 if (offset
!= 0) return info
->invert
;
128 doff
= (tcph
->doff
* 4);
129 data
= (char *)tcph
+ doff
;
130 dlen
= datalen
- doff
;
133 printk(KERN_INFO
"datalen=%u dlen=%d doff=%d\n", datalen
, dlen
, doff
);
135 memcpy(tmp
, data
, sizeof(tmp
));
136 tmp
[sizeof(tmp
) - 1] = 0;
137 printk(KERN_INFO
"[%s]\n", tmp
);
140 // POST / HTTP/1.0$$$$
141 // GET / HTTP/1.0$$$$
142 // 1234567890123456789
143 if (dlen
< 18) return info
->invert
;
146 __u32 sig
= *(__u32
*)data
;
147 if ((sig
!= __constant_htonl(0x47455420)) && (sig
!= __constant_htonl(0x504f5354))) {
158 // POST / HTTP/1.0$$$$
159 // GET / HTTP/1.0$$$$ -- minimum
160 // 0123456789012345678
162 if (((p
= findend(data
+ 14, tail
, 18)) == NULL
) || (memcmp(p
- 9, " HTTP/", 6) != 0))
167 const char *qq
= info
->text
;
169 printk(KERN_INFO
"text=%s\n", qq
);
170 qq
+= strlen(qq
) + 1;
175 switch (info
->mode
) {
177 return !info
->invert
;
179 // entire request line, else host line
180 if (find(data
+ 4, p
- 9, info
->text
)) return !info
->invert
;
183 // left side of '?' or entire line
186 while ((q
< p
) && (*q
!= '?')) ++q
;
187 return find(data
, q
, info
->text
) ^ info
->invert
;
189 // right side of '?' or none
192 while ((q
< p
) && (*q
!= '?')) ++q
;
193 if (q
>= p
) return info
->invert
;
194 return find(q
+ 1, p
, info
->text
) ^ info
->invert
;
196 // entire request line
197 return find(data
+ 4, p
- 9, info
->text
) ^ info
->invert
;
203 // else, IPT_WEB_HOST
206 data
= p
+ 2; // skip previous \r\n
207 p
= findend(data
, tail
, 8); // p = current line's \r
208 if (p
== NULL
) return 0;
212 memcpy(tmp
, data
, 32);
214 printk(KERN_INFO
"data=[%s]\n", tmp
);
217 if (memcmp(data
, "Host: ", 6) == 0)
218 return find(data
+ 6, p
, info
->text
) ^ info
->invert
;
221 return !info
->invert
;
224 static int checkentry(const char *tablename
, const struct ipt_ip
*ip
, void *matchinfo
,
225 unsigned int matchsize
, unsigned int hook_mask
)
227 return (matchsize
== IPT_ALIGN(sizeof(struct ipt_web_info
)));
231 static struct ipt_match web_match
232 = { { NULL
, NULL
}, "web", &match
, &checkentry
, NULL
, THIS_MODULE
};
234 static int __init
init(void)
236 // LOG(KERN_INFO "ipt_web <" __DATE__ " " __TIME__ "> loaded\n");
237 return ipt_register_match(&web_match
);
240 static void __exit
fini(void)
242 ipt_unregister_match(&web_match
);