70bea1f2355559c9dca504dde27523d95bc36558
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, 20130116
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-h";
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 *ip6tablesfile
= "/var/spool/prometheus.ip6tables"; /* temporary file for ip6tables-restore*/
63 char *credit
= "/var/lib/misc/prometheus.credit"; /* credit log file */
64 char *classmap
= "/var/lib/misc/prometheus.classes"; /* credit log file */
65 char *html
= "/var/www/traffic.html"; /* hall of fame - html version */
66 char *preview
= "/var/www/preview.html"; /* hall of fame preview - html version */
67 char *json_traffic
= "/var/www/logs/traffic.json"; /* hall of fame - json version */
68 char *json_preview
= "/var/www/logs/preview.json"; /* hall of fame preview - json version */
69 char *cmdlog
= "/var/log/prometheuslog"; /* command log filename */
70 char *log_dir
= "/var/www/logs/"; /* log directory pathname, ended with slash */
71 char *log_url
= "/logs/"; /* log directory relative URI prefix (partial URL) */
72 char *html_log_dir
= "/var/www/logs/html/";
74 char *jquery_url
= "http://code.jquery.com/jquery-latest.js";
75 char *lms_url
= "/lms/?m=customerinfo&id=";
76 int use_jquery_popups
= TRUE
;
77 int row_odd_even
= 0; /*<tr class="odd/even"> */
79 /* === Configuraration file values defaults - stored in global variables ==== */
81 int filter_type
= 1; /*1 mark, 2 classify*/
83 char *mark_iptables
= "MARK --set-mark ";
84 int dry_run
= FALSE
; /* preview - use puts() instead of system() */
85 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]";
86 FILE *iptables_file
= NULL
;
87 int enable_credit
= TRUE
; /* enable credit file */
88 int use_credit
= FALSE
; /* use credit file (if enabled)*/
89 char *title
= "Hall of Fame - Greatest Suckers"; /* hall of fame title */
90 int hall_of_fame
= TRUE
; /* enable hall of fame */
91 char *lan
= "eth0"; /* LAN interface */
92 char *lan_medium
= "100Mbit"; /* 10Mbit/100Mbit ethernet */
93 char *wan
= "eth1"; /* WAN/ISP interface */
94 char *ip6prefix
= NULL
; /* Prefix for global /48 IPv6 subnet */
95 char *wan_medium
= "100Mbit"; /* 10Mbit/100Mbit ethernet */
96 char *qos_leaf
= "sfq perturb 5"; /* leaf discipline */
97 char *qos_free_zone
= NULL
; /* QoS free zone */
98 int qos_proxy
= TRUE
; /* include proxy port to QoS */
99 int found_lmsid
= FALSE
; /* show links to users in LMS information system */
100 int include_upload
= TRUE
; /* upload+download=total traffic */
101 char *proxy_ip
= "192.168.1.1/32"; /* our IP with proxy port */
102 int proxy_port
= 3128; /* proxy port number */
103 long long int line
= 1024; /* WAN/ISP download in kbps */
104 long long int up
= 1024; /* WAN/ISP upload in kbps */
105 int free_min
= 32; /* minimum guaranted bandwidth for all undefined hosts */
106 int free_max
= 64; /* maximum allowed bandwidth for all undefined hosts */
107 int qos_free_delay
= 0; /* seconds to sleep before applying new QoS rules */
108 int digital_divide
= 2; /* controls digital divide weirdness ratio, 1...3 */
109 int max_nesting
= 3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */
110 int htb_r2q
= 256; /* should work for leaf values 512 kbps to 8 Mbps */
111 int burst
= 8; /* HTB burst (in kbits) */
113 int burst_group
= 32;
114 int magic_treshold
= 8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */
115 int keywordcount
= 0;
118 /* not yet implemented:
119 int fixed_packets = 0; maximum number of pps per IP address (not class!)
120 int packet_limit = 5; maximum number of pps to htn CEIL, not rate !!!
122 FILE *log_file
= NULL
;
123 char *kwd
= "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */
125 const int highest_priority
= 0; /* highest HTB priority (HTB built-in value is 0) */
126 const int lowest_priority
= 7; /* lowest HTB priority (HTB built-in value is 7) */
127 const int idxtable_treshold1
= 24; /* this is no longer configurable */
128 const int idxtable_treshold2
= 12; /* this is no longer configurable */
129 const int idxtable_bitmask1
= 3; /* this is no longer configurable */
130 const int idxtable_bitmask2
= 3; /* this is no longer configurable */
132 struct IP
*ips
= NULL
, *ip
, *sharedip
;
133 struct Group
*groups
= NULL
, *group
;
134 struct Keyword
*keyword
, *defaultkeyword
=NULL
, *keywords
=NULL
;
137 /* implemented in help.c */
139 void get_traffic_statistics(const char *whichiptables
);
140 /* implemented in parseiptables.c */
142 void parse_ip_log(int argc
, char **argv
);
143 /* implemented in parselog.c */
145 void parse_hosts(char *hosts
);
146 /* implemented in parsehosts.c */
148 void write_json_traffic(char *json
);
149 /* implemented in json.c */
151 void write_htmlandlogs(char *html
, char *d
, int total
, int just_preview
);
152 /* implemented in htmlandlogs.c */
154 const char *tr_odd_even(void)
156 row_odd_even
= 1 - row_odd_even
;
159 return "<tr class=\"even\">\n";
163 return "<tr class=\"odd\">\n";
167 /* ==== This is C<<1 stuff - learn C<<1 first! https://dev.arachne.cz/svn/cll1h ==== */
168 /* (except that this code uses obsolete, archaic version of this header file...) */
174 struct Index
*parent
;
178 } *idxs
=NULL
, *idx
, *metaindex
;
181 /* ====== iptables indexes are used to reduce complexity to log8(N) ===== */
183 char *index_id(char *ip
, int bitmask
);
184 /* function implemented in ipv4subnets.c */
186 char *subnet_id(char *ip
, int bitmask
);
187 /* function implemented in ipv4subnets.c */
189 /* ================= Let's parse configuration file here ================ */
191 void reject_config_and_exit(char *filename
)
193 printf("Configuration file %s rejected - abnormal exit.",filename
);
197 void get_config(char *config_filename
)
201 printf("Configured keywords: ");
202 parse(config_filename
)
204 option("keyword",kwd
);
209 create(keyword
,Keyword
);
211 keyword
->asymetry_ratio
=1; /* ratio for ADSL-like upload */
212 keyword
->asymetry_fixed
=0; /* fixed treshold for ADSL-like upload */
213 keyword
->data_limit
=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */
214 keyword
->data_prio
=4; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */
215 keyword
->fixed_limit
=0; /* fixed data limit for setting lower HTB ceil */
216 keyword
->fixed_prio
=0; /* fixed data limit for setting lower HTB prio */
217 keyword
->reserve_min
=8; /* bonus for nominal HTB rate bandwidth (in kbps) */
218 keyword
->reserve_max
=0; /* malus for nominal HTB ceil (in kbps) */
219 keyword
->default_prio
=highest_priority
+1;
220 keyword
->html_color
="000000";
222 keyword
->leaf_discipline
="";
224 push(keyword
,keywords
);
227 defaultkeyword
=keyword
;
235 for_each(keyword
,keywords
)
237 int l
=strlen(keyword
->key
);
239 if(!strncmp(keyword
->key
,_
,l
) && strlen(_
)>l
+2)
241 char *tmptr
=_
; /* <---- l+1 ----> */
242 _
+=l
+1; /* via-prometheus-asymetry-ratio, etc. */
243 ioption("asymetry-ratio",keyword
->asymetry_ratio
);
244 ioption("asymetry-treshold",keyword
->asymetry_fixed
);
245 ioption("magic-relative-limit",keyword
->data_limit
);
246 ioption("magic-relative-prio",keyword
->data_prio
);
247 loption("magic-fixed-limit",keyword
->fixed_limit
);
248 loption("magic-fixed-prio",keyword
->fixed_prio
);
249 ioption("htb-default-prio",keyword
->default_prio
);
250 ioption("htb-rate-bonus",keyword
->reserve_min
);
251 ioption("htb-ceil-malus",keyword
->reserve_max
);
252 option("leaf-discipline",keyword
->leaf_discipline
);
253 option("html-color",keyword
->html_color
);
256 if(keyword
->data_limit
|| keyword
->fixed_limit
||
257 keyword
->data_prio
|| keyword
->fixed_prio
)
266 option("iptables",iptables
);
267 option("iptables-save",iptablessave
);
268 option("iptables-restore",iptablesrestore
);
269 option("ip6tables",ip6tables
);
270 option("ip6tables-save",ip6tablessave
);
271 option("ip6tables-restore",ip6tablesrestore
);
272 option("iptables-in-filename",iptablesfile
);
273 option("ip6tables-in-filename",ip6tablesfile
);
274 option("hosts",hosts
);
275 option("lan-interface",lan
);
276 option("wan-interface",wan
);
277 option("ip6-prefix",ip6prefix
);
278 option("lan-medium",lan_medium
);
279 option("wan-medium",wan_medium
);
280 lloption("wan-download",line
);
281 lloption("wan-upload",up
);
282 ioption("hall-of-fame-enable",hall_of_fame
);
283 option("hall-of-fame-title",title
);
284 option("hall-of-fame-filename",html
);
285 option("json-filename",json_traffic
);
286 option("hall-of-fame-preview",preview
);
287 option("json-preview",json_preview
);
288 option("log-filename",cmdlog
);
289 option("credit-filename",credit
);
290 option("classmap-filename",classmap
);
291 ioption("credit-enable",enable_credit
);
292 option("log-traffic-directory",log_dir
);
293 option("log-traffic-html-directory",html_log_dir
);
294 option("log-traffic-url-path",log_url
);
295 option("jquery-url",jquery_url
);
296 option("lms-url",lms_url
);
297 ioption("use-jquery-popups",use_jquery_popups
);
298 option("qos-free-zone",qos_free_zone
);
299 ioption("qos-free-delay",qos_free_delay
);
300 ioption("qos-proxy-enable",qos_proxy
);
301 option("qos-proxy-ip",proxy_ip
);
302 option("htb-leaf-discipline",qos_leaf
);
303 ioption("qos-proxy-port",proxy_port
);
304 ioption("free-rate",free_min
);
305 ioption("free-ceil",free_max
);
306 ioption("htb-burst",burst
);
307 ioption("htb-burst-main",burst_main
);
308 ioption("htb-burst-group",burst_group
);
309 ioption("htb-nesting-limit",max_nesting
);
310 ioption("htb-r2q",htb_r2q
);
311 ioption("magic-include-upload",include_upload
);
312 ioption("magic-treshold",magic_treshold
);
313 option("filter-type", cnf
);
314 /* not yet implemented:
315 ioption("magic-fixed-packets",fixed_packets);
316 ioption("magic-relative-packets",packet_limit);
321 perror(config_filename
);
322 puts("Warning - using built-in defaults instead ...");
324 done
; /* ugly macro end */
327 /* leaf discipline for keywords */
328 for_each(keyword
,keywords
)
330 if(!strcmpi(keyword
->leaf_discipline
, ""))
332 keyword
->leaf_discipline
= qos_leaf
;
336 if(strcmpi(cnf
, "mark"))
340 mark_iptables
= "CLASSIFY --set-class 1:";
346 mark_iptables
= "MARK --set-mark ";
349 /* are supplied values meaningful ?*/
352 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");
353 reject_config_and_exit(config_filename
);
358 /* ========== This function executes, logs OR ALSO prints command ========== */
360 void safe_run(char *cmd
)
364 printf("\n=>%s\n",cmd
);
372 fprintf(log_file
,"%s\n",cmd
);
376 void save_line(char *line
)
378 fprintf(iptables_file
,"%s\n",line
);
381 void run_restore(void)
384 string(restor
,STRLEN
);
386 /*-----------------------------------------------------------------*/
387 printf("Running %s <%s ...\n", iptablesrestore
, iptablesfile
);
388 /*-----------------------------------------------------------------*/
391 fclose(iptables_file
);
398 done
; /* ugly macro end */
401 sprintf(restor
,"%s <%s",iptablesrestore
, iptablesfile
);
407 char *parse_datafile_line(char *str
)
409 char *ptr
=strchr(str
,' ');
424 /*-----------------------------------------------------------------*/
425 /* Are you looking for int main(int argc, char **argv) ? :-)) */
426 /*-----------------------------------------------------------------*/
430 int i
=0; /* just plain old Fortran style integer :-) */
431 FILE *f
=NULL
; /* everything is just stream of bytes... */
432 char *str
, *ptr
, *d
; /* LET A$=B$ :-) */
436 int just_flush
= FALSE
; /* deactivates all previous actions */
438 int just_preview
= FALSE
; /* preview - generate just stats */
439 int start_shaping
= FALSE
; /* apply FUP - requires classmap file */
440 int just_logs
= FALSE
; /* just parse logs */
444 char *chain_forward
, *chain_postrouting
;
448 Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\
449 Version %s - Copyright (C)2005-2012 Michael Polak, Arachne Labs\n\
450 iptables-restore & burst tunning & classify modification by Ludva\n\
451 Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version
);
453 /*----- Boring... we have to check command line options first: ----*/
456 argument("-c") { nextargument(config
); }
457 argument("-h") { nextargument(althosts
);}
458 argument("-d") { run
=TRUE
; dry_run
=TRUE
; }
459 argument("-f") { run
=TRUE
; just_flush
=TRUE
; }
460 argument("-9") { run
=TRUE
; just_flush
=9; }
461 argument("-p") { run
=TRUE
; just_preview
=TRUE
; }
462 argument("-s") { run
=TRUE
; just_preview
=TRUE
; start_shaping
=TRUE
; }
463 argument("-r") { run
=TRUE
; }
464 argument("-n") { run
=TRUE
; nodelay
=TRUE
; }
465 argument("-l") { just_logs
=TRUE
; }
466 argument("-m") { just_logs
=TRUE
; }
467 argument("-y") { just_logs
=TRUE
; }
468 argument("-?") { help(); exit(0); }
469 argument("--help") { help(); exit(0); }
470 argument("-v") { exit(0); }
471 argument("--version") { exit(0); }
476 puts("*** THIS IS JUST DRY RUN ! ***\n");
479 date(d
); /* this is typical cll1.h macro - prints current date */
481 /*-----------------------------------------------------------------*/
482 printf("Parsing configuration file %s ...\n", config
);
483 /*-----------------------------------------------------------------*/
488 parse_ip_log(argc
,argv
);
504 /*-----------------------------------------------------------------*/
505 puts("Parsing iptables verbose output ...");
506 /*-----------------------------------------------------------------*/
507 get_traffic_statistics(iptables
);
510 /*-----------------------------------------------------------------*/
511 printf("Parsing class defintion file %s ...\n", hosts
);
512 /*-----------------------------------------------------------------*/
515 /*-----------------------------------------------------------------*/
516 /* cll1.h - let's allocate brand new character buffer... */
517 /*-----------------------------------------------------------------*/
520 /*-----------------------------------------------------------------*/
521 puts("Resolving shared connections ...");
522 /*-----------------------------------------------------------------*/
523 for_each(ip
,ips
) if(ip
->sharing
)
525 for_each(sharedip
,ips
) if(eq(sharedip
->name
,ip
->sharing
))
527 sharedip
->traffic
+=ip
->traffic
;
529 ip
->mark
=sharedip
->mark
;
530 ip
->lmsid
=sharedip
->lmsid
;
535 printf("Unresolved shared connection: %s %s sharing-%s\n",
536 ip
->addr
, ip
->name
, ip
->sharing
);
540 if(enable_credit
&& just_flush
<9)
542 /*-----------------------------------------------------------------*/
543 printf("Parsing credit file %s ...\n", credit
);
544 /*-----------------------------------------------------------------*/
547 ptr
=parse_datafile_line(_
);
550 if_exists(ip
,ips
,eq(ip
->addr
,_
))
552 sscanf(ptr
,"%Lu",&(ip
->credit
));
556 done
; /* ugly macro end */
561 /*-----------------------------------------------------------------*/
562 puts("Initializing iptables and tc classes ...");
563 /*-----------------------------------------------------------------*/
565 iptables_file
= fopen(iptablesfile
, "w");
566 if(iptables_file
== NULL
)
568 perror(iptablesfile
);
572 log_file
= fopen(cmdlog
, "w");
579 save_line(iptablespreamble
);
582 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,lan
);
585 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,wan
);
588 iptables_file
=fopen(iptablesfile
,"w");
589 save_line(iptablespreamble
);
591 if(qos_free_zone
&& *qos_free_zone
!='0')
595 sprintf(str
,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone
, wan
);
600 save_line(":post_noproxy - [0:0]");
601 sprintf(str
,"-A POSTROUTING ! -p tcp -o %s -j post_noproxy", lan
);
603 sprintf(str
,"-A POSTROUTING ! -s %s -o %s -j post_noproxy", proxy_ip
, lan
);
605 sprintf(str
,"-A POSTROUTING -s %s -p tcp ! --sport %d -o %s -j post_noproxy", proxy_ip
, proxy_port
, lan
);
608 chain
="post_noproxy";
615 sprintf(str
,"-A %s -s %s -o %s -j ACCEPT", chain
, qos_free_zone
, lan
);
619 if(ip_count
> idxtable_treshold1
&& !just_flush
)
621 int idxcount
=0, bitmask
=32-idxtable_bitmask1
; /* default net mask: 255.255.255.240 */
623 /*-----------------------------------------------------------------*/
624 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count
);
625 /*-----------------------------------------------------------------*/
627 save_line(":post_common - [0:0]");
628 save_line(":forw_common - [0:0]");
630 for_each(ip
,ips
) if(ip
->addr
&& *(ip
->addr
) && !eq(ip
->addr
,"0.0.0.0/0") && !strchr(ip
->addr
,':')) /* only IPv4 */
632 buf
=index_id(ip
->addr
,bitmask
);
633 if_exists(idx
,idxs
,eq(idx
->id
,buf
))
642 idx
->bitmask
=bitmask
;
650 /* brutal perfomance optimalization */
651 while(idxcount
> idxtable_treshold2
&& bitmask
> 2*idxtable_bitmask2
)
653 bitmask
-= idxtable_bitmask2
;
656 for_each(idx
,idxs
) if(idx
->parent
== NULL
)
658 buf
= index_id(idx
->addr
,bitmask
);
659 if_exists(metaindex
,idxs
,eq(metaindex
->id
,buf
))
661 metaindex
->children
++;
665 create(metaindex
,Index
);
666 metaindex
->addr
=idx
->addr
;
668 metaindex
->bitmask
=bitmask
;
669 metaindex
->parent
=NULL
;
670 metaindex
->children
=0;
672 push(metaindex
,idxs
);
674 idx
->parent
=metaindex
;
678 /* this should slightly optimize throughput ... */
679 sort(idx
,idxs
,desc_order_by
,children
);
680 sort(idx
,idxs
,order_by
,bitmask
);
685 subnet
=subnet_id(idx
->addr
,idx
->bitmask
);
686 printf("%d: %s/%d\n",
687 ++i
, subnet
, idx
->bitmask
);
689 sprintf(str
,":post_%s - [0:0]", idx
->id
);
692 sprintf(str
,":forw_%s - [0:0]", idx
->id
);
697 string(buf
,strlen(idx
->parent
->id
)+6);
698 sprintf(buf
,"post_%s",idx
->parent
->id
);
705 sprintf(str
,"-A %s -d %s/%d -o %s -j post_%s", buf
, subnet
, idx
->bitmask
, lan
, idx
->id
);
708 sprintf(str
,"-A %s -d %s/%d -o %s -j post_common", buf
, subnet
, idx
->bitmask
, lan
);
713 string(buf
,strlen(idx
->parent
->id
)+6);
714 sprintf(buf
,"forw_%s",idx
->parent
->id
);
721 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_%s", buf
, subnet
, idx
->bitmask
, wan
, idx
->id
);
724 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_common", buf
, subnet
, idx
->bitmask
, wan
);
727 printf("Total indexed iptables chains created: %d\n", i
);
729 sprintf(str
,"-A FORWARD -o %s -j forw_common", wan
);
732 sprintf(str
,"-A POSTROUTING -o %s -j post_common", lan
);
740 fclose(iptables_file
);
745 puts("Just flushed iptables and tc classes - now exiting ...");
751 if(!dry_run
&& !nodelay
&& qos_free_delay
)
753 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay
);
754 sleep(qos_free_delay
);
757 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",
761 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
762 tc
,lan
,lan_medium
,lan_medium
,burst_main
,highest_priority
);
765 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
766 tc
,lan
,line
,line
,burst_main
,highest_priority
);
769 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc
,wan
,htb_r2q
);
772 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
773 tc
,wan
,wan_medium
,wan_medium
,burst_main
,highest_priority
);
776 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
777 tc
,wan
,up
,up
,burst_main
,highest_priority
);
781 /*-----------------------------------------------------------------*/
782 puts("Locating heavy downloaders and generating root classes ...");
783 /*-----------------------------------------------------------------*/
784 sort(ip
,ips
,desc_order_by
,traffic
);
786 /*-----------------------------------------------------------------*/
787 /* sub-scope - local variables */
789 long long int rate
= line
;
790 long long int max
= line
;
792 FILE *credit_file
= NULL
;
794 if(!just_preview
&& !dry_run
&& enable_credit
)
796 credit_file
= fopen(credit
,"w");
799 for_each(group
,groups
)
804 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",
805 tc
, lan
, parent
, group
->id
, rate
, max
, burst_group
, highest_priority
+1, group
->desired
);
809 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",
810 tc
, wan
, parent
, group
->id
, rate
*up
/line
, max
*up
/line
, burst_group
, highest_priority
+1, group
->desired
);
814 if(group_count
++ < max_nesting
)
819 rate
-= digital_divide
*group
->min
;
820 if(rate
< group
->min
)
825 /*shaping of aggresive downloaders, with credit file support */
828 int group_rate
= group
->min
, priority_sequence
= lowest_priority
;
830 for_each(ip
, ips
) if(ip
->min
== group
->min
&& ip
->max
> ip
->min
)
832 ip
->realquota
=ip
->credit
+(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20));
833 if( ip
->keyword
->data_limit
834 and not ip
->fixedprio
835 and ip
->traffic
> ip
->realquota
)
837 if(group_rate
< ip
->max
)
839 ip
->max
= group_rate
;
841 group_rate
+=magic_treshold
;
842 ip
->prio
=lowest_priority
;
843 if(ip
->prio
<highest_priority
+2)
845 ip
->prio
=highest_priority
+2;
850 if( ip
->keyword
->data_prio
852 && ( ip
->traffic
>ip
->credit
853 + (ip
->min
*ip
->keyword
->data_prio
+(ip
->keyword
->fixed_prio
<<20))) )
855 ip
->prio
=priority_sequence
--;
856 if(ip
->prio
<highest_priority
+1)
858 ip
->prio
=highest_priority
+1;
864 unsigned long long lcredit
=0;
866 if((ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))>ip
->traffic
)
868 lcredit
=(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))-ip
->traffic
;
870 fprintf(credit_file
,"%s %Lu\n",ip
->addr
,lcredit
);
886 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap
);
894 if_exists(ip
,ips
,eq(ip
->addr
,_
))
897 if(ip
->max
< ip
->desired
) /* apply FUP limit immediately.... */
899 printf("Applying limit for %-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
900 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
901 sprintf(str
, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
902 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
904 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
905 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
906 sprintf(str
,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
907 tc
, wan
, ip
->group
, ip
->mark
,
908 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
909 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
918 puts("Warning - classmap file not fund, just generating preview ...");
921 done
; /* ugly macro end */
924 json_traffic
=json_preview
;
927 if(!dry_run
&& !just_flush
)
929 /*-----------------------------------------------------------------*/
930 printf("Writing json traffic overview %s ... ", json_traffic
);
931 /*-----------------------------------------------------------------*/
932 write_json_traffic(json_traffic
);
935 /*-----------------------------------------------------------------*/
936 printf("Writing statistics into HTML page %s ...\n", html
);
937 /*-----------------------------------------------------------------*/
938 write_htmlandlogs(html
, d
,total
, just_preview
);
947 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar
);
953 printf("%-22s %-15s mark\n","name","ip");
956 printf("Writing %s ... ", classmap
);
957 f
= fopen(classmap
, "w");
963 /*-----------------------------------------------------------------*/
964 puts("Generating iptables and tc classes ... ");
965 /*-----------------------------------------------------------------*/
967 for_each(ip
, ips
) if(ip
->mark
> 0 && !strchr(ip
->addr
,':')) /* works only for IPv4 so far */
972 duplicate(ip
->addr
,buf
);
973 buf
=index_id(ip
->addr
,32-idxtable_bitmask1
);
975 string(chain_forward
,6+strlen(buf
));
976 strcpy(chain_forward
,"forw_");
977 strcat(chain_forward
,buf
);
979 string(chain_postrouting
,6+strlen(buf
));
980 strcpy(chain_postrouting
,"post_");
981 strcat(chain_postrouting
,buf
);
987 chain_forward
="FORWARD";
988 chain_postrouting
="POSTROUTING";
992 printf("%-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
995 /* -------------------------------------------------------- mark download */
997 sprintf(str
, "-A %s -d %s/32 -o %s -j %s%d",
998 chain_postrouting
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
999 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/
1000 /* -m limit --limit 1/s */
1005 sprintf(str
, "-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",
1006 chain_postrouting
, proxy_ip
, proxy_port
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
1007 /*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);*/
1011 sprintf(str
, "-A %s -d %s/32 -o %s -j ACCEPT",
1012 chain_postrouting
, ip
->addr
, lan
);
1015 /* -------------------------------------------------------- mark upload */
1016 sprintf(str
, "-A %s -s %s/32 -o %s -j %s%d",
1017 chain_forward
, ip
->addr
, wan
, mark_iptables
, ip
->mark
);
1018 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/
1021 sprintf(str
, "-A %s -s %s/32 -o %s -j ACCEPT",
1022 chain_forward
, ip
->addr
, wan
);
1027 /* -------------------------------------------------------- download class */
1029 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
1032 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1033 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1036 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1038 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1039 tc
, lan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1043 if(filter_type
== 1)
1045 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1046 tc
, lan
, ip
->mark
, ip
->mark
);
1050 /* -------------------------------------------------------- upload class */
1052 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1053 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1056 sprintf(str
,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1057 tc
, wan
, ip
->group
, ip
->mark
,
1058 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1059 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1062 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1064 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1065 tc
, wan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1069 if(filter_type
== 1)
1071 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1072 tc
, wan
, ip
->mark
, ip
->mark
);
1078 fprintf(f
, "%s %d\n", ip
->addr
, ip
->mark
);
1084 printf("(sharing %s)\n", ip
->sharing
);
1097 chain_forward
= "forw_common";
1098 chain_postrouting
= "post_common";
1102 chain_forward
= "FORWARD";
1103 chain_postrouting
= "POSTROUTING";
1105 /* -------------------------------- classify or reject free download */
1107 char *final_chain
= "DROP"; /* REJECT would be better, but it is impossible in mangle */
1110 final_chain
= "ACCEPT";
1116 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s%d",
1117 chain_postrouting
,proxy_ip
,proxy_port
,lan
,mark_iptables
,3);
1120 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s",
1121 chain_postrouting
,proxy_ip
,proxy_port
,lan
,final_chain
);
1126 sprintf(str
,"-A %s -o %s -j %s%d", chain_postrouting
, lan
, mark_iptables
, 3);
1129 sprintf(str
,"-A %s -o %s -j %s", chain_postrouting
, lan
, final_chain
);
1131 /* ------------------------------- classify or reject free upload */
1134 sprintf(str
,"-A %s -o %s -j %s%d", chain_forward
, wan
, mark_iptables
, 3);
1137 sprintf(str
,"-A %s -o %s -j %s", chain_forward
, wan
, final_chain
);
1141 if(free_min
) /* allocate free bandwith if it is not zero... */
1143 /*-----------------------------------------------------------------*/
1144 puts("Generating free bandwith classes ...");
1145 /*-----------------------------------------------------------------*/
1146 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1147 tc
, lan
, parent
, free_min
, free_max
,burst
, lowest_priority
);
1149 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1150 tc
, wan
, parent
, free_min
, free_max
, burst
, lowest_priority
);
1153 if(strcmpi(qos_leaf
, "none"))
1155 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, lan
, qos_leaf
);
1158 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, wan
, qos_leaf
);
1161 /* tc handle 1 fw flowid */
1162 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, lan
);
1165 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, wan
);
1168 printf("Total IP count: %d\n", i
);
1175 /* that's all folks, thank you for reading it all the way up to this point ;-) */
1176 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */
This page took 0.765863 seconds and 4 git commands to generate.