K2.6 patches and update.
[tomato.git] / release / src / router / iptables / extensions / libipt_webmon.c
blob8e55e94db98f50621e073abcbfeaefa93db8cd20
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 <iptables.h>
37 #include <linux/netfilter_ipv4/ipt_webmon.h>
39 #ifdef _XTABLES_H
40 #define iptables_match xtables_match
41 #endif
43 /*
44 * XTABLES_VERSION_CODE is only defined in versions 1.4.1 and later, which
45 * also require the use of xtables_register_match
47 * Version 1.4.0 uses register_match like previous versions
49 #ifdef XTABLES_VERSION_CODE
50 #define register_match xtables_register_match
51 #endif
53 unsigned char* read_entire_file(FILE* in, unsigned long read_block_size, unsigned long *length);
55 #define DEFAULT_MAX 300
57 #define SEARCH_LOAD_FILE 100
58 #define DOMAIN_LOAD_FILE 101
59 #define CLEAR_SEARCH 102
60 #define CLEAR_DOMAIN 103
62 static char* domain_load_file = NULL;
63 static char* search_load_file = NULL;
64 static uint32_t global_max_domains = DEFAULT_MAX;
65 static uint32_t global_max_searches = DEFAULT_MAX;
67 /* Function which prints out usage message. */
68 static void help(void)
70 printf( "webmon options:\n");
73 static struct option opts[] =
75 { .name = "max_domains", .has_arg = 1, .flag = 0, .val = WEBMON_MAXDOMAIN },
76 { .name = "max_searches", .has_arg = 1, .flag = 0, .val = WEBMON_MAXSEARCH },
77 { .name = "search_load_file", .has_arg = 1, .flag = 0, .val = SEARCH_LOAD_FILE },
78 { .name = "domain_load_file", .has_arg = 1, .flag = 0, .val = DOMAIN_LOAD_FILE },
79 { .name = "clear_search", .has_arg = 0, .flag = 0, .val = CLEAR_SEARCH },
80 { .name = "clear_domain", .has_arg = 0, .flag = 0, .val = CLEAR_DOMAIN },
82 { .name = 0 }
85 static void webmon_init(
86 #ifdef _XTABLES_H
87 struct xt_entry_match *match
88 #else
89 struct ipt_entry_match *match, unsigned int *nfcache
90 #endif
93 struct ipt_webmon_info *info = (struct ipt_webmon_info *)match->data;
94 info->max_domains=DEFAULT_MAX;
95 info->max_searches=DEFAULT_MAX;
96 info->ref_count = NULL;
100 /* Function which parses command options; returns true if it ate an option */
101 static int parse( int c,
102 char **argv,
103 int invert,
104 unsigned int *flags,
105 #ifdef _XTABLES_H
106 const void *entry,
107 #else
108 const struct ipt_entry *entry,
109 unsigned int *nfcache,
110 #endif
111 struct ipt_entry_match **match
114 struct ipt_webmon_info *info = (struct ipt_webmon_info *)(*match)->data;
115 int valid_arg = 1;
116 long max;
117 switch (c)
119 case WEBMON_MAXSEARCH:
120 if( sscanf(argv[optind-1], "%ld", &max) == 0)
122 info->max_searches = DEFAULT_MAX ;
123 valid_arg = 0;
125 else
127 info->max_searches = (uint32_t)max;
128 global_max_searches = info->max_searches;
130 break;
131 case WEBMON_MAXDOMAIN:
132 if( sscanf(argv[optind-1], "%ld", &max) == 0)
134 info->max_domains = DEFAULT_MAX ;
135 valid_arg = 0;
137 else
139 info->max_domains = (uint32_t)max;
140 global_max_domains = info->max_domains;
142 break;
143 case SEARCH_LOAD_FILE:
144 search_load_file = strdup(optarg);
145 break;
146 case DOMAIN_LOAD_FILE:
147 domain_load_file = strdup(optarg);
148 break;
149 case CLEAR_SEARCH:
150 search_load_file = strdup("/dev/null");
151 break;
152 case CLEAR_DOMAIN:
153 domain_load_file = strdup("/dev/null");
154 break;
155 default:
156 valid_arg = 0;
158 return valid_arg;
163 static void print_webmon_args( struct ipt_webmon_info* info )
165 printf("--max_domains %ld ", (unsigned long int)info->max_domains);
166 printf("--max_searches %ld ", (unsigned long int)info->max_searches);
170 static void do_load(char* file, uint32_t max, unsigned char type)
172 if(file != NULL)
174 unsigned char* data = NULL;
175 unsigned long data_length = 0;
176 if(strcmp(file, "/dev/null") == 0)
178 data = (unsigned char*)malloc(10);
179 if(data != NULL)
181 uint32_t* maxp = (uint32_t*)(data+1);
182 data_length = 3+sizeof(uint32_t);
183 data[0] = type;
184 *maxp = max;
185 data[ sizeof(uint32_t)+1 ] = ' ';
186 data[ sizeof(uint32_t)+1 ] = '\0';
189 else
191 FILE* in = fopen(file, "r");
192 if(in != NULL)
194 char* file_data = read_entire_file(in, 4096, &data_length);
195 fclose(in);
196 if(file_data != NULL)
198 data_length = strlen(file_data) + sizeof(uint32_t)+2;
199 data = (unsigned char*)malloc(data_length);
200 if(data != NULL)
202 uint32_t* maxp = (uint32_t*)(data+1);
203 data[0] = type;
204 *maxp = max;
205 sprintf( (data+1+sizeof(uint32_t)), "%s", file_data);
207 free(file_data);
212 if(data != NULL && data_length > 0)
214 int sockfd = -1;
215 sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
216 if(sockfd >= 0)
218 setsockopt(sockfd, IPPROTO_IP, WEBMON_SET, data, data_length);
221 if(data != NULL)
223 free(data);
229 static void final_check(unsigned int flags)
231 do_load(domain_load_file, global_max_domains, WEBMON_DOMAIN);
232 do_load(search_load_file, global_max_searches, WEBMON_SEARCH);
235 /* Prints out the matchinfo. */
236 #ifdef _XTABLES_H
237 static void print(const void *ip, const struct xt_entry_match *match, int numeric)
238 #else
239 static void print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric)
240 #endif
242 printf("WEBMON ");
243 struct ipt_webmon_info *info = (struct ipt_webmon_info *)match->data;
245 print_webmon_args(info);
248 /* Saves the union ipt_matchinfo in parsable form to stdout. */
249 #ifdef _XTABLES_H
250 static void save(const void *ip, const struct xt_entry_match *match)
251 #else
252 static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
253 #endif
255 struct ipt_webmon_info *info = (struct ipt_webmon_info *)match->data;
256 print_webmon_args(info);
259 static struct iptables_match webmon =
261 .next = NULL,
262 .name = "webmon",
263 #ifdef XTABLES_VERSION_CODE
264 .version = XTABLES_VERSION,
265 #else
266 .version = IPTABLES_VERSION,
267 #endif
268 .size = IPT_ALIGN(sizeof(struct ipt_webmon_info)),
269 .userspacesize = IPT_ALIGN(sizeof(struct ipt_webmon_info)),
270 .help = &help,
271 .init = &webmon_init,
272 .parse = &parse,
273 .final_check = &final_check,
274 .print = &print,
275 .save = &save,
276 .extra_opts = opts
279 void _init(void)
281 register_match(&webmon);
285 unsigned char* read_entire_file(FILE* in, unsigned long read_block_size, unsigned long *length)
287 int max_read_size = read_block_size;
288 unsigned char* read_string = (unsigned char*)malloc(max_read_size+1);
289 unsigned long bytes_read = 0;
290 int end_found = 0;
291 while(end_found == 0)
293 int nextch = '?';
294 while(nextch != EOF && bytes_read < max_read_size)
296 nextch = fgetc(in);
297 if(nextch != EOF)
299 read_string[bytes_read] = (unsigned char)nextch;
300 bytes_read++;
303 read_string[bytes_read] = '\0';
304 end_found = (nextch == EOF) ? 1 : 0;
305 if(end_found == 0)
307 unsigned char *new_str;
308 max_read_size = max_read_size + read_block_size;
309 new_str = (unsigned char*)malloc(max_read_size+1);
310 memcpy(new_str, read_string, bytes_read);
311 free(read_string);
312 read_string = new_str;
315 *length = bytes_read;
316 return read_string;