1 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2 /* Prometheus QoS - you can "steal fire" from your ISP */
3 /* "fair-per-IP" quality of service (QoS) utility */
4 /* requires Linux 2.4.x or 2.6.x with HTB support */
5 /* Copyright(C) 2005-2012 Michael Polak, Arachne Labs */
6 /* iptables-restore support Copyright(C) 2007-2008 ludva */
7 /* Credit: CZFree.Net,Martin Devera,Netdave,Aquarius,Gandalf */
8 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
10 /* Modified by: xChaos, 20121011
13 Prometheus QoS is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2.1 of
16 the License, or (at your option) any later version.
18 Prometheus QoS is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with Prometheus Qos; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 GNU General Public License is located in file COPYING */
32 #include "cll1-0.6.2.h"
35 const char *version
= "0.8.3-g";
37 /* Version numbers: 0.8.3 is development releases ("beta"), 0.8.4 will be "stable" */
38 /* Debian(RPM) package versions/patchlevels: 0.7.9-2, 0.8.0-1, 0.8.0-2, etc. */
39 /* C source code development versions ("beta"): 0.7.9-a, 0.8.1-b, etc. */
40 /* C source code release versions: 0.8.0, 0.8.2, 0.8.4, etc. */
42 const char *stats_html_signature
= "<span class=\"small\">Statistics generated by Prometheus QoS version %s<br />GPL+Copyright(C)2005-2012 Michael Polak, <a target=\"_blank\" href=\"http://www.arachne.cz/\">Arachne Labs</a></span>\n";
44 /* ======= Help screen is hopefuly self-documenting part of code :-) ======= */
48 puts("Command line switches:\n\
50 -d Dry run (preview tc and iptables commands on stdout)\n\
51 -r Run (reset all statistics and start shaping - daily usage)\n\
52 -p just generate Preview of data transfer statistics and exit (after -r)\n\
53 -s start Shaping FUP limits (keeps data transfer stat like -p) (after -r)\n\
54 -n run Now (like -r delay - overrides qos-free-delay keyword, after boot)\n\
55 -f just Flush iptables and tc classes and exit (stop shaping, no QiS)\n\
56 -9 emergency iptables flush (like -f, but dumps data transfer statistics)\n\
58 -c filename force alternative /etc/prometheus/prometheus.conf filename\n\
59 -h filename force alternative /etc/hosts filename (overrides hosts keyword)\n\
60 -l Mmm YYYY generate HTML summary of Logged traffic (Mmm=Jan-Dec) (and exit)\n\
61 -m generate HTML summary of traffic for yesterday's Month (and exit)\n\
62 -y generate HTML summary of traffic for yesterday's Year (and exit)\n\
63 -? --help show this help scree (and exit)\n\
64 -v --version show Version number of this utility (and exit)\n");
67 /* ======= All path names are defined here (for RPM patch) ======= */
69 const char *tc
= "/sbin/tc"; /* requires tc with HTB support */
70 const char *iptables
= "/sbin/iptables"; /* requires iptables utility */
71 const char *iptablessave
= "/sbin/iptables-save"; /* not yet required */
72 const char *iptablesrestore
= "/sbin/iptables-restore"; /* requires iptables-restore */
73 const char *ls
= "/bin/ls"; /* this is not user configurable :-) */
75 char *config
= "/etc/prometheus/prometheus.conf"; /* main configuration file */
76 char *hosts
= "/etc/prometheus/hosts"; /* per-IP bandwidth definition file */
78 char *iptablesfile
= "/var/spool/prometheus.iptables"; /* temporary file for iptables-restore*/
79 char *credit
= "/var/lib/misc/prometheus.credit"; /* credit log file */
80 char *classmap
= "/var/lib/misc/prometheus.classes"; /* credit log file */
81 char *html
= "/var/www/traffic.html"; /* hall of fame - html version */
82 char *preview
= "/var/www/preview.html"; /* hall of fame preview - html version */
83 char *json_traffic
= "/var/www/logs/traffic.json"; /* hall of fame - json version */
84 char *json_preview
= "/var/www/logs/preview.json"; /* hall of fame preview - json version */
85 char *cmdlog
= "/var/log/prometheuslog"; /* command log filename */
86 char *log_dir
= "/var/www/logs/"; /* log directory pathname, ended with slash */
87 char *log_url
= "/logs/"; /* log directory relative URI prefix (partial URL) */
88 char *html_log_dir
= "/var/www/logs/html/";
90 char *jquery_url
= "http://code.jquery.com/jquery-latest.js";
91 char *lms_url
= "/lms/?m=customerinfo&id=";
92 int use_jquery_popups
= 1;
93 int row_odd_even
= 0; /*<tr class="odd/even"> */
95 /* === Configuraration file values defaults - stored in global variables ==== */
97 int filter_type
= 1; /*1 mark, 2 classify*/
99 char *mark_iptables
= "MARK --set-mark ";
100 int dry_run
= 0; /* preview - use puts() instead of system() */
101 char *iptablespreamble
= "*mangle\n:PREROUTING ACCEPT [0:0]\n:POSTROUTING ACCEPT [0:0]\n:INPUT ACCEPT [0:0]\n:OUTPUT ACCEPT [0:0]\n:FORWARD ACCEPT [0:0]";
102 FILE *iptables_file
= NULL
;
103 int enable_credit
= 1; /* enable credit file */
104 int use_credit
= 0; /* use credit file (if enabled)*/
105 char *title
= "Hall of Fame - Greatest Suckers"; /* hall of fame title */
106 int hall_of_fame
= 1; /* enable hall of fame */
107 char *lan
= "eth0"; /* LAN interface */
108 char *lan_medium
= "100Mbit"; /* 10Mbit/100Mbit ethernet */
109 char *wan
= "eth1"; /* WAN/ISP interface */
110 char *wan_medium
= "100Mbit"; /* 10Mbit/100Mbit ethernet */
111 char *qos_leaf
= "sfq perturb 5"; /* leaf discipline */
112 char *qos_free_zone
= NULL
; /* QoS free zone */
113 int qos_proxy
= 1; /* include proxy port to QoS */
114 int found_lmsid
= 0; /* show links to users in LMS information system */
115 int include_upload
= 1; /* upload+download=total traffic */
116 char *proxy_ip
= "192.168.1.1/32"; /* our IP with proxy port */
117 int proxy_port
= 3128; /* proxy port number */
118 long long int line
= 1024; /* WAN/ISP download in kbps */
119 long long int up
= 1024; /* WAN/ISP upload in kbps */
120 int free_min
= 32; /* minimum guaranted bandwidth for all undefined hosts */
121 int free_max
= 64; /* maximum allowed bandwidth for all undefined hosts */
122 int qos_free_delay
= 0; /* seconds to sleep before applying new QoS rules */
123 int digital_divide
= 2; /* controls digital divide weirdness ratio, 1...3 */
124 int max_nesting
= 3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */
125 int htb_r2q
= 256; /* should work for leaf values 512 kbps to 8 Mbps */
126 int burst
= 8; /* HTB burst (in kbits) */
128 int burst_group
= 32;
129 int magic_treshold
= 8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */
130 int keywordcount
= 0;
133 /* not yet implemented:
134 int fixed_packets = 0; maximum number of pps per IP address (not class!)
135 int packet_limit = 5; maximum number of pps to htn CEIL, not rate !!!
137 FILE *log_file
= NULL
;
138 char *kwd
= "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */
140 const int highest_priority
= 0; /* highest HTB priority (HTB built-in value is 0) */
141 const int lowest_priority
= 7; /* lowest HTB priority (HTB built-in value is 7) */
142 const int idxtable_treshold1
= 24; /* this is no longer configurable */
143 const int idxtable_treshold2
= 12; /* this is no longer configurable */
144 const int idxtable_bitmask1
= 3; /* this is no longer configurable */
145 const int idxtable_bitmask2
= 3; /* this is no longer configurable */
147 struct IP
*ips
= NULL
, *ip
, *sharedip
;
148 struct Group
*groups
= NULL
, *group
;
149 struct Keyword
*keyword
, *defaultkeyword
=NULL
, *keywords
=NULL
;
151 void parse_ip_log(int argc
, char **argv
);
152 /* implemented in parselog.c */
154 void parse_hosts(char *hosts
);
155 /* implemented in parsehosts.c */
157 void write_json_traffic(char *json
);
158 /* implemented in json.c */
160 const char *tr_odd_even(void)
162 row_odd_even
= 1 - row_odd_even
;
165 return "<tr class=\"even\">\n";
169 return "<tr class=\"odd\">\n";
173 /* ==== This is C<<1 stuff - learn C<<1 first! https://dev.arachne.cz/svn/cll1h ==== */
179 struct Index
*parent
;
183 } *idxs
=NULL
, *idx
, *metaindex
;
186 /* function implemented in parsehosts.c */
188 /* ====== iptables indexes are used to reduce complexity to log8(N) ===== */
190 char *index_id(char *ip
, int bitmask
);
191 /* function implemented in ipv4subnets.c */
193 char *subnet_id(char *ip
, int bitmask
);
194 /* function implemented in ipv4subnets.c */
196 /* ================= Let's parse configuration file here ================ */
198 void reject_config_and_exit(char *filename
)
200 printf("Configuration file %s rejected - abnormal exit.",filename
);
204 void get_config(char *config_filename
)
208 printf("Configured keywords: ");
209 parse(config_filename
)
211 option("keyword",kwd
);
216 create(keyword
,Keyword
);
218 keyword
->asymetry_ratio
=1; /* ratio for ADSL-like upload */
219 keyword
->asymetry_fixed
=0; /* fixed treshold for ADSL-like upload */
220 keyword
->data_limit
=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */
221 keyword
->data_prio
=4; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */
222 keyword
->fixed_limit
=0; /* fixed data limit for setting lower HTB ceil */
223 keyword
->fixed_prio
=0; /* fixed data limit for setting lower HTB prio */
224 keyword
->reserve_min
=8; /* bonus for nominal HTB rate bandwidth (in kbps) */
225 keyword
->reserve_max
=0; /* malus for nominal HTB ceil (in kbps) */
226 keyword
->default_prio
=highest_priority
+1;
227 keyword
->html_color
="000000";
229 keyword
->leaf_discipline
="";
231 push(keyword
,keywords
);
232 if(!defaultkeyword
) defaultkeyword
=keyword
;
239 for_each(keyword
,keywords
)
241 int l
=strlen(keyword
->key
);
243 if(!strncmp(keyword
->key
,_
,l
) && strlen(_
)>l
+2)
245 char *tmptr
=_
; /* <---- l+1 ----> */
246 _
+=l
+1; /* via-prometheus-asymetry-ratio, etc. */
247 ioption("asymetry-ratio",keyword
->asymetry_ratio
);
248 ioption("asymetry-treshold",keyword
->asymetry_fixed
);
249 ioption("magic-relative-limit",keyword
->data_limit
);
250 ioption("magic-relative-prio",keyword
->data_prio
);
251 loption("magic-fixed-limit",keyword
->fixed_limit
);
252 loption("magic-fixed-prio",keyword
->fixed_prio
);
253 ioption("htb-default-prio",keyword
->default_prio
);
254 ioption("htb-rate-bonus",keyword
->reserve_min
);
255 ioption("htb-ceil-malus",keyword
->reserve_max
);
256 option("leaf-discipline",keyword
->leaf_discipline
);
257 option("html-color",keyword
->html_color
);
260 if(keyword
->data_limit
|| keyword
->fixed_limit
||
261 keyword
->data_prio
|| keyword
->fixed_prio
)
270 option("iptables",iptables
);
271 option("iptables-save",iptablessave
); /* new */
272 option("iptables-restore",iptablesrestore
); /* new */
273 option("iptables-in-filename",iptablesfile
); /* new */
274 option("hosts",hosts
);
275 option("lan-interface",lan
);
276 option("wan-interface",wan
);
277 option("lan-medium",lan_medium
);
278 option("wan-medium",wan_medium
);
279 lloption("wan-download",line
);
280 lloption("wan-upload",up
);
281 ioption("hall-of-fame-enable",hall_of_fame
);
282 option("hall-of-fame-title",title
);
283 option("hall-of-fame-filename",html
);
284 option("json-filename",json_traffic
);
285 option("hall-of-fame-preview",preview
);
286 option("json-preview",json_preview
);
287 option("log-filename",cmdlog
);
288 option("credit-filename",credit
);
289 option("classmap-filename",classmap
);
290 ioption("credit-enable",enable_credit
);
291 option("log-traffic-directory",log_dir
);
292 option("log-traffic-html-directory",html_log_dir
);
293 option("log-traffic-url-path",log_url
);
294 option("jquery-url",jquery_url
);
295 option("lms-url",lms_url
);
296 ioption("use-jquery-popups",use_jquery_popups
);
297 option("qos-free-zone",qos_free_zone
);
298 ioption("qos-free-delay",qos_free_delay
);
299 ioption("qos-proxy-enable",qos_proxy
);
300 option("qos-proxy-ip",proxy_ip
);
301 option("htb-leaf-discipline",qos_leaf
);
302 ioption("qos-proxy-port",proxy_port
);
303 ioption("free-rate",free_min
);
304 ioption("free-ceil",free_max
);
305 ioption("htb-burst",burst
);
306 ioption("htb-burst-main",burst_main
);
307 ioption("htb-burst-group",burst_group
);
308 ioption("htb-nesting-limit",max_nesting
);
309 ioption("htb-r2q",htb_r2q
);
310 ioption("magic-include-upload",include_upload
);
311 ioption("magic-treshold",magic_treshold
);
312 option("filter-type", cnf
);
313 /* not yet implemented:
314 ioption("magic-fixed-packets",fixed_packets);
315 ioption("magic-relative-packets",packet_limit);
320 perror(config_filename
);
321 puts("Warning - using built-in defaults instead ...");
323 done
; /* ugly macro end */
326 /* leaf discipline for keywords */
327 for_each(keyword
,keywords
)
329 if(!strcmpi(keyword
->leaf_discipline
, ""))
331 keyword
->leaf_discipline
= qos_leaf
;
335 if(strcmpi(cnf
, "mark"))
339 mark_iptables
= "CLASSIFY --set-class 1:";
345 mark_iptables
= "MARK --set-mark ";
348 /* are supplied values meaningful ?*/
351 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");
352 reject_config_and_exit(config_filename
);
356 /* ===================== traffic analyser - uses iptables ================ */
358 void get_traffic_statistics(void)
363 textfile(Pipe
,str
) *line
,*lines
=NULL
;
367 sprintf(cmd
,"%s -L -v -x -n -t mangle",iptables
);
379 int col
, accept
=0,proxyflag
=0,valid
=1,setchainname
=0,commonflag
=0;
380 unsigned long long traffic
=0;
381 unsigned long pkts
=0;
382 char *ipaddr
=NULL
,*ptr
;
384 /* debug puts(line->str); */
385 valid_columns(ptr
,line
->str
,' ',col
)
386 if(valid
) switch(col
)
388 case 1: if(eq(ptr
,"Chain"))
392 else if(eq(ptr
,"pkts"))
398 sscanf(ptr
,"%lu",&pkts
);
401 case 2: if(setchainname
)
403 if(!strncmp(ptr
,"post_",5) || eq(ptr
,"POSTROUTING"))
409 if(!strncmp(ptr
,"forw_",5) || eq(ptr
,"FORWARD"))
414 if(eq(ptr
,"post_common") || eq(ptr
,"forw_common"))
421 sscanf(ptr
,"%Lu",&traffic
);
426 case 3: if((strncmp(ptr
,"post_",5) && strncmp(ptr
,"forw_",5)) || commonflag
)
430 /*if(filter_type==1) accept=eq(ptr,"MARK"); else accept=eq(ptr,"CLASSIFY");*/
432 case 8: if(downloadflag
)
434 if(strstr(proxy_ip
,ptr
))
444 case 9: if(downloadflag
)ipaddr
=ptr
;break;
447 if(accept
&& traffic
>0 && ipaddr
)
453 else if(!downloadflag
)
457 printf("IP %s: %Lu MB (%ld pkts)\n", ipaddr
, traffic
, pkts
);
459 if_exists(ip
,ips
,eq(ip
->addr
,ipaddr
));
464 if(eq(ip
->addr
,"0.0.0.0/0"))
466 ip
->name
="(unregistered)";
468 ip
->max
=ip
->desired
=free_max
;
480 ip
->traffic
+=traffic
;
482 ip
->direct
=ip
->traffic
-ip
->upload
-ip
->proxy
;
491 ip
->traffic
+=traffic
;
495 if(traffic
>ip
->traffic
)
506 /* ========== This function executes, logs OR ALSO prints command ========== */
508 void safe_run(char *cmd
)
512 printf("\n=>%s\n",cmd
);
520 fprintf(log_file
,"%s\n",cmd
);
524 void save_line(char *line
)
526 fprintf(iptables_file
,"%s\n",line
);
529 void run_restore(void)
532 string(restor
,STRLEN
);
534 /*-----------------------------------------------------------------*/
535 printf("Running %s <%s ...\n", iptablesrestore
, iptablesfile
);
536 /*-----------------------------------------------------------------*/
539 fclose(iptables_file
);
546 done
; /* ugly macro end */
549 sprintf(restor
,"%s <%s",iptablesrestore
, iptablesfile
);
555 char *parse_datafile_line(char *str
)
557 char *ptr
=strchr(str
,' ');
571 void append_log(struct IP
*self
) /*using global variables*/
576 date(d
); /* this is typical cll1.h macro - prints current date */
578 sprintf(str
,"%s/%s.log", log_dir
, self
->name
);
582 fprintf(f
,"%ld\t%s\t%Lu\t%Lu\t%Lu\t%Lu\t%d\t%d\t%d\t%d\t%s",
583 time(NULL
), self
->name
, self
->traffic
, self
->direct
, self
->proxy
,
584 self
->upload
, self
->min
, self
->max
, self
->desired
, self
->lmsid
, d
); /* d = date*/
593 /*-----------------------------------------------------------------*/
594 /* Are you looking for int main(int argc, char **argv) ? :-)) */
595 /*-----------------------------------------------------------------*/
599 int i
=0; /* just plain old Fortran style integer :-) */
600 FILE *f
=NULL
; /* everything is just stream of bytes... */
601 char *str
, *ptr
, *d
; /* LET A$=B$ :-) */
605 int just_flush
=FALSE
; /* deactivates all previous actions */
607 int just_preview
=FALSE
; /* preview - generate just stats */
608 int start_shaping
=FALSE
; /* apply FUP - requires classmap file */
609 int just_logs
=FALSE
; /* just parse logs */
613 char *chain_forward
, *chain_postrouting
;
617 Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\
618 Version %s - Copyright (C)2005-2012 Michael Polak, Arachne Labs\n\
619 iptables-restore & burst tunning & classify modification by Ludva\n\
620 Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version
);
622 /*----- Boring... we have to check command line options first: ----*/
625 argument("-c") { nextargument(config
); }
626 argument("-h") { nextargument(althosts
);}
627 argument("-d") { run
=TRUE
; dry_run
=TRUE
; }
628 argument("-f") { run
=TRUE
; just_flush
=TRUE
; }
629 argument("-9") { run
=TRUE
; just_flush
=9; }
630 argument("-p") { run
=TRUE
; just_preview
=TRUE
; }
631 argument("-s") { run
=TRUE
; just_preview
=TRUE
; start_shaping
=TRUE
; }
632 argument("-r") { run
=TRUE
; }
633 argument("-n") { run
=TRUE
; nodelay
=TRUE
; }
634 argument("-l") { just_logs
=TRUE
; }
635 argument("-m") { just_logs
=TRUE
; }
636 argument("-y") { just_logs
=TRUE
; }
637 argument("-?") { help(); exit(0); }
638 argument("--help") { help(); exit(0); }
639 argument("-v") { exit(0); }
640 argument("--version") { exit(0); }
645 puts("*** THIS IS JUST DRY RUN ! ***\n");
648 date(d
); /* this is typical cll1.h macro - prints current date */
650 /*-----------------------------------------------------------------*/
651 printf("Parsing configuration file %s ...\n", config
);
652 /*-----------------------------------------------------------------*/
657 parse_ip_log(argc
,argv
);
673 /*-----------------------------------------------------------------*/
674 puts("Parsing iptables verbose output ...");
675 /*-----------------------------------------------------------------*/
676 get_traffic_statistics();
679 /*-----------------------------------------------------------------*/
680 printf("Parsing class defintion file %s ...\n", hosts
);
681 /*-----------------------------------------------------------------*/
684 /*-----------------------------------------------------------------*/
685 /* cll1.h - let's allocate brand new character buffer... */
686 /*-----------------------------------------------------------------*/
689 /*-----------------------------------------------------------------*/
690 puts("Resolving shared connections ...");
691 /*-----------------------------------------------------------------*/
692 for_each(ip
,ips
) if(ip
->sharing
)
694 for_each(sharedip
,ips
) if(eq(sharedip
->name
,ip
->sharing
))
696 sharedip
->traffic
+=ip
->traffic
;
698 ip
->mark
=sharedip
->mark
;
699 ip
->lmsid
=sharedip
->lmsid
;
704 printf("Unresolved shared connection: %s %s sharing-%s\n",
705 ip
->addr
, ip
->name
, ip
->sharing
);
709 if(enable_credit
&& just_flush
<9)
711 /*-----------------------------------------------------------------*/
712 printf("Parsing credit file %s ...\n", credit
);
713 /*-----------------------------------------------------------------*/
716 ptr
=parse_datafile_line(_
);
719 if_exists(ip
,ips
,eq(ip
->addr
,_
))
721 sscanf(ptr
,"%Lu",&(ip
->credit
));
725 done
; /* ugly macro end */
730 /*-----------------------------------------------------------------*/
731 puts("Initializing iptables and tc classes ...");
732 /*-----------------------------------------------------------------*/
734 iptables_file
=fopen(iptablesfile
,"w");
735 if(iptables_file
== NULL
)
737 puts("Cannot open iptablesfile!");
741 log_file
=fopen(cmdlog
,"w");
744 puts("Cannot open logfile!");
748 save_line(iptablespreamble
);
751 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,lan
);
754 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,wan
);
757 iptables_file
=fopen(iptablesfile
,"w");
758 save_line(iptablespreamble
);
760 if(qos_free_zone
&& *qos_free_zone
!='0')
764 sprintf(str
,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone
, wan
);
769 save_line(":post_noproxy - [0:0]");
770 sprintf(str
,"-A POSTROUTING ! -p tcp -o %s -j post_noproxy", lan
);
772 sprintf(str
,"-A POSTROUTING ! -s %s -o %s -j post_noproxy", proxy_ip
, lan
);
774 sprintf(str
,"-A POSTROUTING -s %s -p tcp ! --sport %d -o %s -j post_noproxy", proxy_ip
, proxy_port
, lan
);
777 chain
="post_noproxy";
784 sprintf(str
,"-A %s -s %s -o %s -j ACCEPT", chain
, qos_free_zone
, lan
);
788 if(ip_count
>idxtable_treshold1
&& !just_flush
)
790 int idxcount
=0, bitmask
=32-idxtable_bitmask1
; /* default net mask: 255.255.255.240 */
792 /*-----------------------------------------------------------------*/
793 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count
);
794 /*-----------------------------------------------------------------*/
796 save_line(":post_common - [0:0]");
797 save_line(":forw_common - [0:0]");
799 for_each(ip
,ips
) if(ip
->addr
&& *(ip
->addr
) && !eq(ip
->addr
,"0.0.0.0/0"))
801 buf
=index_id(ip
->addr
,bitmask
);
802 if_exists(idx
,idxs
,eq(idx
->id
,buf
))
811 idx
->bitmask
=bitmask
;
819 /* brutal perfomance optimalization */
820 while(idxcount
>idxtable_treshold2
&& bitmask
>2*idxtable_bitmask2
)
822 bitmask
-=idxtable_bitmask2
;
825 for_each(idx
,idxs
) if(idx
->parent
== NULL
)
827 buf
=index_id(idx
->addr
,bitmask
);
828 if_exists(metaindex
,idxs
,eq(metaindex
->id
,buf
))
830 metaindex
->children
++;
834 create(metaindex
,Index
);
835 metaindex
->addr
=idx
->addr
;
837 metaindex
->bitmask
=bitmask
;
838 metaindex
->parent
=NULL
;
839 metaindex
->children
=0;
841 push(metaindex
,idxs
);
843 idx
->parent
=metaindex
;
847 /* this should slightly optimize throughout ... */
848 sort(idx
,idxs
,desc_order_by
,children
);
849 sort(idx
,idxs
,order_by
,bitmask
);
854 subnet
=subnet_id(idx
->addr
,idx
->bitmask
);
855 printf("%d: %s/%d\n",
856 ++i
, subnet
, idx
->bitmask
);
858 sprintf(str
,":post_%s - [0:0]", idx
->id
);
861 sprintf(str
,":forw_%s - [0:0]", idx
->id
);
866 string(buf
,strlen(idx
->parent
->id
)+6);
867 sprintf(buf
,"post_%s",idx
->parent
->id
);
874 sprintf(str
,"-A %s -d %s/%d -o %s -j post_%s", buf
, subnet
, idx
->bitmask
, lan
, idx
->id
);
877 sprintf(str
,"-A %s -d %s/%d -o %s -j post_common", buf
, subnet
, idx
->bitmask
, lan
);
882 string(buf
,strlen(idx
->parent
->id
)+6);
883 sprintf(buf
,"forw_%s",idx
->parent
->id
);
890 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_%s", buf
, subnet
, idx
->bitmask
, wan
, idx
->id
);
893 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_common", buf
, subnet
, idx
->bitmask
, wan
);
896 printf("Total indexed iptables chains created: %d\n", i
);
898 sprintf(str
,"-A FORWARD -o %s -j forw_common", wan
);
901 sprintf(str
,"-A POSTROUTING -o %s -j post_common", lan
);
909 fclose(iptables_file
);
914 puts("Just flushed iptables and tc classes - now exiting ...");
920 if(!dry_run
&& !nodelay
&& qos_free_delay
)
922 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay
);
923 sleep(qos_free_delay
);
926 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",
930 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
931 tc
,lan
,lan_medium
,lan_medium
,burst_main
,highest_priority
);
934 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
935 tc
,lan
,line
,line
,burst_main
,highest_priority
);
938 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc
,wan
,htb_r2q
);
941 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
942 tc
,wan
,wan_medium
,wan_medium
,burst_main
,highest_priority
);
945 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
946 tc
,wan
,up
,up
,burst_main
,highest_priority
);
950 /*-----------------------------------------------------------------*/
951 puts("Locating heavy downloaders and generating root classes ...");
952 /*-----------------------------------------------------------------*/
953 sort(ip
,ips
,desc_order_by
,traffic
);
955 /*-----------------------------------------------------------------*/
956 /* sub-scope - local variables */
958 long long int rate
= line
;
959 long long int max
= line
;
961 FILE *credit_file
= NULL
;
963 if(!just_preview
&& !dry_run
&& enable_credit
)
965 credit_file
= fopen(credit
,"w");
968 for_each(group
,groups
)
973 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",
974 tc
, lan
, parent
, group
->id
, rate
, max
, burst_group
, highest_priority
+1, group
->desired
);
978 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",
979 tc
, wan
, parent
, group
->id
, rate
*up
/line
, max
*up
/line
, burst_group
, highest_priority
+1, group
->desired
);
983 if(group_count
++ < max_nesting
)
988 rate
-= digital_divide
*group
->min
;
989 if(rate
< group
->min
)
994 /*shaping of aggresive downloaders, with credit file support */
997 int group_rate
= group
->min
, priority_sequence
= lowest_priority
;
999 for_each(ip
, ips
) if(ip
->min
== group
->min
&& ip
->max
> ip
->min
)
1001 if( ip
->keyword
->data_limit
&& !ip
->fixedprio
1002 && ( ip
->traffic
>ip
->credit
1003 + (ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))) )
1005 if(group_rate
<ip
->max
)
1009 group_rate
+=magic_treshold
;
1010 ip
->prio
=lowest_priority
;
1011 if(ip
->prio
<highest_priority
+2)
1013 ip
->prio
=highest_priority
+2;
1018 if( ip
->keyword
->data_prio
1020 && ( ip
->traffic
>ip
->credit
1021 + (ip
->min
*ip
->keyword
->data_prio
+(ip
->keyword
->fixed_prio
<<20))) )
1023 ip
->prio
=priority_sequence
--;
1024 if(ip
->prio
<highest_priority
+1)
1026 ip
->prio
=highest_priority
+1;
1032 unsigned long long lcredit
=0;
1034 if((ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))>ip
->traffic
)
1036 lcredit
=(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))-ip
->traffic
;
1038 fprintf(credit_file
,"%s %Lu\n",ip
->addr
,lcredit
);
1046 fclose(credit_file
);
1054 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap
);
1062 if_exists(ip
,ips
,eq(ip
->addr
,_
))
1065 if(ip
->max
< ip
->desired
) /* apply FUP limit immediately.... */
1067 printf("Applying limit for %-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
1068 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
1069 sprintf(str
, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1070 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1072 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1073 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1074 sprintf(str
,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1075 tc
, wan
, ip
->group
, ip
->mark
,
1076 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1077 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1086 puts("Warning - classmap file not fund, just generating preview ...");
1087 start_shaping
=FALSE
;
1089 done
; /* ugly macro end */
1092 json_traffic
=json_preview
;
1095 if(!dry_run
&& !just_flush
)
1097 /*-----------------------------------------------------------------*/
1098 printf("Writing json traffic overview %s ... ", json_traffic
);
1099 /*-----------------------------------------------------------------*/
1100 write_json_traffic(json_traffic
);
1109 /*-----------------------------------------------------------------*/
1110 printf("Sorting data and generating statistics page %s ...\n", html
);
1111 /*-----------------------------------------------------------------*/
1113 if(use_jquery_popups
)
1115 fprintf(f
,"<script type=\"text/javascript\" src=\"%s\"></script>\n", jquery_url
);
1117 fputs("<table class=\"decorated last\">\n\
1118 <caption>Bandwidth classes</caption>\n\
1120 <th style=\"text-align: right\">#</th>\n\
1121 <th style=\"text-align: right\">group</th>\n\
1122 <th style=\"text-align: right\">IPs</th>\n\
1123 <th style=\"text-align: right\">requested</th>\n",f
);
1124 fprintf(f
,"<th colspan=\"%d\">data limits</th>\n", keywordcount
);
1125 fputs("</tr></thead><tbody>\n",f
);
1128 for_each(group
, groups
)
1131 printf("%d kb/s group: %d bandwidth requested: %d kb/s\n",group
->min
,group
->count
,group
->desired
);
1133 fprintf(f
, "%s<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d kb/s</td>",
1134 tr_odd_even(), count
, group
->min
);
1135 fprintf(f
, "<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d kb/s</td>",
1136 group
->count
, group
->desired
);
1138 for_each(keyword
, keywords
) if(keyword
->ip_count
)
1140 fprintf(f
,"<td style=\"text-align: right\"><span style=\"color:#%s\">%d MB</span></td>",
1141 keyword
->html_color
, group
->min
*keyword
->data_limit
);
1143 i
+= group
->desired
;
1144 total
+= group
->count
;
1148 printf("Total groups: %d Total bandwidth requested: %d kb/s\nAGGREGATION: 1/%d\n",
1151 fprintf(f
,"</tr></tbody>\n\
1153 <th colspan=\"2\" style=\"text-align: left\">Line %Ld kb/s</td>",line
);
1154 fprintf(f
,"<th style=\"text-align: right\">%d</td><th style=\"text-align: right\">%d kb/s</td>",total
,i
);
1156 for_each(keyword
, keywords
) if(keyword
->ip_count
)
1158 fprintf(f
,"<th style=\"text-align: right\">%d IPs</th>",keyword
->ip_count
);
1160 fprintf(f
,"</tr><tr><th colspan=\"4\">Aggregation 1/%d</th>\n", (int)(0.5+i
/line
));
1161 fprintf(f
,"<th colspan=\"%d\">%d traffic classes</th></tr>\n", keywordcount
, total
);
1163 fputs("</thead></table>\n",f
);
1165 else if(!dry_run
&& !just_flush
)
1173 unsigned long long total_traffic
=0, total_direct
=0, total_proxy
=0, total_upload
=0, tmp_sum
=0;
1174 int active_classes
=0;
1176 struct Sum
{unsigned long long l
; int i
; list(Sum
);} *sum
,*sums
=NULL
;
1177 int limit_count
=0, prio_count
=0;
1185 fprintf(f
,"<p><table class=\"decorated last\">\n<caption>%s",title
);
1186 fprintf(f
," (%s)</caption>\n", d
);
1187 fputs("<thead><tr>\n<th colspan=\"3\"> </th>\n",f
);
1188 fputs("<th style=\"text-align: right\">credit</th>\n\
1189 <th style=\"text-align: right\">FUP</th>\n\
1190 <th style=\"text-align: right\">total</th>\n\
1191 <th style=\"text-align: right\">down</th>\n",f
);
1194 fputs("<th style=\"text-align: right\">proxy</th>\n",f
);
1196 fputs("<th style=\"text-align: right\">up</th>\n\
1197 <th style=\"text-align: right\">min</th>\n\
1198 <th style=\"text-align: right\">max</th>\n\
1199 <th style=\"text-align: right\">limit</th>\n\
1202 <th style=\"text-align: right\">#</th>\n\
1203 <th>hostname [+sharing]</th>\n\
1204 <th style=\"text-align: right\">LMS</th>\n\
1205 <th style=\"text-align: right\">MB</th>\n\
1206 <th style=\"text-align: right\">MB</th>\n\
1207 <th style=\"text-align: right\">MB</th>\n\
1208 <th style=\"text-align: right\">MB</th>\n\
1209 <th style=\"text-align: right\">MB</th>\n\
1210 <th style=\"text-align: right\">kb/s</th>\n\
1211 <th style=\"text-align: right\">kb/s</th>\n\
1212 <th style=\"text-align: right\">kb/s</th>\n\
1214 </tr></thead><tbody>\n",f
);
1217 for_each(ip
,ips
) if(!use_jquery_popups
|| !ip
->sharing
)
1219 char *f1
="", *f2
="";
1222 if(ip
->max
< ip
->desired
)
1224 f1
="<span style=\"color:red\">";
1228 else if(ip
->prio
> highest_priority
+1)
1230 f1
="<span style=\"color:brown\">";
1236 printf("%03d. %-22s %10Lu (%d/%d)\n",i
,ip
->name
, ip
->traffic
, ip
->min
, ip
->max
);
1238 /* hostnames -------------------------------------- */
1239 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",
1240 tr_odd_even(), ip
->name
, i
, log_url
, ip
->name
, ip
->name
);
1242 if(use_jquery_popups
)
1244 fprintf(f
,"<span id=\"sharing_%d\" style=\"display:none\">",i
);
1246 for_each(sharedip
, ips
) if(eq(ip
->name
, sharedip
->sharing
))
1248 fprintf(f
,"<br /><a class=\"blue\" target=\"_blank\" href=\"%s%s.log\">%s</a>\n", log_url
, sharedip
->name
, sharedip
->name
);
1251 fputs("</span>\n",f
);
1254 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>",
1255 i
, i
, i
, popup_button
);
1259 /* ----------------------------------------------- */
1263 fputs("<td style=\"text-align: right\">",f
);
1266 fprintf(f
,"<a class=\"blue\" target=\"_blank\" href=\"%s%d\">%04d</a>\n", lms_url
, ip
->lmsid
, ip
->lmsid
);
1268 else if(ip
->lmsid
== 0)
1274 fprintf(f
,"<td style=\"text-align: right\">%Lu</td>\n", ip
->credit
);
1275 fprintf(f
,"<td style=\"text-align: right\"><span style=\"color:#%s\">%Lu</span></td>",
1276 ip
->keyword
->html_color
,
1277 ip
->credit
+(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20)));
1278 fprintf(f
,"<td style=\"text-align: right\">%s%Lu%s", f1
, ip
->traffic
, f2
);
1280 /* download --------------------------------------- */
1281 fprintf(f
,"</td><td style=\"text-align: right\">%Lu", ip
->direct
);
1282 if(use_jquery_popups
)
1284 fprintf(f
,"<span id=\"download_%d\" style=\"display:none\">",i
);
1285 for_each(sharedip
, ips
) if(eq(ip
->name
, sharedip
->sharing
))
1287 fprintf(f
,"<br />%Lu", sharedip
->direct
);
1289 fputs("</span>\n",f
);
1292 /* ----------------------------------------------- */
1296 fprintf(f
,"<td style=\"text-align: right\">%Lu</td>\n", ip
->proxy
);
1298 /* upload ---------------------------------------- */
1299 fprintf(f
,"<td style=\"text-align: right\">%Lu", ip
->upload
);
1300 if(use_jquery_popups
)
1302 fprintf(f
,"<span id=\"upload_%d\" style=\"display:none\">",i
);
1303 for_each(sharedip
,ips
) if(eq(ip
->name
, sharedip
->sharing
))
1305 fprintf(f
,"<br />%Lu", sharedip
->upload
);
1307 fputs("</span>\n",f
);
1310 /* ----------------------------------------------- */
1312 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1313 <td style=\"text-align: right\">%d</td>\n\
1314 <td style=\"text-align: right\">%s%d%s</td>\n\
1315 <td>%s%d%s</td></tr>\n",
1316 ip
->min
, ip
->desired
,
1320 total_traffic
+=ip
->traffic
;
1321 total_direct
+=ip
->direct
;
1322 total_proxy
+=ip
->proxy
;
1323 total_upload
+=ip
->upload
;
1327 tmp_sum
+=ip
->traffic
;
1330 sum
->i
=active_classes
;
1331 insert(sum
,sums
,order_by
,i
);
1337 for_each(sharedip
,ips
) if(eq(ip
->name
, sharedip
->sharing
))
1339 append_log(sharedip
);
1343 fprintf(f
,"</tbody><thead><tr>\n\
1344 <th colspan=\"%d\" style=\"text-align: left\">%d CLASSES</th>", colspan
-7, i
);
1345 fprintf(f
,"<th style=\"text-align: right\">%Lu</th><th style=\"text-align: right\">%Lu</th>\n", total_traffic
, total_direct
);
1348 fprintf(f
,"<th style=\"text-align: right\">%Lu</th>\n", total_proxy
);
1350 fprintf(f
,"<th style=\"text-align: right\">%Lu</th>", total_upload
);
1351 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
);
1354 if(active_classes
>10)
1356 int top20_count
=0,top20_perc1
=0;
1357 long long top20_perc2
=0;
1358 unsigned long long top20_sum
=0l;
1360 fputs("<a name=\"erp\"></a><p><table class=\"decorated last\"><caption>Enterprise Resource Planning (ERP)</caption>\n",f
);
1361 fputs("<thead><tr>\n\
1362 <th>Analytic category</th>\n\
1363 <th colspan=\"2\" style=\"text-align: center\">Active Classes</th>\n\
1364 <th colspan=\"2\" style=\"text-align: center\">Data transfers</th>\n\
1365 </tr></thead><tbody>\n",f
);
1367 if_exists(sum
,sums
,sum
->l
>=total_traffic
/4)
1369 fprintf(f
,"%s<td>Top 25%% of traffic</td>\n", tr_odd_even());
1370 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1371 <td style=\"text-align: right\">%d %%</td>\n\
1372 <td style=\"text-align: right\">%Lu MB</td>\n\
1373 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1374 sum
->i
, (100*sum
->i
+50)/active_classes
, sum
->l
, (100*sum
->l
+50)/total_traffic
);
1377 if_exists(sum
,sums
,sum
->i
==10)
1379 fprintf(f
,"%s<td>Top 10 downloaders</td>\n", tr_odd_even());
1380 fprintf(f
,"<td style=\"text-align: right\"><strong>10</strong></td>\n\
1381 <td style=\"text-align: right\">%d %%</td>\n\
1382 <td style=\"text-align: right\">%Lu MB</td>\n\
1383 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1384 (100*sum
->i
+50)/active_classes
, sum
->l
, (100*sum
->l
+50)/total_traffic
);
1387 if_exists(sum
,sums
,sum
->l
>=total_traffic
/2)
1389 fprintf(f
,"%s<td>Top 50%% of traffic</td>\n", tr_odd_even());
1390 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1391 <td style=\"text-align: right\">%d %%</td>\n\
1392 <td style=\"text-align: right\">%Lu MB</td>\n\
1393 <td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",
1394 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1397 if_exists(sum
,sums
,sum
->l
>=4*total_traffic
/5)
1399 fprintf(f
,"%s<td>Top 80%% of traffic</td>\n", tr_odd_even());
1400 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1401 <td style=\"text-align: right\">%d %%</td>\n\
1402 <td style=\"text-align: right\">%Lu MB</td>\n\
1403 <td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",
1404 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1407 if_exists(sum
,sums
,sum
->i
>=(active_classes
+1)/5)
1409 fprintf(f
,"%s<td>Top 20%% downloaders</td>\n", tr_odd_even());
1411 top20_perc1
=(100*sum
->i
+50)/active_classes
;
1413 top20_perc2
=(100*sum
->l
+50)/total_traffic
;
1414 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1415 <td style=\"text-align: right\"><strong>%d %%</strong></td>\n\
1416 <td style=\"text-align: right\">%Lu MB</td>\n\
1417 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1418 top20_count
,top20_perc1
,top20_sum
,top20_perc2
);
1421 if_exists(sum
,sums
,sum
->i
>=(active_classes
+1)/4)
1423 fprintf(f
,"%s<td>Top 25%% downloaders</td>\n", tr_odd_even());
1424 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1425 <td style=\"text-align: right\">%d %%</td>\n\
1426 <td style=\"text-align: right\">%Lu MB</td>\n\
1427 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1428 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1431 if_exists(sum
,sums
,sum
->i
>=(active_classes
+1)/2)
1433 fprintf(f
,"%s<td>Top 50%% downloaders</td>\n", tr_odd_even());
1434 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1435 <td style=\"text-align: right\"><strong>%d %%</strong></td>\n\
1436 <td style=\"text-align: right\">%Lu MB</td>\n\
1437 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1438 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1441 if_exists(sum
,sums
,sum
->i
>=4*(active_classes
+1)/5)
1443 fprintf(f
,"%s<td>Top 80%% downloaders</td>\n", tr_odd_even());
1444 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1445 <td style=\"text-align: right\">%d %%</td>\n\
1446 <td style=\"text-align: right\">%Lu MB</td>\n\
1447 <td style=\"text-align: right\">%Ld %%</td></tr></tbody>\n",
1448 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1451 fprintf(f
,"<thead><tr><th><a class=\"blue\" target=\"_blank\" href=\"%sERP.log\">All users, all traffic</a></th>\n", log_url
);
1452 fprintf(f
,"<th style=\"text-align: right\">%d</th>\n\
1453 <th style=\"text-align: right\">100 %%</th>\n\
1454 <th style=\"text-align: right\">%Lu MB</th>\n\
1455 <th style=\"text-align: right\">100 %%</th></tr>\n",active_classes
,total_traffic
);
1456 fputs("</thead></table>\n", f
);
1458 /* write basic ERP data to log directory */
1462 sprintf(str
,"%s/ERP.log",log_dir
);
1463 iplog
=fopen(str
,"a");
1466 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",
1467 time(NULL
), top20_count
, top20_perc1
, top20_sum
, top20_perc2
,
1468 active_classes
, total_traffic
, i
, limit_count
, prio_count
, d
); /* d = date*/
1478 fprintf(f
, stats_html_signature
, version
);
1489 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar
);
1495 printf("%-22s %-15s mark\n","name","ip");
1498 printf("Writing %s ... ", classmap
);
1499 f
= fopen(classmap
, "w");
1505 /*-----------------------------------------------------------------*/
1506 puts("Generating iptables and tc classes ... ");
1507 /*-----------------------------------------------------------------*/
1509 for_each(ip
, ips
) if(ip
->mark
> 0)
1514 duplicate(ip
->addr
,buf
);
1515 buf
=index_id(ip
->addr
,32-idxtable_bitmask1
);
1517 string(chain_forward
,6+strlen(buf
));
1518 strcpy(chain_forward
,"forw_");
1519 strcat(chain_forward
,buf
);
1521 string(chain_postrouting
,6+strlen(buf
));
1522 strcpy(chain_postrouting
,"post_");
1523 strcat(chain_postrouting
,buf
);
1529 chain_forward
="FORWARD";
1530 chain_postrouting
="POSTROUTING";
1534 printf("%-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
1537 /* -------------------------------------------------------- mark download */
1539 sprintf(str
, "-A %s -d %s/32 -o %s -j %s%d",
1540 chain_postrouting
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
1541 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/
1542 /* -m limit --limit 1/s */
1547 sprintf(str
, "-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",
1548 chain_postrouting
, proxy_ip
, proxy_port
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
1549 /*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);*/
1553 sprintf(str
, "-A %s -d %s/32 -o %s -j ACCEPT",
1554 chain_postrouting
, ip
->addr
, lan
);
1557 /* -------------------------------------------------------- mark upload */
1558 sprintf(str
, "-A %s -s %s/32 -o %s -j %s%d",
1559 chain_forward
, ip
->addr
, wan
, mark_iptables
, ip
->mark
);
1560 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/
1563 sprintf(str
, "-A %s -s %s/32 -o %s -j ACCEPT",
1564 chain_forward
, ip
->addr
, wan
);
1569 /* -------------------------------------------------------- download class */
1571 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
1574 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1575 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1578 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1580 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1581 tc
, lan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1585 if(filter_type
== 1)
1587 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1588 tc
, lan
, ip
->mark
, ip
->mark
);
1592 /* -------------------------------------------------------- upload class */
1594 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1595 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1598 sprintf(str
,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1599 tc
, wan
, ip
->group
, ip
->mark
,
1600 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1601 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1604 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1606 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1607 tc
, wan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1611 if(filter_type
== 1)
1613 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1614 tc
, wan
, ip
->mark
, ip
->mark
);
1620 fprintf(f
, "%s %d\n", ip
->addr
, ip
->mark
);
1626 printf("(sharing %s)\n", ip
->sharing
);
1639 chain_forward
= "forw_common";
1640 chain_postrouting
= "post_common";
1644 chain_forward
= "FORWARD";
1645 chain_postrouting
= "POSTROUTING";
1647 /* -------------------------------- classify or reject free download */
1649 char *final_chain
= "DROP"; /* REJECT would be better, but it is impossible in mangle */
1652 final_chain
= "ACCEPT";
1658 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s%d",
1659 chain_postrouting
,proxy_ip
,proxy_port
,lan
,mark_iptables
,3);
1662 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s",
1663 chain_postrouting
,proxy_ip
,proxy_port
,lan
,final_chain
);
1668 sprintf(str
,"-A %s -o %s -j %s%d", chain_postrouting
, lan
, mark_iptables
, 3);
1671 sprintf(str
,"-A %s -o %s -j %s", chain_postrouting
, lan
, final_chain
);
1673 /* ------------------------------- classify or reject free upload */
1676 sprintf(str
,"-A %s -o %s -j %s%d", chain_forward
, wan
, mark_iptables
, 3);
1679 sprintf(str
,"-A %s -o %s -j %s", chain_forward
, wan
, final_chain
);
1683 if(free_min
) /* allocate free bandwith if it is not zero... */
1685 /*-----------------------------------------------------------------*/
1686 puts("Generating free bandwith classes ...");
1687 /*-----------------------------------------------------------------*/
1688 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1689 tc
, lan
, parent
, free_min
, free_max
,burst
, lowest_priority
);
1691 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1692 tc
, wan
, parent
, free_min
, free_max
, burst
, lowest_priority
);
1695 if(strcmpi(qos_leaf
, "none"))
1697 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, lan
, qos_leaf
);
1700 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, wan
, qos_leaf
);
1703 /* tc handle 1 fw flowid */
1704 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, lan
);
1707 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, wan
);
1710 printf("Total IP count: %d\n", i
);
1717 /* that's all folks, thank you for reading it all the way up to this point ;-) */
1718 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */
This page took 1.202122 seconds and 4 git commands to generate.