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