simple iptables based packet limiter to deflect DoS attacks on our clients
[svn/Prometheus-QoS/.git] / prometheus.c
... / ...
CommitLineData
1/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2/* Prometheus QoS - you can "steal fire" from your ISP */\r
3/* "fair-per-IP" quality of service (QoS) utility */\r
4/* requires Linux 2.4.x or 2.6.x with HTB support */\r
5/* Copyright(C) 2005-2013 Michael Polak, Arachne Aerospace */\r
6/* iptables-restore support Copyright(C) 2007-2008 ludva */\r
7/* Credit: CZFree.Net,Martin Devera,Netdave,Aquarius,Gandalf */\r
8/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
9\r
10/* Modified by: xChaos, 20131118\r
11 ludva, 20080415\r
12 \r
13 Prometheus QoS is free software; you can redistribute it and/or\r
14 modify it under the terms of the GNU General Public License as \r
15 published by the Free Software Foundation; either version 2.1 of \r
16 the License, or (at your option) any later version.\r
17\r
18 Prometheus QoS is distributed in the hope that it will be useful,\r
19 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
21 General Public License for more details.\r
22\r
23 You should have received a copy of the GNU General Public License\r
24 along with Prometheus Qos; if not, write to the Free Software\r
25 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA \r
26 \r
27 GNU General Public License is located in file COPYING */\r
28\r
29#include "cll1-0.6.2.h"\r
30#include "ipstruct.h"\r
31\r
32const char *version = "0.8.3-j";\r
33\r
34/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
35/* Versions: 0.8.3 is development release, 0.8.4 will be "stable" */\r
36/* Official Trac URL: https://dev.arachne.cz/svn/prometheus */\r
37/* Official SVN URL: https://dev.arachne.cz/repos/prometheus */\r
38/* BTC donations account: 19rriLx8vR19wGefPaMhakqnCYNYwjLvxq */\r
39/* CZK donations account: 2900242944/2010 (transparent account) */\r
40/* Warning: unofficial Github mirror is not supported by author! */\r
41/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
42\r
43const char *stats_html_signature = "<span class=\"small\">Statistics generated by Prometheus QoS version %s<br />GPL+Copyright(C)2005-2013 Michael Polak, <a target=\"_blank\" href=\"http://www.arachne.cz/\">Arachne Labs</a></span>\n";\r
44\r
45#define STRLEN 512\r
46#undef DEBUG\r
47\r
48/* ======= All path names are defined here (for RPM patch) ======= */\r
49\r
50const char *tc = "/sbin/tc"; /* requires tc with HTB support */\r
51const char *iptables = "/sbin/iptables"; /* requires iptables utility */\r
52const char *ip6tables = "/sbin/ip6tables"; /* requires iptables utility */\r
53const char *iptablessave = "/sbin/iptables-save"; /* not yet required */\r
54const char *iptablesrestore = "/sbin/iptables-restore"; /* requires iptables-restore */\r
55const char *ip6tablessave = "/sbin/ip6tables-save"; /* not yet required */\r
56const char *ip6tablesrestore = "/sbin/ip6tables-restore"; /* requires iptables-restore */\r
57const char *ls = "/bin/ls"; /* this is not user configurable :-) */\r
58\r
59char *config = "/etc/prometheus/prometheus.conf"; /* main configuration file */\r
60char *hosts = "/etc/prometheus/hosts"; /* per-IP bandwidth definition file */\r
61char *iptablesfile = "/var/spool/prometheus.iptables"; /* temporary file for iptables-restore*/\r
62char *ip6tablesfile = "/var/spool/prometheus.ip6tables"; /* temporary file for ip6tables-restore*/\r
63char *credit = "/var/lib/misc/prometheus.credit"; /* credit log file */\r
64char *classmap = "/var/lib/misc/prometheus.classes"; /* credit log file */\r
65char *html = "/var/www/traffic.html"; /* hall of fame - html version */\r
66char *preview = "/var/www/preview.html"; /* hall of fame preview - html version */\r
67char *json_traffic = "/var/www/logs/traffic.json"; /* hall of fame - json version */\r
68char *json_preview = "/var/www/logs/preview.json"; /* hall of fame preview - json version */\r
69char *cmdlog = "/var/log/prometheuslog"; /* command log filename */\r
70char *log_dir = "/var/www/logs/"; /* log directory pathname, ended with slash */\r
71char *log_url = "/logs/"; /* log directory relative URI prefix (partial URL) */\r
72char *html_log_dir = "/var/www/logs/html/";\r
73\r
74char *jquery_url = "http://code.jquery.com/jquery-latest.js";\r
75char *lms_url = "/lms/?m=customerinfo&amp;id=";\r
76int use_jquery_popups = TRUE;\r
77int row_odd_even = 0; /*<tr class="odd/even"> */\r
78 \r
79/* === Configuraration file values defaults - stored in global variables ==== */\r
80\r
81int filter_type = 1; /*1 mark, 2 classify*/\r
82char *final_chain = "DROP"; /* REJECT would be better, but it is impossible in mangle */\r
83char *mark = "MARK";\r
84char *mark_iptables = "MARK --set-mark ";\r
85int dry_run = FALSE; /* preview - use puts() instead of system() */\r
86char *iptablespreamble = "*mangle\n:PREROUTING ACCEPT [0:0]\n:POSTROUTING ACCEPT [0:0]\n:INPUT ACCEPT [0:0]\n:OUTPUT ACCEPT [0:0]\n:FORWARD ACCEPT [0:0]";\r
87char *ip6preamble = "-A FORWARD -p ipv6-icmp -j ACCEPT\n-A POSTROUTING -p ipv6-icmp -j ACCEPT\n-A FORWARD -s fe80::/10 -j ACCEPT\n-A FORWARD -d ff00::/8 -j ACCEPT\n-A POSTROUTING -s fe80::/10 -j ACCEPT\n-A POSTROUTING -d ff00::/8 -j ACCEPT";\r
88FILE *iptables_file = NULL;\r
89FILE *ip6tables_file = NULL;\r
90int enable_credit = TRUE; /* enable credit file */\r
91int use_credit = FALSE; /* use credit file (if enabled)*/\r
92char *title = "Hall of Fame - Greatest Suckers"; /* hall of fame title */\r
93int hall_of_fame = TRUE; /* enable hall of fame */\r
94char *lan = "eth0"; /* LAN interface */\r
95char *lan_medium = "100Mbit"; /* 10Mbit/100Mbit ethernet */\r
96char *wan = "eth1"; /* WAN/ISP interface */\r
97char *ip6prefix = NULL; /* Prefix for global /48 IPv6 subnet */\r
98char *wan_medium = "100Mbit"; /* 10Mbit/100Mbit ethernet */\r
99char *qos_leaf = "sfq perturb 5"; /* leaf discipline */\r
100char *qos_free_zone = NULL; /* QoS free zone */\r
101int qos_proxy = TRUE; /* include proxy port to QoS */\r
102int found_lmsid = FALSE; /* show links to users in LMS information system */\r
103int include_upload = TRUE; /* upload+download=total traffic */\r
104char *proxy_ip = "192.168.1.1/32"; /* our IP with proxy port */\r
105int proxy_port = 3128; /* proxy port number */\r
106long long int line = 1024; /* WAN/ISP download in kbps */\r
107long long int up = 1024; /* WAN/ISP upload in kbps */\r
108int free_min = 256; /* minimum guaranted bandwidth for all undefined hosts */\r
109int free_max = 512; /* maximum allowed bandwidth for all undefined hosts */\r
110int qos_free_delay = 0; /* seconds to sleep before applying new QoS rules */\r
111int digital_divide = 2; /* controls digital divide weirdness ratio, 1...3 */ \r
112int max_nesting = 3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */\r
113int htb_r2q = 256; /* should work for leaf values 512 kbps to 8 Mbps */\r
114int burst = 8; /* HTB burst (in kbits) */\r
115int burst_main = 64;\r
116int burst_group = 32;\r
117int magic_treshold = 8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */\r
118int keywordcount = 0;\r
119int class_count = 0;\r
120int ip_count = 0;\r
121FILE *log_file = NULL;\r
122char *kwd = "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */\r
123\r
124const int highest_priority = 0; /* highest HTB priority (HTB built-in value is 0) */\r
125const int lowest_priority = 7; /* lowest HTB priority (HTB built-in value is 7) */\r
126const int idxtable_treshold1 = 24; /* this is no longer configurable */\r
127const int idxtable_treshold2 = 12; /* this is no longer configurable */\r
128const int idxtable_bitmask1 = 3; /* this is no longer configurable */\r
129const int idxtable_bitmask2 = 3; /* this is no longer configurable */\r
130\r
131struct IP *ips = NULL, *networks = NULL, *ip, *sharedip;\r
132struct Group *groups = NULL, *group;\r
133struct Keyword *keyword, *defaultkeyword=NULL, *keywords=NULL;\r
134\r
135void help(void);\r
136/* implemented in help.c */
137\r
138void get_traffic_statistics(const char *whichiptables, int ipv6);\r
139/* implemented in parseiptables.c */\r
140\r
141void parse_ip_log(int argc, char **argv);\r
142/* implemented in parselog.c */\r
143\r
144void parse_hosts(char *hosts);\r
145/* implemented in parsehosts.c */\r
146\r
147void write_json_traffic(char *json);\r
148/* implemented in json.c */\r
149\r
150void write_htmlandlogs(char *html, char *d, int total, int just_preview);\r
151/* implemented in htmlandlogs.c */\r
152\r
153void analyse_topology(char *traceroute);\r
154/* implemented in networks.c */\r
155\r
156\r
157const char *tr_odd_even(void)\r
158{\r
159 row_odd_even = 1 - row_odd_even;\r
160 if(row_odd_even)\r
161 {\r
162 return "<tr class=\"even\">\n";\r
163 }\r
164 else\r
165 {\r
166 return "<tr class=\"odd\">\n";\r
167 }\r
168}\r
169\r
170/* ==== This is C<<1 stuff - learn C<<1 first! https://dev.arachne.cz/svn/cll1h ==== */\r
171/* (except that this code uses obsolete, archaic version of this header file...) */\r
172\r
173struct Index\r
174{\r
175 char *addr;\r
176 char *id;\r
177 struct Index *parent;\r
178 int bitmask;\r
179 int children;\r
180 int ipv6;\r
181 list(Index);\r
182} *idxs=NULL, *idx, *metaindex;\r
183\r
184\r
185/* ====== iptables indexes are used to reduce complexity to log8(N) ===== */\r
186\r
187char *index_id(char *ip, int bitmask);\r
188/* function implemented in ipv4subnets.c */\r
189\r
190char *subnet_id(char *ip, int bitmask);\r
191/* function implemented in ipv4subnets.c */\r
192\r
193char *index6_id(char *ip, int bitmask);\r
194/* function implemented in ipv6subnets.c */\r
195\r
196char *subnet6_id(char *ip, int bitmask);\r
197/* function implemented in ipv6subnets.c */\r
198\r
199/* ================= Let's parse configuration file here ================ */\r
200\r
201void reject_config_and_exit(char *filename)\r
202{\r
203 printf("Configuration file %s rejected - abnormal exit.",filename);\r
204 exit(-1);\r
205}\r
206\r
207void get_config(char *config_filename)\r
208{\r
209 char *cnf="mark";\r
210 \r
211 printf("Configured keywords: ");\r
212 parse(config_filename)\r
213 {\r
214 option("keyword",kwd);\r
215 if(kwd)\r
216 {\r
217 printf("%s ",kwd);\r
218\r
219 create(keyword,Keyword);\r
220 keyword->key=kwd;\r
221 keyword->asymetry_ratio=1; /* ratio for ADSL-like upload */\r
222 keyword->asymetry_fixed=0; /* fixed treshold for ADSL-like upload */\r
223 keyword->data_limit=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */\r
224 keyword->data_prio=4; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */\r
225 keyword->fixed_limit=0; /* fixed data limit for setting lower HTB ceil */\r
226 keyword->fixed_prio=0; /* fixed data limit for setting lower HTB prio */\r
227 keyword->reserve_min=8; /* bonus for nominal HTB rate bandwidth (in kbps) */\r
228 keyword->reserve_max=0; /* malus for nominal HTB ceil (in kbps) */\r
229 keyword->default_prio=highest_priority+1;\r
230 keyword->html_color="000000";\r
231 keyword->ip_count=0;\r
232 keyword->leaf_discipline="";\r
233\r
234 push(keyword,keywords);\r
235 if(!defaultkeyword)\r
236 {\r
237 defaultkeyword=keyword;\r
238 }\r
239 keywordcount++;\r
240 \r
241 kwd=NULL;\r
242 }\r
243 else\r
244 {\r
245 for_each(keyword,keywords)\r
246 {\r
247 int l=strlen(keyword->key);\r
248\r
249 if(!strncmp(keyword->key,_,l) && strlen(_)>l+2)\r
250 {\r
251 char *tmptr=_; /* <---- l+1 ----> */\r
252 _+=l+1; /* via-prometheus-asymetry-ratio, etc. */\r
253 ioption("asymetry-ratio",keyword->asymetry_ratio);\r
254 ioption("asymetry-treshold",keyword->asymetry_fixed);\r
255 ioption("magic-relative-limit",keyword->data_limit);\r
256 ioption("magic-relative-prio",keyword->data_prio);\r
257 loption("magic-fixed-limit",keyword->fixed_limit);\r
258 loption("magic-fixed-prio",keyword->fixed_prio);\r
259 ioption("htb-default-prio",keyword->default_prio);\r
260 ioption("htb-rate-bonus",keyword->reserve_min);\r
261 ioption("htb-ceil-malus",keyword->reserve_max);\r
262 option("leaf-discipline",keyword->leaf_discipline);\r
263 option("html-color",keyword->html_color);\r
264 _=tmptr;\r
265 \r
266 if(keyword->data_limit || keyword->fixed_limit || \r
267 keyword->data_prio || keyword->fixed_prio)\r
268 {\r
269 use_credit=1; \r
270 }\r
271 }\r
272 }\r
273 }\r
274\r
275 option("tc",tc);\r
276 option("iptables",iptables);\r
277 option("iptables-save",iptablessave);\r
278 option("iptables-restore",iptablesrestore);\r
279 option("ip6tables",ip6tables);\r
280 option("ip6tables-save",ip6tablessave);\r
281 option("ip6tables-restore",ip6tablesrestore);\r
282 option("iptables-in-filename",iptablesfile);\r
283 option("ip6tables-in-filename",ip6tablesfile);\r
284 option("hosts",hosts);\r
285 option("lan-interface",lan);\r
286 option("wan-interface",wan);\r
287 option("ip6-prefix",ip6prefix);\r
288 option("lan-medium",lan_medium);\r
289 option("wan-medium",wan_medium);\r
290 lloption("wan-download",line);\r
291 lloption("wan-upload",up);\r
292 ioption("hall-of-fame-enable",hall_of_fame);\r
293 option("hall-of-fame-title",title);\r
294 option("hall-of-fame-filename",html);\r
295 option("json-filename",json_traffic);\r
296 option("hall-of-fame-preview",preview);\r
297 option("json-preview",json_preview);\r
298 option("log-filename",cmdlog);\r
299 option("credit-filename",credit);\r
300 option("classmap-filename",classmap);\r
301 ioption("credit-enable",enable_credit);\r
302 option("log-traffic-directory",log_dir);\r
303 option("log-traffic-html-directory",html_log_dir);\r
304 option("log-traffic-url-path",log_url);\r
305 option("jquery-url",jquery_url);\r
306 option("lms-url",lms_url);\r
307 ioption("use-jquery-popups",use_jquery_popups);\r
308 option("qos-free-zone",qos_free_zone);\r
309 ioption("qos-free-delay",qos_free_delay);\r
310 ioption("qos-proxy-enable",qos_proxy);\r
311 option("qos-proxy-ip",proxy_ip);\r
312 option("htb-leaf-discipline",qos_leaf);\r
313 ioption("qos-proxy-port",proxy_port);\r
314 ioption("free-rate",free_min);\r
315 ioption("free-ceil",free_max);\r
316 ioption("htb-burst",burst);\r
317 ioption("htb-burst-main",burst_main);\r
318 ioption("htb-burst-group",burst_group);\r
319 ioption("htb-nesting-limit",max_nesting);\r
320 ioption("htb-r2q",htb_r2q);\r
321 ioption("magic-include-upload",include_upload);\r
322 ioption("magic-treshold",magic_treshold); \r
323 option("filter-type", cnf); \r
324/* not yet implemented:\r
325 ioption("magic-fixed-packets",fixed_packets);\r
326 ioption("magic-relative-packets",packet_limit);\r
327*/\r
328 }\r
329 fail\r
330 { \r
331 perror(config_filename);\r
332 puts("Warning - using built-in defaults instead ...");\r
333 }\r
334 done; /* ugly macro end */\r
335 printf("\n");\r
336 \r
337 /* leaf discipline for keywords */\r
338 for_each(keyword,keywords)\r
339 {\r
340 if(!strcmpi(keyword->leaf_discipline, ""))\r
341 {\r
342 keyword->leaf_discipline = qos_leaf;\r
343 }\r
344 }\r
345\r
346 if(strcmpi(cnf, "mark"))\r
347 {\r
348 filter_type = 2;\r
349 mark = "CLASSIFY";\r
350 mark_iptables = "CLASSIFY --set-class 1:";\r
351 }\r
352 else\r
353 {\r
354 filter_type = 1;\r
355 mark = "MARK";\r
356 mark_iptables = "MARK --set-mark ";\r
357 }\r
358\r
359 /* are supplied values meaningful ?*/\r
360 if(line<=0 || up<=0)\r
361 {\r
362 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");\r
363 reject_config_and_exit(config_filename);\r
364 }\r
365}\r
366\r
367 \r
368/* ========== This function executes, logs OR ALSO prints command ========== */\r
369\r
370void safe_run(char *cmd)\r
371{\r
372 if(dry_run)\r
373 {\r
374 printf("\n=>%s\n",cmd);\r
375 }\r
376 else\r
377 {\r
378 system(cmd);\r
379 }\r
380 if(log_file)\r
381 {\r
382 fprintf(log_file,"%s\n",cmd);\r
383 }\r
384}\r
385\r
386void iptables_save_line(char *line, int ipv6)\r
387{\r
388 if(ipv6)\r
389 {\r
390 fprintf(ip6tables_file,"%s\n",line);\r
391 }\r
392 else\r
393 {\r
394 fprintf(iptables_file,"%s\n",line);\r
395 }\r
396}\r
397\r
398void run_iptables_restore(void)\r
399{\r
400 char *restor;\r
401 string(restor,STRLEN);\r
402\r
403 /*-----------------------------------------------------------------*/\r
404 printf("Running %s <%s ...\n", iptablesrestore, iptablesfile);\r
405 /*-----------------------------------------------------------------*/\r
406\r
407 iptables_save_line("COMMIT", FALSE);\r
408 fclose(iptables_file);\r
409 if(dry_run) \r
410 {\r
411 parse(iptablesfile)\r
412 {\r
413 printf("%s\n",_);\r
414 }\r
415 done; /* ugly macro end */\r
416 }\r
417\r
418 sprintf(restor,"%s <%s",iptablesrestore, iptablesfile);\r
419 safe_run(restor);\r
420\r
421 if(ip6prefix)\r
422 {\r
423 /*-----------------------------------------------------------------*/\r
424 printf("Running %s <%s ...\n", ip6tablesrestore, ip6tablesfile);\r
425 /*-----------------------------------------------------------------*/\r
426 iptables_save_line("COMMIT", TRUE);\r
427 fclose(ip6tables_file);\r
428 if(dry_run) \r
429 {\r
430 parse(ip6tablesfile)\r
431 {\r
432 printf("%s\n",_);\r
433 }\r
434 done; /* ugly macro end */\r
435 }\r
436 sprintf(restor,"%s <%s",ip6tablesrestore, ip6tablesfile);\r
437 safe_run(restor);\r
438 }\r
439 free(restor);\r
440}\r
441\r
442char *parse_datafile_line(char *str)\r
443{\r
444 char *ptr=strchr(str,' ');\r
445\r
446 if(ptr)\r
447 {\r
448 *ptr=0;\r
449 ptr++;\r
450 return ptr;\r
451 } \r
452 else \r
453 {\r
454 return NULL;\r
455 }\r
456}\r
457\r
458\r
459/*-----------------------------------------------------------------*/\r
460/* Are you looking for int main(int argc, char **argv) ? :-)) */\r
461/*-----------------------------------------------------------------*/\r
462\r
463program\r
464{\r
465 int i=0; /* just plain old Fortran style integer :-) */\r
466 FILE *f=NULL; /* everything is just stream of bytes... */\r
467 char *str, *ptr, *d; /* LET A$=B$ :-) */\r
468 char *substring, *limit_pkts;\r
469\r
470 int parent = 1;\r
471 int just_networks = FALSE; \r
472 int just_flush = FALSE; /* deactivates all previous actions */\r
473 int nodelay = FALSE;\r
474 int just_preview = FALSE; /* preview - generate just stats */\r
475 int start_shaping = FALSE; /* apply FUP - requires classmap file */\r
476 int stop_shaping = FALSE; /* lift FUP - requires classmap file */\r
477 int reduce_ceil = 0; /* allow only rate+(ceil-rate)/2, /4, etc. */\r
478 int just_logs = FALSE; /* just parse logs */\r
479 int run = FALSE;\r
480 int total = 0;\r
481 \r
482 char *chain_forward, *chain_postrouting;\r
483 char *althosts=NULL;\r
484 \r
485 printf("\n\\r
486Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\\r
487Version %s - Copyright (C)2005-2013 Michael Polak, Arachne Labs\n\\r
488iptables-restore & burst tunning & classify modification by Ludva\n\\r
489Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version);\r
490\r
491 /*----- Boring... we have to check command line options first: ----*/ \r
492 arguments\r
493 {\r
494 argument("-c") { nextargument(config); }\r
495 argument("-h") { nextargument(althosts);}\r
496 argument("-d") { run=TRUE; dry_run=TRUE; }\r
497 argument("-f") { run=TRUE; just_flush=TRUE; }\r
498 argument("-9") { run=TRUE; just_flush=9; }\r
499 argument("-p") { run=TRUE; just_preview=TRUE; }\r
500 argument("-q") { run=TRUE; just_preview=TRUE; stop_shaping=TRUE; }\r
501 argument("-2") { run=TRUE; just_preview=TRUE; reduce_ceil=2; }\r
502 argument("-4") { run=TRUE; just_preview=TRUE; reduce_ceil=4; }\r
503 argument("-s") { run=TRUE; just_preview=TRUE; start_shaping=TRUE; }\r
504 argument("-r") { run=TRUE; }\r
505 argument("-n") { run=TRUE; nodelay=TRUE; }\r
506 argument("-a") { run=TRUE; just_networks=TRUE; }\r
507 argument("-l") { just_logs=TRUE; }\r
508 argument("-m") { just_logs=TRUE; }\r
509 argument("-y") { just_logs=TRUE; }\r
510 argument("-?") { help(); exit(0); }\r
511 argument("--help") { help(); exit(0); }\r
512 argument("-v") { exit(0); } \r
513 argument("--version") { exit(0); } \r
514 }\r
515 \r
516 if(dry_run)\r
517 {\r
518 puts("*** THIS IS JUST DRY RUN ! ***\n");\r
519 }\r
520\r
521 date(d); /* this is typical cll1.h macro - prints current date */\r
522\r
523 /*-----------------------------------------------------------------*/\r
524 printf("Parsing configuration file %s ...\n", config);\r
525 /*-----------------------------------------------------------------*/\r
526 get_config(config);\r
527 \r
528 if(just_logs)\r
529 {\r
530 parse_ip_log(argc,argv);\r
531 exit(0);\r
532 }\r
533 else if(not run)\r
534 {\r
535 help();\r
536 exit(0);\r
537 }\r
538\r
539 if(althosts)\r
540 {\r
541 hosts = althosts;\r
542 }\r
543\r
544 if(just_flush<9)\r
545 {\r
546 /*-----------------------------------------------------------------*/\r
547 puts("Parsing iptables verbose output ...");\r
548 /*-----------------------------------------------------------------*/\r
549 get_traffic_statistics(iptables, FALSE);\r
550 if(ip6prefix)\r
551 {\r
552 /*-----------------------------------------------------------------*/\r
553 puts("Parsing ip6tables verbose output ...");\r
554 /*-----------------------------------------------------------------*/ \r
555 get_traffic_statistics(ip6tables, TRUE);\r
556 }\r
557 }\r
558\r
559 /*-----------------------------------------------------------------*/\r
560 /* cll1.h - let's allocate brand new character buffer... */\r
561 /*-----------------------------------------------------------------*/\r
562 string(str, STRLEN); \r
563 string(limit_pkts, STRLEN);\r
564\r
565 /*-----------------------------------------------------------------*/\r
566 printf("Parsing class defintion file %s ...\n", hosts);\r
567 /*-----------------------------------------------------------------*/\r
568 parse_hosts(hosts);\r
569 if(just_networks)\r
570 {\r
571 analyse_topology("/usr/sbin/traceroute -n -m 10 -w 2 %s.%d");\r
572 exit(-1); \r
573 }\r
574\r
575 /*-----------------------------------------------------------------*/\r
576 puts("Resolving shared connections ...");\r
577 /*-----------------------------------------------------------------*/\r
578 for_each(ip, ips) if(ip->sharing)\r
579 {\r
580 for_each(sharedip, ips) if(eq(sharedip->name, ip->sharing))\r
581 {\r
582 sharedip->traffic += ip->traffic;\r
583 ip->traffic = 0;\r
584 ip->mark = sharedip->mark; \r
585 ip->lmsid = sharedip->lmsid;\r
586 ip->pps_limit = sharedip->pps_limit; /* no other way to do this */\r
587 break;\r
588 }\r
589 if(not sharedip)\r
590 {\r
591 printf("Unresolved shared connection: %s %s sharing-%s\n",\r
592 ip->addr, ip->name, ip->sharing);\r
593 }\r
594 }\r
595\r
596 if(enable_credit && just_flush<9)\r
597 {\r
598 /*-----------------------------------------------------------------*/\r
599 printf("Parsing credit file %s ...\n", credit);\r
600 /*-----------------------------------------------------------------*/\r
601 parse(credit)\r
602 {\r
603 ptr=parse_datafile_line(_);\r
604 if(ptr)\r
605 {\r
606 if_exists(ip,ips,eq(ip->addr,_))\r
607 {\r
608 sscanf(ptr,"%Lu",&(ip->credit));\r
609 }\r
610 }\r
611 }\r
612 done; /* ugly macro end */\r
613 }\r
614\r
615 if(!just_preview)\r
616 {\r
617 /*-----------------------------------------------------------------*/\r
618 puts("Initializing iptables and tc classes ...");\r
619 /*-----------------------------------------------------------------*/\r
620 \r
621 iptables_file = fopen(iptablesfile, "w");\r
622 if(iptables_file == NULL)\r
623 {\r
624 perror(iptablesfile);\r
625 exit(-1);\r
626 }\r
627 iptables_save_line(iptablespreamble, FALSE);\r
628\r
629 if(ip6prefix)\r
630 {\r
631 ip6tables_file = fopen(ip6tablesfile, "w");\r
632 if(ip6tables_file == NULL)\r
633 {\r
634 perror(ip6tablesfile);\r
635 exit(-1);\r
636 }\r
637 iptables_save_line(iptablespreamble, TRUE);\r
638 iptables_save_line(ip6preamble, TRUE);\r
639 }\r
640\r
641 run_iptables_restore();\r
642 \r
643 log_file = fopen(cmdlog, "w");\r
644 if(log_file == NULL) \r
645 {\r
646 perror(cmdlog);\r
647 exit(-1);\r
648 } \r
649 \r
650 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,lan);\r
651 safe_run(str);\r
652\r
653 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,wan);\r
654 safe_run(str);\r
655 \r
656 iptables_file=fopen(iptablesfile,"w");\r
657 iptables_save_line(iptablespreamble, FALSE);\r
658 if(ip6prefix)\r
659 {\r
660 ip6tables_file=fopen(ip6tablesfile,"w");\r
661 iptables_save_line(iptablespreamble, TRUE);\r
662 iptables_save_line(ip6preamble, TRUE);\r
663 }\r
664\r
665 if(qos_free_zone && *qos_free_zone!='0') /* this is currently supported only for IPv4 */\r
666 {\r
667 char *chain;\r
668 \r
669 sprintf(str,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone, wan);\r
670 iptables_save_line(str, FALSE); /* this is currently supported only for IPv4 */\r
671 \r
672 if(qos_proxy)\r
673 {\r
674 iptables_save_line(":post_noproxy - [0:0]", FALSE);\r
675 sprintf(str,"-A POSTROUTING ! -p tcp -o %s -j post_noproxy", lan);\r
676 iptables_save_line(str , FALSE);\r
677 sprintf(str,"-A POSTROUTING ! -s %s -o %s -j post_noproxy", proxy_ip, lan);\r
678 iptables_save_line(str, FALSE);\r
679 sprintf(str,"-A POSTROUTING -s %s -p tcp ! --sport %d -o %s -j post_noproxy", proxy_ip, proxy_port, lan);\r
680 iptables_save_line(str, FALSE);\r
681\r
682 chain="post_noproxy"; \r
683 }\r
684 else\r
685 {\r
686 chain="POSTROUTING";\r
687 }\r
688 \r
689 sprintf(str,"-A %s -s %s -o %s -j ACCEPT", chain, qos_free_zone, lan);\r
690 iptables_save_line(str, FALSE);\r
691 }\r
692 \r
693 if(ip_count > idxtable_treshold1 && !just_flush)\r
694 {\r
695 int idxcount=0, bitmask=32-idxtable_bitmask1;\r
696 char *subnet, *buf;\r
697 /*-----------------------------------------------------------------*/\r
698 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count);\r
699 /*-----------------------------------------------------------------*/\r
700\r
701 iptables_save_line(":post_common - [0:0]", FALSE);\r
702 iptables_save_line(":forw_common - [0:0]", FALSE);\r
703 if(ip6prefix)\r
704 {\r
705 iptables_save_line(":post_common - [0:0]", TRUE);\r
706 iptables_save_line(":forw_common - [0:0]", TRUE);\r
707 }\r
708\r
709 for_each(ip,ips) if(ip->addr && *(ip->addr) && !eq(ip->addr,"0.0.0.0/0")) \r
710 {\r
711 if(ip->v6)\r
712 {\r
713 buf=index6_id(ip->addr,bitmask+32);\r
714 }\r
715 else\r
716 {\r
717 buf=index_id(ip->addr, bitmask);\r
718 }\r
719 \r
720 if_exists(idx,idxs,eq(idx->id,buf))\r
721 {\r
722 idx->children++;\r
723 }\r
724 else\r
725 {\r
726 create(idx,Index);\r
727 idx->addr = ip->addr;\r
728 idx->id = buf;\r
729 idx->bitmask = bitmask+32*ip->v6;\r
730 idx->parent = NULL;\r
731 idx->children = 0;\r
732 idx->ipv6 = ip->v6;\r
733 idxcount++;\r
734 push(idx,idxs);\r
735 }\r
736 }\r
737\r
738 /* brutal perfomance optimalization */\r
739 while(idxcount > idxtable_treshold2 && bitmask > 2*idxtable_bitmask2)\r
740 {\r
741 bitmask -= idxtable_bitmask2;\r
742 idxcount = 0;\r
743\r
744 for_each(idx,idxs) if(idx->parent == NULL)\r
745 {\r
746 if(idx->ipv6)\r
747 {\r
748 buf = index6_id(idx->addr, bitmask+32);\r
749 }\r
750 else\r
751 {\r
752 buf = index_id(idx->addr, bitmask);\r
753 }\r
754 if_exists(metaindex,idxs,eq(metaindex->id,buf))\r
755 {\r
756 metaindex->children++;\r
757 }\r
758 else\r
759 {\r
760 create(metaindex,Index);\r
761 metaindex->addr = idx->addr;\r
762 metaindex->id = buf;\r
763 metaindex->bitmask = bitmask+32*idx->ipv6;\r
764 metaindex->parent = NULL;\r
765 metaindex->children = 0;\r
766 metaindex->ipv6 = idx->ipv6;\r
767 idxcount++;\r
768 push(metaindex,idxs);\r
769 }\r
770 idx->parent=metaindex;\r
771 }\r
772 }\r
773\r
774 /* this should slightly optimize throughput ... */\r
775 sort(idx,idxs,desc_order_by,children);\r
776 sort(idx,idxs,order_by,bitmask);\r
777\r
778 i=0;\r
779 for_each(idx,idxs)\r
780 {\r
781 if(idx->ipv6)\r
782 {\r
783 subnet=subnet6_id(idx->addr, idx->bitmask);\r
784 }\r
785 else\r
786 {\r
787 subnet=subnet_id(idx->addr, idx->bitmask);\r
788 }\r
789 printf("%d: %s/%d\n", ++i, subnet, idx->bitmask);\r
790 \r
791 sprintf(str,":post_%s - [0:0]", idx->id);\r
792 iptables_save_line(str, idx->ipv6);\r
793\r
794 sprintf(str,":forw_%s - [0:0]", idx->id);\r
795 iptables_save_line(str, idx->ipv6);\r
796\r
797 if(idx->parent)\r
798 {\r
799 string(buf,strlen(idx->parent->id)+6);\r
800 sprintf(buf,"post_%s", idx->parent->id);\r
801 }\r
802 else\r
803 {\r
804 buf="POSTROUTING";\r
805 }\r
806\r
807 sprintf(str,"-A %s -d %s/%d -o %s -j post_%s", buf, subnet, idx->bitmask, lan, idx->id);\r
808 iptables_save_line(str, idx->ipv6);\r
809\r
810 sprintf(str,"-A %s -d %s/%d -o %s -j post_common", buf, subnet, idx->bitmask, lan);\r
811 iptables_save_line(str, idx->ipv6);\r
812\r
813 if(idx->parent)\r
814 {\r
815 string(buf,strlen(idx->parent->id)+6);\r
816 sprintf(buf,"forw_%s",idx->parent->id);\r
817 }\r
818 else\r
819 {\r
820 buf="FORWARD";\r
821 }\r
822\r
823 sprintf(str,"-A %s -s %s/%d -o %s -j forw_%s", buf, subnet, idx->bitmask, wan, idx->id);\r
824 iptables_save_line(str, idx->ipv6);\r
825\r
826 sprintf(str,"-A %s -s %s/%d -o %s -j forw_common", buf, subnet, idx->bitmask, wan);\r
827 iptables_save_line(str, idx->ipv6);\r
828 }\r
829 printf("Total indexed iptables chains created: %d\n", i);\r
830\r
831 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);\r
832 iptables_save_line(str, FALSE);\r
833 \r
834 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);\r
835 iptables_save_line(str, FALSE);\r
836\r
837 if(ip6prefix)\r
838 {\r
839 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);\r
840 iptables_save_line(str, TRUE);\r
841 \r
842 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);\r
843 iptables_save_line(str, TRUE);\r
844 }\r
845 }\r
846 }\r
847\r
848 if(just_flush)\r
849 {\r
850 fclose(iptables_file);\r
851 if(log_file)\r
852 { \r
853 fclose(log_file);\r
854 }\r
855 puts("Just flushed iptables and tc classes - now exiting ...");\r
856 exit(0);\r
857 }\r
858\r
859 if(!just_preview)\r
860 {\r
861 if(!dry_run && !nodelay && qos_free_delay)\r
862 {\r
863 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay);\r
864 sleep(qos_free_delay);\r
865 }\r
866\r
867 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",\r
868 tc,lan,htb_r2q);\r
869 safe_run(str);\r
870\r
871 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
872 tc,lan,lan_medium,lan_medium,burst_main,highest_priority);\r
873 safe_run(str);\r
874\r
875 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
876 tc,lan,line,line,burst_main,highest_priority);\r
877 safe_run(str);\r
878\r
879 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc,wan,htb_r2q);\r
880 safe_run(str);\r
881\r
882 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
883 tc,wan,wan_medium,wan_medium,burst_main,highest_priority);\r
884 safe_run(str);\r
885\r
886 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
887 tc,wan,up,up,burst_main,highest_priority);\r
888 safe_run(str);\r
889 }\r
890\r
891 /*-----------------------------------------------------------------*/\r
892 puts("Locating heavy downloaders and generating root classes ...");\r
893 /*-----------------------------------------------------------------*/\r
894 sort(ip,ips,desc_order_by,traffic); \r
895\r
896 /*-----------------------------------------------------------------*/\r
897 /* sub-scope - local variables */ \r
898 {\r
899 long long int rate = line;\r
900 long long int max = line;\r
901 int group_count = 0;\r
902 FILE *credit_file = NULL;\r
903 \r
904 if(!just_preview && !dry_run && enable_credit)\r
905 {\r
906 credit_file = fopen(credit,"w");\r
907 }\r
908 \r
909 for_each(group,groups)\r
910 {\r
911 if(!just_preview)\r
912 {\r
913 //download\r
914 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d #down desired %d", \r
915 tc, lan, parent, group->id, rate, max, burst_group, highest_priority+1, group->desired);\r
916 safe_run(str);\r
917 \r
918 //upload\r
919 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d #up desired %d", \r
920 tc, wan, parent, group->id, rate*up/line, max*up/line, burst_group, highest_priority+1, group->desired);\r
921 safe_run(str);\r
922 }\r
923 \r
924 if(group_count++ < max_nesting)\r
925 {\r
926 parent = group->id;\r
927 }\r
928 \r
929 rate -= digital_divide*group->min;\r
930 if(rate < group->min)\r
931 {\r
932 rate = group->min;\r
933 }\r
934 \r
935 /*shaping of aggresive downloaders, with credit file support */\r
936 if(use_credit)\r
937 {\r
938 int group_rate = group->min, priority_sequence = lowest_priority;\r
939 \r
940 for_each(ip, ips) if(ip->min == group->min && ip->max > ip->min)\r
941 {\r
942 ip->realquota=ip->credit+(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20));\r
943 if( ip->keyword->data_limit \r
944 and not ip->fixedprio \r
945 and ip->traffic > ip->realquota )\r
946 {\r
947 if(group_rate < ip->max)\r
948 {\r
949 ip->max = group_rate;\r
950 }\r
951 group_rate+=magic_treshold;\r
952 ip->prio=lowest_priority;\r
953 if(ip->prio<highest_priority+2)\r
954 {\r
955 ip->prio=highest_priority+2;\r
956 }\r
957 }\r
958 else\r
959 {\r
960 if( ip->keyword->data_prio \r
961 && !ip->fixedprio \r
962 && ( ip->traffic>ip->credit\r
963 + (ip->min*ip->keyword->data_prio+(ip->keyword->fixed_prio<<20))) )\r
964 {\r
965 ip->prio=priority_sequence--;\r
966 if(ip->prio<highest_priority+1)\r
967 {\r
968 ip->prio=highest_priority+1;\r
969 }\r
970 }\r
971 \r
972 if(credit_file)\r
973 {\r
974 unsigned long long lcredit=0;\r
975 \r
976 if((ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))>ip->traffic)\r
977 {\r
978 lcredit=(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))-ip->traffic;\r
979 }\r
980 fprintf(credit_file,"%s %Lu\n",ip->addr,lcredit);\r
981 }\r
982 }\r
983 } \r
984 }\r
985 }\r
986 if(credit_file)\r
987 {\r
988 fclose(credit_file);\r
989 }\r
990 }\r
991\r
992 if(just_preview)\r
993 {\r
994 if(start_shaping || stop_shaping || reduce_ceil)\r
995 {\r
996 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap);\r
997 parse(classmap)\r
998 {\r
999 ptr=strchr(_,' ');\r
1000 if(ptr)\r
1001 {\r
1002 *ptr=0;\r
1003 ptr++;\r
1004 if_exists(ip,ips,eq(ip->addr,_))\r
1005 {\r
1006 ip->mark=atoi(ptr);\r
1007 if(ip->max < ip->desired || stop_shaping || reduce_ceil) /* apply or disable FUP limit immediately.... */\r
1008 {\r
1009 if(stop_shaping)\r
1010 {\r
1011 ip->max = ip->desired;\r
1012 printf("Removing limit for %-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
1013 }\r
1014 else\r
1015 {\r
1016 printf("Applying limit for %-22s %-16s %04d ", ip->name, ip->addr, ip->mark);\r
1017 if(reduce_ceil)\r
1018 {\r
1019 ip->max = ip->min + (ip->desired-ip->min)/reduce_ceil;\r
1020 }\r
1021 }\r
1022 printf("(down: %dk-%dk ", ip->min, ip->max); \r
1023 sprintf(str, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
1024 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
1025 safe_run(str);\r
1026 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1027 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
1028 sprintf(str,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1029 tc, wan, ip->group, ip->mark,\r
1030 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1031 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1032 safe_run(str);\r
1033 }\r
1034 }\r
1035 }\r
1036 }\r
1037 fail\r
1038 { \r
1039 perror(classmap);\r
1040 puts("Warning - classmap file not fund, just generating preview ...");\r
1041 start_shaping=FALSE;\r
1042 stop_shaping=FALSE;\r
1043 }\r
1044 done; /* ugly macro end */\r
1045 }\r
1046 html=preview;\r
1047 json_traffic=json_preview;\r
1048 }\r
1049\r
1050 if(!dry_run && !just_flush)\r
1051 {\r
1052 /*-----------------------------------------------------------------*/\r
1053 printf("Writing json traffic overview %s ... ", json_traffic);\r
1054 /*-----------------------------------------------------------------*/\r
1055 write_json_traffic(json_traffic);\r
1056\r
1057 /*-----------------------------------------------------------------*/\r
1058 printf("Writing statistics into HTML page %s ...\n", html);\r
1059 /*-----------------------------------------------------------------*/\r
1060 write_htmlandlogs(html, d, total, just_preview);\r
1061 }\r
1062\r
1063 if(just_preview)\r
1064 {\r
1065 char swchar='p';\r
1066 if(start_shaping)\r
1067 {\r
1068 swchar='s';\r
1069 }\r
1070 else if(reduce_ceil)\r
1071 {\r
1072 swchar='0'+reduce_ceil; /* -2, -4 */\r
1073 }\r
1074 else if(stop_shaping)\r
1075 {\r
1076 swchar='q';\r
1077 }\r
1078\r
1079 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar);\r
1080 exit(0);\r
1081 } \r
1082\r
1083 i=0;\r
1084#ifdef DEBUG\r
1085 printf("%-22s %-15s mark\n","name","ip");\r
1086#endif\r
1087\r
1088 printf("Writing %s", classmap); \r
1089 f = fopen(classmap, "w"); \r
1090 if(f < 0)\r
1091 {\r
1092 perror(classmap);\r
1093 }\r
1094\r
1095 /*-----------------------------------------------------------------*/\r
1096 printf(" + generating iptables and tc classes ... ");\r
1097 /*-----------------------------------------------------------------*/\r
1098\r
1099 for_each(ip, ips) if(ip->mark > 0) /* works only for IPv4 so far */\r
1100 {\r
1101 if(idxs)\r
1102 {\r
1103 char *buf;\r
1104 duplicate(ip->addr,buf);\r
1105 if(ip->v6)\r
1106 {\r
1107 buf=index6_id(ip->addr,64-idxtable_bitmask1);\r
1108 }\r
1109 else\r
1110 {\r
1111 buf=index_id(ip->addr,32-idxtable_bitmask1);\r
1112 }\r
1113 \r
1114 string(chain_forward,6+strlen(buf));\r
1115 strcpy(chain_forward,"forw_");\r
1116 strcat(chain_forward,buf);\r
1117\r
1118 string(chain_postrouting,6+strlen(buf));\r
1119 strcpy(chain_postrouting,"post_");\r
1120 strcat(chain_postrouting,buf);\r
1121 \r
1122 free(buf);\r
1123 }\r
1124 else\r
1125 {\r
1126 chain_forward="FORWARD";\r
1127 chain_postrouting="POSTROUTING";\r
1128 }\r
1129\r
1130#ifdef DEBUG\r
1131 printf("%-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
1132#endif\r
1133\r
1134 /* -------------------------------------------------------- mark download */\r
1135 \r
1136 sprintf(str, "-A %s -d %s/%d -o %s -j %s%d",\r
1137 chain_postrouting, ip->addr, 32*(1+ip->v6),\r
1138 lan, mark_iptables, ip->mark);\r
1139 /* -m limit --limit 1/s */ \r
1140 iptables_save_line(str, ip->v6);\r
1141\r
1142 if(qos_proxy)\r
1143 {\r
1144 sprintf(str, "-A %s -s %s -p tcp --sport %d -d %s/%d -o %s -j %s%d",\r
1145 chain_postrouting, proxy_ip, proxy_port, ip->addr,\r
1146 32*(1+ip->v6), lan, mark_iptables, ip->mark);\r
1147 iptables_save_line(str, ip->v6);\r
1148 }\r
1149\r
1150 /* this will be optional in future - hardcoded for now*/\r
1151 sprintf(limit_pkts,"-m limit --limit %d/s ", ip->pps_limit);\r
1152\r
1153 sprintf(str, "-A %s -d %s/%d -o %s %s-j ACCEPT",\r
1154 chain_postrouting, ip->addr, 32*(1+ip->v6), lan, limit_pkts);\r
1155 iptables_save_line(str, ip->v6);\r
1156\r
1157 /* -------------------------------------------------------- mark upload */\r
1158 sprintf(str, "-A %s -s %s/%d -o %s -j %s%d", \r
1159 chain_forward, ip->addr, 32*(1+ip->v6), wan, mark_iptables, ip->mark);\r
1160 iptables_save_line(str, ip->v6);\r
1161\r
1162 sprintf(str, "-A %s -s %s/%d -o %s %s-j ACCEPT",\r
1163 chain_forward, ip->addr, 32*(1+ip->v6), wan, limit_pkts);\r
1164 iptables_save_line(str, ip->v6);\r
1165\r
1166 if(ip->min)\r
1167 {\r
1168 /* -------------------------------------------------------- download class */\r
1169#ifdef DEBUG\r
1170 printf("(down: %dk-%dk ", ip->min, ip->max); \r
1171#endif\r
1172\r
1173 sprintf(str, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
1174 tc, lan, ip->group, ip->mark, ip->min, ip->max, burst, ip->prio);\r
1175 safe_run(str);\r
1176\r
1177 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
1178 {\r
1179 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s", \r
1180 tc, lan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
1181 safe_run(str);\r
1182 }\r
1183\r
1184 if(filter_type == 1)\r
1185 {\r
1186 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
1187 tc, lan, ip->mark, ip->mark);\r
1188 safe_run(str);\r
1189 }\r
1190\r
1191 /* -------------------------------------------------------- upload class */\r
1192#ifdef DEBUG\r
1193 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1194 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
1195#endif\r
1196\r
1197 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1198 tc, wan, ip->group, ip->mark,\r
1199 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1200 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1201 safe_run(str);\r
1202 \r
1203 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
1204 {\r
1205 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s",\r
1206 tc, wan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
1207 safe_run(str);\r
1208 } \r
1209\r
1210 if(filter_type == 1)\r
1211 {\r
1212 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
1213 tc, wan, ip->mark, ip->mark);\r
1214 safe_run(str);\r
1215 }\r
1216 \r
1217 if(f > 0)\r
1218 {\r
1219 fprintf(f, "%s %d\n", ip->addr, ip->mark);\r
1220 }\r
1221 }\r
1222 else\r
1223 {\r
1224#ifdef DEBUG\r
1225 printf("(sharing %s)\n", ip->sharing);\r
1226#endif\r
1227 }\r
1228 i++;\r
1229 }\r
1230 if(f > 0)\r
1231 {\r
1232 puts("done.");\r
1233 fclose(f);\r
1234 }\r
1235 \r
1236 if(idxs)\r
1237 {\r
1238 chain_forward = "forw_common";\r
1239 chain_postrouting = "post_common";\r
1240 }\r
1241 else\r
1242 {\r
1243 chain_forward = "FORWARD";\r
1244 chain_postrouting = "POSTROUTING";\r
1245 }\r
1246\r
1247 if(free_min)\r
1248 {\r
1249 final_chain = "ACCEPT";\r
1250 }\r
1251\r
1252 if(qos_proxy)\r
1253 {\r
1254 if(free_min) \r
1255 {\r
1256 sprintf(str, "-A %s -s %s -p tcp --sport %d -o %s -j %s%d",\r
1257 chain_postrouting,proxy_ip,proxy_port,lan,mark_iptables, 3);\r
1258 iptables_save_line(str, FALSE); /* only for IPv4 */\r
1259 }\r
1260 sprintf(str, "-A %s -s %s -p tcp --sport %d -o %s -j %s",\r
1261 chain_postrouting,proxy_ip,proxy_port,lan,final_chain);\r
1262 iptables_save_line(str, FALSE); /* only for IPv4 */\r
1263 }\r
1264\r
1265 if(free_min)\r
1266 {\r
1267 sprintf(str, "-A %s -o %s -j %s%d",\r
1268 chain_postrouting, lan, mark_iptables, 3);\r
1269 iptables_save_line(str, FALSE); /* only for IPv4 */\r
1270 }\r
1271\r
1272 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
1273 iptables_save_line(str, FALSE);\r
1274 if(ip6prefix)\r
1275 {\r
1276 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
1277 iptables_save_line(str, TRUE);\r
1278 }\r
1279\r
1280 if(free_min)\r
1281 {\r
1282 sprintf(str,"-A %s -o %s -j %s%d", chain_forward, wan, mark_iptables, 3);\r
1283 iptables_save_line(str, FALSE); /* only for IPv4 */\r
1284 }\r
1285\r
1286 sprintf(str,"-A %s -o %s -j %s", chain_forward, wan, final_chain);\r
1287 iptables_save_line(str, FALSE);\r
1288 if(ip6prefix)\r
1289 {\r
1290 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
1291 iptables_save_line(str, TRUE);\r
1292 }\r
1293\r
1294 if(free_min) /* allocate free bandwith if it is not zero... */ \r
1295 {\r
1296 /*-----------------------------------------------------------------*/\r
1297 puts("Generating free bandwith classes ...");\r
1298 /*-----------------------------------------------------------------*/\r
1299 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1300 tc, lan, parent, free_min, free_max,burst, lowest_priority);\r
1301 safe_run(str);\r
1302 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1303 tc, wan, parent, free_min, free_max, burst, lowest_priority);\r
1304 safe_run(str);\r
1305 /* tc SFQ */\r
1306 if(strcmpi(qos_leaf, "none"))\r
1307 {\r
1308 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, lan, qos_leaf);\r
1309 safe_run(str);\r
1310 \r
1311 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, wan, qos_leaf);\r
1312 safe_run(str);\r
1313 } \r
1314 /* tc handle 1 fw flowid */\r
1315 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, lan);\r
1316 safe_run(str);\r
1317\r
1318 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, wan);\r
1319 safe_run(str);\r
1320 }\r
1321 printf("Total IP count: %d\n", i);\r
1322 run_iptables_restore();\r
1323 if(log_file)\r
1324 {\r
1325 fclose(log_file);\r
1326 }\r
1327 return 0;\r
1328 /* that's all folks, thank you for reading it all the way up to this point ;-) */\r
1329 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */\r
1330}\r
This page took 0.216589 seconds and 4 git commands to generate.