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>
12 #include <linux/version.h>
14 #include <linux/tcp.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
)
31 while ((data
< tail
) && (*data
== ' ')) ++data
;
32 while ((tail
> data
) && (*(tail
- 1) == ' ')) --tail
;
47 if (*(text
+ n
) == '$') {
50 if ((dlen
== n
) && (memcmp(data
, text
+ 1, n
) == 0)) {
51 LOG(KERN_INFO
"matched %s\n", text
);
57 if ((dlen
>= n
) && (memcmp(data
, text
+ 1, n
) == 0)) {
58 LOG(KERN_INFO
"matched %s\n", text
);
63 else if (*(text
+ n
- 1) == '$') {
66 if (memcmp(tail
- n
, text
, n
) == 0) {
67 LOG(KERN_INFO
"matched %s\n", text
);
76 if (memcmp(p
, text
, n
) == 0) {
77 LOG(KERN_INFO
"matched %s\n", text
);
89 static inline const char *findend(const char *data
, const char *tail
, int min
)
94 if (*data
== '\r') return data
;
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;
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
;
127 sig
= *(__u32
*)data
;
128 if ((sig
!= __constant_htonl(0x47455420)) && (sig
!= __constant_htonl(0x504f5354))) {
138 // POST / HTTP/1.0$$$$
139 // GET / HTTP/1.0$$$$ -- minimum
140 // 0123456789012345678
142 if (((p
= findend(data
+ 14, tail
, 18)) == NULL
) || (memcmp(p
- 9, " HTTP/", 6) != 0))
145 switch (info
->mode
) {
147 return !info
->invert
;
149 // entire request line, else host line
150 if (find(data
+ 4, p
- 9, info
->text
)) return !info
->invert
;
153 // left side of '?' or entire line
156 while ((q
< p
) && (*q
!= '?')) ++q
;
157 return find(data
, q
, info
->text
) ^ info
->invert
;
159 // right side of '?' or none
162 while ((q
< p
) && (*q
!= '?')) ++q
;
163 if (q
>= p
) return info
->invert
;
164 return find(q
+ 1, p
, info
->text
) ^ info
->invert
;
166 // entire request line
167 return find(data
+ 4, p
- 9, info
->text
) ^ info
->invert
;
173 // else, IPT_WEB_HOST
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
;
188 checkentry(const struct xt_mtchk_param
*par
)
193 static struct xt_match web_match
= {
197 .matchsize
= sizeof(struct ipt_web_info
),
198 .checkentry
= &checkentry
,
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
);