717971410549b1ce35de9bc6eadc77ce1ae55fe3
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, 20121007
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 /* ======= All path names are defined here (for RPM patch) ======= */
46 const char *tc
= "/sbin/tc"; /* requires tc with HTB support */
47 const char *iptables
= "/sbin/iptables"; /* requires iptables utility */
48 const char *iptablessave
= "/sbin/iptables-save"; /* not yet required */
49 const char *iptablesrestore
= "/sbin/iptables-restore"; /* requires iptables-restore */
50 const char *ls
= "/bin/ls"; /* this is not user configurable :-) */
52 char *config
= "/etc/prometheus/prometheus.conf"; /* main configuration file */
53 char *hosts
= "/etc/prometheus/hosts"; /* per-IP bandwidth definition file */
55 char *iptablesfile
= "/var/spool/prometheus.iptables"; /* temporary file for iptables-restore*/
56 char *credit
= "/var/lib/misc/prometheus.credit"; /* credit log file */
57 char *classmap
= "/var/lib/misc/prometheus.classes"; /* credit log file */
58 char *html
= "/var/www/traffic.html"; /* hall of fame - html version */
59 char *preview
= "/var/www/preview.html"; /* hall of fame preview - html version */
60 char *json
= "/var/www/logs/traffic.json"; /* hall of fame - json version */
61 char *json_preview
= "/var/www/logs/preview.json"; /* hall of fame preview - json version */
62 char *cmdlog
= "/var/log/prometheuslog"; /* command log filename */
63 char *log_dir
= "/var/www/logs/"; /* log directory pathname, ended with slash */
64 char *log_url
= "/logs/"; /* log directory relative URI prefix (partial URL) */
65 char *html_log_dir
= "/var/www/logs/html/";
67 char *jquery_url
= "http://code.jquery.com/jquery-latest.js";
68 char *lms_url
= "/lms/?m=customerinfo&id=";
69 int use_jquery_popups
= 1;
70 int row_odd_even
= 0; /*<tr class="odd/even"> */
73 void parse_ip_log(int argc
, char **argv
);
74 /* implementid in parselog.c */
76 void parse_hosts(char *hosts
);
77 /* implementid in parsehosts.c */
79 const char *tr_odd_even(void)
81 row_odd_even
= 1 - row_odd_even
;
84 return "<tr class=\"even\">\n";
88 return "<tr class=\"odd\">\n";
92 /* ======= Help screen is hopefuly self-documenting part of code :-) ======= */
96 puts("Command line switches:\n\
98 -d Dry run (preview tc and iptables commands on stdout)\n\
99 -r Run (reset all statistics and start shaping - daily usage)\n\
100 -p just generate Preview of data transfer statistics and exit (after -r)\n\
101 -s start Shaping FUP limits (keeps data transfer stat like -p) (after -r)\n\
102 -n run Now (like -r delay - overrides qos-free-delay keyword, after boot)\n\
103 -f just Flush iptables and tc classes and exit (stop shaping, no QiS)\n\
104 -9 emergency iptables flush (like -f, but dumps data transfer statistics)\n\
106 -c filename force alternative /etc/prometheus/prometheus.conf filename\n\
107 -h filename force alternative /etc/hosts filename (overrides hosts keyword)\n\
108 -l Mmm YYYY generate HTML summary of Logged traffic (Mmm=Jan-Dec) (and exit)\n\
109 -m generate HTML summary of traffic for yesterday's Month (and exit)\n\
110 -y generate HTML summary of traffic for yesterday's Year (and exit)\n\
111 -? --help show this help scree (and exit)\n\
112 -v --version show Version number of this utility (and exit)\n");
115 /* === Configuraration file values defaults - stored in global variables ==== */
117 int filter_type
= 1; /*1 mark, 2 classify*/
119 char *mark_iptables
= "MARK --set-mark ";
120 int dry_run
= 0; /* preview - use puts() instead of system() */
121 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]";
122 FILE *iptables_file
= NULL
;
123 int enable_credit
= 1; /* enable credit file */
124 int use_credit
= 0; /* use credit file (if enabled)*/
125 char *title
= "Hall of Fame - Greatest Suckers"; /* hall of fame title */
126 int hall_of_fame
= 1; /* enable hall of fame */
127 char *lan
= "eth0"; /* LAN interface */
128 char *lan_medium
= "100Mbit"; /* 10Mbit/100Mbit ethernet */
129 char *wan
= "eth1"; /* WAN/ISP interface */
130 char *wan_medium
= "100Mbit"; /* 10Mbit/100Mbit ethernet */
131 char *qos_leaf
= "sfq perturb 5"; /* leaf discipline */
132 char *qos_free_zone
= NULL
; /* QoS free zone */
133 int qos_proxy
= 1; /* include proxy port to QoS */
134 int found_lmsid
= 0; /* show links to users in LMS information system */
135 int include_upload
= 1; /* upload+download=total traffic */
136 char *proxy_ip
= "192.168.1.1/32"; /* our IP with proxy port */
137 int proxy_port
= 3128; /* proxy port number */
138 long long int line
= 1024; /* WAN/ISP download in kbps */
139 long long int up
= 1024; /* WAN/ISP upload in kbps */
140 int free_min
= 32; /* minimum guaranted bandwidth for all undefined hosts */
141 int free_max
= 64; /* maximum allowed bandwidth for all undefined hosts */
142 int qos_free_delay
= 0; /* seconds to sleep before applying new QoS rules */
143 int digital_divide
= 2; /* controls digital divide weirdness ratio, 1...3 */
144 int max_nesting
= 3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */
145 int htb_r2q
= 256; /* should work for leaf values 512 kbps to 8 Mbps */
146 int burst
= 8; /* HTB burst (in kbits) */
148 int burst_group
= 32;
149 int magic_treshold
= 8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */
150 int keywordcount
= 0;
153 /* not yet implemented:
154 int fixed_packets = 0; maximum number of pps per IP address (not class!)
155 int packet_limit = 5; maximum number of pps to htn CEIL, not rate !!!
157 FILE *log_file
= NULL
;
158 char *kwd
= "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */
160 const int highest_priority
= 0; /* highest HTB priority (HTB built-in value is 0) */
161 const int lowest_priority
= 7; /* lowest HTB priority (HTB built-in value is 7) */
162 const int idxtable_treshold1
= 24; /* this is no longer configurable */
163 const int idxtable_treshold2
= 12; /* this is no longer configurable */
164 const int idxtable_bitmask1
= 3; /* this is no longer configurable */
165 const int idxtable_bitmask2
= 3; /* this is no longer configurable */
167 struct IP
*ips
= NULL
, *ip
, *sharedip
;
168 struct Group
*groups
= NULL
, *group
;
169 struct Keyword
*keyword
, *defaultkeyword
=NULL
, *keywords
=NULL
;
171 /* ==== This is C<<1 stuff - learn C<<1 first! https://dev.arachne.cz/svn/cll1h ==== */
177 struct Index
*parent
;
181 } *idxs
=NULL
, *idx
, *metaindex
;
186 /* function implemented in parsehosts.c */
188 /* ====== iptables indexes are used to reduce complexity to log8(N) ===== */
190 char *very_ugly_ipv4_code(char *inip
,int bitmask
,int format_as_chainname
)
192 /* warning: this function was debugged only for bitmask values 20,24,28 !!!*/
194 char *ip
,*outip
,*outptr
,*fmt
;
197 /* debug printf("(%s,%d) -> ",ip,bitmask); */
199 if(ip
&& *ip
&& bitmask
>=0 && bitmask
<=32)
201 string(outip
,strlen(ip
)+10); /*fuck unicode? assertion: 10>strlen("_%d_%d") */
205 /* should never exit here */
213 if(dot
<(bitmask
/8-1))
215 if(format_as_chainname
)
228 char *cutdot
=strchr(ip
+1,'.'); /*for bitmask<24*/
234 if(format_as_chainname
)
245 n
= atoi(ip
+1)-atoi(ip
+1)%(1<<(8-bitmask
%8));
252 /*debug printf("%d/%d => [_%d_%d]\n",atoi(ip+1),bitmask,n,bitmask); */
253 sprintf(outptr
,fmt
,n
,bitmask
);
254 if(!format_as_chainname
)
262 /* debug printf("[%s]\n",outip); */
273 /*should never exit here*/
278 char *hash_id(char *ip
,int bitmask
)
280 return very_ugly_ipv4_code(ip
,bitmask
,1);
283 char *subnet_id(char *ip
,int bitmask
)
285 return very_ugly_ipv4_code(ip
,bitmask
,0);
288 /* ================= Let's parse configuration file here =================== */
290 void reject_config_and_exit(char *filename
)
292 printf("Configuration file %s rejected - abnormal exit.",filename
);
296 void get_config(char *config_filename
)
300 printf("Configured keywords: ");
301 parse(config_filename
)
303 option("keyword",kwd
);
308 create(keyword
,Keyword
);
310 keyword
->asymetry_ratio
=1; /* ratio for ADSL-like upload */
311 keyword
->asymetry_fixed
=0; /* fixed treshold for ADSL-like upload */
312 keyword
->data_limit
=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */
313 keyword
->data_prio
=4; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */
314 keyword
->fixed_limit
=0; /* fixed data limit for setting lower HTB ceil */
315 keyword
->fixed_prio
=0; /* fixed data limit for setting lower HTB prio */
316 keyword
->reserve_min
=8; /* bonus for nominal HTB rate bandwidth (in kbps) */
317 keyword
->reserve_max
=0; /* malus for nominal HTB ceil (in kbps) */
318 keyword
->default_prio
=highest_priority
+1;
319 keyword
->html_color
="000000";
321 keyword
->leaf_discipline
="";
323 push(keyword
,keywords
);
324 if(!defaultkeyword
) defaultkeyword
=keyword
;
331 for_each(keyword
,keywords
)
333 int l
=strlen(keyword
->key
);
335 if(!strncmp(keyword
->key
,_
,l
) && strlen(_
)>l
+2)
337 char *tmptr
=_
; /* <---- l+1 ----> */
338 _
+=l
+1; /* via-prometheus-asymetry-ratio, etc. */
339 ioption("asymetry-ratio",keyword
->asymetry_ratio
);
340 ioption("asymetry-treshold",keyword
->asymetry_fixed
);
341 ioption("magic-relative-limit",keyword
->data_limit
);
342 ioption("magic-relative-prio",keyword
->data_prio
);
343 loption("magic-fixed-limit",keyword
->fixed_limit
);
344 loption("magic-fixed-prio",keyword
->fixed_prio
);
345 ioption("htb-default-prio",keyword
->default_prio
);
346 ioption("htb-rate-bonus",keyword
->reserve_min
);
347 ioption("htb-ceil-malus",keyword
->reserve_max
);
348 option("leaf-discipline",keyword
->leaf_discipline
);
349 option("html-color",keyword
->html_color
);
352 if(keyword
->data_limit
|| keyword
->fixed_limit
||
353 keyword
->data_prio
|| keyword
->fixed_prio
)
362 option("iptables",iptables
);
363 option("iptables-save",iptablessave
); /* new */
364 option("iptables-restore",iptablesrestore
); /* new */
365 option("iptables-in-filename",iptablesfile
); /* new */
366 option("hosts",hosts
);
367 option("lan-interface",lan
);
368 option("wan-interface",wan
);
369 option("lan-medium",lan_medium
);
370 option("wan-medium",wan_medium
);
371 lloption("wan-download",line
);
372 lloption("wan-upload",up
);
373 ioption("hall-of-fame-enable",hall_of_fame
);
374 option("hall-of-fame-title",title
);
375 option("hall-of-fame-filename",html
);
376 option("json-filename",json
);
377 option("hall-of-fame-preview",preview
);
378 option("json-preview",json_preview
);
379 option("log-filename",cmdlog
);
380 option("credit-filename",credit
);
381 option("classmap-filename",classmap
);
382 ioption("credit-enable",enable_credit
);
383 option("log-traffic-directory",log_dir
);
384 option("log-traffic-html-directory",html_log_dir
);
385 option("log-traffic-url-path",log_url
);
386 option("jquery-url",jquery_url
);
387 option("lms-url",lms_url
);
388 ioption("use-jquery-popups",use_jquery_popups
);
389 option("qos-free-zone",qos_free_zone
);
390 ioption("qos-free-delay",qos_free_delay
);
391 ioption("qos-proxy-enable",qos_proxy
);
392 option("qos-proxy-ip",proxy_ip
);
393 option("htb-leaf-discipline",qos_leaf
);
394 ioption("qos-proxy-port",proxy_port
);
395 ioption("free-rate",free_min
);
396 ioption("free-ceil",free_max
);
397 ioption("htb-burst",burst
);
398 ioption("htb-burst-main",burst_main
);
399 ioption("htb-burst-group",burst_group
);
400 ioption("htb-nesting-limit",max_nesting
);
401 ioption("htb-r2q",htb_r2q
);
402 ioption("magic-include-upload",include_upload
);
403 ioption("magic-treshold",magic_treshold
);
404 option("filter-type", cnf
);
405 /* not yet implemented:
406 ioption("magic-fixed-packets",fixed_packets);
407 ioption("magic-relative-packets",packet_limit);
412 perror(config_filename
);
413 puts("Warning - using built-in defaults instead ...");
415 done
; /* ugly macro end */
418 /* leaf discipline for keywords */
419 for_each(keyword
,keywords
)
421 if(!strcmpi(keyword
->leaf_discipline
, ""))
423 keyword
->leaf_discipline
= qos_leaf
;
427 if(strcmpi(cnf
, "mark"))
431 mark_iptables
= "CLASSIFY --set-class 1:";
437 mark_iptables
= "MARK --set-mark ";
440 /* are supplied values meaningful ?*/
443 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");
444 reject_config_and_exit(config_filename
);
448 /* ===================== traffic analyser - uses iptables ================ */
450 void get_traffic_statistics(void)
455 textfile(Pipe
,str
) *line
,*lines
=NULL
;
459 sprintf(cmd
,"%s -L -v -x -n -t mangle",iptables
);
471 int col
, accept
=0,proxyflag
=0,valid
=1,setchainname
=0,commonflag
=0;
472 unsigned long long traffic
=0;
473 unsigned long pkts
=0;
474 char *ipaddr
=NULL
,*ptr
;
476 /* debug puts(line->str); */
477 valid_columns(ptr
,line
->str
,' ',col
)
478 if(valid
) switch(col
)
480 case 1: if(eq(ptr
,"Chain"))
484 else if(eq(ptr
,"pkts"))
490 sscanf(ptr
,"%lu",&pkts
);
493 case 2: if(setchainname
)
495 if(!strncmp(ptr
,"post_",5) || eq(ptr
,"POSTROUTING"))
501 if(!strncmp(ptr
,"forw_",5) || eq(ptr
,"FORWARD"))
506 if(eq(ptr
,"post_common") || eq(ptr
,"forw_common"))
513 sscanf(ptr
,"%Lu",&traffic
);
518 case 3: if((strncmp(ptr
,"post_",5) && strncmp(ptr
,"forw_",5)) || commonflag
)
522 /*if(filter_type==1) accept=eq(ptr,"MARK"); else accept=eq(ptr,"CLASSIFY");*/
524 case 8: if(downloadflag
)
526 if(strstr(proxy_ip
,ptr
))
536 case 9: if(downloadflag
)ipaddr
=ptr
;break;
539 if(accept
&& traffic
>0 && ipaddr
)
545 else if(!downloadflag
)
549 printf("IP %s: %Lu MB (%ld pkts)\n", ipaddr
, traffic
, pkts
);
551 if_exists(ip
,ips
,eq(ip
->addr
,ipaddr
));
556 if(eq(ip
->addr
,"0.0.0.0/0"))
558 ip
->name
="(unregistered)";
560 ip
->max
=ip
->desired
=free_max
;
572 ip
->traffic
+=traffic
;
574 ip
->direct
=ip
->traffic
-ip
->upload
-ip
->proxy
;
583 ip
->traffic
+=traffic
;
587 if(traffic
>ip
->traffic
)
598 /* ========== This function executes, logs OR ALSO prints command ========== */
600 void safe_run(char *cmd
)
604 printf("\n=>%s\n",cmd
);
612 fprintf(log_file
,"%s\n",cmd
);
616 void save_line(char *line
)
618 fprintf(iptables_file
,"%s\n",line
);
621 void run_restore(void)
624 string(restor
,STRLEN
);
626 /*-----------------------------------------------------------------*/
627 printf("Running %s <%s ...\n", iptablesrestore
, iptablesfile
);
628 /*-----------------------------------------------------------------*/
631 fclose(iptables_file
);
638 done
; /* ugly macro end */
641 sprintf(restor
,"%s <%s",iptablesrestore
, iptablesfile
);
647 char *parse_datafile_line(char *str
)
649 char *ptr
=strchr(str
,' ');
663 void append_log(struct IP
*self
) /*using global variables*/
668 date(d
); /* this is typical cll1.h macro - prints current date */
670 sprintf(str
,"%s/%s.log", log_dir
, self
->name
);
674 fprintf(f
,"%ld\t%s\t%Lu\t%Lu\t%Lu\t%Lu\t%d\t%d\t%d\t%d\t%s",
675 time(NULL
), self
->name
, self
->traffic
, self
->direct
, self
->proxy
,
676 self
->upload
, self
->min
, self
->max
, self
->desired
, self
->lmsid
, d
); /* d = date*/
685 /*-----------------------------------------------------------------*/
686 /* Are you looking for int main(int argc, char **argv) ? :-)) */
687 /*-----------------------------------------------------------------*/
691 int i
=0; /* just plain old Fortran style integer :-) */
692 FILE *f
=NULL
; /* everything is just stream of bytes... */
693 char *str
, *ptr
, *d
; /* LET A$=B$ :-) */
697 int just_flush
=FALSE
; /* deactivates all previous actions */
699 int just_preview
=FALSE
; /* preview - generate just stats */
700 int start_shaping
=FALSE
; /* apply FUP - requires classmap file */
701 int just_logs
=FALSE
; /* just parse logs */
705 char *chain_forward
, *chain_postrouting
;
709 Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\
710 Version %s - Copyright (C)2005-2012 Michael Polak, Arachne Labs\n\
711 iptables-restore & burst tunning & classify modification by Ludva\n\
712 Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version
);
714 /*----- Boring... we have to check command line options first: ----*/
717 argument("-c") { nextargument(config
); }
718 argument("-h") { nextargument(althosts
);}
719 argument("-d") { run
=TRUE
; dry_run
=TRUE
; }
720 argument("-f") { run
=TRUE
; just_flush
=TRUE
; }
721 argument("-9") { run
=TRUE
; just_flush
=9; }
722 argument("-p") { run
=TRUE
; just_preview
=TRUE
; }
723 argument("-s") { run
=TRUE
; just_preview
=TRUE
; start_shaping
=TRUE
; }
724 argument("-r") { run
=TRUE
; }
725 argument("-n") { run
=TRUE
; nodelay
=TRUE
; }
726 argument("-l") { just_logs
=TRUE
; }
727 argument("-m") { just_logs
=TRUE
; }
728 argument("-y") { just_logs
=TRUE
; }
729 argument("-?") { help(); exit(0); }
730 argument("--help") { help(); exit(0); }
731 argument("-v") { exit(0); }
732 argument("--version") { exit(0); }
737 puts("*** THIS IS JUST DRY RUN ! ***\n");
740 date(d
); /* this is typical cll1.h macro - prints current date */
742 /*-----------------------------------------------------------------*/
743 printf("Parsing configuration file %s ...\n", config
);
744 /*-----------------------------------------------------------------*/
749 parse_ip_log(argc
,argv
);
765 /*-----------------------------------------------------------------*/
766 puts("Parsing iptables verbose output ...");
767 /*-----------------------------------------------------------------*/
768 get_traffic_statistics();
771 /*-----------------------------------------------------------------*/
772 printf("Parsing class defintion file %s ...\n", hosts
);
773 /*-----------------------------------------------------------------*/
776 /*-----------------------------------------------------------------*/
777 /* cll1.h - let's allocate brand new character buffer... */
778 /*-----------------------------------------------------------------*/
781 /*-----------------------------------------------------------------*/
782 puts("Resolving shared connections ...");
783 /*-----------------------------------------------------------------*/
784 for_each(ip
,ips
) if(ip
->sharing
)
786 for_each(sharedip
,ips
) if(eq(sharedip
->name
,ip
->sharing
))
788 sharedip
->traffic
+=ip
->traffic
;
790 ip
->mark
=sharedip
->mark
;
791 ip
->lmsid
=sharedip
->lmsid
;
796 printf("Unresolved shared connection: %s %s sharing-%s\n",
797 ip
->addr
, ip
->name
, ip
->sharing
);
801 if(enable_credit
&& just_flush
<9)
803 /*-----------------------------------------------------------------*/
804 printf("Parsing credit file %s ...\n", credit
);
805 /*-----------------------------------------------------------------*/
808 ptr
=parse_datafile_line(_
);
811 if_exists(ip
,ips
,eq(ip
->addr
,_
))
813 sscanf(ptr
,"%Lu",&(ip
->credit
));
817 done
; /* ugly macro end */
822 /*-----------------------------------------------------------------*/
823 puts("Initializing iptables and tc classes ...");
824 /*-----------------------------------------------------------------*/
826 iptables_file
=fopen(iptablesfile
,"w");
827 if(iptables_file
== NULL
)
829 puts("Cannot open iptablesfile!");
833 log_file
=fopen(cmdlog
,"w");
836 puts("Cannot open logfile!");
840 save_line(iptablespreamble
);
843 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,lan
);
846 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,wan
);
849 iptables_file
=fopen(iptablesfile
,"w");
850 save_line(iptablespreamble
);
852 if(qos_free_zone
&& *qos_free_zone
!='0')
856 sprintf(str
,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone
, wan
);
861 save_line(":post_noproxy - [0:0]");
862 sprintf(str
,"-A POSTROUTING ! -p tcp -o %s -j post_noproxy", lan
);
864 sprintf(str
,"-A POSTROUTING ! -s %s -o %s -j post_noproxy", proxy_ip
, lan
);
866 sprintf(str
,"-A POSTROUTING -s %s -p tcp ! --sport %d -o %s -j post_noproxy", proxy_ip
, proxy_port
, lan
);
869 chain
="post_noproxy";
876 sprintf(str
,"-A %s -s %s -o %s -j ACCEPT", chain
, qos_free_zone
, lan
);
880 if(ip_count
>idxtable_treshold1
&& !just_flush
)
882 int idxcount
=0, bitmask
=32-idxtable_bitmask1
; /* default net mask: 255.255.255.240 */
884 /*-----------------------------------------------------------------*/
885 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count
);
886 /*-----------------------------------------------------------------*/
888 save_line(":post_common - [0:0]");
889 save_line(":forw_common - [0:0]");
891 for_each(ip
,ips
) if(ip
->addr
&& *(ip
->addr
) && !eq(ip
->addr
,"0.0.0.0/0"))
893 buf
=hash_id(ip
->addr
,bitmask
);
894 if_exists(idx
,idxs
,eq(idx
->id
,buf
))
903 idx
->bitmask
=bitmask
;
911 /* brutal perfomance optimalization */
912 while(idxcount
>idxtable_treshold2
&& bitmask
>2*idxtable_bitmask2
)
914 bitmask
-=idxtable_bitmask2
;
917 for_each(idx
,idxs
) if(idx
->parent
== NULL
)
919 buf
=hash_id(idx
->addr
,bitmask
);
920 if_exists(metaindex
,idxs
,eq(metaindex
->id
,buf
))
922 metaindex
->children
++;
926 create(metaindex
,Index
);
927 metaindex
->addr
=idx
->addr
;
929 metaindex
->bitmask
=bitmask
;
930 metaindex
->parent
=NULL
;
931 metaindex
->children
=0;
933 push(metaindex
,idxs
);
935 idx
->parent
=metaindex
;
939 /* this should slightly optimize throughout ... */
940 sort(idx
,idxs
,desc_order_by
,children
);
941 sort(idx
,idxs
,order_by
,bitmask
);
946 subnet
=subnet_id(idx
->addr
,idx
->bitmask
);
947 printf("%d: %s/%d\n",
948 ++i
, subnet
, idx
->bitmask
);
950 sprintf(str
,":post_%s - [0:0]", idx
->id
);
953 sprintf(str
,":forw_%s - [0:0]", idx
->id
);
958 string(buf
,strlen(idx
->parent
->id
)+6);
959 sprintf(buf
,"post_%s",idx
->parent
->id
);
966 sprintf(str
,"-A %s -d %s/%d -o %s -j post_%s", buf
, subnet
, idx
->bitmask
, lan
, idx
->id
);
969 sprintf(str
,"-A %s -d %s/%d -o %s -j post_common", buf
, subnet
, idx
->bitmask
, lan
);
974 string(buf
,strlen(idx
->parent
->id
)+6);
975 sprintf(buf
,"forw_%s",idx
->parent
->id
);
982 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_%s", buf
, subnet
, idx
->bitmask
, wan
, idx
->id
);
985 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_common", buf
, subnet
, idx
->bitmask
, wan
);
988 printf("Total indexed iptables chains created: %d\n", i
);
990 sprintf(str
,"-A FORWARD -o %s -j forw_common", wan
);
993 sprintf(str
,"-A POSTROUTING -o %s -j post_common", lan
);
1001 fclose(iptables_file
);
1006 puts("Just flushed iptables and tc classes - now exiting ...");
1012 if(!dry_run
&& !nodelay
&& qos_free_delay
)
1014 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay
);
1015 sleep(qos_free_delay
);
1018 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",
1022 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
1023 tc
,lan
,lan_medium
,lan_medium
,burst_main
,highest_priority
);
1026 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
1027 tc
,lan
,line
,line
,burst_main
,highest_priority
);
1030 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc
,wan
,htb_r2q
);
1033 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
1034 tc
,wan
,wan_medium
,wan_medium
,burst_main
,highest_priority
);
1037 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
1038 tc
,wan
,up
,up
,burst_main
,highest_priority
);
1042 /*-----------------------------------------------------------------*/
1043 puts("Locating heavy downloaders and generating root classes ...");
1044 /*-----------------------------------------------------------------*/
1045 sort(ip
,ips
,desc_order_by
,traffic
);
1047 /*-----------------------------------------------------------------*/
1048 /* sub-scope - local variables */
1050 long long int rate
= line
;
1051 long long int max
= line
;
1052 int group_count
= 0;
1053 FILE *credit_file
= NULL
;
1055 if(!just_preview
&& !dry_run
&& enable_credit
)
1057 credit_file
= fopen(credit
,"w");
1060 for_each(group
,groups
)
1065 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",
1066 tc
, lan
, parent
, group
->id
, rate
, max
, burst_group
, highest_priority
+1, group
->desired
);
1070 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",
1071 tc
, wan
, parent
, group
->id
, rate
*up
/line
, max
*up
/line
, burst_group
, highest_priority
+1, group
->desired
);
1075 if(group_count
++ < max_nesting
)
1080 rate
-= digital_divide
*group
->min
;
1081 if(rate
< group
->min
)
1086 /*shaping of aggresive downloaders, with credit file support */
1089 int group_rate
= group
->min
, priority_sequence
= lowest_priority
;
1091 for_each(ip
, ips
) if(ip
->min
== group
->min
&& ip
->max
> ip
->min
)
1093 if( ip
->keyword
->data_limit
&& !ip
->fixedprio
1094 && ( ip
->traffic
>ip
->credit
1095 + (ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))) )
1097 if(group_rate
<ip
->max
)
1101 group_rate
+=magic_treshold
;
1102 ip
->prio
=lowest_priority
;
1103 if(ip
->prio
<highest_priority
+2)
1105 ip
->prio
=highest_priority
+2;
1110 if( ip
->keyword
->data_prio
1112 && ( ip
->traffic
>ip
->credit
1113 + (ip
->min
*ip
->keyword
->data_prio
+(ip
->keyword
->fixed_prio
<<20))) )
1115 ip
->prio
=priority_sequence
--;
1116 if(ip
->prio
<highest_priority
+1)
1118 ip
->prio
=highest_priority
+1;
1124 unsigned long long lcredit
=0;
1126 if((ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))>ip
->traffic
)
1128 lcredit
=(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))-ip
->traffic
;
1130 fprintf(credit_file
,"%s %Lu\n",ip
->addr
,lcredit
);
1138 fclose(credit_file
);
1146 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap
);
1154 if_exists(ip
,ips
,eq(ip
->addr
,_
))
1157 if(ip
->max
< ip
->desired
) /* apply FUP limit immediately.... */
1159 printf("Applying limit for %-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
1160 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
1161 sprintf(str
, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1162 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1164 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1165 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1166 sprintf(str
,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1167 tc
, wan
, ip
->group
, ip
->mark
,
1168 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1169 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1178 puts("Warning - classmap file not fund, just generating preview ...");
1179 start_shaping
=FALSE
;
1181 done
; /* ugly macro end */
1187 if(!dry_run
&& !just_flush
)
1189 /*-----------------------------------------------------------------*/
1190 printf("Writing json overview %s ... ", json
);
1191 /*-----------------------------------------------------------------*/
1200 && (ip
->traffic
|| ip
->direct
|| ip
->proxy
|| ip
->upload
))
1206 fprintf(f
, " \"%s\":{ \"lms\": %d, \"ip\":\"%s\", \"total\":%Lu, \"down\":%Lu, \"proxy\":%Lu, \"up\":%Lu, \"min\":%d, \"max\":%d, \"limit\":%d }",
1207 ip
->name
, ip
->lmsid
, ip
->addr
, ip
->traffic
, ip
->direct
, ip
->proxy
, ip
->upload
, ip
->min
, ip
->desired
, ip
->max
);
1227 /*-----------------------------------------------------------------*/
1228 printf("Sorting data and generating statistics page %s ...\n", html
);
1229 /*-----------------------------------------------------------------*/
1231 if(use_jquery_popups
)
1233 fprintf(f
,"<script type=\"text/javascript\" src=\"%s\"></script>\n", jquery_url
);
1235 fputs("<table class=\"decorated last\">\n\
1236 <caption>Bandwidth classes</caption>\n\
1238 <th style=\"text-align: right\">#</th>\n\
1239 <th style=\"text-align: right\">group</th>\n\
1240 <th style=\"text-align: right\">IPs</th>\n\
1241 <th style=\"text-align: right\">requested</th>\n",f
);
1242 fprintf(f
,"<th colspan=\"%d\">data limits</th>\n", keywordcount
);
1243 fputs("</tr></thead><tbody>\n",f
);
1246 for_each(group
, groups
)
1249 printf("%d kb/s group: %d bandwidth requested: %d kb/s\n",group
->min
,group
->count
,group
->desired
);
1251 fprintf(f
, "%s<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d kb/s</td>",
1252 tr_odd_even(), count
, group
->min
);
1253 fprintf(f
, "<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d kb/s</td>",
1254 group
->count
, group
->desired
);
1256 for_each(keyword
, keywords
) if(keyword
->ip_count
)
1258 fprintf(f
,"<td style=\"text-align: right\"><span style=\"color:#%s\">%d MB</span></td>",
1259 keyword
->html_color
, group
->min
*keyword
->data_limit
);
1261 i
+= group
->desired
;
1262 total
+= group
->count
;
1266 printf("Total groups: %d Total bandwidth requested: %d kb/s\nAGGREGATION: 1/%d\n",
1269 fprintf(f
,"</tr></tbody>\n\
1271 <th colspan=\"2\" style=\"text-align: left\">Line %Ld kb/s</td>",line
);
1272 fprintf(f
,"<th style=\"text-align: right\">%d</td><th style=\"text-align: right\">%d kb/s</td>",total
,i
);
1274 for_each(keyword
, keywords
) if(keyword
->ip_count
)
1276 fprintf(f
,"<th style=\"text-align: right\">%d IPs</th>",keyword
->ip_count
);
1278 fprintf(f
,"</tr><tr><th colspan=\"4\">Aggregation 1/%d</th>\n", (int)(0.5+i
/line
));
1279 fprintf(f
,"<th colspan=\"%d\">%d traffic classes</th></tr>\n", keywordcount
, total
);
1281 fputs("</thead></table>\n",f
);
1283 else if(!dry_run
&& !just_flush
)
1291 unsigned long long total_traffic
=0, total_direct
=0, total_proxy
=0, total_upload
=0, tmp_sum
=0;
1292 int active_classes
=0;
1294 struct Sum
{unsigned long long l
; int i
; list(Sum
);} *sum
,*sums
=NULL
;
1295 int limit_count
=0, prio_count
=0;
1303 fprintf(f
,"<p><table class=\"decorated last\">\n<caption>%s",title
);
1304 fprintf(f
," (%s)</caption>\n", d
);
1305 fputs("<thead><tr>\n<th colspan=\"3\"> </th>\n",f
);
1306 fputs("<th style=\"text-align: right\">credit</th>\n\
1307 <th style=\"text-align: right\">FUP</th>\n\
1308 <th style=\"text-align: right\">total</th>\n\
1309 <th style=\"text-align: right\">down</th>\n",f
);
1312 fputs("<th style=\"text-align: right\">proxy</th>\n",f
);
1314 fputs("<th style=\"text-align: right\">up</th>\n\
1315 <th style=\"text-align: right\">min</th>\n\
1316 <th style=\"text-align: right\">max</th>\n\
1317 <th style=\"text-align: right\">limit</th>\n\
1320 <th style=\"text-align: right\">#</th>\n\
1321 <th>hostname [+sharing]</th>\n\
1322 <th style=\"text-align: right\">LMS</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\">MB</th>\n\
1327 <th style=\"text-align: right\">MB</th>\n\
1328 <th style=\"text-align: right\">kb/s</th>\n\
1329 <th style=\"text-align: right\">kb/s</th>\n\
1330 <th style=\"text-align: right\">kb/s</th>\n\
1332 </tr></thead><tbody>\n",f
);
1335 for_each(ip
,ips
) if(!use_jquery_popups
|| !ip
->sharing
)
1337 char *f1
="", *f2
="";
1340 if(ip
->max
< ip
->desired
)
1342 f1
="<span style=\"color:red\">";
1346 else if(ip
->prio
> highest_priority
+1)
1348 f1
="<span style=\"color:brown\">";
1354 printf("%03d. %-22s %10Lu (%d/%d)\n",i
,ip
->name
, ip
->traffic
, ip
->min
, ip
->max
);
1356 /* hostnames -------------------------------------- */
1357 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",
1358 tr_odd_even(), ip
->name
, i
, log_url
, ip
->name
, ip
->name
);
1360 if(use_jquery_popups
)
1362 fprintf(f
,"<span id=\"sharing_%d\" style=\"display:none\">",i
);
1364 for_each(sharedip
, ips
) if(eq(ip
->name
, sharedip
->sharing
))
1366 fprintf(f
,"<br /><a class=\"blue\" target=\"_blank\" href=\"%s%s.log\">%s</a>\n", log_url
, sharedip
->name
, sharedip
->name
);
1369 fputs("</span>\n",f
);
1372 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>",
1373 i
, i
, i
, popup_button
);
1377 /* ----------------------------------------------- */
1381 fputs("<td style=\"text-align: right\">",f
);
1384 fprintf(f
,"<a class=\"blue\" target=\"_blank\" href=\"%s%d\">%04d</a>\n", lms_url
, ip
->lmsid
, ip
->lmsid
);
1386 else if(ip
->lmsid
== 0)
1392 fprintf(f
,"<td style=\"text-align: right\">%Lu</td>\n", ip
->credit
);
1393 fprintf(f
,"<td style=\"text-align: right\"><span style=\"color:#%s\">%Lu</span></td>",
1394 ip
->keyword
->html_color
,
1395 ip
->credit
+(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20)));
1396 fprintf(f
,"<td style=\"text-align: right\">%s%Lu%s", f1
, ip
->traffic
, f2
);
1398 /* download --------------------------------------- */
1399 fprintf(f
,"</td><td style=\"text-align: right\">%Lu", ip
->direct
);
1400 if(use_jquery_popups
)
1402 fprintf(f
,"<span id=\"download_%d\" style=\"display:none\">",i
);
1403 for_each(sharedip
, ips
) if(eq(ip
->name
, sharedip
->sharing
))
1405 fprintf(f
,"<br />%Lu", sharedip
->direct
);
1407 fputs("</span>\n",f
);
1410 /* ----------------------------------------------- */
1414 fprintf(f
,"<td style=\"text-align: right\">%Lu</td>\n", ip
->proxy
);
1416 /* upload ---------------------------------------- */
1417 fprintf(f
,"<td style=\"text-align: right\">%Lu", ip
->upload
);
1418 if(use_jquery_popups
)
1420 fprintf(f
,"<span id=\"upload_%d\" style=\"display:none\">",i
);
1421 for_each(sharedip
,ips
) if(eq(ip
->name
, sharedip
->sharing
))
1423 fprintf(f
,"<br />%Lu", sharedip
->upload
);
1425 fputs("</span>\n",f
);
1428 /* ----------------------------------------------- */
1430 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1431 <td style=\"text-align: right\">%d</td>\n\
1432 <td style=\"text-align: right\">%s%d%s</td>\n\
1433 <td>%s%d%s</td></tr>\n",
1434 ip
->min
, ip
->desired
,
1438 total_traffic
+=ip
->traffic
;
1439 total_direct
+=ip
->direct
;
1440 total_proxy
+=ip
->proxy
;
1441 total_upload
+=ip
->upload
;
1445 tmp_sum
+=ip
->traffic
;
1448 sum
->i
=active_classes
;
1449 insert(sum
,sums
,order_by
,i
);
1455 for_each(sharedip
,ips
) if(eq(ip
->name
, sharedip
->sharing
))
1457 append_log(sharedip
);
1461 fprintf(f
,"</tbody><thead><tr>\n\
1462 <th colspan=\"%d\" style=\"text-align: left\">%d CLASSES</th>", colspan
-7, i
);
1463 fprintf(f
,"<th style=\"text-align: right\">%Lu</th><th style=\"text-align: right\">%Lu</th>\n", total_traffic
, total_direct
);
1466 fprintf(f
,"<th style=\"text-align: right\">%Lu</th>\n", total_proxy
);
1468 fprintf(f
,"<th style=\"text-align: right\">%Lu</th>", total_upload
);
1469 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
);
1472 if(active_classes
>10)
1474 int top20_count
=0,top20_perc1
=0;
1475 long long top20_perc2
=0;
1476 unsigned long long top20_sum
=0l;
1478 fputs("<a name=\"erp\"></a><p><table class=\"decorated last\"><caption>Enterprise Resource Planning (ERP)</caption>\n",f
);
1479 fputs("<thead><tr>\n\
1480 <th>Analytic category</th>\n\
1481 <th colspan=\"2\" style=\"text-align: center\">Active Classes</th>\n\
1482 <th colspan=\"2\" style=\"text-align: center\">Data transfers</th>\n\
1483 </tr></thead><tbody>\n",f
);
1485 if_exists(sum
,sums
,sum
->l
>=total_traffic
/4)
1487 fprintf(f
,"%s<td>Top 25%% of traffic</td>\n", tr_odd_even());
1488 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1489 <td style=\"text-align: right\">%d %%</td>\n\
1490 <td style=\"text-align: right\">%Lu MB</td>\n\
1491 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1492 sum
->i
, (100*sum
->i
+50)/active_classes
, sum
->l
, (100*sum
->l
+50)/total_traffic
);
1495 if_exists(sum
,sums
,sum
->i
==10)
1497 fprintf(f
,"%s<td>Top 10 downloaders</td>\n", tr_odd_even());
1498 fprintf(f
,"<td style=\"text-align: right\"><strong>10</strong></td>\n\
1499 <td style=\"text-align: right\">%d %%</td>\n\
1500 <td style=\"text-align: right\">%Lu MB</td>\n\
1501 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1502 (100*sum
->i
+50)/active_classes
, sum
->l
, (100*sum
->l
+50)/total_traffic
);
1505 if_exists(sum
,sums
,sum
->l
>=total_traffic
/2)
1507 fprintf(f
,"%s<td>Top 50%% of traffic</td>\n", tr_odd_even());
1508 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1509 <td style=\"text-align: right\">%d %%</td>\n\
1510 <td style=\"text-align: right\">%Lu MB</td>\n\
1511 <td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",
1512 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1515 if_exists(sum
,sums
,sum
->l
>=4*total_traffic
/5)
1517 fprintf(f
,"%s<td>Top 80%% of traffic</td>\n", tr_odd_even());
1518 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1519 <td style=\"text-align: right\">%d %%</td>\n\
1520 <td style=\"text-align: right\">%Lu MB</td>\n\
1521 <td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",
1522 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1525 if_exists(sum
,sums
,sum
->i
>=(active_classes
+1)/5)
1527 fprintf(f
,"%s<td>Top 20%% downloaders</td>\n", tr_odd_even());
1529 top20_perc1
=(100*sum
->i
+50)/active_classes
;
1531 top20_perc2
=(100*sum
->l
+50)/total_traffic
;
1532 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1533 <td style=\"text-align: right\"><strong>%d %%</strong></td>\n\
1534 <td style=\"text-align: right\">%Lu MB</td>\n\
1535 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1536 top20_count
,top20_perc1
,top20_sum
,top20_perc2
);
1539 if_exists(sum
,sums
,sum
->i
>=(active_classes
+1)/4)
1541 fprintf(f
,"%s<td>Top 25%% downloaders</td>\n", tr_odd_even());
1542 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1543 <td style=\"text-align: right\">%d %%</td>\n\
1544 <td style=\"text-align: right\">%Lu MB</td>\n\
1545 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1546 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1549 if_exists(sum
,sums
,sum
->i
>=(active_classes
+1)/2)
1551 fprintf(f
,"%s<td>Top 50%% downloaders</td>\n", tr_odd_even());
1552 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1553 <td style=\"text-align: right\"><strong>%d %%</strong></td>\n\
1554 <td style=\"text-align: right\">%Lu MB</td>\n\
1555 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1556 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1559 if_exists(sum
,sums
,sum
->i
>=4*(active_classes
+1)/5)
1561 fprintf(f
,"%s<td>Top 80%% downloaders</td>\n", tr_odd_even());
1562 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1563 <td style=\"text-align: right\">%d %%</td>\n\
1564 <td style=\"text-align: right\">%Lu MB</td>\n\
1565 <td style=\"text-align: right\">%Ld %%</td></tr></tbody>\n",
1566 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1569 fprintf(f
,"<thead><tr><th><a class=\"blue\" target=\"_blank\" href=\"%sERP.log\">All users, all traffic</a></th>\n", log_url
);
1570 fprintf(f
,"<th style=\"text-align: right\">%d</th>\n\
1571 <th style=\"text-align: right\">100 %%</th>\n\
1572 <th style=\"text-align: right\">%Lu MB</th>\n\
1573 <th style=\"text-align: right\">100 %%</th></tr>\n",active_classes
,total_traffic
);
1574 fputs("</thead></table>\n", f
);
1576 /* write basic ERP data to log directory */
1580 sprintf(str
,"%s/ERP.log",log_dir
);
1581 iplog
=fopen(str
,"a");
1584 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",
1585 time(NULL
), top20_count
, top20_perc1
, top20_sum
, top20_perc2
,
1586 active_classes
, total_traffic
, i
, limit_count
, prio_count
, d
); /* d = date*/
1596 fprintf(f
, stats_html_signature
, version
);
1607 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar
);
1613 printf("%-22s %-15s mark\n","name","ip");
1616 printf("Writing %s ... ", classmap
);
1617 f
= fopen(classmap
, "w");
1623 /*-----------------------------------------------------------------*/
1624 puts("Generating iptables and tc classes ... ");
1625 /*-----------------------------------------------------------------*/
1627 for_each(ip
, ips
) if(ip
->mark
> 0)
1632 duplicate(ip
->addr
,buf
);
1633 buf
=hash_id(ip
->addr
,32-idxtable_bitmask1
);
1635 string(chain_forward
,6+strlen(buf
));
1636 strcpy(chain_forward
,"forw_");
1637 strcat(chain_forward
,buf
);
1639 string(chain_postrouting
,6+strlen(buf
));
1640 strcpy(chain_postrouting
,"post_");
1641 strcat(chain_postrouting
,buf
);
1647 chain_forward
="FORWARD";
1648 chain_postrouting
="POSTROUTING";
1652 printf("%-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
1655 /* -------------------------------------------------------- mark download */
1657 sprintf(str
, "-A %s -d %s/32 -o %s -j %s%d",
1658 chain_postrouting
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
1659 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/
1660 /* -m limit --limit 1/s */
1665 sprintf(str
, "-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",
1666 chain_postrouting
, proxy_ip
, proxy_port
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
1667 /*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);*/
1671 sprintf(str
, "-A %s -d %s/32 -o %s -j ACCEPT",
1672 chain_postrouting
, ip
->addr
, lan
);
1675 /* -------------------------------------------------------- mark upload */
1676 sprintf(str
, "-A %s -s %s/32 -o %s -j %s%d",
1677 chain_forward
, ip
->addr
, wan
, mark_iptables
, ip
->mark
);
1678 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/
1681 sprintf(str
, "-A %s -s %s/32 -o %s -j ACCEPT",
1682 chain_forward
, ip
->addr
, wan
);
1687 /* -------------------------------------------------------- download class */
1689 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
1692 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1693 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1696 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1698 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1699 tc
, lan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1703 if(filter_type
== 1)
1705 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1706 tc
, lan
, ip
->mark
, ip
->mark
);
1710 /* -------------------------------------------------------- upload class */
1712 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1713 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1716 sprintf(str
,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1717 tc
, wan
, ip
->group
, ip
->mark
,
1718 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1719 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1722 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1724 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1725 tc
, wan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1729 if(filter_type
== 1)
1731 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1732 tc
, wan
, ip
->mark
, ip
->mark
);
1738 fprintf(f
, "%s %d\n", ip
->addr
, ip
->mark
);
1744 printf("(sharing %s)\n", ip
->sharing
);
1757 chain_forward
= "forw_common";
1758 chain_postrouting
= "post_common";
1762 chain_forward
= "FORWARD";
1763 chain_postrouting
= "POSTROUTING";
1765 /* -------------------------------- classify or reject free download */
1767 char *final_chain
= "DROP"; /* REJECT would be better, but it is impossible in mangle */
1770 final_chain
= "ACCEPT";
1776 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s%d",
1777 chain_postrouting
,proxy_ip
,proxy_port
,lan
,mark_iptables
,3);
1780 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s",
1781 chain_postrouting
,proxy_ip
,proxy_port
,lan
,final_chain
);
1786 sprintf(str
,"-A %s -o %s -j %s%d", chain_postrouting
, lan
, mark_iptables
, 3);
1789 sprintf(str
,"-A %s -o %s -j %s", chain_postrouting
, lan
, final_chain
);
1791 /* ------------------------------- classify or reject free upload */
1794 sprintf(str
,"-A %s -o %s -j %s%d", chain_forward
, wan
, mark_iptables
, 3);
1797 sprintf(str
,"-A %s -o %s -j %s", chain_forward
, wan
, final_chain
);
1801 if(free_min
) /* allocate free bandwith if it is not zero... */
1803 /*-----------------------------------------------------------------*/
1804 puts("Generating free bandwith classes ...");
1805 /*-----------------------------------------------------------------*/
1806 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1807 tc
, lan
, parent
, free_min
, free_max
,burst
, lowest_priority
);
1809 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1810 tc
, wan
, parent
, free_min
, free_max
, burst
, lowest_priority
);
1813 if(strcmpi(qos_leaf
, "none"))
1815 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, lan
, qos_leaf
);
1818 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, wan
, qos_leaf
);
1821 /* tc handle 1 fw flowid */
1822 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, lan
);
1825 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, wan
);
1828 printf("Total IP count: %d\n", i
);
1835 /* that's all folks, thank you for reading it all the way up to this point ;-) */
1836 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */
This page took 1.353618 seconds and 3 git commands to generate.