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