• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/net/netfilter/
1/* Kernel module to match a string into a packet.
2 *
3 * Copyright (C) 2000 Emmanuel Roger  <winfield@freegates.be>
4 *
5 * ChangeLog
6 *	19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
7 *		Fixed SMP re-entrancy problem using per-cpu data areas
8 *		for the skip/shift tables.
9 *	02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
10 *		Fixed kernel panic, due to overrunning boyer moore string
11 *		tables. Also slightly tweaked heuristic for deciding what
12 * 		search algo to use.
13 * 	27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
14 * 		Implemented Boyer Moore Sublinear search algorithm
15 * 		alongside the existing linear search based on memcmp().
16 * 		Also a quick check to decide which method to use on a per
17 * 		packet basis.
18 */
19
20/* Kernel module to match a http header string into a packet.
21 *
22 * Copyright (C) 2003, CyberTAN Corporation
23 * All Rights Reserved.
24 *
25 * Description:
26 *   This is kernel module for web content inspection. It was derived from
27 *   'string' match module, declared as above.
28 *
29 *   The module follows the Netfilter framework, called extended packet
30 *   matching modules.
31 */
32
33/* Linux Kernel 2.6 Port ( 2.4 ipt-> 2.6 xt)
34 * Copyright (C) 2008, Ralink Technology Corporation.
35 * All Rights Reserved.
36 */
37
38#include <linux/module.h>
39#include <linux/skbuff.h>
40#include <linux/netfilter/x_tables.h>
41#include <linux/ip.h>
42#include <linux/ipv6.h>
43#include <linux/tcp.h>
44#include <net/sock.h>
45
46#define BM_MAX_NLEN 256
47#define BM_MAX_HLEN 1024
48
49#define BLK_JAVA        0x01
50#define BLK_ACTIVE      0x02
51#define BLK_COOKIE      0x04
52#define BLK_PROXY       0x08
53
54typedef char *(*proc_ipt_search) (char *, char *, int, int);
55
56struct ipt_webstr_info {
57    char string[BM_MAX_NLEN];
58    u_int16_t invert;
59    u_int16_t len;
60    u_int8_t type;
61};
62
63enum xt_webstr_type
64{
65    IPT_WEBSTR_HOST,
66    IPT_WEBSTR_URL,
67    IPT_WEBSTR_CONTENT
68};
69
70
71#define	isdigit(x) ((x) >= '0' && (x) <= '9')
72#define	isupper(x) (((unsigned)(x) >= 'A') && ((unsigned)(x) <= 'Z'))
73#define	islower(x) (((unsigned)(x) >= 'a') && ((unsigned)(x) <= 'z'))
74#define	isalpha(x) (isupper(x) || islower(x))
75#define	toupper(x) (isupper(x) ? (x) : (x) - 'a' + 'A')
76#define tolower(x) (isupper(x) ? ((x) - 'A' + 'a') : (x))
77
78#define split(word, wordlist, next, delim) \
79    for (next = wordlist, \
80	strncpy(word, next, sizeof(word)), \
81	word[(next=strstr(next, delim)) ? strstr(word, delim) - word : sizeof(word) - 1] = '\0', \
82	next = next ? next + sizeof(delim) - 1 : NULL ; \
83	strlen(word); \
84	next = next ? : "", \
85	strncpy(word, next, sizeof(word)), \
86	word[(next=strstr(next, delim)) ? strstr(word, delim) - word : sizeof(word) - 1] = '\0', \
87	next = next ? next + sizeof(delim) - 1 : NULL)
88
89#define BUFSIZE 	1024
90
91/* Flags for get_http_info() */
92#define HTTP_HOST	0x01
93#define HTTP_URL	0x02
94/* Flags for mangle_http_header() */
95#define HTTP_COOKIE	0x04
96
97#if 0
98#define SPARQ_LOG       printk
99#else
100#define SPARQ_LOG(format, args...)
101#endif
102
103typedef struct httpinfo {
104    char host[BUFSIZE + 1];
105    int hostlen;
106    char url[BUFSIZE + 1];
107    int urllen;
108} httpinfo_t;
109
110/* Return 1 for match, 0 for accept, -1 for partial. */
111static int find_pattern2(const char *data, size_t dlen,
112	const char *pattern, size_t plen,
113	char term,
114	unsigned int *numoff,
115	unsigned int *numlen)
116{
117    size_t i, j, k;
118    int state = 0;
119    *numoff = *numlen = 0;
120
121    SPARQ_LOG("%s: pattern = '%s', dlen = %u\n",__FUNCTION__, pattern, dlen);
122    if (dlen == 0)
123	return 0;
124
125    if (dlen <= plen) {	/* Short packet: try for partial? */
126	if (strnicmp(data, pattern, dlen) == 0)
127	    return -1;
128	else
129	    return 0;
130    }
131    for (i = 0; i <= (dlen - plen); i++) {
132	/* DFA : \r\n\r\n :: 1234 */
133	if (*(data + i) == '\r') {
134	    if (!(state % 2)) state++;	/* forwarding move */
135	    else state = 0;		/* reset */
136	}
137	else if (*(data + i) == '\n') {
138	    if (state % 2) state++;
139	    else state = 0;
140	}
141	else state = 0;
142
143	if (state >= 4)
144	    break;
145
146	/* pattern compare */
147	if (memcmp(data + i, pattern, plen ) != 0)
148	    continue;
149
150	/* Here, it means patten match!! */
151	*numoff=i + plen;
152	for (j = *numoff, k = 0; data[j] != term; j++, k++)
153	    if (j > dlen) return -1 ;	/* no terminal char */
154
155	*numlen = k;
156	return 1;
157    }
158    return 0;
159}
160
161#if 0
162static int mangle_http_header(const struct sk_buff *skb, int flags)
163{
164    struct iphdr *iph = (skb)->nh.iph;
165    struct tcphdr *tcph = (void *)iph + iph->ihl*4;
166    unsigned char *data = (void *)tcph + tcph->doff*4;
167    unsigned int datalen = (skb)->len - (iph->ihl*4) - (tcph->doff*4);
168
169    int found, offset, len;
170    int ret = 0;
171
172
173    SPARQ_LOG("%s: seq=%u\n", __FUNCTION__, ntohl(tcph->seq));
174
175    /* Basic checking, is it HTTP packet? */
176    if (datalen < 10)
177	return ret;	/* Not enough length, ignore it */
178    if (memcmp(data, "GET ", sizeof("GET ") - 1) != 0 &&
179        memcmp(data, "POST ", sizeof("POST ") - 1) != 0 &&
180        memcmp(data, "HEAD ", sizeof("HEAD ") - 1) != 0) //zg add 2006.09.28 for cdrouter3.3 item 186(cdrouter_urlfilter_15)
181	return ret;	/* Pass it */
182
183    /* COOKIE modification */
184    if (flags & HTTP_COOKIE) {
185	found = find_pattern2(data, datalen, "Cookie: ",
186		sizeof("Cookie: ")-1, '\r', &offset, &len);
187	if (found) {
188	    char c;
189	    offset -= (sizeof("Cookie: ") - 1);
190	    /* Swap the 2rd and 4th bit */
191	    c = *(data + offset + 2) ;
192	    *(data + offset + 2) = *(data + offset + 4) ;
193	    *(data + offset + 4) = c ;
194	    ret++;
195	}
196    }
197
198    return ret;
199}
200#endif
201
202static int get_http_info(const struct sk_buff *skb, int flags, httpinfo_t *info)
203{
204    struct iphdr *iph = ip_hdr(skb);
205    struct tcphdr *tcph = (void *)iph + iph->ihl*4;
206    unsigned char *data = (void *)tcph + tcph->doff*4;
207    unsigned int datalen = (skb)->len - (iph->ihl*4) - (tcph->doff*4);
208
209    int found, offset;
210    int hostlen, pathlen;
211    int ret = 0;
212
213
214    SPARQ_LOG("%s: seq=%u\n", __FUNCTION__, ntohl(tcph->seq));
215
216    /* Basic checking, is it HTTP packet? */
217    if (datalen < 10)
218	return ret;	/* Not enough length, ignore it */
219    if (memcmp(data, "GET ", sizeof("GET ") - 1) != 0 &&
220        memcmp(data, "POST ", sizeof("POST ") - 1) != 0 &&
221        memcmp(data, "HEAD ", sizeof("HEAD ") - 1) != 0) //zg add 2006.09.28 for cdrouter3.3 item 186(cdrouter_urlfilter_15)
222	return ret;	/* Pass it */
223
224    if (!(flags & (HTTP_HOST | HTTP_URL)))
225	return ret;
226
227    /* find the 'Host: ' value */
228    found = find_pattern2(data, datalen, "Host: ",
229	    sizeof("Host: ") - 1, '\r', &offset, &hostlen);
230    SPARQ_LOG("Host found=%d\n", found);
231
232    if (!found || !hostlen)
233	return ret;
234
235    ret++;	/* Host found, increase the return value */
236    hostlen = (hostlen < BUFSIZE) ? hostlen : BUFSIZE;
237    strncpy(info->host, data + offset, hostlen);
238    *(info->host + hostlen) = 0;		/* null-terminated */
239    info->hostlen = hostlen;
240    SPARQ_LOG("HOST=%s, hostlen=%d\n", info->host, info->hostlen);
241
242    if (!(flags & HTTP_URL))
243	return ret;
244
245    /* find the 'GET ' or 'POST ' or 'HEAD ' value */
246    found = find_pattern2(data, datalen, "GET ",
247	    sizeof("GET ") - 1, '\r', &offset, &pathlen);
248    if (!found)
249	found = find_pattern2(data, datalen, "POST ",
250		sizeof("POST ") - 1, '\r', &offset, &pathlen);
251    /******* zg add 2006.09.28 for cdrouter3.3 item 186(cdrouter_urlfilter_15) ******/
252    if (!found)
253        found = find_pattern2(data, datalen, "HEAD ",
254                sizeof("HEAD ") - 1, '\r', &offset, &pathlen);
255    /************************* zg end 2006.09.28 ****************************/
256    SPARQ_LOG("GET/POST found=%d\n", found);
257
258    if (!found || (pathlen -= (sizeof(" HTTP/x.x") - 1)) <= 0)/* ignor this field */
259	return ret;
260
261    ret++;	/* GET/POST/HEAD found, increase the return value */
262    pathlen = ((pathlen + hostlen) < BUFSIZE) ? pathlen : BUFSIZE - hostlen;
263    strncpy(info->url, info->host, hostlen);
264    strncpy(info->url + hostlen, data + offset, pathlen);
265    *(info->url + hostlen + pathlen) = 0;	/* null-terminated */
266    info->urllen = hostlen + pathlen;
267    SPARQ_LOG("URL=%s, urllen=%d\n", info->url, info->urllen);
268
269    return ret;
270}
271
272static int get_http_info6(const struct sk_buff *skb, int flags, httpinfo_t *info)
273{
274    struct ipv6hdr *ip6h = ipv6_hdr(skb);
275    struct tcphdr *tcph = tcp_hdr(skb);
276    unsigned char *data = (void *)tcph + tcph->doff*4;
277    unsigned int datalen = ntohs(ip6h->payload_len);
278
279    int found, offset;
280    int hostlen, pathlen;
281    int ret = 0;
282
283
284    SPARQ_LOG("%s: seq=%u\n", __FUNCTION__, ntohl(tcph->seq));
285
286    /* Basic checking, is it HTTP packet? */
287    if (datalen < 10)
288	return ret;	/* Not enough length, ignore it */
289    if (memcmp(data, "GET ", sizeof("GET ") - 1) != 0 &&
290        memcmp(data, "POST ", sizeof("POST ") - 1) != 0 &&
291        memcmp(data, "HEAD ", sizeof("HEAD ") - 1) != 0) //zg add 2006.09.28 for cdrouter3.3 item 186(cdrouter_urlfilter_15)
292	return ret;	/* Pass it */
293
294    if (!(flags & (HTTP_HOST | HTTP_URL)))
295	return ret;
296
297    /* find the 'Host: ' value */
298    found = find_pattern2(data, datalen, "Host: ",
299	    sizeof("Host: ") - 1, '\r', &offset, &hostlen);
300    SPARQ_LOG("Host found=%d\n", found);
301
302    if (!found || !hostlen)
303	return ret;
304
305    ret++;	/* Host found, increase the return value */
306    hostlen = (hostlen < BUFSIZE) ? hostlen : BUFSIZE;
307    strncpy(info->host, data + offset, hostlen);
308    *(info->host + hostlen) = 0;		/* null-terminated */
309    info->hostlen = hostlen;
310    SPARQ_LOG("HOST=%s, hostlen=%d\n", info->host, info->hostlen);
311
312    if (!(flags & HTTP_URL))
313	return ret;
314
315    /* find the 'GET ' or 'POST ' or 'HEAD ' value */
316    found = find_pattern2(data, datalen, "GET ",
317	    sizeof("GET ") - 1, '\r', &offset, &pathlen);
318    if (!found)
319	found = find_pattern2(data, datalen, "POST ",
320		sizeof("POST ") - 1, '\r', &offset, &pathlen);
321    /******* zg add 2006.09.28 for cdrouter3.3 item 186(cdrouter_urlfilter_15) ******/
322    if (!found)
323        found = find_pattern2(data, datalen, "HEAD ",
324                sizeof("HEAD ") - 1, '\r', &offset, &pathlen);
325    /************************* zg end 2006.09.28 ****************************/
326    SPARQ_LOG("GET/POST found=%d\n", found);
327
328    if (!found || (pathlen -= (sizeof(" HTTP/x.x") - 1)) <= 0)/* ignor this field */
329	return ret;
330
331    ret++;	/* GET/POST/HEAD found, increase the return value */
332    pathlen = ((pathlen + hostlen) < BUFSIZE) ? pathlen : BUFSIZE - hostlen;
333    strncpy(info->url, info->host, hostlen);
334    strncpy(info->url + hostlen, data + offset, pathlen);
335    *(info->url + hostlen + pathlen) = 0;	/* null-terminated */
336    info->urllen = hostlen + pathlen;
337    SPARQ_LOG("URL=%s, urllen=%d\n", info->url, info->urllen);
338
339    return ret;
340}
341
342/* Linear string search based on memcmp() */
343static char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len)
344{
345	char *k = haystack + (haystack_len-needle_len);
346	char *t = haystack;
347
348	SPARQ_LOG("%s: haystack=%s, needle=%s\n", __FUNCTION__, t, needle);
349	for(; t <= k; t++) {
350		//SPARQ_LOG("%s: haystack=%s, needle=%s\n", __FUNCTION__, t, needle);
351		if (strnicmp(t, needle, needle_len) == 0) return t;
352		//if ( memcmp(t, needle, needle_len) == 0 ) return t;
353	}
354
355	return NULL;
356}
357
358
359static bool match(const struct sk_buff *skb, struct xt_action_param *par)
360{
361	const struct ipt_webstr_info *info = par->matchinfo;
362	struct iphdr *ip = ip_hdr(skb);
363	proc_ipt_search search=search_linear;
364
365	char token[] = "<&nbsp;>";
366	char *wordlist = (char *)&info->string;
367	httpinfo_t htinfo;
368	int flags = 0;
369	int found = 0;
370	long int opt = 0;
371
372
373	if (!ip || info->len < 1)
374	    return 0;
375
376	SPARQ_LOG("\n************************************************\n"
377		"%s: type=%s\n", __FUNCTION__, (info->type == IPT_WEBSTR_URL)
378		? "IPT_WEBSTR_URL"  : (info->type == IPT_WEBSTR_HOST)
379		? "IPT_WEBSTR_HOST" : "IPT_WEBSTR_CONTENT" );
380
381	/* Determine the flags value for get_http_info(), and mangle packet
382	 * if needed. */
383	switch(info->type)
384	{
385	    case IPT_WEBSTR_URL:	/* fall through */
386		flags |= HTTP_URL;
387
388	    case IPT_WEBSTR_HOST:
389		flags |= HTTP_HOST;
390		break;
391
392	    case IPT_WEBSTR_CONTENT:
393		opt = simple_strtol(wordlist, (char **)NULL, 10);
394		SPARQ_LOG("%s: string=%s, opt=%#lx\n", __FUNCTION__, wordlist, opt);
395
396		if (opt & (BLK_JAVA | BLK_ACTIVE | BLK_PROXY))
397		    flags |= HTTP_URL;
398		if (opt & BLK_PROXY)
399		    flags |= HTTP_HOST;
400#if 0
401		// Could we modify the packet payload in a "match" module?  --YY@Ralink
402		if (opt & BLK_COOKIE)
403		    mangle_http_header(skb, HTTP_COOKIE);
404#endif
405		break;
406
407	    default:
408		printk("%s: Sorry! Cannot find this match option.\n", __FILE__);
409		return 0;
410	}
411
412	/* Get the http header info */
413	if (get_http_info(skb, flags, &htinfo) < 1)
414	    return 0;
415
416	/* Check if the http header content contains the forbidden keyword */
417	if (info->type == IPT_WEBSTR_HOST || info->type == IPT_WEBSTR_URL) {
418	    int nlen = 0, hlen = 0;
419	    char needle[BUFSIZE], *haystack = NULL;
420	    char *next;
421
422	    if (info->type == IPT_WEBSTR_HOST) {
423		haystack = htinfo.host;
424		hlen = htinfo.hostlen;
425	    }
426	    else {
427		haystack = htinfo.url;
428		hlen = htinfo.urllen;
429	    }
430	    split(needle, wordlist, next, token) {
431		nlen = strlen(needle);
432		SPARQ_LOG("keyword=%s, nlen=%d, hlen=%d\n", needle, nlen, hlen);
433		if (!nlen || !hlen || nlen > hlen) continue;
434		if (search(needle, haystack, nlen, hlen) != NULL) {
435		    found = 1;
436		    break;
437		}
438	    }
439	}
440	else {		/* IPT_WEBSTR_CONTENT */
441	    int vicelen;
442
443	    if (opt & BLK_JAVA) {
444		vicelen = sizeof(".js") - 1;
445		if (strnicmp(htinfo.url + htinfo.urllen - vicelen, ".js", vicelen) == 0) {
446		    SPARQ_LOG("%s: MATCH....java\n", __FUNCTION__);
447		    found = 1;
448		    goto match_ret;
449		}
450		vicelen = sizeof(".class") - 1;
451		if (strnicmp(htinfo.url + htinfo.urllen - vicelen, ".class", vicelen) == 0) {
452		    SPARQ_LOG("%s: MATCH....java\n", __FUNCTION__);
453		    found = 1;
454		    goto match_ret;
455		}
456	    }
457	    if (opt & BLK_ACTIVE){
458		vicelen = sizeof(".ocx") - 1;
459		if (strnicmp(htinfo.url + htinfo.urllen - vicelen, ".ocx", vicelen) == 0) {
460		    SPARQ_LOG("%s: MATCH....activex\n", __FUNCTION__);
461		    found = 1;
462		    goto match_ret;
463		}
464		vicelen = sizeof(".cab") - 1;
465		if (strnicmp(htinfo.url + htinfo.urllen - vicelen, ".cab", vicelen) == 0) {
466		    SPARQ_LOG("%s: MATCH....activex\n", __FUNCTION__);
467		    found = 1;
468		    goto match_ret;
469		}
470	    }
471	    if (opt & BLK_PROXY){
472		if (strnicmp(htinfo.url + htinfo.hostlen, "http://", sizeof("http://") - 1) == 0) {
473		    SPARQ_LOG("%s: MATCH....proxy\n", __FUNCTION__);
474		    found = 1;
475		    goto match_ret;
476		}
477	    }
478	}
479
480match_ret:
481	SPARQ_LOG("%s: Verdict =======> %s \n",__FUNCTION__
482		, found ? "DROP" : "ACCEPT");
483
484	return (found ^ info->invert);
485}
486
487static bool match6(const struct sk_buff *skb, struct xt_action_param *par)
488{
489	const struct ipt_webstr_info *info = par->matchinfo;
490	struct ipv6hdr *ip6 = ipv6_hdr(skb);
491	proc_ipt_search search=search_linear;
492
493	char token[] = "<&nbsp;>";
494	char *wordlist = (char *)&info->string;
495	httpinfo_t htinfo;
496	int flags = 0;
497	int found = 0;
498	long int opt = 0;
499
500
501	if (!ip6 || info->len < 1)
502	    return 0;
503
504	SPARQ_LOG("\n************************************************\n"
505		"%s: type=%s\n", __FUNCTION__, (info->type == IPT_WEBSTR_URL)
506		? "IPT_WEBSTR_URL"  : (info->type == IPT_WEBSTR_HOST)
507		? "IPT_WEBSTR_HOST" : "IPT_WEBSTR_CONTENT" );
508
509	/* Determine the flags value for get_http_info(), and mangle packet
510	 * if needed. */
511	switch(info->type)
512	{
513	    case IPT_WEBSTR_URL:	/* fall through */
514		flags |= HTTP_URL;
515
516	    case IPT_WEBSTR_HOST:
517		flags |= HTTP_HOST;
518		break;
519
520	    case IPT_WEBSTR_CONTENT:
521		opt = simple_strtol(wordlist, (char **)NULL, 10);
522		SPARQ_LOG("%s: string=%s, opt=%#lx\n", __FUNCTION__, wordlist, opt);
523
524		if (opt & (BLK_JAVA | BLK_ACTIVE | BLK_PROXY))
525		    flags |= HTTP_URL;
526		if (opt & BLK_PROXY)
527		    flags |= HTTP_HOST;
528		break;
529
530	    default:
531		printk("%s: Sorry! Cannot find this match option.\n", __FILE__);
532		return 0;
533	}
534
535	/* Get the http header info */
536	if (get_http_info6(skb, flags, &htinfo) < 1)
537	    return 0;
538
539	/* Check if the http header content contains the forbidden keyword */
540	if (info->type == IPT_WEBSTR_HOST || info->type == IPT_WEBSTR_URL) {
541	    int nlen = 0, hlen = 0;
542	    char needle[BUFSIZE], *haystack = NULL;
543	    char *next;
544
545	    if (info->type == IPT_WEBSTR_HOST) {
546		haystack = htinfo.host;
547		hlen = htinfo.hostlen;
548	    }
549	    else {
550		haystack = htinfo.url;
551		hlen = htinfo.urllen;
552	    }
553	    split(needle, wordlist, next, token) {
554		nlen = strlen(needle);
555		SPARQ_LOG("keyword=%s, nlen=%d, hlen=%d\n", needle, nlen, hlen);
556		if (!nlen || !hlen || nlen > hlen) continue;
557		if (search(needle, haystack, nlen, hlen) != NULL) {
558		    found = 1;
559		    break;
560		}
561	    }
562	}
563	else {		/* IPT_WEBSTR_CONTENT */
564	    int vicelen;
565
566	    if (opt & BLK_JAVA) {
567		vicelen = sizeof(".js") - 1;
568		if (strnicmp(htinfo.url + htinfo.urllen - vicelen, ".js", vicelen) == 0) {
569		    SPARQ_LOG("%s: MATCH....java\n", __FUNCTION__);
570		    found = 1;
571		    goto match_ret;
572		}
573		vicelen = sizeof(".class") - 1;
574		if (strnicmp(htinfo.url + htinfo.urllen - vicelen, ".class", vicelen) == 0) {
575		    SPARQ_LOG("%s: MATCH....java\n", __FUNCTION__);
576		    found = 1;
577		    goto match_ret;
578		}
579	    }
580	    if (opt & BLK_ACTIVE){
581		vicelen = sizeof(".ocx") - 1;
582		if (strnicmp(htinfo.url + htinfo.urllen - vicelen, ".ocx", vicelen) == 0) {
583		    SPARQ_LOG("%s: MATCH....activex\n", __FUNCTION__);
584		    found = 1;
585		    goto match_ret;
586		}
587		vicelen = sizeof(".cab") - 1;
588		if (strnicmp(htinfo.url + htinfo.urllen - vicelen, ".cab", vicelen) == 0) {
589		    SPARQ_LOG("%s: MATCH....activex\n", __FUNCTION__);
590		    found = 1;
591		    goto match_ret;
592		}
593	    }
594	    if (opt & BLK_PROXY){
595		if (strnicmp(htinfo.url + htinfo.hostlen, "http://", sizeof("http://") - 1) == 0) {
596		    SPARQ_LOG("%s: MATCH....proxy\n", __FUNCTION__);
597		    found = 1;
598		    goto match_ret;
599		}
600	    }
601	}
602
603match_ret:
604	SPARQ_LOG("%s: Verdict =======> %s \n",__FUNCTION__
605		, found ? "DROP" : "ACCEPT");
606
607	return (found ^ info->invert);
608}
609
610static int checkentry(const struct xt_mtchk_param *par)
611{
612#if 0
613       if (matchsize != IPT_ALIGN(sizeof(struct ipt_webstr_info)))
614               return 0;
615#endif
616       return 0;
617}
618
619static struct xt_match xt_webstr_match[] = {
620	{
621	.name		= "webstr",
622	.family		= AF_INET,
623	.match		= match,
624	.checkentry	= checkentry,
625	.matchsize	= sizeof(struct ipt_webstr_info),
626	.me		= THIS_MODULE
627	},
628	{
629	.name		= "webstr",
630	.family		= AF_INET6,
631	.match		= match6,
632	.checkentry	= checkentry,
633	.matchsize	= sizeof(struct ipt_webstr_info),
634	.me		= THIS_MODULE
635	},
636
637};
638
639static int __init init(void)
640{
641	return xt_register_matches(xt_webstr_match, ARRAY_SIZE(xt_webstr_match));
642}
643
644static void __exit fini(void)
645{
646	xt_unregister_matches(xt_webstr_match, ARRAY_SIZE(xt_webstr_match));
647}
648
649module_init(init);
650module_exit(fini);
651