9743b30b271033548202234fab31a4900087a8f1
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 /* ======= Help screen is hopefuly self-documenting part of code :-) ======= */
51 /* ======= All path names are defined here (for RPM patch) ======= */
53 const char *tc
= "/sbin/tc"; /* requires tc with HTB support */
54 const char *iptables
= "/sbin/iptables"; /* requires iptables utility */
55 const char *iptablessave
= "/sbin/iptables-save"; /* not yet required */
56 const char *iptablesrestore
= "/sbin/iptables-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 */
62 char *iptablesfile
= "/var/spool/prometheus.iptables"; /* temporary file for iptables-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 *wan_medium
= "100Mbit"; /* 10Mbit/100Mbit ethernet */
95 char *qos_leaf
= "sfq perturb 5"; /* leaf discipline */
96 char *qos_free_zone
= NULL
; /* QoS free zone */
97 int qos_proxy
= TRUE
; /* include proxy port to QoS */
98 int found_lmsid
= FALSE
; /* show links to users in LMS information system */
99 int include_upload
= TRUE
; /* upload+download=total traffic */
100 char *proxy_ip
= "192.168.1.1/32"; /* our IP with proxy port */
101 int proxy_port
= 3128; /* proxy port number */
102 long long int line
= 1024; /* WAN/ISP download in kbps */
103 long long int up
= 1024; /* WAN/ISP upload in kbps */
104 int free_min
= 32; /* minimum guaranted bandwidth for all undefined hosts */
105 int free_max
= 64; /* maximum allowed bandwidth for all undefined hosts */
106 int qos_free_delay
= 0; /* seconds to sleep before applying new QoS rules */
107 int digital_divide
= 2; /* controls digital divide weirdness ratio, 1...3 */
108 int max_nesting
= 3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */
109 int htb_r2q
= 256; /* should work for leaf values 512 kbps to 8 Mbps */
110 int burst
= 8; /* HTB burst (in kbits) */
112 int burst_group
= 32;
113 int magic_treshold
= 8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */
114 int keywordcount
= 0;
117 /* not yet implemented:
118 int fixed_packets = 0; maximum number of pps per IP address (not class!)
119 int packet_limit = 5; maximum number of pps to htn CEIL, not rate !!!
121 FILE *log_file
= NULL
;
122 char *kwd
= "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */
124 const int highest_priority
= 0; /* highest HTB priority (HTB built-in value is 0) */
125 const int lowest_priority
= 7; /* lowest HTB priority (HTB built-in value is 7) */
126 const int idxtable_treshold1
= 24; /* this is no longer configurable */
127 const int idxtable_treshold2
= 12; /* this is no longer configurable */
128 const int idxtable_bitmask1
= 3; /* this is no longer configurable */
129 const int idxtable_bitmask2
= 3; /* this is no longer configurable */
131 struct IP
*ips
= NULL
, *ip
, *sharedip
;
132 struct Group
*groups
= NULL
, *group
;
133 struct Keyword
*keyword
, *defaultkeyword
=NULL
, *keywords
=NULL
;
136 /* implemented in help.c */
138 void parse_ip_log(int argc
, char **argv
);
139 /* implemented in parselog.c */
141 void parse_hosts(char *hosts
);
142 /* implemented in parsehosts.c */
144 void write_json_traffic(char *json
);
145 /* implemented in json.c */
147 void write_htmlandlogs(char *html
, char *d
, int total
, int just_preview
);
148 /* implemented in htmlandlogs.c */
150 const char *tr_odd_even(void)
152 row_odd_even
= 1 - row_odd_even
;
155 return "<tr class=\"even\">\n";
159 return "<tr class=\"odd\">\n";
163 /* ==== This is C<<1 stuff - learn C<<1 first! https://dev.arachne.cz/svn/cll1h ==== */
164 /* (except that this code uses obsolete, archaic version of this header file...) */
170 struct Index
*parent
;
174 } *idxs
=NULL
, *idx
, *metaindex
;
177 /* function implemented in parsehosts.c */
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("iptables-in-filename",iptablesfile
); /* new */
268 option("hosts",hosts
);
269 option("lan-interface",lan
);
270 option("wan-interface",wan
);
271 option("lan-medium",lan_medium
);
272 option("wan-medium",wan_medium
);
273 lloption("wan-download",line
);
274 lloption("wan-upload",up
);
275 ioption("hall-of-fame-enable",hall_of_fame
);
276 option("hall-of-fame-title",title
);
277 option("hall-of-fame-filename",html
);
278 option("json-filename",json_traffic
);
279 option("hall-of-fame-preview",preview
);
280 option("json-preview",json_preview
);
281 option("log-filename",cmdlog
);
282 option("credit-filename",credit
);
283 option("classmap-filename",classmap
);
284 ioption("credit-enable",enable_credit
);
285 option("log-traffic-directory",log_dir
);
286 option("log-traffic-html-directory",html_log_dir
);
287 option("log-traffic-url-path",log_url
);
288 option("jquery-url",jquery_url
);
289 option("lms-url",lms_url
);
290 ioption("use-jquery-popups",use_jquery_popups
);
291 option("qos-free-zone",qos_free_zone
);
292 ioption("qos-free-delay",qos_free_delay
);
293 ioption("qos-proxy-enable",qos_proxy
);
294 option("qos-proxy-ip",proxy_ip
);
295 option("htb-leaf-discipline",qos_leaf
);
296 ioption("qos-proxy-port",proxy_port
);
297 ioption("free-rate",free_min
);
298 ioption("free-ceil",free_max
);
299 ioption("htb-burst",burst
);
300 ioption("htb-burst-main",burst_main
);
301 ioption("htb-burst-group",burst_group
);
302 ioption("htb-nesting-limit",max_nesting
);
303 ioption("htb-r2q",htb_r2q
);
304 ioption("magic-include-upload",include_upload
);
305 ioption("magic-treshold",magic_treshold
);
306 option("filter-type", cnf
);
307 /* not yet implemented:
308 ioption("magic-fixed-packets",fixed_packets);
309 ioption("magic-relative-packets",packet_limit);
314 perror(config_filename
);
315 puts("Warning - using built-in defaults instead ...");
317 done
; /* ugly macro end */
320 /* leaf discipline for keywords */
321 for_each(keyword
,keywords
)
323 if(!strcmpi(keyword
->leaf_discipline
, ""))
325 keyword
->leaf_discipline
= qos_leaf
;
329 if(strcmpi(cnf
, "mark"))
333 mark_iptables
= "CLASSIFY --set-class 1:";
339 mark_iptables
= "MARK --set-mark ";
342 /* are supplied values meaningful ?*/
345 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");
346 reject_config_and_exit(config_filename
);
350 /* ===================== traffic analyser - uses iptables ================ */
352 void get_traffic_statistics(void)
357 textfile(Pipe
,str
) *line
,*lines
=NULL
;
361 sprintf(cmd
,"%s -L -v -x -n -t mangle",iptables
);
373 int col
, accept
=0,proxyflag
=0,valid
=1,setchainname
=0,commonflag
=0;
374 unsigned long long traffic
=0;
375 unsigned long pkts
=0;
376 char *ipaddr
=NULL
,*ptr
;
378 /* debug puts(line->str); */
379 valid_columns(ptr
,line
->str
,' ',col
)
380 if(valid
) switch(col
)
382 case 1: if(eq(ptr
,"Chain"))
386 else if(eq(ptr
,"pkts"))
392 sscanf(ptr
,"%lu",&pkts
);
395 case 2: if(setchainname
)
397 if(!strncmp(ptr
,"post_",5) || eq(ptr
,"POSTROUTING"))
403 if(!strncmp(ptr
,"forw_",5) || eq(ptr
,"FORWARD"))
408 if(eq(ptr
,"post_common") || eq(ptr
,"forw_common"))
415 sscanf(ptr
,"%Lu",&traffic
);
420 case 3: if((strncmp(ptr
,"post_",5) && strncmp(ptr
,"forw_",5)) || commonflag
)
424 /*if(filter_type==1) accept=eq(ptr,"MARK"); else accept=eq(ptr,"CLASSIFY");*/
426 case 8: if(downloadflag
)
428 if(strstr(proxy_ip
,ptr
))
438 case 9: if(downloadflag
)ipaddr
=ptr
;break;
441 if(accept
&& traffic
>0 && ipaddr
)
447 else if(!downloadflag
)
451 printf("IP %s: %Lu MB (%ld pkts)\n", ipaddr
, traffic
, pkts
);
453 if_exists(ip
,ips
,eq(ip
->addr
,ipaddr
));
458 if(eq(ip
->addr
,"0.0.0.0/0"))
460 ip
->name
= "(unregistered)";
462 ip
->max
= ip
->desired
=free_max
;
478 ip
->traffic
+=traffic
;
480 ip
->direct
=ip
->traffic
-ip
->upload
-ip
->proxy
;
489 ip
->traffic
+=traffic
;
493 if(traffic
>ip
->traffic
)
504 /* ========== This function executes, logs OR ALSO prints command ========== */
506 void safe_run(char *cmd
)
510 printf("\n=>%s\n",cmd
);
518 fprintf(log_file
,"%s\n",cmd
);
522 void save_line(char *line
)
524 fprintf(iptables_file
,"%s\n",line
);
527 void run_restore(void)
530 string(restor
,STRLEN
);
532 /*-----------------------------------------------------------------*/
533 printf("Running %s <%s ...\n", iptablesrestore
, iptablesfile
);
534 /*-----------------------------------------------------------------*/
537 fclose(iptables_file
);
544 done
; /* ugly macro end */
547 sprintf(restor
,"%s <%s",iptablesrestore
, iptablesfile
);
553 char *parse_datafile_line(char *str
)
555 char *ptr
=strchr(str
,' ');
570 /*-----------------------------------------------------------------*/
571 /* Are you looking for int main(int argc, char **argv) ? :-)) */
572 /*-----------------------------------------------------------------*/
576 int i
=0; /* just plain old Fortran style integer :-) */
577 FILE *f
=NULL
; /* everything is just stream of bytes... */
578 char *str
, *ptr
, *d
; /* LET A$=B$ :-) */
582 int just_flush
= FALSE
; /* deactivates all previous actions */
584 int just_preview
= FALSE
; /* preview - generate just stats */
585 int start_shaping
= FALSE
; /* apply FUP - requires classmap file */
586 int just_logs
= FALSE
; /* just parse logs */
590 char *chain_forward
, *chain_postrouting
;
594 Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\
595 Version %s - Copyright (C)2005-2012 Michael Polak, Arachne Labs\n\
596 iptables-restore & burst tunning & classify modification by Ludva\n\
597 Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version
);
599 /*----- Boring... we have to check command line options first: ----*/
602 argument("-c") { nextargument(config
); }
603 argument("-h") { nextargument(althosts
);}
604 argument("-d") { run
=TRUE
; dry_run
=TRUE
; }
605 argument("-f") { run
=TRUE
; just_flush
=TRUE
; }
606 argument("-9") { run
=TRUE
; just_flush
=9; }
607 argument("-p") { run
=TRUE
; just_preview
=TRUE
; }
608 argument("-s") { run
=TRUE
; just_preview
=TRUE
; start_shaping
=TRUE
; }
609 argument("-r") { run
=TRUE
; }
610 argument("-n") { run
=TRUE
; nodelay
=TRUE
; }
611 argument("-l") { just_logs
=TRUE
; }
612 argument("-m") { just_logs
=TRUE
; }
613 argument("-y") { just_logs
=TRUE
; }
614 argument("-?") { help(); exit(0); }
615 argument("--help") { help(); exit(0); }
616 argument("-v") { exit(0); }
617 argument("--version") { exit(0); }
622 puts("*** THIS IS JUST DRY RUN ! ***\n");
625 date(d
); /* this is typical cll1.h macro - prints current date */
627 /*-----------------------------------------------------------------*/
628 printf("Parsing configuration file %s ...\n", config
);
629 /*-----------------------------------------------------------------*/
634 parse_ip_log(argc
,argv
);
650 /*-----------------------------------------------------------------*/
651 puts("Parsing iptables verbose output ...");
652 /*-----------------------------------------------------------------*/
653 get_traffic_statistics();
656 /*-----------------------------------------------------------------*/
657 printf("Parsing class defintion file %s ...\n", hosts
);
658 /*-----------------------------------------------------------------*/
661 /*-----------------------------------------------------------------*/
662 /* cll1.h - let's allocate brand new character buffer... */
663 /*-----------------------------------------------------------------*/
666 /*-----------------------------------------------------------------*/
667 puts("Resolving shared connections ...");
668 /*-----------------------------------------------------------------*/
669 for_each(ip
,ips
) if(ip
->sharing
)
671 for_each(sharedip
,ips
) if(eq(sharedip
->name
,ip
->sharing
))
673 sharedip
->traffic
+=ip
->traffic
;
675 ip
->mark
=sharedip
->mark
;
676 ip
->lmsid
=sharedip
->lmsid
;
681 printf("Unresolved shared connection: %s %s sharing-%s\n",
682 ip
->addr
, ip
->name
, ip
->sharing
);
686 if(enable_credit
&& just_flush
<9)
688 /*-----------------------------------------------------------------*/
689 printf("Parsing credit file %s ...\n", credit
);
690 /*-----------------------------------------------------------------*/
693 ptr
=parse_datafile_line(_
);
696 if_exists(ip
,ips
,eq(ip
->addr
,_
))
698 sscanf(ptr
,"%Lu",&(ip
->credit
));
702 done
; /* ugly macro end */
707 /*-----------------------------------------------------------------*/
708 puts("Initializing iptables and tc classes ...");
709 /*-----------------------------------------------------------------*/
711 iptables_file
=fopen(iptablesfile
,"w");
712 if(iptables_file
== NULL
)
714 puts("Cannot open iptablesfile!");
718 log_file
=fopen(cmdlog
,"w");
721 puts("Cannot open logfile!");
725 save_line(iptablespreamble
);
728 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,lan
);
731 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,wan
);
734 iptables_file
=fopen(iptablesfile
,"w");
735 save_line(iptablespreamble
);
737 if(qos_free_zone
&& *qos_free_zone
!='0')
741 sprintf(str
,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone
, wan
);
746 save_line(":post_noproxy - [0:0]");
747 sprintf(str
,"-A POSTROUTING ! -p tcp -o %s -j post_noproxy", lan
);
749 sprintf(str
,"-A POSTROUTING ! -s %s -o %s -j post_noproxy", proxy_ip
, lan
);
751 sprintf(str
,"-A POSTROUTING -s %s -p tcp ! --sport %d -o %s -j post_noproxy", proxy_ip
, proxy_port
, lan
);
754 chain
="post_noproxy";
761 sprintf(str
,"-A %s -s %s -o %s -j ACCEPT", chain
, qos_free_zone
, lan
);
765 if(ip_count
>idxtable_treshold1
&& !just_flush
)
767 int idxcount
=0, bitmask
=32-idxtable_bitmask1
; /* default net mask: 255.255.255.240 */
769 /*-----------------------------------------------------------------*/
770 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count
);
771 /*-----------------------------------------------------------------*/
773 save_line(":post_common - [0:0]");
774 save_line(":forw_common - [0:0]");
776 for_each(ip
,ips
) if(ip
->addr
&& *(ip
->addr
) && !eq(ip
->addr
,"0.0.0.0/0"))
778 buf
=index_id(ip
->addr
,bitmask
);
779 if_exists(idx
,idxs
,eq(idx
->id
,buf
))
788 idx
->bitmask
=bitmask
;
796 /* brutal perfomance optimalization */
797 while(idxcount
>idxtable_treshold2
&& bitmask
>2*idxtable_bitmask2
)
799 bitmask
-=idxtable_bitmask2
;
802 for_each(idx
,idxs
) if(idx
->parent
== NULL
)
804 buf
=index_id(idx
->addr
,bitmask
);
805 if_exists(metaindex
,idxs
,eq(metaindex
->id
,buf
))
807 metaindex
->children
++;
811 create(metaindex
,Index
);
812 metaindex
->addr
=idx
->addr
;
814 metaindex
->bitmask
=bitmask
;
815 metaindex
->parent
=NULL
;
816 metaindex
->children
=0;
818 push(metaindex
,idxs
);
820 idx
->parent
=metaindex
;
824 /* this should slightly optimize throughout ... */
825 sort(idx
,idxs
,desc_order_by
,children
);
826 sort(idx
,idxs
,order_by
,bitmask
);
831 subnet
=subnet_id(idx
->addr
,idx
->bitmask
);
832 printf("%d: %s/%d\n",
833 ++i
, subnet
, idx
->bitmask
);
835 sprintf(str
,":post_%s - [0:0]", idx
->id
);
838 sprintf(str
,":forw_%s - [0:0]", idx
->id
);
843 string(buf
,strlen(idx
->parent
->id
)+6);
844 sprintf(buf
,"post_%s",idx
->parent
->id
);
851 sprintf(str
,"-A %s -d %s/%d -o %s -j post_%s", buf
, subnet
, idx
->bitmask
, lan
, idx
->id
);
854 sprintf(str
,"-A %s -d %s/%d -o %s -j post_common", buf
, subnet
, idx
->bitmask
, lan
);
859 string(buf
,strlen(idx
->parent
->id
)+6);
860 sprintf(buf
,"forw_%s",idx
->parent
->id
);
867 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_%s", buf
, subnet
, idx
->bitmask
, wan
, idx
->id
);
870 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_common", buf
, subnet
, idx
->bitmask
, wan
);
873 printf("Total indexed iptables chains created: %d\n", i
);
875 sprintf(str
,"-A FORWARD -o %s -j forw_common", wan
);
878 sprintf(str
,"-A POSTROUTING -o %s -j post_common", lan
);
886 fclose(iptables_file
);
891 puts("Just flushed iptables and tc classes - now exiting ...");
897 if(!dry_run
&& !nodelay
&& qos_free_delay
)
899 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay
);
900 sleep(qos_free_delay
);
903 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",
907 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
908 tc
,lan
,lan_medium
,lan_medium
,burst_main
,highest_priority
);
911 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
912 tc
,lan
,line
,line
,burst_main
,highest_priority
);
915 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc
,wan
,htb_r2q
);
918 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
919 tc
,wan
,wan_medium
,wan_medium
,burst_main
,highest_priority
);
922 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
923 tc
,wan
,up
,up
,burst_main
,highest_priority
);
927 /*-----------------------------------------------------------------*/
928 puts("Locating heavy downloaders and generating root classes ...");
929 /*-----------------------------------------------------------------*/
930 sort(ip
,ips
,desc_order_by
,traffic
);
932 /*-----------------------------------------------------------------*/
933 /* sub-scope - local variables */
935 long long int rate
= line
;
936 long long int max
= line
;
938 FILE *credit_file
= NULL
;
940 if(!just_preview
&& !dry_run
&& enable_credit
)
942 credit_file
= fopen(credit
,"w");
945 for_each(group
,groups
)
950 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",
951 tc
, lan
, parent
, group
->id
, rate
, max
, burst_group
, highest_priority
+1, group
->desired
);
955 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",
956 tc
, wan
, parent
, group
->id
, rate
*up
/line
, max
*up
/line
, burst_group
, highest_priority
+1, group
->desired
);
960 if(group_count
++ < max_nesting
)
965 rate
-= digital_divide
*group
->min
;
966 if(rate
< group
->min
)
971 /*shaping of aggresive downloaders, with credit file support */
974 int group_rate
= group
->min
, priority_sequence
= lowest_priority
;
976 for_each(ip
, ips
) if(ip
->min
== group
->min
&& ip
->max
> ip
->min
)
978 ip
->realquota
=ip
->credit
+(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20));
979 if( ip
->keyword
->data_limit
980 and not ip
->fixedprio
981 and ip
->traffic
> ip
->realquota
)
983 if(group_rate
< ip
->max
)
985 ip
->max
= group_rate
;
987 group_rate
+=magic_treshold
;
988 ip
->prio
=lowest_priority
;
989 if(ip
->prio
<highest_priority
+2)
991 ip
->prio
=highest_priority
+2;
996 if( ip
->keyword
->data_prio
998 && ( ip
->traffic
>ip
->credit
999 + (ip
->min
*ip
->keyword
->data_prio
+(ip
->keyword
->fixed_prio
<<20))) )
1001 ip
->prio
=priority_sequence
--;
1002 if(ip
->prio
<highest_priority
+1)
1004 ip
->prio
=highest_priority
+1;
1010 unsigned long long lcredit
=0;
1012 if((ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))>ip
->traffic
)
1014 lcredit
=(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))-ip
->traffic
;
1016 fprintf(credit_file
,"%s %Lu\n",ip
->addr
,lcredit
);
1024 fclose(credit_file
);
1032 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap
);
1040 if_exists(ip
,ips
,eq(ip
->addr
,_
))
1043 if(ip
->max
< ip
->desired
) /* apply FUP limit immediately.... */
1045 printf("Applying limit for %-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
1046 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
1047 sprintf(str
, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1048 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1050 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1051 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1052 sprintf(str
,"%s class change 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
);
1064 puts("Warning - classmap file not fund, just generating preview ...");
1065 start_shaping
=FALSE
;
1067 done
; /* ugly macro end */
1070 json_traffic
=json_preview
;
1073 if(!dry_run
&& !just_flush
)
1075 /*-----------------------------------------------------------------*/
1076 printf("Writing json traffic overview %s ... ", json_traffic
);
1077 /*-----------------------------------------------------------------*/
1078 write_json_traffic(json_traffic
);
1081 /*-----------------------------------------------------------------*/
1082 printf("Writing statistics into HTML page %s ...\n", html
);
1083 /*-----------------------------------------------------------------*/
1084 write_htmlandlogs(html
, d
,total
, just_preview
);
1093 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar
);
1099 printf("%-22s %-15s mark\n","name","ip");
1102 printf("Writing %s ... ", classmap
);
1103 f
= fopen(classmap
, "w");
1109 /*-----------------------------------------------------------------*/
1110 puts("Generating iptables and tc classes ... ");
1111 /*-----------------------------------------------------------------*/
1113 for_each(ip
, ips
) if(ip
->mark
> 0)
1118 duplicate(ip
->addr
,buf
);
1119 buf
=index_id(ip
->addr
,32-idxtable_bitmask1
);
1121 string(chain_forward
,6+strlen(buf
));
1122 strcpy(chain_forward
,"forw_");
1123 strcat(chain_forward
,buf
);
1125 string(chain_postrouting
,6+strlen(buf
));
1126 strcpy(chain_postrouting
,"post_");
1127 strcat(chain_postrouting
,buf
);
1133 chain_forward
="FORWARD";
1134 chain_postrouting
="POSTROUTING";
1138 printf("%-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
1141 /* -------------------------------------------------------- mark download */
1143 sprintf(str
, "-A %s -d %s/32 -o %s -j %s%d",
1144 chain_postrouting
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
1145 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/
1146 /* -m limit --limit 1/s */
1151 sprintf(str
, "-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",
1152 chain_postrouting
, proxy_ip
, proxy_port
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
1153 /*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);*/
1157 sprintf(str
, "-A %s -d %s/32 -o %s -j ACCEPT",
1158 chain_postrouting
, ip
->addr
, lan
);
1161 /* -------------------------------------------------------- mark upload */
1162 sprintf(str
, "-A %s -s %s/32 -o %s -j %s%d",
1163 chain_forward
, ip
->addr
, wan
, mark_iptables
, ip
->mark
);
1164 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/
1167 sprintf(str
, "-A %s -s %s/32 -o %s -j ACCEPT",
1168 chain_forward
, ip
->addr
, wan
);
1173 /* -------------------------------------------------------- download class */
1175 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
1178 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1179 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1182 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1184 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1185 tc
, lan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1189 if(filter_type
== 1)
1191 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1192 tc
, lan
, ip
->mark
, ip
->mark
);
1196 /* -------------------------------------------------------- upload class */
1198 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1199 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1202 sprintf(str
,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1203 tc
, wan
, ip
->group
, ip
->mark
,
1204 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1205 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1208 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1210 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1211 tc
, wan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1215 if(filter_type
== 1)
1217 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1218 tc
, wan
, ip
->mark
, ip
->mark
);
1224 fprintf(f
, "%s %d\n", ip
->addr
, ip
->mark
);
1230 printf("(sharing %s)\n", ip
->sharing
);
1243 chain_forward
= "forw_common";
1244 chain_postrouting
= "post_common";
1248 chain_forward
= "FORWARD";
1249 chain_postrouting
= "POSTROUTING";
1251 /* -------------------------------- classify or reject free download */
1253 char *final_chain
= "DROP"; /* REJECT would be better, but it is impossible in mangle */
1256 final_chain
= "ACCEPT";
1262 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s%d",
1263 chain_postrouting
,proxy_ip
,proxy_port
,lan
,mark_iptables
,3);
1266 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s",
1267 chain_postrouting
,proxy_ip
,proxy_port
,lan
,final_chain
);
1272 sprintf(str
,"-A %s -o %s -j %s%d", chain_postrouting
, lan
, mark_iptables
, 3);
1275 sprintf(str
,"-A %s -o %s -j %s", chain_postrouting
, lan
, final_chain
);
1277 /* ------------------------------- classify or reject free upload */
1280 sprintf(str
,"-A %s -o %s -j %s%d", chain_forward
, wan
, mark_iptables
, 3);
1283 sprintf(str
,"-A %s -o %s -j %s", chain_forward
, wan
, final_chain
);
1287 if(free_min
) /* allocate free bandwith if it is not zero... */
1289 /*-----------------------------------------------------------------*/
1290 puts("Generating free bandwith classes ...");
1291 /*-----------------------------------------------------------------*/
1292 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1293 tc
, lan
, parent
, free_min
, free_max
,burst
, lowest_priority
);
1295 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1296 tc
, wan
, parent
, free_min
, free_max
, burst
, lowest_priority
);
1299 if(strcmpi(qos_leaf
, "none"))
1301 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, lan
, qos_leaf
);
1304 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, wan
, qos_leaf
);
1307 /* tc handle 1 fw flowid */
1308 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, lan
);
1311 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, wan
);
1314 printf("Total IP count: %d\n", i
);
1321 /* that's all folks, thank you for reading it all the way up to this point ;-) */
1322 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */
This page took 1.349426 seconds and 3 git commands to generate.