07980f637bfbd4a3762065dc7e3b812b974678f6
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
;
184 /* Damned, this must be object oriented! This looks almost like constructor ;-) */
192 ip
->prio
= highest_priority
+1;
206 ip
->keyword
= keywords
;
210 /* ====== iptables indexes are used to reduce complexity to log8(N) ===== */
212 char *very_ugly_ipv4_code(char *inip
,int bitmask
,int format_as_chainname
)
214 /* warning: this function was debugged only for bitmask values 20,24,28 !!!*/
216 char *ip
,*outip
,*outptr
,*fmt
;
219 /* debug printf("(%s,%d) -> ",ip,bitmask); */
221 if(ip
&& *ip
&& bitmask
>=0 && bitmask
<=32)
223 string(outip
,strlen(ip
)+10); /*fuck unicode? assertion: 10>strlen("_%d_%d") */
227 /* should never exit here */
235 if(dot
<(bitmask
/8-1))
237 if(format_as_chainname
)
250 char *cutdot
=strchr(ip
+1,'.'); /*for bitmask<24*/
256 if(format_as_chainname
)
267 n
= atoi(ip
+1)-atoi(ip
+1)%(1<<(8-bitmask
%8));
274 /*debug printf("%d/%d => [_%d_%d]\n",atoi(ip+1),bitmask,n,bitmask); */
275 sprintf(outptr
,fmt
,n
,bitmask
);
276 if(!format_as_chainname
)
284 /* debug printf("[%s]\n",outip); */
295 /*should never exit here*/
300 char *hash_id(char *ip
,int bitmask
)
302 return very_ugly_ipv4_code(ip
,bitmask
,1);
305 char *subnet_id(char *ip
,int bitmask
)
307 return very_ugly_ipv4_code(ip
,bitmask
,0);
310 /* ================= Let's parse configuration file here =================== */
312 void reject_config_and_exit(char *filename
)
314 printf("Configuration file %s rejected - abnormal exit.",filename
);
318 void get_config(char *config_filename
)
322 printf("Configured keywords: ");
323 parse(config_filename
)
325 option("keyword",kwd
);
330 create(keyword
,Keyword
);
332 keyword
->asymetry_ratio
=1; /* ratio for ADSL-like upload */
333 keyword
->asymetry_fixed
=0; /* fixed treshold for ADSL-like upload */
334 keyword
->data_limit
=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */
335 keyword
->data_prio
=4; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */
336 keyword
->fixed_limit
=0; /* fixed data limit for setting lower HTB ceil */
337 keyword
->fixed_prio
=0; /* fixed data limit for setting lower HTB prio */
338 keyword
->reserve_min
=8; /* bonus for nominal HTB rate bandwidth (in kbps) */
339 keyword
->reserve_max
=0; /* malus for nominal HTB ceil (in kbps) */
340 keyword
->default_prio
=highest_priority
+1;
341 keyword
->html_color
="000000";
343 keyword
->leaf_discipline
="";
345 push(keyword
,keywords
);
346 if(!defaultkeyword
) defaultkeyword
=keyword
;
353 for_each(keyword
,keywords
)
355 int l
=strlen(keyword
->key
);
357 if(!strncmp(keyword
->key
,_
,l
) && strlen(_
)>l
+2)
359 char *tmptr
=_
; /* <---- l+1 ----> */
360 _
+=l
+1; /* via-prometheus-asymetry-ratio, etc. */
361 ioption("asymetry-ratio",keyword
->asymetry_ratio
);
362 ioption("asymetry-treshold",keyword
->asymetry_fixed
);
363 ioption("magic-relative-limit",keyword
->data_limit
);
364 ioption("magic-relative-prio",keyword
->data_prio
);
365 loption("magic-fixed-limit",keyword
->fixed_limit
);
366 loption("magic-fixed-prio",keyword
->fixed_prio
);
367 ioption("htb-default-prio",keyword
->default_prio
);
368 ioption("htb-rate-bonus",keyword
->reserve_min
);
369 ioption("htb-ceil-malus",keyword
->reserve_max
);
370 option("leaf-discipline",keyword
->leaf_discipline
);
371 option("html-color",keyword
->html_color
);
374 if(keyword
->data_limit
|| keyword
->fixed_limit
||
375 keyword
->data_prio
|| keyword
->fixed_prio
)
384 option("iptables",iptables
);
385 option("iptables-save",iptablessave
); /* new */
386 option("iptables-restore",iptablesrestore
); /* new */
387 option("iptables-in-filename",iptablesfile
); /* new */
388 option("hosts",hosts
);
389 option("lan-interface",lan
);
390 option("wan-interface",wan
);
391 option("lan-medium",lan_medium
);
392 option("wan-medium",wan_medium
);
393 lloption("wan-download",line
);
394 lloption("wan-upload",up
);
395 ioption("hall-of-fame-enable",hall_of_fame
);
396 option("hall-of-fame-title",title
);
397 option("hall-of-fame-filename",html
);
398 option("json-filename",json
);
399 option("hall-of-fame-preview",preview
);
400 option("json-preview",json_preview
);
401 option("log-filename",cmdlog
);
402 option("credit-filename",credit
);
403 option("classmap-filename",classmap
);
404 ioption("credit-enable",enable_credit
);
405 option("log-traffic-directory",log_dir
);
406 option("log-traffic-html-directory",html_log_dir
);
407 option("log-traffic-url-path",log_url
);
408 option("jquery-url",jquery_url
);
409 option("lms-url",lms_url
);
410 ioption("use-jquery-popups",use_jquery_popups
);
411 option("qos-free-zone",qos_free_zone
);
412 ioption("qos-free-delay",qos_free_delay
);
413 ioption("qos-proxy-enable",qos_proxy
);
414 option("qos-proxy-ip",proxy_ip
);
415 option("htb-leaf-discipline",qos_leaf
);
416 ioption("qos-proxy-port",proxy_port
);
417 ioption("free-rate",free_min
);
418 ioption("free-ceil",free_max
);
419 ioption("htb-burst",burst
);
420 ioption("htb-burst-main",burst_main
);
421 ioption("htb-burst-group",burst_group
);
422 ioption("htb-nesting-limit",max_nesting
);
423 ioption("htb-r2q",htb_r2q
);
424 ioption("magic-include-upload",include_upload
);
425 ioption("magic-treshold",magic_treshold
);
426 option("filter-type", cnf
);
427 /* not yet implemented:
428 ioption("magic-fixed-packets",fixed_packets);
429 ioption("magic-relative-packets",packet_limit);
434 perror(config_filename
);
435 puts("Warning - using built-in defaults instead ...");
437 done
; /* ugly macro end */
440 /* leaf discipline for keywords */
441 for_each(keyword
,keywords
)
443 if(!strcmpi(keyword
->leaf_discipline
, ""))
445 keyword
->leaf_discipline
= qos_leaf
;
449 if(strcmpi(cnf
, "mark"))
453 mark_iptables
= "CLASSIFY --set-class 1:";
459 mark_iptables
= "MARK --set-mark ";
462 /* are supplied values meaningful ?*/
465 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");
466 reject_config_and_exit(config_filename
);
470 /* ===================== traffic analyser - uses iptables ================ */
472 void get_traffic_statistics(void)
477 textfile(Pipe
,str
) *line
,*lines
=NULL
;
481 sprintf(cmd
,"%s -L -v -x -n -t mangle",iptables
);
493 int col
, accept
=0,proxyflag
=0,valid
=1,setchainname
=0,commonflag
=0;
494 unsigned long long traffic
=0;
495 unsigned long pkts
=0;
496 char *ipaddr
=NULL
,*ptr
;
498 /* debug puts(line->str); */
499 valid_columns(ptr
,line
->str
,' ',col
)
500 if(valid
) switch(col
)
502 case 1: if(eq(ptr
,"Chain"))
506 else if(eq(ptr
,"pkts"))
512 sscanf(ptr
,"%lu",&pkts
);
515 case 2: if(setchainname
)
517 if(!strncmp(ptr
,"post_",5) || eq(ptr
,"POSTROUTING"))
523 if(!strncmp(ptr
,"forw_",5) || eq(ptr
,"FORWARD"))
528 if(eq(ptr
,"post_common") || eq(ptr
,"forw_common"))
535 sscanf(ptr
,"%Lu",&traffic
);
540 case 3: if((strncmp(ptr
,"post_",5) && strncmp(ptr
,"forw_",5)) || commonflag
)
544 /*if(filter_type==1) accept=eq(ptr,"MARK"); else accept=eq(ptr,"CLASSIFY");*/
546 case 8: if(downloadflag
)
548 if(strstr(proxy_ip
,ptr
))
558 case 9: if(downloadflag
)ipaddr
=ptr
;break;
561 if(accept
&& traffic
>0 && ipaddr
)
567 else if(!downloadflag
)
571 printf("IP %s: %Lu MB (%ld pkts)\n", ipaddr
, traffic
, pkts
);
573 if_exists(ip
,ips
,eq(ip
->addr
,ipaddr
));
578 if(eq(ip
->addr
,"0.0.0.0/0"))
580 ip
->name
="(unregistered)";
582 ip
->max
=ip
->desired
=free_max
;
594 ip
->traffic
+=traffic
;
596 ip
->direct
=ip
->traffic
-ip
->upload
-ip
->proxy
;
605 ip
->traffic
+=traffic
;
609 if(traffic
>ip
->traffic
)
620 /* ========== This function executes, logs OR ALSO prints command ========== */
622 void safe_run(char *cmd
)
626 printf("\n=>%s\n",cmd
);
634 fprintf(log_file
,"%s\n",cmd
);
638 void save_line(char *line
)
640 fprintf(iptables_file
,"%s\n",line
);
643 void run_restore(void)
646 string(restor
,STRLEN
);
648 /*-----------------------------------------------------------------*/
649 printf("Running %s <%s ...\n", iptablesrestore
, iptablesfile
);
650 /*-----------------------------------------------------------------*/
653 fclose(iptables_file
);
660 done
; /* ugly macro end */
663 sprintf(restor
,"%s <%s",iptablesrestore
, iptablesfile
);
669 char *parse_datafile_line(char *str
)
671 char *ptr
=strchr(str
,' ');
685 void append_log(struct IP
*self
) /*using global variables*/
690 date(d
); /* this is typical cll1.h macro - prints current date */
692 sprintf(str
,"%s/%s.log", log_dir
, self
->name
);
696 fprintf(f
,"%ld\t%s\t%Lu\t%Lu\t%Lu\t%Lu\t%d\t%d\t%d\t%d\t%s",
697 time(NULL
), self
->name
, self
->traffic
, self
->direct
, self
->proxy
,
698 self
->upload
, self
->min
, self
->max
, self
->desired
, self
->lmsid
, d
); /* d = date*/
707 /*-----------------------------------------------------------------*/
708 /* Are you looking for int main(int argc, char **argv) ? :-)) */
709 /*-----------------------------------------------------------------*/
713 int i
=0; /* just plain old Fortran style integer :-) */
714 FILE *f
=NULL
; /* everything is just stream of bytes... */
715 char *str
, *ptr
, *d
; /* LET A$=B$ :-) */
719 int just_flush
=FALSE
; /* deactivates all previous actions */
721 int just_preview
=FALSE
; /* preview - generate just stats */
722 int start_shaping
=FALSE
; /* apply FUP - requires classmap file */
723 int just_logs
=FALSE
; /* just parse logs */
727 char *chain_forward
, *chain_postrouting
;
731 Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\
732 Version %s - Copyright (C)2005-2012 Michael Polak, Arachne Labs\n\
733 iptables-restore & burst tunning & classify modification by Ludva\n\
734 Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version
);
736 /*----- Boring... we have to check command line options first: ----*/
739 argument("-c") { nextargument(config
); }
740 argument("-h") { nextargument(althosts
);}
741 argument("-d") { run
=TRUE
; dry_run
=TRUE
; }
742 argument("-f") { run
=TRUE
; just_flush
=TRUE
; }
743 argument("-9") { run
=TRUE
; just_flush
=9; }
744 argument("-p") { run
=TRUE
; just_preview
=TRUE
; }
745 argument("-s") { run
=TRUE
; just_preview
=TRUE
; start_shaping
=TRUE
; }
746 argument("-r") { run
=TRUE
; }
747 argument("-n") { run
=TRUE
; nodelay
=TRUE
; }
748 argument("-l") { just_logs
=TRUE
; }
749 argument("-m") { just_logs
=TRUE
; }
750 argument("-y") { just_logs
=TRUE
; }
751 argument("-?") { help(); exit(0); }
752 argument("--help") { help(); exit(0); }
753 argument("-v") { exit(0); }
754 argument("--version") { exit(0); }
759 puts("*** THIS IS JUST DRY RUN ! ***\n");
762 date(d
); /* this is typical cll1.h macro - prints current date */
764 /*-----------------------------------------------------------------*/
765 printf("Parsing configuration file %s ...\n", config
);
766 /*-----------------------------------------------------------------*/
771 parse_ip_log(argc
,argv
);
787 /*-----------------------------------------------------------------*/
788 puts("Parsing iptables verbose output ...");
789 /*-----------------------------------------------------------------*/
790 get_traffic_statistics();
793 /*-----------------------------------------------------------------*/
794 printf("Parsing class defintion file %s ...\n", hosts
);
795 /*-----------------------------------------------------------------*/
798 /*-----------------------------------------------------------------*/
799 /* cll1.h - let's allocate brand new character buffer... */
800 /*-----------------------------------------------------------------*/
803 /*-----------------------------------------------------------------*/
804 puts("Resolving shared connections ...");
805 /*-----------------------------------------------------------------*/
806 for_each(ip
,ips
) if(ip
->sharing
)
808 for_each(sharedip
,ips
) if(eq(sharedip
->name
,ip
->sharing
))
810 sharedip
->traffic
+=ip
->traffic
;
812 ip
->mark
=sharedip
->mark
;
813 ip
->lmsid
=sharedip
->lmsid
;
818 printf("Unresolved shared connection: %s %s sharing-%s\n",
819 ip
->addr
, ip
->name
, ip
->sharing
);
823 if(enable_credit
&& just_flush
<9)
825 /*-----------------------------------------------------------------*/
826 printf("Parsing credit file %s ...\n", credit
);
827 /*-----------------------------------------------------------------*/
830 ptr
=parse_datafile_line(_
);
833 if_exists(ip
,ips
,eq(ip
->addr
,_
))
835 sscanf(ptr
,"%Lu",&(ip
->credit
));
839 done
; /* ugly macro end */
844 /*-----------------------------------------------------------------*/
845 puts("Initializing iptables and tc classes ...");
846 /*-----------------------------------------------------------------*/
848 iptables_file
=fopen(iptablesfile
,"w");
849 if(iptables_file
== NULL
)
851 puts("Cannot open iptablesfile!");
855 log_file
=fopen(cmdlog
,"w");
858 puts("Cannot open logfile!");
862 save_line(iptablespreamble
);
865 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,lan
);
868 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,wan
);
871 iptables_file
=fopen(iptablesfile
,"w");
872 save_line(iptablespreamble
);
874 if(qos_free_zone
&& *qos_free_zone
!='0')
878 sprintf(str
,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone
, wan
);
883 save_line(":post_noproxy - [0:0]");
884 sprintf(str
,"-A POSTROUTING -p ! tcp -o %s -j post_noproxy", lan
);
886 sprintf(str
,"-A POSTROUTING -s ! %s -o %s -j post_noproxy", proxy_ip
, lan
);
888 sprintf(str
,"-A POSTROUTING -s %s -p tcp --sport ! %d -o %s -j post_noproxy", proxy_ip
, proxy_port
, lan
);
891 chain
="post_noproxy";
898 sprintf(str
,"-A %s -s %s -o %s -j ACCEPT", chain
, qos_free_zone
, lan
);
902 if(ip_count
>idxtable_treshold1
&& !just_flush
)
904 int idxcount
=0, bitmask
=32-idxtable_bitmask1
; /* default net mask: 255.255.255.240 */
906 /*-----------------------------------------------------------------*/
907 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count
);
908 /*-----------------------------------------------------------------*/
910 save_line(":post_common - [0:0]");
911 save_line(":forw_common - [0:0]");
913 for_each(ip
,ips
) if(ip
->addr
&& *(ip
->addr
) && !eq(ip
->addr
,"0.0.0.0/0"))
915 buf
=hash_id(ip
->addr
,bitmask
);
916 if_exists(idx
,idxs
,eq(idx
->id
,buf
))
925 idx
->bitmask
=bitmask
;
933 /* brutal perfomance optimalization */
934 while(idxcount
>idxtable_treshold2
&& bitmask
>2*idxtable_bitmask2
)
936 bitmask
-=idxtable_bitmask2
;
939 for_each(idx
,idxs
) if(idx
->parent
== NULL
)
941 buf
=hash_id(idx
->addr
,bitmask
);
942 if_exists(metaindex
,idxs
,eq(metaindex
->id
,buf
))
944 metaindex
->children
++;
948 create(metaindex
,Index
);
949 metaindex
->addr
=idx
->addr
;
951 metaindex
->bitmask
=bitmask
;
952 metaindex
->parent
=NULL
;
953 metaindex
->children
=0;
955 push(metaindex
,idxs
);
957 idx
->parent
=metaindex
;
961 /* this should slightly optimize throughout ... */
962 sort(idx
,idxs
,desc_order_by
,children
);
963 sort(idx
,idxs
,order_by
,bitmask
);
968 subnet
=subnet_id(idx
->addr
,idx
->bitmask
);
969 printf("%d: %s/%d\n",
970 ++i
, subnet
, idx
->bitmask
);
972 sprintf(str
,":post_%s - [0:0]", idx
->id
);
975 sprintf(str
,":forw_%s - [0:0]", idx
->id
);
980 string(buf
,strlen(idx
->parent
->id
)+6);
981 sprintf(buf
,"post_%s",idx
->parent
->id
);
988 sprintf(str
,"-A %s -d %s/%d -o %s -j post_%s", buf
, subnet
, idx
->bitmask
, lan
, idx
->id
);
991 sprintf(str
,"-A %s -d %s/%d -o %s -j post_common", buf
, subnet
, idx
->bitmask
, lan
);
996 string(buf
,strlen(idx
->parent
->id
)+6);
997 sprintf(buf
,"forw_%s",idx
->parent
->id
);
1004 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_%s", buf
, subnet
, idx
->bitmask
, wan
, idx
->id
);
1007 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_common", buf
, subnet
, idx
->bitmask
, wan
);
1010 printf("Total indexed iptables chains created: %d\n", i
);
1012 sprintf(str
,"-A FORWARD -o %s -j forw_common", wan
);
1015 sprintf(str
,"-A POSTROUTING -o %s -j post_common", lan
);
1023 fclose(iptables_file
);
1028 puts("Just flushed iptables and tc classes - now exiting ...");
1034 if(!dry_run
&& !nodelay
&& qos_free_delay
)
1036 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay
);
1037 sleep(qos_free_delay
);
1040 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",
1044 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
1045 tc
,lan
,lan_medium
,lan_medium
,burst_main
,highest_priority
);
1048 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
1049 tc
,lan
,line
,line
,burst_main
,highest_priority
);
1052 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc
,wan
,htb_r2q
);
1055 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
1056 tc
,wan
,wan_medium
,wan_medium
,burst_main
,highest_priority
);
1059 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
1060 tc
,wan
,up
,up
,burst_main
,highest_priority
);
1064 /*-----------------------------------------------------------------*/
1065 puts("Locating heavy downloaders and generating root classes ...");
1066 /*-----------------------------------------------------------------*/
1067 sort(ip
,ips
,desc_order_by
,traffic
);
1069 /*-----------------------------------------------------------------*/
1070 /* sub-scope - local variables */
1072 long long int rate
= line
;
1073 long long int max
= line
;
1074 int group_count
= 0;
1075 FILE *credit_file
= NULL
;
1077 if(!just_preview
&& !dry_run
&& enable_credit
)
1079 credit_file
= fopen(credit
,"w");
1082 for_each(group
,groups
)
1087 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",
1088 tc
, lan
, parent
, group
->id
, rate
, max
, burst_group
, highest_priority
+1, group
->desired
);
1092 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",
1093 tc
, wan
, parent
, group
->id
, rate
*up
/line
, max
*up
/line
, burst_group
, highest_priority
+1, group
->desired
);
1097 if(group_count
++ < max_nesting
)
1102 rate
-= digital_divide
*group
->min
;
1103 if(rate
< group
->min
)
1108 /*shaping of aggresive downloaders, with credit file support */
1111 int group_rate
= group
->min
, priority_sequence
= lowest_priority
;
1113 for_each(ip
, ips
) if(ip
->min
== group
->min
&& ip
->max
> ip
->min
)
1115 if( ip
->keyword
->data_limit
&& !ip
->fixedprio
1116 && ( ip
->traffic
>ip
->credit
1117 + (ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))) )
1119 if(group_rate
<ip
->max
)
1123 group_rate
+=magic_treshold
;
1124 ip
->prio
=lowest_priority
;
1125 if(ip
->prio
<highest_priority
+2)
1127 ip
->prio
=highest_priority
+2;
1132 if( ip
->keyword
->data_prio
1134 && ( ip
->traffic
>ip
->credit
1135 + (ip
->min
*ip
->keyword
->data_prio
+(ip
->keyword
->fixed_prio
<<20))) )
1137 ip
->prio
=priority_sequence
--;
1138 if(ip
->prio
<highest_priority
+1)
1140 ip
->prio
=highest_priority
+1;
1146 unsigned long long lcredit
=0;
1148 if((ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))>ip
->traffic
)
1150 lcredit
=(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))-ip
->traffic
;
1152 fprintf(credit_file
,"%s %Lu\n",ip
->addr
,lcredit
);
1160 fclose(credit_file
);
1168 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap
);
1176 if_exists(ip
,ips
,eq(ip
->addr
,_
))
1179 if(ip
->max
< ip
->desired
) /* apply FUP limit immediately.... */
1181 printf("Applying limit for %-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
1182 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
1183 sprintf(str
, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1184 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1186 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1187 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1188 sprintf(str
,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1189 tc
, wan
, ip
->group
, ip
->mark
,
1190 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1191 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1200 puts("Warning - classmap file not fund, just generating preview ...");
1201 start_shaping
=FALSE
;
1203 done
; /* ugly macro end */
1209 if(!dry_run
&& !just_flush
)
1211 /*-----------------------------------------------------------------*/
1212 printf("Writing json overview %s ... ", json
);
1213 /*-----------------------------------------------------------------*/
1222 && (ip
->traffic
|| ip
->direct
|| ip
->proxy
|| ip
->upload
))
1228 fprintf(f
, " \"%s\":{ \"lms\": %d, \"ip\":\"%s\", \"total\":%Lu, \"down\":%Lu, \"proxy\":%Lu, \"up\":%Lu, \"min\":%d, \"max\":%d, \"limit\":%d }",
1229 ip
->name
, ip
->lmsid
, ip
->addr
, ip
->traffic
, ip
->direct
, ip
->proxy
, ip
->upload
, ip
->min
, ip
->desired
, ip
->max
);
1249 /*-----------------------------------------------------------------*/
1250 printf("Sorting data and generating statistics page %s ...\n", html
);
1251 /*-----------------------------------------------------------------*/
1253 if(use_jquery_popups
)
1255 fprintf(f
,"<script type=\"text/javascript\" src=\"%s\"></script>\n", jquery_url
);
1257 fputs("<table class=\"decorated last\">\n\
1258 <caption>Bandwidth classes</caption>\n\
1260 <th style=\"text-align: right\">#</th>\n\
1261 <th style=\"text-align: right\">group</th>\n\
1262 <th style=\"text-align: right\">IPs</th>\n\
1263 <th style=\"text-align: right\">requested</th>\n",f
);
1264 fprintf(f
,"<th colspan=\"%d\">data limits</th>\n", keywordcount
);
1265 fputs("</tr></thead><tbody>\n",f
);
1268 for_each(group
, groups
)
1271 printf("%d kb/s group: %d bandwidth requested: %d kb/s\n",group
->min
,group
->count
,group
->desired
);
1273 fprintf(f
, "%s<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d kb/s</td>",
1274 tr_odd_even(), count
, group
->min
);
1275 fprintf(f
, "<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d kb/s</td>",
1276 group
->count
, group
->desired
);
1278 for_each(keyword
, keywords
) if(keyword
->ip_count
)
1280 fprintf(f
,"<td style=\"text-align: right\"><span style=\"color:#%s\">%d MB</span></td>",
1281 keyword
->html_color
, group
->min
*keyword
->data_limit
);
1283 i
+= group
->desired
;
1284 total
+= group
->count
;
1288 printf("Total groups: %d Total bandwidth requested: %d kb/s\nAGGREGATION: 1/%d\n",
1291 fprintf(f
,"</tr></tbody>\n\
1293 <th colspan=\"2\" style=\"text-align: left\">Line %Ld kb/s</td>",line
);
1294 fprintf(f
,"<th style=\"text-align: right\">%d</td><th style=\"text-align: right\">%d kb/s</td>",total
,i
);
1296 for_each(keyword
, keywords
) if(keyword
->ip_count
)
1298 fprintf(f
,"<th style=\"text-align: right\">%d IPs</th>",keyword
->ip_count
);
1300 fprintf(f
,"</tr><tr><th colspan=\"4\">Aggregation 1/%d</th>\n", (int)(0.5+i
/line
));
1301 fprintf(f
,"<th colspan=\"%d\">%d traffic classes</th></tr>\n", keywordcount
, total
);
1303 fputs("</thead></table>\n",f
);
1305 else if(!dry_run
&& !just_flush
)
1313 unsigned long long total_traffic
=0, total_direct
=0, total_proxy
=0, total_upload
=0, tmp_sum
=0;
1314 int active_classes
=0;
1316 struct Sum
{unsigned long long l
; int i
; list(Sum
);} *sum
,*sums
=NULL
;
1317 int limit_count
=0, prio_count
=0;
1325 fprintf(f
,"<p><table class=\"decorated last\">\n<caption>%s",title
);
1326 fprintf(f
," (%s)</caption>\n", d
);
1327 fputs("<thead><tr>\n<th colspan=\"3\"> </th>\n",f
);
1328 fputs("<th style=\"text-align: right\">credit</th>\n\
1329 <th style=\"text-align: right\">FUP</th>\n\
1330 <th style=\"text-align: right\">total</th>\n\
1331 <th style=\"text-align: right\">down</th>\n",f
);
1334 fputs("<th style=\"text-align: right\">proxy</th>\n",f
);
1336 fputs("<th style=\"text-align: right\">up</th>\n\
1337 <th style=\"text-align: right\">min</th>\n\
1338 <th style=\"text-align: right\">max</th>\n\
1339 <th style=\"text-align: right\">limit</th>\n\
1342 <th style=\"text-align: right\">#</th>\n\
1343 <th>hostname [+sharing]</th>\n\
1344 <th style=\"text-align: right\">LMS</th>\n\
1345 <th style=\"text-align: right\">MB</th>\n\
1346 <th style=\"text-align: right\">MB</th>\n\
1347 <th style=\"text-align: right\">MB</th>\n\
1348 <th style=\"text-align: right\">MB</th>\n\
1349 <th style=\"text-align: right\">MB</th>\n\
1350 <th style=\"text-align: right\">kb/s</th>\n\
1351 <th style=\"text-align: right\">kb/s</th>\n\
1352 <th style=\"text-align: right\">kb/s</th>\n\
1354 </tr></thead><tbody>\n",f
);
1357 for_each(ip
,ips
) if(!use_jquery_popups
|| !ip
->sharing
)
1359 char *f1
="", *f2
="";
1362 if(ip
->max
< ip
->desired
)
1364 f1
="<span style=\"color:red\">";
1368 else if(ip
->prio
> highest_priority
+1)
1370 f1
="<span style=\"color:brown\">";
1376 printf("%03d. %-22s %10Lu (%d/%d)\n",i
,ip
->name
, ip
->traffic
, ip
->min
, ip
->max
);
1378 /* hostnames -------------------------------------- */
1379 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",
1380 tr_odd_even(), ip
->name
, i
, log_url
, ip
->name
, ip
->name
);
1382 if(use_jquery_popups
)
1384 fprintf(f
,"<span id=\"sharing_%d\" style=\"display:none\">",i
);
1386 for_each(sharedip
, ips
) if(eq(ip
->name
, sharedip
->sharing
))
1388 fprintf(f
,"<br /><a class=\"blue\" target=\"_blank\" href=\"%s%s.log\">%s</a>\n", log_url
, sharedip
->name
, sharedip
->name
);
1391 fputs("</span>\n",f
);
1394 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>",
1395 i
, i
, i
, popup_button
);
1399 /* ----------------------------------------------- */
1403 fputs("<td style=\"text-align: right\">",f
);
1406 fprintf(f
,"<a class=\"blue\" target=\"_blank\" href=\"%s%d\">%04d</a>\n", lms_url
, ip
->lmsid
, ip
->lmsid
);
1408 else if(ip
->lmsid
== 0)
1414 fprintf(f
,"<td style=\"text-align: right\">%Lu</td>\n", ip
->credit
);
1415 fprintf(f
,"<td style=\"text-align: right\"><span style=\"color:#%s\">%Lu</span></td>",
1416 ip
->keyword
->html_color
,
1417 ip
->credit
+(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20)));
1418 fprintf(f
,"<td style=\"text-align: right\">%s%Lu%s", f1
, ip
->traffic
, f2
);
1420 /* download --------------------------------------- */
1421 fprintf(f
,"</td><td style=\"text-align: right\">%Lu", ip
->direct
);
1422 if(use_jquery_popups
)
1424 fprintf(f
,"<span id=\"download_%d\" style=\"display:none\">",i
);
1425 for_each(sharedip
, ips
) if(eq(ip
->name
, sharedip
->sharing
))
1427 fprintf(f
,"<br />%Lu", sharedip
->direct
);
1429 fputs("</span>\n",f
);
1432 /* ----------------------------------------------- */
1436 fprintf(f
,"<td style=\"text-align: right\">%Lu</td>\n", ip
->proxy
);
1438 /* upload ---------------------------------------- */
1439 fprintf(f
,"<td style=\"text-align: right\">%Lu", ip
->upload
);
1440 if(use_jquery_popups
)
1442 fprintf(f
,"<span id=\"upload_%d\" style=\"display:none\">",i
);
1443 for_each(sharedip
,ips
) if(eq(ip
->name
, sharedip
->sharing
))
1445 fprintf(f
,"<br />%Lu", sharedip
->upload
);
1447 fputs("</span>\n",f
);
1450 /* ----------------------------------------------- */
1452 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1453 <td style=\"text-align: right\">%d</td>\n\
1454 <td style=\"text-align: right\">%s%d%s</td>\n\
1455 <td>%s%d%s</td></tr>\n",
1456 ip
->min
, ip
->desired
,
1460 total_traffic
+=ip
->traffic
;
1461 total_direct
+=ip
->direct
;
1462 total_proxy
+=ip
->proxy
;
1463 total_upload
+=ip
->upload
;
1467 tmp_sum
+=ip
->traffic
;
1470 sum
->i
=active_classes
;
1471 insert(sum
,sums
,order_by
,i
);
1477 for_each(sharedip
,ips
) if(eq(ip
->name
, sharedip
->sharing
))
1479 append_log(sharedip
);
1483 fprintf(f
,"</tbody><thead><tr>\n\
1484 <th colspan=\"%d\" style=\"text-align: left\">%d CLASSES</th>", colspan
-7, i
);
1485 fprintf(f
,"<th style=\"text-align: right\">%Lu</th><th style=\"text-align: right\">%Lu</th>\n", total_traffic
, total_direct
);
1488 fprintf(f
,"<th style=\"text-align: right\">%Lu</th>\n", total_proxy
);
1490 fprintf(f
,"<th style=\"text-align: right\">%Lu</th>", total_upload
);
1491 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
);
1494 if(active_classes
>10)
1496 int top20_count
=0,top20_perc1
=0;
1497 long long top20_perc2
=0;
1498 unsigned long long top20_sum
=0l;
1500 fputs("<a name=\"erp\"></a><p><table class=\"decorated last\"><caption>Enterprise Resource Planning (ERP)</caption>\n",f
);
1501 fputs("<thead><tr>\n\
1502 <th>Analytic category</th>\n\
1503 <th colspan=\"2\" style=\"text-align: center\">Active Classes</th>\n\
1504 <th colspan=\"2\" style=\"text-align: center\">Data transfers</th>\n\
1505 </tr></thead><tbody>\n",f
);
1507 if_exists(sum
,sums
,sum
->l
>=total_traffic
/4)
1509 fprintf(f
,"%s<td>Top 25%% of traffic</td>\n", tr_odd_even());
1510 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1511 <td style=\"text-align: right\">%d %%</td>\n\
1512 <td style=\"text-align: right\">%Lu MB</td>\n\
1513 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1514 sum
->i
, (100*sum
->i
+50)/active_classes
, sum
->l
, (100*sum
->l
+50)/total_traffic
);
1517 if_exists(sum
,sums
,sum
->i
==10)
1519 fprintf(f
,"%s<td>Top 10 downloaders</td>\n", tr_odd_even());
1520 fprintf(f
,"<td style=\"text-align: right\"><strong>10</strong></td>\n\
1521 <td style=\"text-align: right\">%d %%</td>\n\
1522 <td style=\"text-align: right\">%Lu MB</td>\n\
1523 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1524 (100*sum
->i
+50)/active_classes
, sum
->l
, (100*sum
->l
+50)/total_traffic
);
1527 if_exists(sum
,sums
,sum
->l
>=total_traffic
/2)
1529 fprintf(f
,"%s<td>Top 50%% of traffic</td>\n", tr_odd_even());
1530 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1531 <td style=\"text-align: right\">%d %%</td>\n\
1532 <td style=\"text-align: right\">%Lu MB</td>\n\
1533 <td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",
1534 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1537 if_exists(sum
,sums
,sum
->l
>=4*total_traffic
/5)
1539 fprintf(f
,"%s<td>Top 80%% of traffic</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\"><strong>%Ld %%</strong></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)/5)
1549 fprintf(f
,"%s<td>Top 20%% downloaders</td>\n", tr_odd_even());
1551 top20_perc1
=(100*sum
->i
+50)/active_classes
;
1553 top20_perc2
=(100*sum
->l
+50)/total_traffic
;
1554 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1555 <td style=\"text-align: right\"><strong>%d %%</strong></td>\n\
1556 <td style=\"text-align: right\">%Lu MB</td>\n\
1557 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1558 top20_count
,top20_perc1
,top20_sum
,top20_perc2
);
1561 if_exists(sum
,sums
,sum
->i
>=(active_classes
+1)/4)
1563 fprintf(f
,"%s<td>Top 25%% downloaders</td>\n", tr_odd_even());
1564 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1565 <td style=\"text-align: right\">%d %%</td>\n\
1566 <td style=\"text-align: right\">%Lu MB</td>\n\
1567 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1568 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1571 if_exists(sum
,sums
,sum
->i
>=(active_classes
+1)/2)
1573 fprintf(f
,"%s<td>Top 50%% downloaders</td>\n", tr_odd_even());
1574 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1575 <td style=\"text-align: right\"><strong>%d %%</strong></td>\n\
1576 <td style=\"text-align: right\">%Lu MB</td>\n\
1577 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1578 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1581 if_exists(sum
,sums
,sum
->i
>=4*(active_classes
+1)/5)
1583 fprintf(f
,"%s<td>Top 80%% downloaders</td>\n", tr_odd_even());
1584 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1585 <td style=\"text-align: right\">%d %%</td>\n\
1586 <td style=\"text-align: right\">%Lu MB</td>\n\
1587 <td style=\"text-align: right\">%Ld %%</td></tr></tbody>\n",
1588 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1591 fprintf(f
,"<thead><tr><th><a class=\"blue\" target=\"_blank\" href=\"%sERP.log\">All users, all traffic</a></th>\n", log_url
);
1592 fprintf(f
,"<th style=\"text-align: right\">%d</th>\n\
1593 <th style=\"text-align: right\">100 %%</th>\n\
1594 <th style=\"text-align: right\">%Lu MB</th>\n\
1595 <th style=\"text-align: right\">100 %%</th></tr>\n",active_classes
,total_traffic
);
1596 fputs("</thead></table>\n", f
);
1598 /* write basic ERP data to log directory */
1602 sprintf(str
,"%s/ERP.log",log_dir
);
1603 iplog
=fopen(str
,"a");
1606 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",
1607 time(NULL
), top20_count
, top20_perc1
, top20_sum
, top20_perc2
,
1608 active_classes
, total_traffic
, i
, limit_count
, prio_count
, d
); /* d = date*/
1618 fprintf(f
, stats_html_signature
, version
);
1629 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar
);
1635 printf("%-22s %-15s mark\n","name","ip");
1638 printf("Writing %s ... ", classmap
);
1639 f
= fopen(classmap
, "w");
1645 /*-----------------------------------------------------------------*/
1646 puts("Generating iptables and tc classes ... ");
1647 /*-----------------------------------------------------------------*/
1649 for_each(ip
, ips
) if(ip
->mark
> 0)
1654 duplicate(ip
->addr
,buf
);
1655 buf
=hash_id(ip
->addr
,32-idxtable_bitmask1
);
1657 string(chain_forward
,6+strlen(buf
));
1658 strcpy(chain_forward
,"forw_");
1659 strcat(chain_forward
,buf
);
1661 string(chain_postrouting
,6+strlen(buf
));
1662 strcpy(chain_postrouting
,"post_");
1663 strcat(chain_postrouting
,buf
);
1669 chain_forward
="FORWARD";
1670 chain_postrouting
="POSTROUTING";
1674 printf("%-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
1677 /* -------------------------------------------------------- mark download */
1679 sprintf(str
, "-A %s -d %s/32 -o %s -j %s%d",
1680 chain_postrouting
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
1681 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/
1682 /* -m limit --limit 1/s */
1687 sprintf(str
, "-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",
1688 chain_postrouting
, proxy_ip
, proxy_port
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
1689 /*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);*/
1693 sprintf(str
, "-A %s -d %s/32 -o %s -j ACCEPT",
1694 chain_postrouting
, ip
->addr
, lan
);
1697 /* -------------------------------------------------------- mark upload */
1698 sprintf(str
, "-A %s -s %s/32 -o %s -j %s%d",
1699 chain_forward
, ip
->addr
, wan
, mark_iptables
, ip
->mark
);
1700 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/
1703 sprintf(str
, "-A %s -s %s/32 -o %s -j ACCEPT",
1704 chain_forward
, ip
->addr
, wan
);
1709 /* -------------------------------------------------------- download class */
1711 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
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
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1718 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1720 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1721 tc
, lan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1725 if(filter_type
== 1)
1727 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1728 tc
, lan
, ip
->mark
, ip
->mark
);
1732 /* -------------------------------------------------------- upload class */
1734 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1735 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1738 sprintf(str
,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1739 tc
, wan
, ip
->group
, ip
->mark
,
1740 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1741 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1744 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1746 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1747 tc
, wan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1751 if(filter_type
== 1)
1753 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1754 tc
, wan
, ip
->mark
, ip
->mark
);
1760 fprintf(f
, "%s %d\n", ip
->addr
, ip
->mark
);
1766 printf("(sharing %s)\n", ip
->sharing
);
1779 chain_forward
= "forw_common";
1780 chain_postrouting
= "post_common";
1784 chain_forward
= "FORWARD";
1785 chain_postrouting
= "POSTROUTING";
1787 /* -------------------------------- classify or reject free download */
1789 char *final_chain
= "DROP"; /* REJECT would be better, but it is impossible in mangle */
1792 final_chain
= "ACCEPT";
1798 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s%d",
1799 chain_postrouting
,proxy_ip
,proxy_port
,lan
,mark_iptables
,3);
1802 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s",
1803 chain_postrouting
,proxy_ip
,proxy_port
,lan
,final_chain
);
1808 sprintf(str
,"-A %s -o %s -j %s%d", chain_postrouting
, lan
, mark_iptables
, 3);
1811 sprintf(str
,"-A %s -o %s -j %s", chain_postrouting
, lan
, final_chain
);
1813 /* ------------------------------- classify or reject free upload */
1816 sprintf(str
,"-A %s -o %s -j %s%d", chain_forward
, wan
, mark_iptables
, 3);
1819 sprintf(str
,"-A %s -o %s -j %s", chain_forward
, wan
, final_chain
);
1823 if(free_min
) /* allocate free bandwith if it is not zero... */
1825 /*-----------------------------------------------------------------*/
1826 puts("Generating free bandwith classes ...");
1827 /*-----------------------------------------------------------------*/
1828 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1829 tc
, lan
, parent
, free_min
, free_max
,burst
, lowest_priority
);
1831 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1832 tc
, wan
, parent
, free_min
, free_max
, burst
, lowest_priority
);
1835 if(strcmpi(qos_leaf
, "none"))
1837 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, lan
, qos_leaf
);
1840 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, wan
, qos_leaf
);
1843 /* tc handle 1 fw flowid */
1844 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, lan
);
1847 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, wan
);
1850 printf("Total IP count: %d\n", i
);
1857 /* that's all folks, thank you for reading it all the way up to this point ;-) */
1858 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */
This page took 1.960188 seconds and 4 git commands to generate.