b4de143676ff19ec7a58c47c800ec895de2951ef
1 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2 /* Prometheus QoS - you can "steal fire" from your ISP */
3 /* "fair-per-IP" quality of service (QoS) utility */
4 /* requires Linux 2.4.x or 2.6.x with HTB support */
5 /* Copyright(C) 2005-2013 Michael Polak, Arachne Aerospace */
6 /* iptables-restore support Copyright(C) 2007-2008 ludva */
7 /* Credit: CZFree.Net,Martin Devera,Netdave,Aquarius,Gandalf */
8 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
10 /* Modified by: xChaos, 20130114
13 Prometheus QoS is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2.1 of
16 the License, or (at your option) any later version.
18 Prometheus QoS is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with Prometheus Qos; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 GNU General Public License is located in file COPYING */
29 #include "cll1-0.6.2.h"
32 const char *version
= "0.8.3-g";
34 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
35 /* Versions: 0.8.3 is development release, 0.8.4 will be "stable" */
36 /* Official Trac URL: https://dev.arachne.cz/svn/prometheus */
37 /* Official SVN URL: https://dev.arachne.cz/repos/prometheus */
38 /* BTC donations account: 19rriLx8vR19wGefPaMhakqnCYNYwjLvxq */
39 /* CZK donations account: 2900242944/2010 (transparent account) */
40 /* Warning: unofficial Github mirror is not supported by author! */
41 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
43 const 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";
48 /* ======= All path names are defined here (for RPM patch) ======= */
50 const char *tc
= "/sbin/tc"; /* requires tc with HTB support */
51 const char *iptables
= "/sbin/iptables"; /* requires iptables utility */
52 const char *ip6tables
= "/sbin/ip6tables"; /* requires iptables utility */
53 const char *iptablessave
= "/sbin/iptables-save"; /* not yet required */
54 const char *iptablesrestore
= "/sbin/iptables-restore"; /* requires iptables-restore */
55 const char *ip6tablessave
= "/sbin/ip6tables-save"; /* not yet required */
56 const char *ip6tablesrestore
= "/sbin/ip6tables-restore"; /* requires iptables-restore */
57 const char *ls
= "/bin/ls"; /* this is not user configurable :-) */
59 char *config
= "/etc/prometheus/prometheus.conf"; /* main configuration file */
60 char *hosts
= "/etc/prometheus/hosts"; /* per-IP bandwidth definition file */
61 char *iptablesfile
= "/var/spool/prometheus.iptables"; /* temporary file for iptables-restore*/
62 char *credit
= "/var/lib/misc/prometheus.credit"; /* credit log file */
63 char *classmap
= "/var/lib/misc/prometheus.classes"; /* credit log file */
64 char *html
= "/var/www/traffic.html"; /* hall of fame - html version */
65 char *preview
= "/var/www/preview.html"; /* hall of fame preview - html version */
66 char *json_traffic
= "/var/www/logs/traffic.json"; /* hall of fame - json version */
67 char *json_preview
= "/var/www/logs/preview.json"; /* hall of fame preview - json version */
68 char *cmdlog
= "/var/log/prometheuslog"; /* command log filename */
69 char *log_dir
= "/var/www/logs/"; /* log directory pathname, ended with slash */
70 char *log_url
= "/logs/"; /* log directory relative URI prefix (partial URL) */
71 char *html_log_dir
= "/var/www/logs/html/";
73 char *jquery_url
= "http://code.jquery.com/jquery-latest.js";
74 char *lms_url
= "/lms/?m=customerinfo&id=";
75 int use_jquery_popups
= TRUE
;
76 int row_odd_even
= 0; /*<tr class="odd/even"> */
78 /* === Configuraration file values defaults - stored in global variables ==== */
80 int filter_type
= 1; /*1 mark, 2 classify*/
82 char *mark_iptables
= "MARK --set-mark ";
83 int dry_run
= FALSE
; /* preview - use puts() instead of system() */
84 char *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]";
85 FILE *iptables_file
= NULL
;
86 int enable_credit
= TRUE
; /* enable credit file */
87 int use_credit
= FALSE
; /* use credit file (if enabled)*/
88 char *title
= "Hall of Fame - Greatest Suckers"; /* hall of fame title */
89 int hall_of_fame
= TRUE
; /* enable hall of fame */
90 char *lan
= "eth0"; /* LAN interface */
91 char *lan_medium
= "100Mbit"; /* 10Mbit/100Mbit ethernet */
92 char *wan
= "eth1"; /* WAN/ISP interface */
93 char *wan_medium
= "100Mbit"; /* 10Mbit/100Mbit ethernet */
94 char *qos_leaf
= "sfq perturb 5"; /* leaf discipline */
95 char *qos_free_zone
= NULL
; /* QoS free zone */
96 int qos_proxy
= TRUE
; /* include proxy port to QoS */
97 int found_lmsid
= FALSE
; /* show links to users in LMS information system */
98 int include_upload
= TRUE
; /* upload+download=total traffic */
99 char *proxy_ip
= "192.168.1.1/32"; /* our IP with proxy port */
100 int proxy_port
= 3128; /* proxy port number */
101 long long int line
= 1024; /* WAN/ISP download in kbps */
102 long long int up
= 1024; /* WAN/ISP upload in kbps */
103 int free_min
= 32; /* minimum guaranted bandwidth for all undefined hosts */
104 int free_max
= 64; /* maximum allowed bandwidth for all undefined hosts */
105 int qos_free_delay
= 0; /* seconds to sleep before applying new QoS rules */
106 int digital_divide
= 2; /* controls digital divide weirdness ratio, 1...3 */
107 int max_nesting
= 3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */
108 int htb_r2q
= 256; /* should work for leaf values 512 kbps to 8 Mbps */
109 int burst
= 8; /* HTB burst (in kbits) */
111 int burst_group
= 32;
112 int magic_treshold
= 8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */
113 int keywordcount
= 0;
116 /* not yet implemented:
117 int fixed_packets = 0; maximum number of pps per IP address (not class!)
118 int packet_limit = 5; maximum number of pps to htn CEIL, not rate !!!
120 FILE *log_file
= NULL
;
121 char *kwd
= "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */
123 const int highest_priority
= 0; /* highest HTB priority (HTB built-in value is 0) */
124 const int lowest_priority
= 7; /* lowest HTB priority (HTB built-in value is 7) */
125 const int idxtable_treshold1
= 24; /* this is no longer configurable */
126 const int idxtable_treshold2
= 12; /* this is no longer configurable */
127 const int idxtable_bitmask1
= 3; /* this is no longer configurable */
128 const int idxtable_bitmask2
= 3; /* this is no longer configurable */
130 struct IP
*ips
= NULL
, *ip
, *sharedip
;
131 struct Group
*groups
= NULL
, *group
;
132 struct Keyword
*keyword
, *defaultkeyword
=NULL
, *keywords
=NULL
;
135 /* implemented in help.c */
137 void get_traffic_statistics(const char *whichiptables
);
138 /* implemented in parseiptables.c */
140 void parse_ip_log(int argc
, char **argv
);
141 /* implemented in parselog.c */
143 void parse_hosts(char *hosts
);
144 /* implemented in parsehosts.c */
146 void write_json_traffic(char *json
);
147 /* implemented in json.c */
149 void write_htmlandlogs(char *html
, char *d
, int total
, int just_preview
);
150 /* implemented in htmlandlogs.c */
152 const char *tr_odd_even(void)
154 row_odd_even
= 1 - row_odd_even
;
157 return "<tr class=\"even\">\n";
161 return "<tr class=\"odd\">\n";
165 /* ==== This is C<<1 stuff - learn C<<1 first! https://dev.arachne.cz/svn/cll1h ==== */
166 /* (except that this code uses obsolete, archaic version of this header file...) */
172 struct Index
*parent
;
176 } *idxs
=NULL
, *idx
, *metaindex
;
179 /* ====== iptables indexes are used to reduce complexity to log8(N) ===== */
181 char *index_id(char *ip
, int bitmask
);
182 /* function implemented in ipv4subnets.c */
184 char *subnet_id(char *ip
, int bitmask
);
185 /* function implemented in ipv4subnets.c */
187 /* ================= Let's parse configuration file here ================ */
189 void reject_config_and_exit(char *filename
)
191 printf("Configuration file %s rejected - abnormal exit.",filename
);
195 void get_config(char *config_filename
)
199 printf("Configured keywords: ");
200 parse(config_filename
)
202 option("keyword",kwd
);
207 create(keyword
,Keyword
);
209 keyword
->asymetry_ratio
=1; /* ratio for ADSL-like upload */
210 keyword
->asymetry_fixed
=0; /* fixed treshold for ADSL-like upload */
211 keyword
->data_limit
=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */
212 keyword
->data_prio
=4; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */
213 keyword
->fixed_limit
=0; /* fixed data limit for setting lower HTB ceil */
214 keyword
->fixed_prio
=0; /* fixed data limit for setting lower HTB prio */
215 keyword
->reserve_min
=8; /* bonus for nominal HTB rate bandwidth (in kbps) */
216 keyword
->reserve_max
=0; /* malus for nominal HTB ceil (in kbps) */
217 keyword
->default_prio
=highest_priority
+1;
218 keyword
->html_color
="000000";
220 keyword
->leaf_discipline
="";
222 push(keyword
,keywords
);
225 defaultkeyword
=keyword
;
233 for_each(keyword
,keywords
)
235 int l
=strlen(keyword
->key
);
237 if(!strncmp(keyword
->key
,_
,l
) && strlen(_
)>l
+2)
239 char *tmptr
=_
; /* <---- l+1 ----> */
240 _
+=l
+1; /* via-prometheus-asymetry-ratio, etc. */
241 ioption("asymetry-ratio",keyword
->asymetry_ratio
);
242 ioption("asymetry-treshold",keyword
->asymetry_fixed
);
243 ioption("magic-relative-limit",keyword
->data_limit
);
244 ioption("magic-relative-prio",keyword
->data_prio
);
245 loption("magic-fixed-limit",keyword
->fixed_limit
);
246 loption("magic-fixed-prio",keyword
->fixed_prio
);
247 ioption("htb-default-prio",keyword
->default_prio
);
248 ioption("htb-rate-bonus",keyword
->reserve_min
);
249 ioption("htb-ceil-malus",keyword
->reserve_max
);
250 option("leaf-discipline",keyword
->leaf_discipline
);
251 option("html-color",keyword
->html_color
);
254 if(keyword
->data_limit
|| keyword
->fixed_limit
||
255 keyword
->data_prio
|| keyword
->fixed_prio
)
264 option("iptables",iptables
);
265 option("iptables-save",iptablessave
); /* new */
266 option("iptables-restore",iptablesrestore
); /* new */
267 option("ip6tables",ip6tables
);
268 option("ip6tables-save",ip6tablessave
); /* new */
269 option("ip6tables-restore",ip6tablesrestore
); /* new */
270 option("iptables-in-filename",iptablesfile
); /* new */
271 option("hosts",hosts
);
272 option("lan-interface",lan
);
273 option("wan-interface",wan
);
274 option("lan-medium",lan_medium
);
275 option("wan-medium",wan_medium
);
276 lloption("wan-download",line
);
277 lloption("wan-upload",up
);
278 ioption("hall-of-fame-enable",hall_of_fame
);
279 option("hall-of-fame-title",title
);
280 option("hall-of-fame-filename",html
);
281 option("json-filename",json_traffic
);
282 option("hall-of-fame-preview",preview
);
283 option("json-preview",json_preview
);
284 option("log-filename",cmdlog
);
285 option("credit-filename",credit
);
286 option("classmap-filename",classmap
);
287 ioption("credit-enable",enable_credit
);
288 option("log-traffic-directory",log_dir
);
289 option("log-traffic-html-directory",html_log_dir
);
290 option("log-traffic-url-path",log_url
);
291 option("jquery-url",jquery_url
);
292 option("lms-url",lms_url
);
293 ioption("use-jquery-popups",use_jquery_popups
);
294 option("qos-free-zone",qos_free_zone
);
295 ioption("qos-free-delay",qos_free_delay
);
296 ioption("qos-proxy-enable",qos_proxy
);
297 option("qos-proxy-ip",proxy_ip
);
298 option("htb-leaf-discipline",qos_leaf
);
299 ioption("qos-proxy-port",proxy_port
);
300 ioption("free-rate",free_min
);
301 ioption("free-ceil",free_max
);
302 ioption("htb-burst",burst
);
303 ioption("htb-burst-main",burst_main
);
304 ioption("htb-burst-group",burst_group
);
305 ioption("htb-nesting-limit",max_nesting
);
306 ioption("htb-r2q",htb_r2q
);
307 ioption("magic-include-upload",include_upload
);
308 ioption("magic-treshold",magic_treshold
);
309 option("filter-type", cnf
);
310 /* not yet implemented:
311 ioption("magic-fixed-packets",fixed_packets);
312 ioption("magic-relative-packets",packet_limit);
317 perror(config_filename
);
318 puts("Warning - using built-in defaults instead ...");
320 done
; /* ugly macro end */
323 /* leaf discipline for keywords */
324 for_each(keyword
,keywords
)
326 if(!strcmpi(keyword
->leaf_discipline
, ""))
328 keyword
->leaf_discipline
= qos_leaf
;
332 if(strcmpi(cnf
, "mark"))
336 mark_iptables
= "CLASSIFY --set-class 1:";
342 mark_iptables
= "MARK --set-mark ";
345 /* are supplied values meaningful ?*/
348 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");
349 reject_config_and_exit(config_filename
);
354 /* ========== This function executes, logs OR ALSO prints command ========== */
356 void safe_run(char *cmd
)
360 printf("\n=>%s\n",cmd
);
368 fprintf(log_file
,"%s\n",cmd
);
372 void save_line(char *line
)
374 fprintf(iptables_file
,"%s\n",line
);
377 void run_restore(void)
380 string(restor
,STRLEN
);
382 /*-----------------------------------------------------------------*/
383 printf("Running %s <%s ...\n", iptablesrestore
, iptablesfile
);
384 /*-----------------------------------------------------------------*/
387 fclose(iptables_file
);
394 done
; /* ugly macro end */
397 sprintf(restor
,"%s <%s",iptablesrestore
, iptablesfile
);
403 char *parse_datafile_line(char *str
)
405 char *ptr
=strchr(str
,' ');
420 /*-----------------------------------------------------------------*/
421 /* Are you looking for int main(int argc, char **argv) ? :-)) */
422 /*-----------------------------------------------------------------*/
426 int i
=0; /* just plain old Fortran style integer :-) */
427 FILE *f
=NULL
; /* everything is just stream of bytes... */
428 char *str
, *ptr
, *d
; /* LET A$=B$ :-) */
432 int just_flush
= FALSE
; /* deactivates all previous actions */
434 int just_preview
= FALSE
; /* preview - generate just stats */
435 int start_shaping
= FALSE
; /* apply FUP - requires classmap file */
436 int just_logs
= FALSE
; /* just parse logs */
440 char *chain_forward
, *chain_postrouting
;
444 Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\
445 Version %s - Copyright (C)2005-2012 Michael Polak, Arachne Labs\n\
446 iptables-restore & burst tunning & classify modification by Ludva\n\
447 Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version
);
449 /*----- Boring... we have to check command line options first: ----*/
452 argument("-c") { nextargument(config
); }
453 argument("-h") { nextargument(althosts
);}
454 argument("-d") { run
=TRUE
; dry_run
=TRUE
; }
455 argument("-f") { run
=TRUE
; just_flush
=TRUE
; }
456 argument("-9") { run
=TRUE
; just_flush
=9; }
457 argument("-p") { run
=TRUE
; just_preview
=TRUE
; }
458 argument("-s") { run
=TRUE
; just_preview
=TRUE
; start_shaping
=TRUE
; }
459 argument("-r") { run
=TRUE
; }
460 argument("-n") { run
=TRUE
; nodelay
=TRUE
; }
461 argument("-l") { just_logs
=TRUE
; }
462 argument("-m") { just_logs
=TRUE
; }
463 argument("-y") { just_logs
=TRUE
; }
464 argument("-?") { help(); exit(0); }
465 argument("--help") { help(); exit(0); }
466 argument("-v") { exit(0); }
467 argument("--version") { exit(0); }
472 puts("*** THIS IS JUST DRY RUN ! ***\n");
475 date(d
); /* this is typical cll1.h macro - prints current date */
477 /*-----------------------------------------------------------------*/
478 printf("Parsing configuration file %s ...\n", config
);
479 /*-----------------------------------------------------------------*/
484 parse_ip_log(argc
,argv
);
500 /*-----------------------------------------------------------------*/
501 puts("Parsing iptables verbose output ...");
502 /*-----------------------------------------------------------------*/
503 get_traffic_statistics(iptables
);
506 /*-----------------------------------------------------------------*/
507 printf("Parsing class defintion file %s ...\n", hosts
);
508 /*-----------------------------------------------------------------*/
511 /*-----------------------------------------------------------------*/
512 /* cll1.h - let's allocate brand new character buffer... */
513 /*-----------------------------------------------------------------*/
516 /*-----------------------------------------------------------------*/
517 puts("Resolving shared connections ...");
518 /*-----------------------------------------------------------------*/
519 for_each(ip
,ips
) if(ip
->sharing
)
521 for_each(sharedip
,ips
) if(eq(sharedip
->name
,ip
->sharing
))
523 sharedip
->traffic
+=ip
->traffic
;
525 ip
->mark
=sharedip
->mark
;
526 ip
->lmsid
=sharedip
->lmsid
;
531 printf("Unresolved shared connection: %s %s sharing-%s\n",
532 ip
->addr
, ip
->name
, ip
->sharing
);
536 if(enable_credit
&& just_flush
<9)
538 /*-----------------------------------------------------------------*/
539 printf("Parsing credit file %s ...\n", credit
);
540 /*-----------------------------------------------------------------*/
543 ptr
=parse_datafile_line(_
);
546 if_exists(ip
,ips
,eq(ip
->addr
,_
))
548 sscanf(ptr
,"%Lu",&(ip
->credit
));
552 done
; /* ugly macro end */
557 /*-----------------------------------------------------------------*/
558 puts("Initializing iptables and tc classes ...");
559 /*-----------------------------------------------------------------*/
561 iptables_file
=fopen(iptablesfile
,"w");
562 if(iptables_file
== NULL
)
564 puts("Cannot open iptablesfile!");
568 log_file
=fopen(cmdlog
,"w");
571 puts("Cannot open logfile!");
575 save_line(iptablespreamble
);
578 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,lan
);
581 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,wan
);
584 iptables_file
=fopen(iptablesfile
,"w");
585 save_line(iptablespreamble
);
587 if(qos_free_zone
&& *qos_free_zone
!='0')
591 sprintf(str
,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone
, wan
);
596 save_line(":post_noproxy - [0:0]");
597 sprintf(str
,"-A POSTROUTING ! -p tcp -o %s -j post_noproxy", lan
);
599 sprintf(str
,"-A POSTROUTING ! -s %s -o %s -j post_noproxy", proxy_ip
, lan
);
601 sprintf(str
,"-A POSTROUTING -s %s -p tcp ! --sport %d -o %s -j post_noproxy", proxy_ip
, proxy_port
, lan
);
604 chain
="post_noproxy";
611 sprintf(str
,"-A %s -s %s -o %s -j ACCEPT", chain
, qos_free_zone
, lan
);
615 if(ip_count
>idxtable_treshold1
&& !just_flush
)
617 int idxcount
=0, bitmask
=32-idxtable_bitmask1
; /* default net mask: 255.255.255.240 */
619 /*-----------------------------------------------------------------*/
620 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count
);
621 /*-----------------------------------------------------------------*/
623 save_line(":post_common - [0:0]");
624 save_line(":forw_common - [0:0]");
626 for_each(ip
,ips
) if(ip
->addr
&& *(ip
->addr
) && !eq(ip
->addr
,"0.0.0.0/0"))
628 buf
=index_id(ip
->addr
,bitmask
);
629 if_exists(idx
,idxs
,eq(idx
->id
,buf
))
638 idx
->bitmask
=bitmask
;
646 /* brutal perfomance optimalization */
647 while(idxcount
>idxtable_treshold2
&& bitmask
>2*idxtable_bitmask2
)
649 bitmask
-=idxtable_bitmask2
;
652 for_each(idx
,idxs
) if(idx
->parent
== NULL
)
654 buf
=index_id(idx
->addr
,bitmask
);
655 if_exists(metaindex
,idxs
,eq(metaindex
->id
,buf
))
657 metaindex
->children
++;
661 create(metaindex
,Index
);
662 metaindex
->addr
=idx
->addr
;
664 metaindex
->bitmask
=bitmask
;
665 metaindex
->parent
=NULL
;
666 metaindex
->children
=0;
668 push(metaindex
,idxs
);
670 idx
->parent
=metaindex
;
674 /* this should slightly optimize throughout ... */
675 sort(idx
,idxs
,desc_order_by
,children
);
676 sort(idx
,idxs
,order_by
,bitmask
);
681 subnet
=subnet_id(idx
->addr
,idx
->bitmask
);
682 printf("%d: %s/%d\n",
683 ++i
, subnet
, idx
->bitmask
);
685 sprintf(str
,":post_%s - [0:0]", idx
->id
);
688 sprintf(str
,":forw_%s - [0:0]", idx
->id
);
693 string(buf
,strlen(idx
->parent
->id
)+6);
694 sprintf(buf
,"post_%s",idx
->parent
->id
);
701 sprintf(str
,"-A %s -d %s/%d -o %s -j post_%s", buf
, subnet
, idx
->bitmask
, lan
, idx
->id
);
704 sprintf(str
,"-A %s -d %s/%d -o %s -j post_common", buf
, subnet
, idx
->bitmask
, lan
);
709 string(buf
,strlen(idx
->parent
->id
)+6);
710 sprintf(buf
,"forw_%s",idx
->parent
->id
);
717 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_%s", buf
, subnet
, idx
->bitmask
, wan
, idx
->id
);
720 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_common", buf
, subnet
, idx
->bitmask
, wan
);
723 printf("Total indexed iptables chains created: %d\n", i
);
725 sprintf(str
,"-A FORWARD -o %s -j forw_common", wan
);
728 sprintf(str
,"-A POSTROUTING -o %s -j post_common", lan
);
736 fclose(iptables_file
);
741 puts("Just flushed iptables and tc classes - now exiting ...");
747 if(!dry_run
&& !nodelay
&& qos_free_delay
)
749 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay
);
750 sleep(qos_free_delay
);
753 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",
757 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
758 tc
,lan
,lan_medium
,lan_medium
,burst_main
,highest_priority
);
761 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
762 tc
,lan
,line
,line
,burst_main
,highest_priority
);
765 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc
,wan
,htb_r2q
);
768 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
769 tc
,wan
,wan_medium
,wan_medium
,burst_main
,highest_priority
);
772 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
773 tc
,wan
,up
,up
,burst_main
,highest_priority
);
777 /*-----------------------------------------------------------------*/
778 puts("Locating heavy downloaders and generating root classes ...");
779 /*-----------------------------------------------------------------*/
780 sort(ip
,ips
,desc_order_by
,traffic
);
782 /*-----------------------------------------------------------------*/
783 /* sub-scope - local variables */
785 long long int rate
= line
;
786 long long int max
= line
;
788 FILE *credit_file
= NULL
;
790 if(!just_preview
&& !dry_run
&& enable_credit
)
792 credit_file
= fopen(credit
,"w");
795 for_each(group
,groups
)
800 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",
801 tc
, lan
, parent
, group
->id
, rate
, max
, burst_group
, highest_priority
+1, group
->desired
);
805 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",
806 tc
, wan
, parent
, group
->id
, rate
*up
/line
, max
*up
/line
, burst_group
, highest_priority
+1, group
->desired
);
810 if(group_count
++ < max_nesting
)
815 rate
-= digital_divide
*group
->min
;
816 if(rate
< group
->min
)
821 /*shaping of aggresive downloaders, with credit file support */
824 int group_rate
= group
->min
, priority_sequence
= lowest_priority
;
826 for_each(ip
, ips
) if(ip
->min
== group
->min
&& ip
->max
> ip
->min
)
828 ip
->realquota
=ip
->credit
+(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20));
829 if( ip
->keyword
->data_limit
830 and not ip
->fixedprio
831 and ip
->traffic
> ip
->realquota
)
833 if(group_rate
< ip
->max
)
835 ip
->max
= group_rate
;
837 group_rate
+=magic_treshold
;
838 ip
->prio
=lowest_priority
;
839 if(ip
->prio
<highest_priority
+2)
841 ip
->prio
=highest_priority
+2;
846 if( ip
->keyword
->data_prio
848 && ( ip
->traffic
>ip
->credit
849 + (ip
->min
*ip
->keyword
->data_prio
+(ip
->keyword
->fixed_prio
<<20))) )
851 ip
->prio
=priority_sequence
--;
852 if(ip
->prio
<highest_priority
+1)
854 ip
->prio
=highest_priority
+1;
860 unsigned long long lcredit
=0;
862 if((ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))>ip
->traffic
)
864 lcredit
=(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))-ip
->traffic
;
866 fprintf(credit_file
,"%s %Lu\n",ip
->addr
,lcredit
);
882 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap
);
890 if_exists(ip
,ips
,eq(ip
->addr
,_
))
893 if(ip
->max
< ip
->desired
) /* apply FUP limit immediately.... */
895 printf("Applying limit for %-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
896 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
897 sprintf(str
, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
898 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
900 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
901 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
902 sprintf(str
,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
903 tc
, wan
, ip
->group
, ip
->mark
,
904 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
905 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
914 puts("Warning - classmap file not fund, just generating preview ...");
917 done
; /* ugly macro end */
920 json_traffic
=json_preview
;
923 if(!dry_run
&& !just_flush
)
925 /*-----------------------------------------------------------------*/
926 printf("Writing json traffic overview %s ... ", json_traffic
);
927 /*-----------------------------------------------------------------*/
928 write_json_traffic(json_traffic
);
931 /*-----------------------------------------------------------------*/
932 printf("Writing statistics into HTML page %s ...\n", html
);
933 /*-----------------------------------------------------------------*/
934 write_htmlandlogs(html
, d
,total
, just_preview
);
943 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar
);
949 printf("%-22s %-15s mark\n","name","ip");
952 printf("Writing %s ... ", classmap
);
953 f
= fopen(classmap
, "w");
959 /*-----------------------------------------------------------------*/
960 puts("Generating iptables and tc classes ... ");
961 /*-----------------------------------------------------------------*/
963 for_each(ip
, ips
) if(ip
->mark
> 0)
968 duplicate(ip
->addr
,buf
);
969 buf
=index_id(ip
->addr
,32-idxtable_bitmask1
);
971 string(chain_forward
,6+strlen(buf
));
972 strcpy(chain_forward
,"forw_");
973 strcat(chain_forward
,buf
);
975 string(chain_postrouting
,6+strlen(buf
));
976 strcpy(chain_postrouting
,"post_");
977 strcat(chain_postrouting
,buf
);
983 chain_forward
="FORWARD";
984 chain_postrouting
="POSTROUTING";
988 printf("%-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
991 /* -------------------------------------------------------- mark download */
993 sprintf(str
, "-A %s -d %s/32 -o %s -j %s%d",
994 chain_postrouting
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
995 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/
996 /* -m limit --limit 1/s */
1001 sprintf(str
, "-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",
1002 chain_postrouting
, proxy_ip
, proxy_port
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
1003 /*sprintf(str,"-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,proxy_ip,proxy_port,ip->addr,lan,ip->mark);*/
1007 sprintf(str
, "-A %s -d %s/32 -o %s -j ACCEPT",
1008 chain_postrouting
, ip
->addr
, lan
);
1011 /* -------------------------------------------------------- mark upload */
1012 sprintf(str
, "-A %s -s %s/32 -o %s -j %s%d",
1013 chain_forward
, ip
->addr
, wan
, mark_iptables
, ip
->mark
);
1014 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/
1017 sprintf(str
, "-A %s -s %s/32 -o %s -j ACCEPT",
1018 chain_forward
, ip
->addr
, wan
);
1023 /* -------------------------------------------------------- download class */
1025 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
1028 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1029 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1032 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1034 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1035 tc
, lan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1039 if(filter_type
== 1)
1041 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1042 tc
, lan
, ip
->mark
, ip
->mark
);
1046 /* -------------------------------------------------------- upload class */
1048 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1049 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1052 sprintf(str
,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1053 tc
, wan
, ip
->group
, ip
->mark
,
1054 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1055 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1058 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1060 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1061 tc
, wan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1065 if(filter_type
== 1)
1067 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1068 tc
, wan
, ip
->mark
, ip
->mark
);
1074 fprintf(f
, "%s %d\n", ip
->addr
, ip
->mark
);
1080 printf("(sharing %s)\n", ip
->sharing
);
1093 chain_forward
= "forw_common";
1094 chain_postrouting
= "post_common";
1098 chain_forward
= "FORWARD";
1099 chain_postrouting
= "POSTROUTING";
1101 /* -------------------------------- classify or reject free download */
1103 char *final_chain
= "DROP"; /* REJECT would be better, but it is impossible in mangle */
1106 final_chain
= "ACCEPT";
1112 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s%d",
1113 chain_postrouting
,proxy_ip
,proxy_port
,lan
,mark_iptables
,3);
1116 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s",
1117 chain_postrouting
,proxy_ip
,proxy_port
,lan
,final_chain
);
1122 sprintf(str
,"-A %s -o %s -j %s%d", chain_postrouting
, lan
, mark_iptables
, 3);
1125 sprintf(str
,"-A %s -o %s -j %s", chain_postrouting
, lan
, final_chain
);
1127 /* ------------------------------- classify or reject free upload */
1130 sprintf(str
,"-A %s -o %s -j %s%d", chain_forward
, wan
, mark_iptables
, 3);
1133 sprintf(str
,"-A %s -o %s -j %s", chain_forward
, wan
, final_chain
);
1137 if(free_min
) /* allocate free bandwith if it is not zero... */
1139 /*-----------------------------------------------------------------*/
1140 puts("Generating free bandwith classes ...");
1141 /*-----------------------------------------------------------------*/
1142 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1143 tc
, lan
, parent
, free_min
, free_max
,burst
, lowest_priority
);
1145 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1146 tc
, wan
, parent
, free_min
, free_max
, burst
, lowest_priority
);
1149 if(strcmpi(qos_leaf
, "none"))
1151 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, lan
, qos_leaf
);
1154 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, wan
, qos_leaf
);
1157 /* tc handle 1 fw flowid */
1158 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, lan
);
1161 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, wan
);
1164 printf("Total IP count: %d\n", i
);
1171 /* that's all folks, thank you for reading it all the way up to this point ;-) */
1172 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */
This page took 0.96434 seconds and 3 git commands to generate.