40b886528d77a3d72fe97684faf1df1f7bdf9e2c
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-2012 Michael Polak, Arachne Labs */
6 /* iptables-restore support Copyright(C) 2007-2008 ludva */
7 /* Credit: CZFree.Net,Martin Devera,Netdave,Aquarius,Gandalf */
8 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
10 /* Modified by: xChaos, 20121011
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 */
32 #include "cll1-0.6.2.h"
35 const char *version
= "0.8.3-g";
37 /* Version numbers: 0.8.3 is development releases ("beta"), 0.8.4 will be "stable" */
38 /* Debian(RPM) package versions/patchlevels: 0.7.9-2, 0.8.0-1, 0.8.0-2, etc. */
39 /* C source code development versions ("beta"): 0.7.9-a, 0.8.1-b, etc. */
40 /* C source code release versions: 0.8.0, 0.8.2, 0.8.4, etc. */
42 const char *stats_html_signature
= "<span class=\"small\">Statistics generated by Prometheus QoS version %s<br />GPL+Copyright(C)2005-2012 Michael Polak, <a target=\"_blank\" href=\"http://www.arachne.cz/\">Arachne Labs</a></span>\n";
44 /* ======= Help screen is hopefuly self-documenting part of code :-) ======= */
48 puts("Command line switches:\n\
50 -d Dry run (preview tc and iptables commands on stdout)\n\
51 -r Run (reset all statistics and start shaping - daily usage)\n\
52 -p just generate Preview of data transfer statistics and exit (after -r)\n\
53 -s start Shaping FUP limits (keeps data transfer stat like -p) (after -r)\n\
54 -n run Now (like -r delay - overrides qos-free-delay keyword, after boot)\n\
55 -f just Flush iptables and tc classes and exit (stop shaping, no QiS)\n\
56 -9 emergency iptables flush (like -f, but dumps data transfer statistics)\n\
58 -c filename force alternative /etc/prometheus/prometheus.conf filename\n\
59 -h filename force alternative /etc/hosts filename (overrides hosts keyword)\n\
60 -l Mmm YYYY generate HTML summary of Logged traffic (Mmm=Jan-Dec) (and exit)\n\
61 -m generate HTML summary of traffic for yesterday's Month (and exit)\n\
62 -y generate HTML summary of traffic for yesterday's Year (and exit)\n\
63 -? --help show this help scree (and exit)\n\
64 -v --version show Version number of this utility (and exit)\n");
67 /* ======= All path names are defined here (for RPM patch) ======= */
69 const char *tc
= "/sbin/tc"; /* requires tc with HTB support */
70 const char *iptables
= "/sbin/iptables"; /* requires iptables utility */
71 const char *iptablessave
= "/sbin/iptables-save"; /* not yet required */
72 const char *iptablesrestore
= "/sbin/iptables-restore"; /* requires iptables-restore */
73 const char *ls
= "/bin/ls"; /* this is not user configurable :-) */
75 char *config
= "/etc/prometheus/prometheus.conf"; /* main configuration file */
76 char *hosts
= "/etc/prometheus/hosts"; /* per-IP bandwidth definition file */
78 char *iptablesfile
= "/var/spool/prometheus.iptables"; /* temporary file for iptables-restore*/
79 char *credit
= "/var/lib/misc/prometheus.credit"; /* credit log file */
80 char *classmap
= "/var/lib/misc/prometheus.classes"; /* credit log file */
81 char *html
= "/var/www/traffic.html"; /* hall of fame - html version */
82 char *preview
= "/var/www/preview.html"; /* hall of fame preview - html version */
83 char *json
= "/var/www/logs/traffic.json"; /* hall of fame - json version */
84 char *json_preview
= "/var/www/logs/preview.json"; /* hall of fame preview - json version */
85 char *cmdlog
= "/var/log/prometheuslog"; /* command log filename */
86 char *log_dir
= "/var/www/logs/"; /* log directory pathname, ended with slash */
87 char *log_url
= "/logs/"; /* log directory relative URI prefix (partial URL) */
88 char *html_log_dir
= "/var/www/logs/html/";
90 char *jquery_url
= "http://code.jquery.com/jquery-latest.js";
91 char *lms_url
= "/lms/?m=customerinfo&id=";
92 int use_jquery_popups
= 1;
93 int row_odd_even
= 0; /*<tr class="odd/even"> */
95 /* === Configuraration file values defaults - stored in global variables ==== */
97 int filter_type
= 1; /*1 mark, 2 classify*/
99 char *mark_iptables
= "MARK --set-mark ";
100 int dry_run
= 0; /* preview - use puts() instead of system() */
101 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]";
102 FILE *iptables_file
= NULL
;
103 int enable_credit
= 1; /* enable credit file */
104 int use_credit
= 0; /* use credit file (if enabled)*/
105 char *title
= "Hall of Fame - Greatest Suckers"; /* hall of fame title */
106 int hall_of_fame
= 1; /* enable hall of fame */
107 char *lan
= "eth0"; /* LAN interface */
108 char *lan_medium
= "100Mbit"; /* 10Mbit/100Mbit ethernet */
109 char *wan
= "eth1"; /* WAN/ISP interface */
110 char *wan_medium
= "100Mbit"; /* 10Mbit/100Mbit ethernet */
111 char *qos_leaf
= "sfq perturb 5"; /* leaf discipline */
112 char *qos_free_zone
= NULL
; /* QoS free zone */
113 int qos_proxy
= 1; /* include proxy port to QoS */
114 int found_lmsid
= 0; /* show links to users in LMS information system */
115 int include_upload
= 1; /* upload+download=total traffic */
116 char *proxy_ip
= "192.168.1.1/32"; /* our IP with proxy port */
117 int proxy_port
= 3128; /* proxy port number */
118 long long int line
= 1024; /* WAN/ISP download in kbps */
119 long long int up
= 1024; /* WAN/ISP upload in kbps */
120 int free_min
= 32; /* minimum guaranted bandwidth for all undefined hosts */
121 int free_max
= 64; /* maximum allowed bandwidth for all undefined hosts */
122 int qos_free_delay
= 0; /* seconds to sleep before applying new QoS rules */
123 int digital_divide
= 2; /* controls digital divide weirdness ratio, 1...3 */
124 int max_nesting
= 3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */
125 int htb_r2q
= 256; /* should work for leaf values 512 kbps to 8 Mbps */
126 int burst
= 8; /* HTB burst (in kbits) */
128 int burst_group
= 32;
129 int magic_treshold
= 8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */
130 int keywordcount
= 0;
133 /* not yet implemented:
134 int fixed_packets = 0; maximum number of pps per IP address (not class!)
135 int packet_limit = 5; maximum number of pps to htn CEIL, not rate !!!
137 FILE *log_file
= NULL
;
138 char *kwd
= "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */
140 const int highest_priority
= 0; /* highest HTB priority (HTB built-in value is 0) */
141 const int lowest_priority
= 7; /* lowest HTB priority (HTB built-in value is 7) */
142 const int idxtable_treshold1
= 24; /* this is no longer configurable */
143 const int idxtable_treshold2
= 12; /* this is no longer configurable */
144 const int idxtable_bitmask1
= 3; /* this is no longer configurable */
145 const int idxtable_bitmask2
= 3; /* this is no longer configurable */
147 struct IP
*ips
= NULL
, *ip
, *sharedip
;
148 struct Group
*groups
= NULL
, *group
;
149 struct Keyword
*keyword
, *defaultkeyword
=NULL
, *keywords
=NULL
;
151 void parse_ip_log(int argc
, char **argv
);
152 /* implementid in parselog.c */
154 void parse_hosts(char *hosts
);
155 /* implementid in parsehosts.c */
157 const char *tr_odd_even(void)
159 row_odd_even
= 1 - row_odd_even
;
162 return "<tr class=\"even\">\n";
166 return "<tr class=\"odd\">\n";
170 /* ==== This is C<<1 stuff - learn C<<1 first! https://dev.arachne.cz/svn/cll1h ==== */
176 struct Index
*parent
;
180 } *idxs
=NULL
, *idx
, *metaindex
;
184 /* function implemented in parsehosts.c */
186 /* ====== iptables indexes are used to reduce complexity to log8(N) ===== */
188 char *very_ugly_ipv4_code(char *inip
, int bitmask
, int format_as_chainname
)
190 /* warning: this function was debugged only for bitmask values 20,24,28 !!!*/
192 char *ip
,*outip
,*outptr
,*fmt
;
195 /* debug printf("(%s,%d) -> ",ip,bitmask); */
197 if(ip
&& *ip
&& bitmask
>=0 && bitmask
<=32)
199 string(outip
,strlen(ip
)+10); /*fuck unicode? assertion: 10>strlen("_%d_%d") */
203 /* should never exit here */
211 if(dot
<(bitmask
/8-1))
213 if(format_as_chainname
)
226 char *cutdot
=strchr(ip
+1,'.'); /*for bitmask<24*/
232 if(format_as_chainname
)
243 n
= atoi(ip
+1)-atoi(ip
+1)%(1<<(8-bitmask
%8));
250 /*debug printf("%d/%d => [_%d_%d]\n",atoi(ip+1),bitmask,n,bitmask); */
251 sprintf(outptr
,fmt
,n
,bitmask
);
252 if(!format_as_chainname
)
260 /* debug printf("[%s]\n",outip); */
271 /*should never exit here*/
276 char *index_id(char *ip
,int bitmask
)
278 return very_ugly_ipv4_code(ip
,bitmask
,1);
281 char *subnet_id(char *ip
,int bitmask
)
283 return very_ugly_ipv4_code(ip
,bitmask
,0);
286 /* ================= Let's parse configuration file here =================== */
288 void reject_config_and_exit(char *filename
)
290 printf("Configuration file %s rejected - abnormal exit.",filename
);
294 void get_config(char *config_filename
)
298 printf("Configured keywords: ");
299 parse(config_filename
)
301 option("keyword",kwd
);
306 create(keyword
,Keyword
);
308 keyword
->asymetry_ratio
=1; /* ratio for ADSL-like upload */
309 keyword
->asymetry_fixed
=0; /* fixed treshold for ADSL-like upload */
310 keyword
->data_limit
=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */
311 keyword
->data_prio
=4; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */
312 keyword
->fixed_limit
=0; /* fixed data limit for setting lower HTB ceil */
313 keyword
->fixed_prio
=0; /* fixed data limit for setting lower HTB prio */
314 keyword
->reserve_min
=8; /* bonus for nominal HTB rate bandwidth (in kbps) */
315 keyword
->reserve_max
=0; /* malus for nominal HTB ceil (in kbps) */
316 keyword
->default_prio
=highest_priority
+1;
317 keyword
->html_color
="000000";
319 keyword
->leaf_discipline
="";
321 push(keyword
,keywords
);
322 if(!defaultkeyword
) defaultkeyword
=keyword
;
329 for_each(keyword
,keywords
)
331 int l
=strlen(keyword
->key
);
333 if(!strncmp(keyword
->key
,_
,l
) && strlen(_
)>l
+2)
335 char *tmptr
=_
; /* <---- l+1 ----> */
336 _
+=l
+1; /* via-prometheus-asymetry-ratio, etc. */
337 ioption("asymetry-ratio",keyword
->asymetry_ratio
);
338 ioption("asymetry-treshold",keyword
->asymetry_fixed
);
339 ioption("magic-relative-limit",keyword
->data_limit
);
340 ioption("magic-relative-prio",keyword
->data_prio
);
341 loption("magic-fixed-limit",keyword
->fixed_limit
);
342 loption("magic-fixed-prio",keyword
->fixed_prio
);
343 ioption("htb-default-prio",keyword
->default_prio
);
344 ioption("htb-rate-bonus",keyword
->reserve_min
);
345 ioption("htb-ceil-malus",keyword
->reserve_max
);
346 option("leaf-discipline",keyword
->leaf_discipline
);
347 option("html-color",keyword
->html_color
);
350 if(keyword
->data_limit
|| keyword
->fixed_limit
||
351 keyword
->data_prio
|| keyword
->fixed_prio
)
360 option("iptables",iptables
);
361 option("iptables-save",iptablessave
); /* new */
362 option("iptables-restore",iptablesrestore
); /* new */
363 option("iptables-in-filename",iptablesfile
); /* new */
364 option("hosts",hosts
);
365 option("lan-interface",lan
);
366 option("wan-interface",wan
);
367 option("lan-medium",lan_medium
);
368 option("wan-medium",wan_medium
);
369 lloption("wan-download",line
);
370 lloption("wan-upload",up
);
371 ioption("hall-of-fame-enable",hall_of_fame
);
372 option("hall-of-fame-title",title
);
373 option("hall-of-fame-filename",html
);
374 option("json-filename",json
);
375 option("hall-of-fame-preview",preview
);
376 option("json-preview",json_preview
);
377 option("log-filename",cmdlog
);
378 option("credit-filename",credit
);
379 option("classmap-filename",classmap
);
380 ioption("credit-enable",enable_credit
);
381 option("log-traffic-directory",log_dir
);
382 option("log-traffic-html-directory",html_log_dir
);
383 option("log-traffic-url-path",log_url
);
384 option("jquery-url",jquery_url
);
385 option("lms-url",lms_url
);
386 ioption("use-jquery-popups",use_jquery_popups
);
387 option("qos-free-zone",qos_free_zone
);
388 ioption("qos-free-delay",qos_free_delay
);
389 ioption("qos-proxy-enable",qos_proxy
);
390 option("qos-proxy-ip",proxy_ip
);
391 option("htb-leaf-discipline",qos_leaf
);
392 ioption("qos-proxy-port",proxy_port
);
393 ioption("free-rate",free_min
);
394 ioption("free-ceil",free_max
);
395 ioption("htb-burst",burst
);
396 ioption("htb-burst-main",burst_main
);
397 ioption("htb-burst-group",burst_group
);
398 ioption("htb-nesting-limit",max_nesting
);
399 ioption("htb-r2q",htb_r2q
);
400 ioption("magic-include-upload",include_upload
);
401 ioption("magic-treshold",magic_treshold
);
402 option("filter-type", cnf
);
403 /* not yet implemented:
404 ioption("magic-fixed-packets",fixed_packets);
405 ioption("magic-relative-packets",packet_limit);
410 perror(config_filename
);
411 puts("Warning - using built-in defaults instead ...");
413 done
; /* ugly macro end */
416 /* leaf discipline for keywords */
417 for_each(keyword
,keywords
)
419 if(!strcmpi(keyword
->leaf_discipline
, ""))
421 keyword
->leaf_discipline
= qos_leaf
;
425 if(strcmpi(cnf
, "mark"))
429 mark_iptables
= "CLASSIFY --set-class 1:";
435 mark_iptables
= "MARK --set-mark ";
438 /* are supplied values meaningful ?*/
441 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");
442 reject_config_and_exit(config_filename
);
446 /* ===================== traffic analyser - uses iptables ================ */
448 void get_traffic_statistics(void)
453 textfile(Pipe
,str
) *line
,*lines
=NULL
;
457 sprintf(cmd
,"%s -L -v -x -n -t mangle",iptables
);
469 int col
, accept
=0,proxyflag
=0,valid
=1,setchainname
=0,commonflag
=0;
470 unsigned long long traffic
=0;
471 unsigned long pkts
=0;
472 char *ipaddr
=NULL
,*ptr
;
474 /* debug puts(line->str); */
475 valid_columns(ptr
,line
->str
,' ',col
)
476 if(valid
) switch(col
)
478 case 1: if(eq(ptr
,"Chain"))
482 else if(eq(ptr
,"pkts"))
488 sscanf(ptr
,"%lu",&pkts
);
491 case 2: if(setchainname
)
493 if(!strncmp(ptr
,"post_",5) || eq(ptr
,"POSTROUTING"))
499 if(!strncmp(ptr
,"forw_",5) || eq(ptr
,"FORWARD"))
504 if(eq(ptr
,"post_common") || eq(ptr
,"forw_common"))
511 sscanf(ptr
,"%Lu",&traffic
);
516 case 3: if((strncmp(ptr
,"post_",5) && strncmp(ptr
,"forw_",5)) || commonflag
)
520 /*if(filter_type==1) accept=eq(ptr,"MARK"); else accept=eq(ptr,"CLASSIFY");*/
522 case 8: if(downloadflag
)
524 if(strstr(proxy_ip
,ptr
))
534 case 9: if(downloadflag
)ipaddr
=ptr
;break;
537 if(accept
&& traffic
>0 && ipaddr
)
543 else if(!downloadflag
)
547 printf("IP %s: %Lu MB (%ld pkts)\n", ipaddr
, traffic
, pkts
);
549 if_exists(ip
,ips
,eq(ip
->addr
,ipaddr
));
554 if(eq(ip
->addr
,"0.0.0.0/0"))
556 ip
->name
="(unregistered)";
558 ip
->max
=ip
->desired
=free_max
;
570 ip
->traffic
+=traffic
;
572 ip
->direct
=ip
->traffic
-ip
->upload
-ip
->proxy
;
581 ip
->traffic
+=traffic
;
585 if(traffic
>ip
->traffic
)
596 /* ========== This function executes, logs OR ALSO prints command ========== */
598 void safe_run(char *cmd
)
602 printf("\n=>%s\n",cmd
);
610 fprintf(log_file
,"%s\n",cmd
);
614 void save_line(char *line
)
616 fprintf(iptables_file
,"%s\n",line
);
619 void run_restore(void)
622 string(restor
,STRLEN
);
624 /*-----------------------------------------------------------------*/
625 printf("Running %s <%s ...\n", iptablesrestore
, iptablesfile
);
626 /*-----------------------------------------------------------------*/
629 fclose(iptables_file
);
636 done
; /* ugly macro end */
639 sprintf(restor
,"%s <%s",iptablesrestore
, iptablesfile
);
645 char *parse_datafile_line(char *str
)
647 char *ptr
=strchr(str
,' ');
661 void append_log(struct IP
*self
) /*using global variables*/
666 date(d
); /* this is typical cll1.h macro - prints current date */
668 sprintf(str
,"%s/%s.log", log_dir
, self
->name
);
672 fprintf(f
,"%ld\t%s\t%Lu\t%Lu\t%Lu\t%Lu\t%d\t%d\t%d\t%d\t%s",
673 time(NULL
), self
->name
, self
->traffic
, self
->direct
, self
->proxy
,
674 self
->upload
, self
->min
, self
->max
, self
->desired
, self
->lmsid
, d
); /* d = date*/
683 /*-----------------------------------------------------------------*/
684 /* Are you looking for int main(int argc, char **argv) ? :-)) */
685 /*-----------------------------------------------------------------*/
689 int i
=0; /* just plain old Fortran style integer :-) */
690 FILE *f
=NULL
; /* everything is just stream of bytes... */
691 char *str
, *ptr
, *d
; /* LET A$=B$ :-) */
695 int just_flush
=FALSE
; /* deactivates all previous actions */
697 int just_preview
=FALSE
; /* preview - generate just stats */
698 int start_shaping
=FALSE
; /* apply FUP - requires classmap file */
699 int just_logs
=FALSE
; /* just parse logs */
703 char *chain_forward
, *chain_postrouting
;
707 Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\
708 Version %s - Copyright (C)2005-2012 Michael Polak, Arachne Labs\n\
709 iptables-restore & burst tunning & classify modification by Ludva\n\
710 Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version
);
712 /*----- Boring... we have to check command line options first: ----*/
715 argument("-c") { nextargument(config
); }
716 argument("-h") { nextargument(althosts
);}
717 argument("-d") { run
=TRUE
; dry_run
=TRUE
; }
718 argument("-f") { run
=TRUE
; just_flush
=TRUE
; }
719 argument("-9") { run
=TRUE
; just_flush
=9; }
720 argument("-p") { run
=TRUE
; just_preview
=TRUE
; }
721 argument("-s") { run
=TRUE
; just_preview
=TRUE
; start_shaping
=TRUE
; }
722 argument("-r") { run
=TRUE
; }
723 argument("-n") { run
=TRUE
; nodelay
=TRUE
; }
724 argument("-l") { just_logs
=TRUE
; }
725 argument("-m") { just_logs
=TRUE
; }
726 argument("-y") { just_logs
=TRUE
; }
727 argument("-?") { help(); exit(0); }
728 argument("--help") { help(); exit(0); }
729 argument("-v") { exit(0); }
730 argument("--version") { exit(0); }
735 puts("*** THIS IS JUST DRY RUN ! ***\n");
738 date(d
); /* this is typical cll1.h macro - prints current date */
740 /*-----------------------------------------------------------------*/
741 printf("Parsing configuration file %s ...\n", config
);
742 /*-----------------------------------------------------------------*/
747 parse_ip_log(argc
,argv
);
763 /*-----------------------------------------------------------------*/
764 puts("Parsing iptables verbose output ...");
765 /*-----------------------------------------------------------------*/
766 get_traffic_statistics();
769 /*-----------------------------------------------------------------*/
770 printf("Parsing class defintion file %s ...\n", hosts
);
771 /*-----------------------------------------------------------------*/
774 /*-----------------------------------------------------------------*/
775 /* cll1.h - let's allocate brand new character buffer... */
776 /*-----------------------------------------------------------------*/
779 /*-----------------------------------------------------------------*/
780 puts("Resolving shared connections ...");
781 /*-----------------------------------------------------------------*/
782 for_each(ip
,ips
) if(ip
->sharing
)
784 for_each(sharedip
,ips
) if(eq(sharedip
->name
,ip
->sharing
))
786 sharedip
->traffic
+=ip
->traffic
;
788 ip
->mark
=sharedip
->mark
;
789 ip
->lmsid
=sharedip
->lmsid
;
794 printf("Unresolved shared connection: %s %s sharing-%s\n",
795 ip
->addr
, ip
->name
, ip
->sharing
);
799 if(enable_credit
&& just_flush
<9)
801 /*-----------------------------------------------------------------*/
802 printf("Parsing credit file %s ...\n", credit
);
803 /*-----------------------------------------------------------------*/
806 ptr
=parse_datafile_line(_
);
809 if_exists(ip
,ips
,eq(ip
->addr
,_
))
811 sscanf(ptr
,"%Lu",&(ip
->credit
));
815 done
; /* ugly macro end */
820 /*-----------------------------------------------------------------*/
821 puts("Initializing iptables and tc classes ...");
822 /*-----------------------------------------------------------------*/
824 iptables_file
=fopen(iptablesfile
,"w");
825 if(iptables_file
== NULL
)
827 puts("Cannot open iptablesfile!");
831 log_file
=fopen(cmdlog
,"w");
834 puts("Cannot open logfile!");
838 save_line(iptablespreamble
);
841 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,lan
);
844 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,wan
);
847 iptables_file
=fopen(iptablesfile
,"w");
848 save_line(iptablespreamble
);
850 if(qos_free_zone
&& *qos_free_zone
!='0')
854 sprintf(str
,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone
, wan
);
859 save_line(":post_noproxy - [0:0]");
860 sprintf(str
,"-A POSTROUTING ! -p tcp -o %s -j post_noproxy", lan
);
862 sprintf(str
,"-A POSTROUTING ! -s %s -o %s -j post_noproxy", proxy_ip
, lan
);
864 sprintf(str
,"-A POSTROUTING -s %s -p tcp ! --sport %d -o %s -j post_noproxy", proxy_ip
, proxy_port
, lan
);
867 chain
="post_noproxy";
874 sprintf(str
,"-A %s -s %s -o %s -j ACCEPT", chain
, qos_free_zone
, lan
);
878 if(ip_count
>idxtable_treshold1
&& !just_flush
)
880 int idxcount
=0, bitmask
=32-idxtable_bitmask1
; /* default net mask: 255.255.255.240 */
882 /*-----------------------------------------------------------------*/
883 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count
);
884 /*-----------------------------------------------------------------*/
886 save_line(":post_common - [0:0]");
887 save_line(":forw_common - [0:0]");
889 for_each(ip
,ips
) if(ip
->addr
&& *(ip
->addr
) && !eq(ip
->addr
,"0.0.0.0/0"))
891 buf
=index_id(ip
->addr
,bitmask
);
892 if_exists(idx
,idxs
,eq(idx
->id
,buf
))
901 idx
->bitmask
=bitmask
;
909 /* brutal perfomance optimalization */
910 while(idxcount
>idxtable_treshold2
&& bitmask
>2*idxtable_bitmask2
)
912 bitmask
-=idxtable_bitmask2
;
915 for_each(idx
,idxs
) if(idx
->parent
== NULL
)
917 buf
=index_id(idx
->addr
,bitmask
);
918 if_exists(metaindex
,idxs
,eq(metaindex
->id
,buf
))
920 metaindex
->children
++;
924 create(metaindex
,Index
);
925 metaindex
->addr
=idx
->addr
;
927 metaindex
->bitmask
=bitmask
;
928 metaindex
->parent
=NULL
;
929 metaindex
->children
=0;
931 push(metaindex
,idxs
);
933 idx
->parent
=metaindex
;
937 /* this should slightly optimize throughout ... */
938 sort(idx
,idxs
,desc_order_by
,children
);
939 sort(idx
,idxs
,order_by
,bitmask
);
944 subnet
=subnet_id(idx
->addr
,idx
->bitmask
);
945 printf("%d: %s/%d\n",
946 ++i
, subnet
, idx
->bitmask
);
948 sprintf(str
,":post_%s - [0:0]", idx
->id
);
951 sprintf(str
,":forw_%s - [0:0]", idx
->id
);
956 string(buf
,strlen(idx
->parent
->id
)+6);
957 sprintf(buf
,"post_%s",idx
->parent
->id
);
964 sprintf(str
,"-A %s -d %s/%d -o %s -j post_%s", buf
, subnet
, idx
->bitmask
, lan
, idx
->id
);
967 sprintf(str
,"-A %s -d %s/%d -o %s -j post_common", buf
, subnet
, idx
->bitmask
, lan
);
972 string(buf
,strlen(idx
->parent
->id
)+6);
973 sprintf(buf
,"forw_%s",idx
->parent
->id
);
980 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_%s", buf
, subnet
, idx
->bitmask
, wan
, idx
->id
);
983 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_common", buf
, subnet
, idx
->bitmask
, wan
);
986 printf("Total indexed iptables chains created: %d\n", i
);
988 sprintf(str
,"-A FORWARD -o %s -j forw_common", wan
);
991 sprintf(str
,"-A POSTROUTING -o %s -j post_common", lan
);
999 fclose(iptables_file
);
1004 puts("Just flushed iptables and tc classes - now exiting ...");
1010 if(!dry_run
&& !nodelay
&& qos_free_delay
)
1012 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay
);
1013 sleep(qos_free_delay
);
1016 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",
1020 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
1021 tc
,lan
,lan_medium
,lan_medium
,burst_main
,highest_priority
);
1024 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
1025 tc
,lan
,line
,line
,burst_main
,highest_priority
);
1028 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc
,wan
,htb_r2q
);
1031 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
1032 tc
,wan
,wan_medium
,wan_medium
,burst_main
,highest_priority
);
1035 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
1036 tc
,wan
,up
,up
,burst_main
,highest_priority
);
1040 /*-----------------------------------------------------------------*/
1041 puts("Locating heavy downloaders and generating root classes ...");
1042 /*-----------------------------------------------------------------*/
1043 sort(ip
,ips
,desc_order_by
,traffic
);
1045 /*-----------------------------------------------------------------*/
1046 /* sub-scope - local variables */
1048 long long int rate
= line
;
1049 long long int max
= line
;
1050 int group_count
= 0;
1051 FILE *credit_file
= NULL
;
1053 if(!just_preview
&& !dry_run
&& enable_credit
)
1055 credit_file
= fopen(credit
,"w");
1058 for_each(group
,groups
)
1063 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",
1064 tc
, lan
, parent
, group
->id
, rate
, max
, burst_group
, highest_priority
+1, group
->desired
);
1068 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",
1069 tc
, wan
, parent
, group
->id
, rate
*up
/line
, max
*up
/line
, burst_group
, highest_priority
+1, group
->desired
);
1073 if(group_count
++ < max_nesting
)
1078 rate
-= digital_divide
*group
->min
;
1079 if(rate
< group
->min
)
1084 /*shaping of aggresive downloaders, with credit file support */
1087 int group_rate
= group
->min
, priority_sequence
= lowest_priority
;
1089 for_each(ip
, ips
) if(ip
->min
== group
->min
&& ip
->max
> ip
->min
)
1091 if( ip
->keyword
->data_limit
&& !ip
->fixedprio
1092 && ( ip
->traffic
>ip
->credit
1093 + (ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))) )
1095 if(group_rate
<ip
->max
)
1099 group_rate
+=magic_treshold
;
1100 ip
->prio
=lowest_priority
;
1101 if(ip
->prio
<highest_priority
+2)
1103 ip
->prio
=highest_priority
+2;
1108 if( ip
->keyword
->data_prio
1110 && ( ip
->traffic
>ip
->credit
1111 + (ip
->min
*ip
->keyword
->data_prio
+(ip
->keyword
->fixed_prio
<<20))) )
1113 ip
->prio
=priority_sequence
--;
1114 if(ip
->prio
<highest_priority
+1)
1116 ip
->prio
=highest_priority
+1;
1122 unsigned long long lcredit
=0;
1124 if((ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))>ip
->traffic
)
1126 lcredit
=(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))-ip
->traffic
;
1128 fprintf(credit_file
,"%s %Lu\n",ip
->addr
,lcredit
);
1136 fclose(credit_file
);
1144 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap
);
1152 if_exists(ip
,ips
,eq(ip
->addr
,_
))
1155 if(ip
->max
< ip
->desired
) /* apply FUP limit immediately.... */
1157 printf("Applying limit for %-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
1158 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
1159 sprintf(str
, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1160 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1162 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1163 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1164 sprintf(str
,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1165 tc
, wan
, ip
->group
, ip
->mark
,
1166 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1167 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1176 puts("Warning - classmap file not fund, just generating preview ...");
1177 start_shaping
=FALSE
;
1179 done
; /* ugly macro end */
1185 if(!dry_run
&& !just_flush
)
1187 /*-----------------------------------------------------------------*/
1188 printf("Writing json overview %s ... ", json
);
1189 /*-----------------------------------------------------------------*/
1198 && (ip
->traffic
|| ip
->direct
|| ip
->proxy
|| ip
->upload
))
1204 fprintf(f
, " \"%s\":{ \"lms\": %d, \"ip\":\"%s\", \"total\":%Lu, \"down\":%Lu, \"proxy\":%Lu, \"up\":%Lu, \"min\":%d, \"max\":%d, \"limit\":%d }",
1205 ip
->name
, ip
->lmsid
, ip
->addr
, ip
->traffic
, ip
->direct
, ip
->proxy
, ip
->upload
, ip
->min
, ip
->desired
, ip
->max
);
1225 /*-----------------------------------------------------------------*/
1226 printf("Sorting data and generating statistics page %s ...\n", html
);
1227 /*-----------------------------------------------------------------*/
1229 if(use_jquery_popups
)
1231 fprintf(f
,"<script type=\"text/javascript\" src=\"%s\"></script>\n", jquery_url
);
1233 fputs("<table class=\"decorated last\">\n\
1234 <caption>Bandwidth classes</caption>\n\
1236 <th style=\"text-align: right\">#</th>\n\
1237 <th style=\"text-align: right\">group</th>\n\
1238 <th style=\"text-align: right\">IPs</th>\n\
1239 <th style=\"text-align: right\">requested</th>\n",f
);
1240 fprintf(f
,"<th colspan=\"%d\">data limits</th>\n", keywordcount
);
1241 fputs("</tr></thead><tbody>\n",f
);
1244 for_each(group
, groups
)
1247 printf("%d kb/s group: %d bandwidth requested: %d kb/s\n",group
->min
,group
->count
,group
->desired
);
1249 fprintf(f
, "%s<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d kb/s</td>",
1250 tr_odd_even(), count
, group
->min
);
1251 fprintf(f
, "<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d kb/s</td>",
1252 group
->count
, group
->desired
);
1254 for_each(keyword
, keywords
) if(keyword
->ip_count
)
1256 fprintf(f
,"<td style=\"text-align: right\"><span style=\"color:#%s\">%d MB</span></td>",
1257 keyword
->html_color
, group
->min
*keyword
->data_limit
);
1259 i
+= group
->desired
;
1260 total
+= group
->count
;
1264 printf("Total groups: %d Total bandwidth requested: %d kb/s\nAGGREGATION: 1/%d\n",
1267 fprintf(f
,"</tr></tbody>\n\
1269 <th colspan=\"2\" style=\"text-align: left\">Line %Ld kb/s</td>",line
);
1270 fprintf(f
,"<th style=\"text-align: right\">%d</td><th style=\"text-align: right\">%d kb/s</td>",total
,i
);
1272 for_each(keyword
, keywords
) if(keyword
->ip_count
)
1274 fprintf(f
,"<th style=\"text-align: right\">%d IPs</th>",keyword
->ip_count
);
1276 fprintf(f
,"</tr><tr><th colspan=\"4\">Aggregation 1/%d</th>\n", (int)(0.5+i
/line
));
1277 fprintf(f
,"<th colspan=\"%d\">%d traffic classes</th></tr>\n", keywordcount
, total
);
1279 fputs("</thead></table>\n",f
);
1281 else if(!dry_run
&& !just_flush
)
1289 unsigned long long total_traffic
=0, total_direct
=0, total_proxy
=0, total_upload
=0, tmp_sum
=0;
1290 int active_classes
=0;
1292 struct Sum
{unsigned long long l
; int i
; list(Sum
);} *sum
,*sums
=NULL
;
1293 int limit_count
=0, prio_count
=0;
1301 fprintf(f
,"<p><table class=\"decorated last\">\n<caption>%s",title
);
1302 fprintf(f
," (%s)</caption>\n", d
);
1303 fputs("<thead><tr>\n<th colspan=\"3\"> </th>\n",f
);
1304 fputs("<th style=\"text-align: right\">credit</th>\n\
1305 <th style=\"text-align: right\">FUP</th>\n\
1306 <th style=\"text-align: right\">total</th>\n\
1307 <th style=\"text-align: right\">down</th>\n",f
);
1310 fputs("<th style=\"text-align: right\">proxy</th>\n",f
);
1312 fputs("<th style=\"text-align: right\">up</th>\n\
1313 <th style=\"text-align: right\">min</th>\n\
1314 <th style=\"text-align: right\">max</th>\n\
1315 <th style=\"text-align: right\">limit</th>\n\
1318 <th style=\"text-align: right\">#</th>\n\
1319 <th>hostname [+sharing]</th>\n\
1320 <th style=\"text-align: right\">LMS</th>\n\
1321 <th style=\"text-align: right\">MB</th>\n\
1322 <th style=\"text-align: right\">MB</th>\n\
1323 <th style=\"text-align: right\">MB</th>\n\
1324 <th style=\"text-align: right\">MB</th>\n\
1325 <th style=\"text-align: right\">MB</th>\n\
1326 <th style=\"text-align: right\">kb/s</th>\n\
1327 <th style=\"text-align: right\">kb/s</th>\n\
1328 <th style=\"text-align: right\">kb/s</th>\n\
1330 </tr></thead><tbody>\n",f
);
1333 for_each(ip
,ips
) if(!use_jquery_popups
|| !ip
->sharing
)
1335 char *f1
="", *f2
="";
1338 if(ip
->max
< ip
->desired
)
1340 f1
="<span style=\"color:red\">";
1344 else if(ip
->prio
> highest_priority
+1)
1346 f1
="<span style=\"color:brown\">";
1352 printf("%03d. %-22s %10Lu (%d/%d)\n",i
,ip
->name
, ip
->traffic
, ip
->min
, ip
->max
);
1354 /* hostnames -------------------------------------- */
1355 fprintf(f
,"%s<td style=\"text-align: right\"><a name=\"%s\"></a>%d</td><td><a class=\"blue\" target=\"_blank\" href=\"%s%s.log\">%s</a>\n",
1356 tr_odd_even(), ip
->name
, i
, log_url
, ip
->name
, ip
->name
);
1358 if(use_jquery_popups
)
1360 fprintf(f
,"<span id=\"sharing_%d\" style=\"display:none\">",i
);
1362 for_each(sharedip
, ips
) if(eq(ip
->name
, sharedip
->sharing
))
1364 fprintf(f
,"<br /><a class=\"blue\" target=\"_blank\" href=\"%s%s.log\">%s</a>\n", log_url
, sharedip
->name
, sharedip
->name
);
1367 fputs("</span>\n",f
);
1370 fprintf(f
,"<span>[<a class=\"blue\" href=\"#\" onClick=\"$(this).parent().hide();$(\'#sharing_%d\').show();$(\'#download_%d\').show();$(\'#upload_%d\').show();return(false);\" style=\"cursor: pointer;\">+%d</a>]</span>",
1371 i
, i
, i
, popup_button
);
1375 /* ----------------------------------------------- */
1379 fputs("<td style=\"text-align: right\">",f
);
1382 fprintf(f
,"<a class=\"blue\" target=\"_blank\" href=\"%s%d\">%04d</a>\n", lms_url
, ip
->lmsid
, ip
->lmsid
);
1384 else if(ip
->lmsid
== 0)
1390 fprintf(f
,"<td style=\"text-align: right\">%Lu</td>\n", ip
->credit
);
1391 fprintf(f
,"<td style=\"text-align: right\"><span style=\"color:#%s\">%Lu</span></td>",
1392 ip
->keyword
->html_color
,
1393 ip
->credit
+(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20)));
1394 fprintf(f
,"<td style=\"text-align: right\">%s%Lu%s", f1
, ip
->traffic
, f2
);
1396 /* download --------------------------------------- */
1397 fprintf(f
,"</td><td style=\"text-align: right\">%Lu", ip
->direct
);
1398 if(use_jquery_popups
)
1400 fprintf(f
,"<span id=\"download_%d\" style=\"display:none\">",i
);
1401 for_each(sharedip
, ips
) if(eq(ip
->name
, sharedip
->sharing
))
1403 fprintf(f
,"<br />%Lu", sharedip
->direct
);
1405 fputs("</span>\n",f
);
1408 /* ----------------------------------------------- */
1412 fprintf(f
,"<td style=\"text-align: right\">%Lu</td>\n", ip
->proxy
);
1414 /* upload ---------------------------------------- */
1415 fprintf(f
,"<td style=\"text-align: right\">%Lu", ip
->upload
);
1416 if(use_jquery_popups
)
1418 fprintf(f
,"<span id=\"upload_%d\" style=\"display:none\">",i
);
1419 for_each(sharedip
,ips
) if(eq(ip
->name
, sharedip
->sharing
))
1421 fprintf(f
,"<br />%Lu", sharedip
->upload
);
1423 fputs("</span>\n",f
);
1426 /* ----------------------------------------------- */
1428 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1429 <td style=\"text-align: right\">%d</td>\n\
1430 <td style=\"text-align: right\">%s%d%s</td>\n\
1431 <td>%s%d%s</td></tr>\n",
1432 ip
->min
, ip
->desired
,
1436 total_traffic
+=ip
->traffic
;
1437 total_direct
+=ip
->direct
;
1438 total_proxy
+=ip
->proxy
;
1439 total_upload
+=ip
->upload
;
1443 tmp_sum
+=ip
->traffic
;
1446 sum
->i
=active_classes
;
1447 insert(sum
,sums
,order_by
,i
);
1453 for_each(sharedip
,ips
) if(eq(ip
->name
, sharedip
->sharing
))
1455 append_log(sharedip
);
1459 fprintf(f
,"</tbody><thead><tr>\n\
1460 <th colspan=\"%d\" style=\"text-align: left\">%d CLASSES</th>", colspan
-7, i
);
1461 fprintf(f
,"<th style=\"text-align: right\">%Lu</th><th style=\"text-align: right\">%Lu</th>\n", total_traffic
, total_direct
);
1464 fprintf(f
,"<th style=\"text-align: right\">%Lu</th>\n", total_proxy
);
1466 fprintf(f
,"<th style=\"text-align: right\">%Lu</th>", total_upload
);
1467 fprintf(f
,"<th colspan=\"4\"><span style=\"color:red\">LIMIT %dx</span> <span style=\"color:brown\">LOW-PRIO %dx</span></th></tr>\n</thead></table>\n",limit_count
,prio_count
);
1470 if(active_classes
>10)
1472 int top20_count
=0,top20_perc1
=0;
1473 long long top20_perc2
=0;
1474 unsigned long long top20_sum
=0l;
1476 fputs("<a name=\"erp\"></a><p><table class=\"decorated last\"><caption>Enterprise Resource Planning (ERP)</caption>\n",f
);
1477 fputs("<thead><tr>\n\
1478 <th>Analytic category</th>\n\
1479 <th colspan=\"2\" style=\"text-align: center\">Active Classes</th>\n\
1480 <th colspan=\"2\" style=\"text-align: center\">Data transfers</th>\n\
1481 </tr></thead><tbody>\n",f
);
1483 if_exists(sum
,sums
,sum
->l
>=total_traffic
/4)
1485 fprintf(f
,"%s<td>Top 25%% of traffic</td>\n", tr_odd_even());
1486 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1487 <td style=\"text-align: right\">%d %%</td>\n\
1488 <td style=\"text-align: right\">%Lu MB</td>\n\
1489 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1490 sum
->i
, (100*sum
->i
+50)/active_classes
, sum
->l
, (100*sum
->l
+50)/total_traffic
);
1493 if_exists(sum
,sums
,sum
->i
==10)
1495 fprintf(f
,"%s<td>Top 10 downloaders</td>\n", tr_odd_even());
1496 fprintf(f
,"<td style=\"text-align: right\"><strong>10</strong></td>\n\
1497 <td style=\"text-align: right\">%d %%</td>\n\
1498 <td style=\"text-align: right\">%Lu MB</td>\n\
1499 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1500 (100*sum
->i
+50)/active_classes
, sum
->l
, (100*sum
->l
+50)/total_traffic
);
1503 if_exists(sum
,sums
,sum
->l
>=total_traffic
/2)
1505 fprintf(f
,"%s<td>Top 50%% of traffic</td>\n", tr_odd_even());
1506 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1507 <td style=\"text-align: right\">%d %%</td>\n\
1508 <td style=\"text-align: right\">%Lu MB</td>\n\
1509 <td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",
1510 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1513 if_exists(sum
,sums
,sum
->l
>=4*total_traffic
/5)
1515 fprintf(f
,"%s<td>Top 80%% of traffic</td>\n", tr_odd_even());
1516 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1517 <td style=\"text-align: right\">%d %%</td>\n\
1518 <td style=\"text-align: right\">%Lu MB</td>\n\
1519 <td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",
1520 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1523 if_exists(sum
,sums
,sum
->i
>=(active_classes
+1)/5)
1525 fprintf(f
,"%s<td>Top 20%% downloaders</td>\n", tr_odd_even());
1527 top20_perc1
=(100*sum
->i
+50)/active_classes
;
1529 top20_perc2
=(100*sum
->l
+50)/total_traffic
;
1530 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1531 <td style=\"text-align: right\"><strong>%d %%</strong></td>\n\
1532 <td style=\"text-align: right\">%Lu MB</td>\n\
1533 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1534 top20_count
,top20_perc1
,top20_sum
,top20_perc2
);
1537 if_exists(sum
,sums
,sum
->i
>=(active_classes
+1)/4)
1539 fprintf(f
,"%s<td>Top 25%% downloaders</td>\n", tr_odd_even());
1540 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1541 <td style=\"text-align: right\">%d %%</td>\n\
1542 <td style=\"text-align: right\">%Lu MB</td>\n\
1543 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1544 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1547 if_exists(sum
,sums
,sum
->i
>=(active_classes
+1)/2)
1549 fprintf(f
,"%s<td>Top 50%% downloaders</td>\n", tr_odd_even());
1550 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1551 <td style=\"text-align: right\"><strong>%d %%</strong></td>\n\
1552 <td style=\"text-align: right\">%Lu MB</td>\n\
1553 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1554 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1557 if_exists(sum
,sums
,sum
->i
>=4*(active_classes
+1)/5)
1559 fprintf(f
,"%s<td>Top 80%% downloaders</td>\n", tr_odd_even());
1560 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1561 <td style=\"text-align: right\">%d %%</td>\n\
1562 <td style=\"text-align: right\">%Lu MB</td>\n\
1563 <td style=\"text-align: right\">%Ld %%</td></tr></tbody>\n",
1564 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1567 fprintf(f
,"<thead><tr><th><a class=\"blue\" target=\"_blank\" href=\"%sERP.log\">All users, all traffic</a></th>\n", log_url
);
1568 fprintf(f
,"<th style=\"text-align: right\">%d</th>\n\
1569 <th style=\"text-align: right\">100 %%</th>\n\
1570 <th style=\"text-align: right\">%Lu MB</th>\n\
1571 <th style=\"text-align: right\">100 %%</th></tr>\n",active_classes
,total_traffic
);
1572 fputs("</thead></table>\n", f
);
1574 /* write basic ERP data to log directory */
1578 sprintf(str
,"%s/ERP.log",log_dir
);
1579 iplog
=fopen(str
,"a");
1582 fprintf(iplog
,"%ld\t%d\t%d %%\t%Lu M\t%Ld %%\tACTIVE %d\tTRAFFIC %Lu M\tCLASSES %d\tFUP-LIMIT %d\tLOW-PRIO %d\t%s",
1583 time(NULL
), top20_count
, top20_perc1
, top20_sum
, top20_perc2
,
1584 active_classes
, total_traffic
, i
, limit_count
, prio_count
, d
); /* d = date*/
1594 fprintf(f
, stats_html_signature
, version
);
1605 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar
);
1611 printf("%-22s %-15s mark\n","name","ip");
1614 printf("Writing %s ... ", classmap
);
1615 f
= fopen(classmap
, "w");
1621 /*-----------------------------------------------------------------*/
1622 puts("Generating iptables and tc classes ... ");
1623 /*-----------------------------------------------------------------*/
1625 for_each(ip
, ips
) if(ip
->mark
> 0)
1630 duplicate(ip
->addr
,buf
);
1631 buf
=index_id(ip
->addr
,32-idxtable_bitmask1
);
1633 string(chain_forward
,6+strlen(buf
));
1634 strcpy(chain_forward
,"forw_");
1635 strcat(chain_forward
,buf
);
1637 string(chain_postrouting
,6+strlen(buf
));
1638 strcpy(chain_postrouting
,"post_");
1639 strcat(chain_postrouting
,buf
);
1645 chain_forward
="FORWARD";
1646 chain_postrouting
="POSTROUTING";
1650 printf("%-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
1653 /* -------------------------------------------------------- mark download */
1655 sprintf(str
, "-A %s -d %s/32 -o %s -j %s%d",
1656 chain_postrouting
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
1657 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/
1658 /* -m limit --limit 1/s */
1663 sprintf(str
, "-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",
1664 chain_postrouting
, proxy_ip
, proxy_port
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
1665 /*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);*/
1669 sprintf(str
, "-A %s -d %s/32 -o %s -j ACCEPT",
1670 chain_postrouting
, ip
->addr
, lan
);
1673 /* -------------------------------------------------------- mark upload */
1674 sprintf(str
, "-A %s -s %s/32 -o %s -j %s%d",
1675 chain_forward
, ip
->addr
, wan
, mark_iptables
, ip
->mark
);
1676 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/
1679 sprintf(str
, "-A %s -s %s/32 -o %s -j ACCEPT",
1680 chain_forward
, ip
->addr
, wan
);
1685 /* -------------------------------------------------------- download class */
1687 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
1690 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1691 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1694 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1696 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1697 tc
, lan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1701 if(filter_type
== 1)
1703 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1704 tc
, lan
, ip
->mark
, ip
->mark
);
1708 /* -------------------------------------------------------- upload class */
1710 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1711 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1714 sprintf(str
,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1715 tc
, wan
, ip
->group
, ip
->mark
,
1716 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1717 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1720 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1722 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1723 tc
, wan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1727 if(filter_type
== 1)
1729 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1730 tc
, wan
, ip
->mark
, ip
->mark
);
1736 fprintf(f
, "%s %d\n", ip
->addr
, ip
->mark
);
1742 printf("(sharing %s)\n", ip
->sharing
);
1755 chain_forward
= "forw_common";
1756 chain_postrouting
= "post_common";
1760 chain_forward
= "FORWARD";
1761 chain_postrouting
= "POSTROUTING";
1763 /* -------------------------------- classify or reject free download */
1765 char *final_chain
= "DROP"; /* REJECT would be better, but it is impossible in mangle */
1768 final_chain
= "ACCEPT";
1774 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s%d",
1775 chain_postrouting
,proxy_ip
,proxy_port
,lan
,mark_iptables
,3);
1778 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s",
1779 chain_postrouting
,proxy_ip
,proxy_port
,lan
,final_chain
);
1784 sprintf(str
,"-A %s -o %s -j %s%d", chain_postrouting
, lan
, mark_iptables
, 3);
1787 sprintf(str
,"-A %s -o %s -j %s", chain_postrouting
, lan
, final_chain
);
1789 /* ------------------------------- classify or reject free upload */
1792 sprintf(str
,"-A %s -o %s -j %s%d", chain_forward
, wan
, mark_iptables
, 3);
1795 sprintf(str
,"-A %s -o %s -j %s", chain_forward
, wan
, final_chain
);
1799 if(free_min
) /* allocate free bandwith if it is not zero... */
1801 /*-----------------------------------------------------------------*/
1802 puts("Generating free bandwith classes ...");
1803 /*-----------------------------------------------------------------*/
1804 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1805 tc
, lan
, parent
, free_min
, free_max
,burst
, lowest_priority
);
1807 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1808 tc
, wan
, parent
, free_min
, free_max
, burst
, lowest_priority
);
1811 if(strcmpi(qos_leaf
, "none"))
1813 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, lan
, qos_leaf
);
1816 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, wan
, qos_leaf
);
1819 /* tc handle 1 fw flowid */
1820 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, lan
);
1823 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, wan
);
1826 printf("Total IP count: %d\n", i
);
1833 /* that's all folks, thank you for reading it all the way up to this point ;-) */
1834 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */
This page took 1.256188 seconds and 3 git commands to generate.