K2.6 patches and update.
[tomato.git] / release / src / router / iptables / extensions / libip6t_webmon.c
blob3c52cc77c20185df82db36012e5dc02763214145
1 /* webmon -- An iptables extension to match URLs in HTTP requests
2 * This module can match using string match or regular expressions
3 * Originally designed for use with Gargoyle router firmware (gargoyle-router.com)
6 * Copyright © 2008-2010 by Eric Bishop <eric@gargoyle-router.com>
7 *
8 * This file is free software: you may copy, redistribute and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 2 of the License, or (at your
11 * option) any later version.
13 * This file is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include <stdio.h>
24 #include <netdb.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <getopt.h>
29 #include <arpa/inet.h>
32 * in iptables 1.4.0 and higher, iptables.h includes xtables.h, which
33 * we can use to check whether we need to deal with the new requirements
34 * in pre-processor directives below
36 #include <ip6tables.h>
37 #include <linux/netfilter_ipv6/ip6_tables.h>
39 #include <linux/netfilter_ipv4/ipt_webmon.h>
41 #ifdef _XTABLES_H
42 #define iptables_match xtables_match
43 #define ip6t_entry_match xt_entry_match
44 #endif
46 /*
47 * XTABLES_VERSION_CODE is only defined in versions 1.4.1 and later, which
48 * also require the use of xtables_register_match
50 * Version 1.4.0 uses register_match like previous versions
52 #ifdef XTABLES_VERSION_CODE
53 #define register_match6 xtables_register_match
54 #endif
56 unsigned char* read_entire_file(FILE* in, unsigned long read_block_size, unsigned long *length);
58 #define DEFAULT_MAX 300
60 #define SEARCH_LOAD_FILE 100
61 #define DOMAIN_LOAD_FILE 101
62 #define CLEAR_SEARCH 102
63 #define CLEAR_DOMAIN 103
65 static char* domain_load_file = NULL;
66 static char* search_load_file = NULL;
67 static uint32_t global_max_domains = DEFAULT_MAX;
68 static uint32_t global_max_searches = DEFAULT_MAX;
70 /* Function which prints out usage message. */
71 static void help(void)
73 printf( "webmon options:\n");
76 static struct option opts[] =
78 { .name = "max_domains", .has_arg = 1, .flag = 0, .val = WEBMON_MAXDOMAIN },
79 { .name = "max_searches", .has_arg = 1, .flag = 0, .val = WEBMON_MAXSEARCH },
80 { .name = "search_load_file", .has_arg = 1, .flag = 0, .val = SEARCH_LOAD_FILE },
81 { .name = "domain_load_file", .has_arg = 1, .flag = 0, .val = DOMAIN_LOAD_FILE },
82 { .name = "clear_search", .has_arg = 0, .flag = 0, .val = CLEAR_SEARCH },
83 { .name = "clear_domain", .has_arg = 0, .flag = 0, .val = CLEAR_DOMAIN },
85 { .name = 0 }
88 static void webmon_init(
89 #ifdef _XTABLES_H
90 struct xt_entry_match *match
91 #else
92 struct ip6t_entry_match *match, unsigned int *nfcache
93 #endif
96 struct ipt_webmon_info *info = (struct ipt_webmon_info *)match->data;
97 info->max_domains=DEFAULT_MAX;
98 info->max_searches=DEFAULT_MAX;
99 info->ref_count = NULL;
103 /* Function which parses command options; returns true if it ate an option */
104 static int parse( int c,
105 char **argv,
106 int invert,
107 unsigned int *flags,
108 #ifdef _XTABLES_H
109 const void *entry,
110 #else
111 const struct ip6t_entry *entry,
112 unsigned int *nfcache,
113 #endif
114 struct ip6t_entry_match **match
117 struct ipt_webmon_info *info = (struct ipt_webmon_info *)(*match)->data;
118 int valid_arg = 1;
119 long max;
120 switch (c)
122 case WEBMON_MAXSEARCH:
123 if( sscanf(argv[optind-1], "%ld", &max) == 0)
125 info->max_searches = DEFAULT_MAX ;
126 valid_arg = 0;
128 else
130 info->max_searches = (uint32_t)max;
131 global_max_searches = info->max_searches;
133 break;
134 case WEBMON_MAXDOMAIN:
135 if( sscanf(argv[optind-1], "%ld", &max) == 0)
137 info->max_domains = DEFAULT_MAX ;
138 valid_arg = 0;
140 else
142 info->max_domains = (uint32_t)max;
143 global_max_domains = info->max_domains;
145 break;
146 case SEARCH_LOAD_FILE:
147 search_load_file = strdup(optarg);
148 break;
149 case DOMAIN_LOAD_FILE:
150 domain_load_file = strdup(optarg);
151 break;
152 case CLEAR_SEARCH:
153 search_load_file = strdup("/dev/null");
154 break;
155 case CLEAR_DOMAIN:
156 domain_load_file = strdup("/dev/null");
157 break;
158 default:
159 valid_arg = 0;
161 return valid_arg;
167 static void print_webmon_args( struct ipt_webmon_info* info )
169 printf("--max_domains %ld ", (unsigned long int)info->max_domains);
170 printf("--max_searches %ld ", (unsigned long int)info->max_searches);
174 static void do_load(char* file, uint32_t max, unsigned char type)
176 if(file != NULL)
178 unsigned char* data = NULL;
179 unsigned long data_length = 0;
180 if(strcmp(file, "/dev/null") == 0)
182 data = (unsigned char*)malloc(10);
183 if(data != NULL)
185 uint32_t* maxp = (uint32_t*)(data+1);
186 data_length = 3+sizeof(uint32_t);
187 data[0] = type;
188 *maxp = max;
189 data[ sizeof(uint32_t)+1 ] = ' ';
190 data[ sizeof(uint32_t)+1 ] = '\0';
193 else
195 FILE* in = fopen(file, "r");
196 if(in != NULL)
198 char* file_data = read_entire_file(in, 4096, &data_length);
199 fclose(in);
200 if(file_data != NULL)
202 data_length = strlen(file_data) + sizeof(uint32_t)+2;
203 data = (unsigned char*)malloc(data_length);
204 if(data != NULL)
206 uint32_t* maxp = (uint32_t*)(data+1);
207 data[0] = type;
208 *maxp = max;
209 sprintf( (data+1+sizeof(uint32_t)), "%s", file_data);
211 free(file_data);
216 if(data != NULL && data_length > 0)
218 int sockfd = -1;
219 sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
220 if(sockfd >= 0)
222 setsockopt(sockfd, IPPROTO_IP, WEBMON_SET, data, data_length);
225 if(data != NULL)
227 free(data);
233 static void final_check(unsigned int flags)
235 do_load(domain_load_file, global_max_domains, WEBMON_DOMAIN);
236 do_load(search_load_file, global_max_searches, WEBMON_SEARCH);
239 /* Prints out the matchinfo. */
240 #ifdef _XTABLES_H
241 static void print(const void *ip, const struct xt_entry_match *match, int numeric)
242 #else
243 static void print(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match, int numeric)
244 #endif
246 printf("WEBMON ");
247 struct ipt_webmon_info *info = (struct ipt_webmon_info *)match->data;
249 print_webmon_args(info);
252 /* Saves the union ipt_matchinfo in parsable form to stdout. */
253 #ifdef _XTABLES_H
254 static void save(const void *ip, const struct xt_entry_match *match)
255 #else
256 static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
257 #endif
259 struct ipt_webmon_info *info = (struct ipt_webmon_info *)match->data;
260 print_webmon_args(info);
263 static struct ip6tables_match webmon =
265 .next = NULL,
266 .name = "webmon",
267 #ifdef XTABLES_VERSION_CODE
268 .version = XTABLES_VERSION,
269 .family = PF_INET6,
270 #else
271 .version = IPTABLES_VERSION,
272 #endif
273 .size = IP6T_ALIGN(sizeof(struct ipt_webmon_info)),
274 .userspacesize = IP6T_ALIGN(sizeof(struct ipt_webmon_info)),
275 .help = &help,
276 .init = &webmon_init,
277 .parse = &parse,
278 .final_check = &final_check,
279 .print = &print,
280 .save = &save,
281 .extra_opts = opts
284 void _init(void)
286 register_match6(&webmon);
290 unsigned char* read_entire_file(FILE* in, unsigned long read_block_size, unsigned long *length)
292 int max_read_size = read_block_size;
293 unsigned char* read_string = (unsigned char*)malloc(max_read_size+1);
294 unsigned long bytes_read = 0;
295 int end_found = 0;
296 while(end_found == 0)
298 int nextch = '?';
299 while(nextch != EOF && bytes_read < max_read_size)
301 nextch = fgetc(in);
302 if(nextch != EOF)
304 read_string[bytes_read] = (unsigned char)nextch;
305 bytes_read++;
308 read_string[bytes_read] = '\0';
309 end_found = (nextch == EOF) ? 1 : 0;
310 if(end_found == 0)
312 unsigned char *new_str;
313 max_read_size = max_read_size + read_block_size;
314 new_str = (unsigned char*)malloc(max_read_size+1);
315 memcpy(new_str, read_string, bytes_read);
316 free(read_string);
317 read_string = new_str;
320 *length = bytes_read;
321 return read_string;