beaffcb78b2b4266e82ff7a14dbce57b312a0b8e
1 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2 /* Prometheus QoS - you can "steal fire" from your ISP */
3 /* "fair-per-IP" quality of service (QoS) utility */
4 /* requires Linux 2.4.x or 2.6.x with HTB support */
5 /* Copyright(C) 2005-2012 Michael Polak, Arachne Labs */
6 /* iptables-restore support Copyright(C) 2007-2008 ludva */
7 /* Credit: CZFree.Net,Martin Devera,Netdave,Aquarius,Gandalf */
8 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
10 /* Modified by: xChaos, 20121011
13 Prometheus QoS is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2.1 of
16 the License, or (at your option) any later version.
18 Prometheus QoS is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with Prometheus Qos; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 GNU General Public License is located in file COPYING */
32 #include "cll1-0.6.2.h"
35 const char *version
= "0.8.3-g";
37 /* Version numbers: 0.8.3 is development releases ("beta"), 0.8.4 will be "stable" */
38 /* Debian(RPM) package versions/patchlevels: 0.7.9-2, 0.8.0-1, 0.8.0-2, etc. */
39 /* C source code development versions ("beta"): 0.7.9-a, 0.8.1-b, etc. */
40 /* C source code release versions: 0.8.0, 0.8.2, 0.8.4, etc. */
42 const char *stats_html_signature
= "<span class=\"small\">Statistics generated by Prometheus QoS version %s<br />GPL+Copyright(C)2005-2012 Michael Polak, <a target=\"_blank\" href=\"http://www.arachne.cz/\">Arachne Labs</a></span>\n";
44 /* ======= Help screen is hopefuly self-documenting part of code :-) ======= */
48 puts("Command line switches:\n\
50 -d Dry run (preview tc and iptables commands on stdout)\n\
51 -r Run (reset all statistics and start shaping - daily usage)\n\
52 -p just generate Preview of data transfer statistics and exit (after -r)\n\
53 -s start Shaping FUP limits (keeps data transfer stat like -p) (after -r)\n\
54 -n run Now (like -r delay - overrides qos-free-delay keyword, after boot)\n\
55 -f just Flush iptables and tc classes and exit (stop shaping, no QiS)\n\
56 -9 emergency iptables flush (like -f, but dumps data transfer statistics)\n\
58 -c filename force alternative /etc/prometheus/prometheus.conf filename\n\
59 -h filename force alternative /etc/hosts filename (overrides hosts keyword)\n\
60 -l Mmm YYYY generate HTML summary of Logged traffic (Mmm=Jan-Dec) (and exit)\n\
61 -m generate HTML summary of traffic for yesterday's Month (and exit)\n\
62 -y generate HTML summary of traffic for yesterday's Year (and exit)\n\
63 -? --help show this help scree (and exit)\n\
64 -v --version show Version number of this utility (and exit)\n");
67 /* ======= All path names are defined here (for RPM patch) ======= */
69 const char *tc
= "/sbin/tc"; /* requires tc with HTB support */
70 const char *iptables
= "/sbin/iptables"; /* requires iptables utility */
71 const char *iptablessave
= "/sbin/iptables-save"; /* not yet required */
72 const char *iptablesrestore
= "/sbin/iptables-restore"; /* requires iptables-restore */
73 const char *ls
= "/bin/ls"; /* this is not user configurable :-) */
75 char *config
= "/etc/prometheus/prometheus.conf"; /* main configuration file */
76 char *hosts
= "/etc/prometheus/hosts"; /* per-IP bandwidth definition file */
78 char *iptablesfile
= "/var/spool/prometheus.iptables"; /* temporary file for iptables-restore*/
79 char *credit
= "/var/lib/misc/prometheus.credit"; /* credit log file */
80 char *classmap
= "/var/lib/misc/prometheus.classes"; /* credit log file */
81 char *html
= "/var/www/traffic.html"; /* hall of fame - html version */
82 char *preview
= "/var/www/preview.html"; /* hall of fame preview - html version */
83 char *json
= "/var/www/logs/traffic.json"; /* hall of fame - json version */
84 char *json_preview
= "/var/www/logs/preview.json"; /* hall of fame preview - json version */
85 char *cmdlog
= "/var/log/prometheuslog"; /* command log filename */
86 char *log_dir
= "/var/www/logs/"; /* log directory pathname, ended with slash */
87 char *log_url
= "/logs/"; /* log directory relative URI prefix (partial URL) */
88 char *html_log_dir
= "/var/www/logs/html/";
90 char *jquery_url
= "http://code.jquery.com/jquery-latest.js";
91 char *lms_url
= "/lms/?m=customerinfo&id=";
92 int use_jquery_popups
= 1;
93 int row_odd_even
= 0; /*<tr class="odd/even"> */
95 /* === Configuraration file values defaults - stored in global variables ==== */
97 int filter_type
= 1; /*1 mark, 2 classify*/
99 char *mark_iptables
= "MARK --set-mark ";
100 int dry_run
= 0; /* preview - use puts() instead of system() */
101 char *iptablespreamble
= "*mangle\n:PREROUTING ACCEPT [0:0]\n:POSTROUTING ACCEPT [0:0]\n:INPUT ACCEPT [0:0]\n:OUTPUT ACCEPT [0:0]\n:FORWARD ACCEPT [0:0]";
102 FILE *iptables_file
= NULL
;
103 int enable_credit
= 1; /* enable credit file */
104 int use_credit
= 0; /* use credit file (if enabled)*/
105 char *title
= "Hall of Fame - Greatest Suckers"; /* hall of fame title */
106 int hall_of_fame
= 1; /* enable hall of fame */
107 char *lan
= "eth0"; /* LAN interface */
108 char *lan_medium
= "100Mbit"; /* 10Mbit/100Mbit ethernet */
109 char *wan
= "eth1"; /* WAN/ISP interface */
110 char *wan_medium
= "100Mbit"; /* 10Mbit/100Mbit ethernet */
111 char *qos_leaf
= "sfq perturb 5"; /* leaf discipline */
112 char *qos_free_zone
= NULL
; /* QoS free zone */
113 int qos_proxy
= 1; /* include proxy port to QoS */
114 int found_lmsid
= 0; /* show links to users in LMS information system */
115 int include_upload
= 1; /* upload+download=total traffic */
116 char *proxy_ip
= "192.168.1.1/32"; /* our IP with proxy port */
117 int proxy_port
= 3128; /* proxy port number */
118 long long int line
= 1024; /* WAN/ISP download in kbps */
119 long long int up
= 1024; /* WAN/ISP upload in kbps */
120 int free_min
= 32; /* minimum guaranted bandwidth for all undefined hosts */
121 int free_max
= 64; /* maximum allowed bandwidth for all undefined hosts */
122 int qos_free_delay
= 0; /* seconds to sleep before applying new QoS rules */
123 int digital_divide
= 2; /* controls digital divide weirdness ratio, 1...3 */
124 int max_nesting
= 3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */
125 int htb_r2q
= 256; /* should work for leaf values 512 kbps to 8 Mbps */
126 int burst
= 8; /* HTB burst (in kbits) */
128 int burst_group
= 32;
129 int magic_treshold
= 8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */
130 int keywordcount
= 0;
133 /* not yet implemented:
134 int fixed_packets = 0; maximum number of pps per IP address (not class!)
135 int packet_limit = 5; maximum number of pps to htn CEIL, not rate !!!
137 FILE *log_file
= NULL
;
138 char *kwd
= "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */
140 const int highest_priority
= 0; /* highest HTB priority (HTB built-in value is 0) */
141 const int lowest_priority
= 7; /* lowest HTB priority (HTB built-in value is 7) */
142 const int idxtable_treshold1
= 24; /* this is no longer configurable */
143 const int idxtable_treshold2
= 12; /* this is no longer configurable */
144 const int idxtable_bitmask1
= 3; /* this is no longer configurable */
145 const int idxtable_bitmask2
= 3; /* this is no longer configurable */
147 struct IP
*ips
= NULL
, *ip
, *sharedip
;
148 struct Group
*groups
= NULL
, *group
;
149 struct Keyword
*keyword
, *defaultkeyword
=NULL
, *keywords
=NULL
;
151 void parse_ip_log(int argc
, char **argv
);
152 /* implementid in parselog.c */
154 void parse_hosts(char *hosts
);
155 /* implementid in parsehosts.c */
157 const char *tr_odd_even(void)
159 row_odd_even
= 1 - row_odd_even
;
162 return "<tr class=\"even\">\n";
166 return "<tr class=\"odd\">\n";
170 /* ==== This is C<<1 stuff - learn C<<1 first! https://dev.arachne.cz/svn/cll1h ==== */
176 struct Index
*parent
;
180 } *idxs
=NULL
, *idx
, *metaindex
;
183 /* function implemented in parsehosts.c */
185 /* ====== iptables indexes are used to reduce complexity to log8(N) ===== */
187 char *index_id(char *ip
, int bitmask
);
188 /* function implemented in ipv4subnets.c */
190 char *subnet_id(char *ip
, int bitmask
);
191 /* function implemented in ipv4subnets.c */
193 /* ================= Let's parse configuration file here ================ */
195 void reject_config_and_exit(char *filename
)
197 printf("Configuration file %s rejected - abnormal exit.",filename
);
201 void get_config(char *config_filename
)
205 printf("Configured keywords: ");
206 parse(config_filename
)
208 option("keyword",kwd
);
213 create(keyword
,Keyword
);
215 keyword
->asymetry_ratio
=1; /* ratio for ADSL-like upload */
216 keyword
->asymetry_fixed
=0; /* fixed treshold for ADSL-like upload */
217 keyword
->data_limit
=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */
218 keyword
->data_prio
=4; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */
219 keyword
->fixed_limit
=0; /* fixed data limit for setting lower HTB ceil */
220 keyword
->fixed_prio
=0; /* fixed data limit for setting lower HTB prio */
221 keyword
->reserve_min
=8; /* bonus for nominal HTB rate bandwidth (in kbps) */
222 keyword
->reserve_max
=0; /* malus for nominal HTB ceil (in kbps) */
223 keyword
->default_prio
=highest_priority
+1;
224 keyword
->html_color
="000000";
226 keyword
->leaf_discipline
="";
228 push(keyword
,keywords
);
229 if(!defaultkeyword
) defaultkeyword
=keyword
;
236 for_each(keyword
,keywords
)
238 int l
=strlen(keyword
->key
);
240 if(!strncmp(keyword
->key
,_
,l
) && strlen(_
)>l
+2)
242 char *tmptr
=_
; /* <---- l+1 ----> */
243 _
+=l
+1; /* via-prometheus-asymetry-ratio, etc. */
244 ioption("asymetry-ratio",keyword
->asymetry_ratio
);
245 ioption("asymetry-treshold",keyword
->asymetry_fixed
);
246 ioption("magic-relative-limit",keyword
->data_limit
);
247 ioption("magic-relative-prio",keyword
->data_prio
);
248 loption("magic-fixed-limit",keyword
->fixed_limit
);
249 loption("magic-fixed-prio",keyword
->fixed_prio
);
250 ioption("htb-default-prio",keyword
->default_prio
);
251 ioption("htb-rate-bonus",keyword
->reserve_min
);
252 ioption("htb-ceil-malus",keyword
->reserve_max
);
253 option("leaf-discipline",keyword
->leaf_discipline
);
254 option("html-color",keyword
->html_color
);
257 if(keyword
->data_limit
|| keyword
->fixed_limit
||
258 keyword
->data_prio
|| keyword
->fixed_prio
)
267 option("iptables",iptables
);
268 option("iptables-save",iptablessave
); /* new */
269 option("iptables-restore",iptablesrestore
); /* new */
270 option("iptables-in-filename",iptablesfile
); /* new */
271 option("hosts",hosts
);
272 option("lan-interface",lan
);
273 option("wan-interface",wan
);
274 option("lan-medium",lan_medium
);
275 option("wan-medium",wan_medium
);
276 lloption("wan-download",line
);
277 lloption("wan-upload",up
);
278 ioption("hall-of-fame-enable",hall_of_fame
);
279 option("hall-of-fame-title",title
);
280 option("hall-of-fame-filename",html
);
281 option("json-filename",json
);
282 option("hall-of-fame-preview",preview
);
283 option("json-preview",json_preview
);
284 option("log-filename",cmdlog
);
285 option("credit-filename",credit
);
286 option("classmap-filename",classmap
);
287 ioption("credit-enable",enable_credit
);
288 option("log-traffic-directory",log_dir
);
289 option("log-traffic-html-directory",html_log_dir
);
290 option("log-traffic-url-path",log_url
);
291 option("jquery-url",jquery_url
);
292 option("lms-url",lms_url
);
293 ioption("use-jquery-popups",use_jquery_popups
);
294 option("qos-free-zone",qos_free_zone
);
295 ioption("qos-free-delay",qos_free_delay
);
296 ioption("qos-proxy-enable",qos_proxy
);
297 option("qos-proxy-ip",proxy_ip
);
298 option("htb-leaf-discipline",qos_leaf
);
299 ioption("qos-proxy-port",proxy_port
);
300 ioption("free-rate",free_min
);
301 ioption("free-ceil",free_max
);
302 ioption("htb-burst",burst
);
303 ioption("htb-burst-main",burst_main
);
304 ioption("htb-burst-group",burst_group
);
305 ioption("htb-nesting-limit",max_nesting
);
306 ioption("htb-r2q",htb_r2q
);
307 ioption("magic-include-upload",include_upload
);
308 ioption("magic-treshold",magic_treshold
);
309 option("filter-type", cnf
);
310 /* not yet implemented:
311 ioption("magic-fixed-packets",fixed_packets);
312 ioption("magic-relative-packets",packet_limit);
317 perror(config_filename
);
318 puts("Warning - using built-in defaults instead ...");
320 done
; /* ugly macro end */
323 /* leaf discipline for keywords */
324 for_each(keyword
,keywords
)
326 if(!strcmpi(keyword
->leaf_discipline
, ""))
328 keyword
->leaf_discipline
= qos_leaf
;
332 if(strcmpi(cnf
, "mark"))
336 mark_iptables
= "CLASSIFY --set-class 1:";
342 mark_iptables
= "MARK --set-mark ";
345 /* are supplied values meaningful ?*/
348 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");
349 reject_config_and_exit(config_filename
);
353 /* ===================== traffic analyser - uses iptables ================ */
355 void get_traffic_statistics(void)
360 textfile(Pipe
,str
) *line
,*lines
=NULL
;
364 sprintf(cmd
,"%s -L -v -x -n -t mangle",iptables
);
376 int col
, accept
=0,proxyflag
=0,valid
=1,setchainname
=0,commonflag
=0;
377 unsigned long long traffic
=0;
378 unsigned long pkts
=0;
379 char *ipaddr
=NULL
,*ptr
;
381 /* debug puts(line->str); */
382 valid_columns(ptr
,line
->str
,' ',col
)
383 if(valid
) switch(col
)
385 case 1: if(eq(ptr
,"Chain"))
389 else if(eq(ptr
,"pkts"))
395 sscanf(ptr
,"%lu",&pkts
);
398 case 2: if(setchainname
)
400 if(!strncmp(ptr
,"post_",5) || eq(ptr
,"POSTROUTING"))
406 if(!strncmp(ptr
,"forw_",5) || eq(ptr
,"FORWARD"))
411 if(eq(ptr
,"post_common") || eq(ptr
,"forw_common"))
418 sscanf(ptr
,"%Lu",&traffic
);
423 case 3: if((strncmp(ptr
,"post_",5) && strncmp(ptr
,"forw_",5)) || commonflag
)
427 /*if(filter_type==1) accept=eq(ptr,"MARK"); else accept=eq(ptr,"CLASSIFY");*/
429 case 8: if(downloadflag
)
431 if(strstr(proxy_ip
,ptr
))
441 case 9: if(downloadflag
)ipaddr
=ptr
;break;
444 if(accept
&& traffic
>0 && ipaddr
)
450 else if(!downloadflag
)
454 printf("IP %s: %Lu MB (%ld pkts)\n", ipaddr
, traffic
, pkts
);
456 if_exists(ip
,ips
,eq(ip
->addr
,ipaddr
));
461 if(eq(ip
->addr
,"0.0.0.0/0"))
463 ip
->name
="(unregistered)";
465 ip
->max
=ip
->desired
=free_max
;
477 ip
->traffic
+=traffic
;
479 ip
->direct
=ip
->traffic
-ip
->upload
-ip
->proxy
;
488 ip
->traffic
+=traffic
;
492 if(traffic
>ip
->traffic
)
503 /* ========== This function executes, logs OR ALSO prints command ========== */
505 void safe_run(char *cmd
)
509 printf("\n=>%s\n",cmd
);
517 fprintf(log_file
,"%s\n",cmd
);
521 void save_line(char *line
)
523 fprintf(iptables_file
,"%s\n",line
);
526 void run_restore(void)
529 string(restor
,STRLEN
);
531 /*-----------------------------------------------------------------*/
532 printf("Running %s <%s ...\n", iptablesrestore
, iptablesfile
);
533 /*-----------------------------------------------------------------*/
536 fclose(iptables_file
);
543 done
; /* ugly macro end */
546 sprintf(restor
,"%s <%s",iptablesrestore
, iptablesfile
);
552 char *parse_datafile_line(char *str
)
554 char *ptr
=strchr(str
,' ');
568 void append_log(struct IP
*self
) /*using global variables*/
573 date(d
); /* this is typical cll1.h macro - prints current date */
575 sprintf(str
,"%s/%s.log", log_dir
, self
->name
);
579 fprintf(f
,"%ld\t%s\t%Lu\t%Lu\t%Lu\t%Lu\t%d\t%d\t%d\t%d\t%s",
580 time(NULL
), self
->name
, self
->traffic
, self
->direct
, self
->proxy
,
581 self
->upload
, self
->min
, self
->max
, self
->desired
, self
->lmsid
, d
); /* d = date*/
590 /*-----------------------------------------------------------------*/
591 /* Are you looking for int main(int argc, char **argv) ? :-)) */
592 /*-----------------------------------------------------------------*/
596 int i
=0; /* just plain old Fortran style integer :-) */
597 FILE *f
=NULL
; /* everything is just stream of bytes... */
598 char *str
, *ptr
, *d
; /* LET A$=B$ :-) */
602 int just_flush
=FALSE
; /* deactivates all previous actions */
604 int just_preview
=FALSE
; /* preview - generate just stats */
605 int start_shaping
=FALSE
; /* apply FUP - requires classmap file */
606 int just_logs
=FALSE
; /* just parse logs */
610 char *chain_forward
, *chain_postrouting
;
614 Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\
615 Version %s - Copyright (C)2005-2012 Michael Polak, Arachne Labs\n\
616 iptables-restore & burst tunning & classify modification by Ludva\n\
617 Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version
);
619 /*----- Boring... we have to check command line options first: ----*/
622 argument("-c") { nextargument(config
); }
623 argument("-h") { nextargument(althosts
);}
624 argument("-d") { run
=TRUE
; dry_run
=TRUE
; }
625 argument("-f") { run
=TRUE
; just_flush
=TRUE
; }
626 argument("-9") { run
=TRUE
; just_flush
=9; }
627 argument("-p") { run
=TRUE
; just_preview
=TRUE
; }
628 argument("-s") { run
=TRUE
; just_preview
=TRUE
; start_shaping
=TRUE
; }
629 argument("-r") { run
=TRUE
; }
630 argument("-n") { run
=TRUE
; nodelay
=TRUE
; }
631 argument("-l") { just_logs
=TRUE
; }
632 argument("-m") { just_logs
=TRUE
; }
633 argument("-y") { just_logs
=TRUE
; }
634 argument("-?") { help(); exit(0); }
635 argument("--help") { help(); exit(0); }
636 argument("-v") { exit(0); }
637 argument("--version") { exit(0); }
642 puts("*** THIS IS JUST DRY RUN ! ***\n");
645 date(d
); /* this is typical cll1.h macro - prints current date */
647 /*-----------------------------------------------------------------*/
648 printf("Parsing configuration file %s ...\n", config
);
649 /*-----------------------------------------------------------------*/
654 parse_ip_log(argc
,argv
);
670 /*-----------------------------------------------------------------*/
671 puts("Parsing iptables verbose output ...");
672 /*-----------------------------------------------------------------*/
673 get_traffic_statistics();
676 /*-----------------------------------------------------------------*/
677 printf("Parsing class defintion file %s ...\n", hosts
);
678 /*-----------------------------------------------------------------*/
681 /*-----------------------------------------------------------------*/
682 /* cll1.h - let's allocate brand new character buffer... */
683 /*-----------------------------------------------------------------*/
686 /*-----------------------------------------------------------------*/
687 puts("Resolving shared connections ...");
688 /*-----------------------------------------------------------------*/
689 for_each(ip
,ips
) if(ip
->sharing
)
691 for_each(sharedip
,ips
) if(eq(sharedip
->name
,ip
->sharing
))
693 sharedip
->traffic
+=ip
->traffic
;
695 ip
->mark
=sharedip
->mark
;
696 ip
->lmsid
=sharedip
->lmsid
;
701 printf("Unresolved shared connection: %s %s sharing-%s\n",
702 ip
->addr
, ip
->name
, ip
->sharing
);
706 if(enable_credit
&& just_flush
<9)
708 /*-----------------------------------------------------------------*/
709 printf("Parsing credit file %s ...\n", credit
);
710 /*-----------------------------------------------------------------*/
713 ptr
=parse_datafile_line(_
);
716 if_exists(ip
,ips
,eq(ip
->addr
,_
))
718 sscanf(ptr
,"%Lu",&(ip
->credit
));
722 done
; /* ugly macro end */
727 /*-----------------------------------------------------------------*/
728 puts("Initializing iptables and tc classes ...");
729 /*-----------------------------------------------------------------*/
731 iptables_file
=fopen(iptablesfile
,"w");
732 if(iptables_file
== NULL
)
734 puts("Cannot open iptablesfile!");
738 log_file
=fopen(cmdlog
,"w");
741 puts("Cannot open logfile!");
745 save_line(iptablespreamble
);
748 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,lan
);
751 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,wan
);
754 iptables_file
=fopen(iptablesfile
,"w");
755 save_line(iptablespreamble
);
757 if(qos_free_zone
&& *qos_free_zone
!='0')
761 sprintf(str
,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone
, wan
);
766 save_line(":post_noproxy - [0:0]");
767 sprintf(str
,"-A POSTROUTING ! -p tcp -o %s -j post_noproxy", lan
);
769 sprintf(str
,"-A POSTROUTING ! -s %s -o %s -j post_noproxy", proxy_ip
, lan
);
771 sprintf(str
,"-A POSTROUTING -s %s -p tcp ! --sport %d -o %s -j post_noproxy", proxy_ip
, proxy_port
, lan
);
774 chain
="post_noproxy";
781 sprintf(str
,"-A %s -s %s -o %s -j ACCEPT", chain
, qos_free_zone
, lan
);
785 if(ip_count
>idxtable_treshold1
&& !just_flush
)
787 int idxcount
=0, bitmask
=32-idxtable_bitmask1
; /* default net mask: 255.255.255.240 */
789 /*-----------------------------------------------------------------*/
790 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count
);
791 /*-----------------------------------------------------------------*/
793 save_line(":post_common - [0:0]");
794 save_line(":forw_common - [0:0]");
796 for_each(ip
,ips
) if(ip
->addr
&& *(ip
->addr
) && !eq(ip
->addr
,"0.0.0.0/0"))
798 buf
=index_id(ip
->addr
,bitmask
);
799 if_exists(idx
,idxs
,eq(idx
->id
,buf
))
808 idx
->bitmask
=bitmask
;
816 /* brutal perfomance optimalization */
817 while(idxcount
>idxtable_treshold2
&& bitmask
>2*idxtable_bitmask2
)
819 bitmask
-=idxtable_bitmask2
;
822 for_each(idx
,idxs
) if(idx
->parent
== NULL
)
824 buf
=index_id(idx
->addr
,bitmask
);
825 if_exists(metaindex
,idxs
,eq(metaindex
->id
,buf
))
827 metaindex
->children
++;
831 create(metaindex
,Index
);
832 metaindex
->addr
=idx
->addr
;
834 metaindex
->bitmask
=bitmask
;
835 metaindex
->parent
=NULL
;
836 metaindex
->children
=0;
838 push(metaindex
,idxs
);
840 idx
->parent
=metaindex
;
844 /* this should slightly optimize throughout ... */
845 sort(idx
,idxs
,desc_order_by
,children
);
846 sort(idx
,idxs
,order_by
,bitmask
);
851 subnet
=subnet_id(idx
->addr
,idx
->bitmask
);
852 printf("%d: %s/%d\n",
853 ++i
, subnet
, idx
->bitmask
);
855 sprintf(str
,":post_%s - [0:0]", idx
->id
);
858 sprintf(str
,":forw_%s - [0:0]", idx
->id
);
863 string(buf
,strlen(idx
->parent
->id
)+6);
864 sprintf(buf
,"post_%s",idx
->parent
->id
);
871 sprintf(str
,"-A %s -d %s/%d -o %s -j post_%s", buf
, subnet
, idx
->bitmask
, lan
, idx
->id
);
874 sprintf(str
,"-A %s -d %s/%d -o %s -j post_common", buf
, subnet
, idx
->bitmask
, lan
);
879 string(buf
,strlen(idx
->parent
->id
)+6);
880 sprintf(buf
,"forw_%s",idx
->parent
->id
);
887 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_%s", buf
, subnet
, idx
->bitmask
, wan
, idx
->id
);
890 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_common", buf
, subnet
, idx
->bitmask
, wan
);
893 printf("Total indexed iptables chains created: %d\n", i
);
895 sprintf(str
,"-A FORWARD -o %s -j forw_common", wan
);
898 sprintf(str
,"-A POSTROUTING -o %s -j post_common", lan
);
906 fclose(iptables_file
);
911 puts("Just flushed iptables and tc classes - now exiting ...");
917 if(!dry_run
&& !nodelay
&& qos_free_delay
)
919 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay
);
920 sleep(qos_free_delay
);
923 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",
927 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
928 tc
,lan
,lan_medium
,lan_medium
,burst_main
,highest_priority
);
931 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
932 tc
,lan
,line
,line
,burst_main
,highest_priority
);
935 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc
,wan
,htb_r2q
);
938 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
939 tc
,wan
,wan_medium
,wan_medium
,burst_main
,highest_priority
);
942 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
943 tc
,wan
,up
,up
,burst_main
,highest_priority
);
947 /*-----------------------------------------------------------------*/
948 puts("Locating heavy downloaders and generating root classes ...");
949 /*-----------------------------------------------------------------*/
950 sort(ip
,ips
,desc_order_by
,traffic
);
952 /*-----------------------------------------------------------------*/
953 /* sub-scope - local variables */
955 long long int rate
= line
;
956 long long int max
= line
;
958 FILE *credit_file
= NULL
;
960 if(!just_preview
&& !dry_run
&& enable_credit
)
962 credit_file
= fopen(credit
,"w");
965 for_each(group
,groups
)
970 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",
971 tc
, lan
, parent
, group
->id
, rate
, max
, burst_group
, highest_priority
+1, group
->desired
);
975 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",
976 tc
, wan
, parent
, group
->id
, rate
*up
/line
, max
*up
/line
, burst_group
, highest_priority
+1, group
->desired
);
980 if(group_count
++ < max_nesting
)
985 rate
-= digital_divide
*group
->min
;
986 if(rate
< group
->min
)
991 /*shaping of aggresive downloaders, with credit file support */
994 int group_rate
= group
->min
, priority_sequence
= lowest_priority
;
996 for_each(ip
, ips
) if(ip
->min
== group
->min
&& ip
->max
> ip
->min
)
998 if( ip
->keyword
->data_limit
&& !ip
->fixedprio
999 && ( ip
->traffic
>ip
->credit
1000 + (ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))) )
1002 if(group_rate
<ip
->max
)
1006 group_rate
+=magic_treshold
;
1007 ip
->prio
=lowest_priority
;
1008 if(ip
->prio
<highest_priority
+2)
1010 ip
->prio
=highest_priority
+2;
1015 if( ip
->keyword
->data_prio
1017 && ( ip
->traffic
>ip
->credit
1018 + (ip
->min
*ip
->keyword
->data_prio
+(ip
->keyword
->fixed_prio
<<20))) )
1020 ip
->prio
=priority_sequence
--;
1021 if(ip
->prio
<highest_priority
+1)
1023 ip
->prio
=highest_priority
+1;
1029 unsigned long long lcredit
=0;
1031 if((ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))>ip
->traffic
)
1033 lcredit
=(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))-ip
->traffic
;
1035 fprintf(credit_file
,"%s %Lu\n",ip
->addr
,lcredit
);
1043 fclose(credit_file
);
1051 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap
);
1059 if_exists(ip
,ips
,eq(ip
->addr
,_
))
1062 if(ip
->max
< ip
->desired
) /* apply FUP limit immediately.... */
1064 printf("Applying limit for %-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
1065 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
1066 sprintf(str
, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1067 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1069 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1070 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1071 sprintf(str
,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1072 tc
, wan
, ip
->group
, ip
->mark
,
1073 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1074 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1083 puts("Warning - classmap file not fund, just generating preview ...");
1084 start_shaping
=FALSE
;
1086 done
; /* ugly macro end */
1092 if(!dry_run
&& !just_flush
)
1094 /*-----------------------------------------------------------------*/
1095 printf("Writing json overview %s ... ", json
);
1096 /*-----------------------------------------------------------------*/
1105 && (ip
->traffic
|| ip
->direct
|| ip
->proxy
|| ip
->upload
))
1111 fprintf(f
, " \"%s\":{ \"lms\": %d, \"ip\":\"%s\", \"total\":%Lu, \"down\":%Lu, \"proxy\":%Lu, \"up\":%Lu, \"min\":%d, \"max\":%d, \"limit\":%d }",
1112 ip
->name
, ip
->lmsid
, ip
->addr
, ip
->traffic
, ip
->direct
, ip
->proxy
, ip
->upload
, ip
->min
, ip
->desired
, ip
->max
);
1132 /*-----------------------------------------------------------------*/
1133 printf("Sorting data and generating statistics page %s ...\n", html
);
1134 /*-----------------------------------------------------------------*/
1136 if(use_jquery_popups
)
1138 fprintf(f
,"<script type=\"text/javascript\" src=\"%s\"></script>\n", jquery_url
);
1140 fputs("<table class=\"decorated last\">\n\
1141 <caption>Bandwidth classes</caption>\n\
1143 <th style=\"text-align: right\">#</th>\n\
1144 <th style=\"text-align: right\">group</th>\n\
1145 <th style=\"text-align: right\">IPs</th>\n\
1146 <th style=\"text-align: right\">requested</th>\n",f
);
1147 fprintf(f
,"<th colspan=\"%d\">data limits</th>\n", keywordcount
);
1148 fputs("</tr></thead><tbody>\n",f
);
1151 for_each(group
, groups
)
1154 printf("%d kb/s group: %d bandwidth requested: %d kb/s\n",group
->min
,group
->count
,group
->desired
);
1156 fprintf(f
, "%s<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d kb/s</td>",
1157 tr_odd_even(), count
, group
->min
);
1158 fprintf(f
, "<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d kb/s</td>",
1159 group
->count
, group
->desired
);
1161 for_each(keyword
, keywords
) if(keyword
->ip_count
)
1163 fprintf(f
,"<td style=\"text-align: right\"><span style=\"color:#%s\">%d MB</span></td>",
1164 keyword
->html_color
, group
->min
*keyword
->data_limit
);
1166 i
+= group
->desired
;
1167 total
+= group
->count
;
1171 printf("Total groups: %d Total bandwidth requested: %d kb/s\nAGGREGATION: 1/%d\n",
1174 fprintf(f
,"</tr></tbody>\n\
1176 <th colspan=\"2\" style=\"text-align: left\">Line %Ld kb/s</td>",line
);
1177 fprintf(f
,"<th style=\"text-align: right\">%d</td><th style=\"text-align: right\">%d kb/s</td>",total
,i
);
1179 for_each(keyword
, keywords
) if(keyword
->ip_count
)
1181 fprintf(f
,"<th style=\"text-align: right\">%d IPs</th>",keyword
->ip_count
);
1183 fprintf(f
,"</tr><tr><th colspan=\"4\">Aggregation 1/%d</th>\n", (int)(0.5+i
/line
));
1184 fprintf(f
,"<th colspan=\"%d\">%d traffic classes</th></tr>\n", keywordcount
, total
);
1186 fputs("</thead></table>\n",f
);
1188 else if(!dry_run
&& !just_flush
)
1196 unsigned long long total_traffic
=0, total_direct
=0, total_proxy
=0, total_upload
=0, tmp_sum
=0;
1197 int active_classes
=0;
1199 struct Sum
{unsigned long long l
; int i
; list(Sum
);} *sum
,*sums
=NULL
;
1200 int limit_count
=0, prio_count
=0;
1208 fprintf(f
,"<p><table class=\"decorated last\">\n<caption>%s",title
);
1209 fprintf(f
," (%s)</caption>\n", d
);
1210 fputs("<thead><tr>\n<th colspan=\"3\"> </th>\n",f
);
1211 fputs("<th style=\"text-align: right\">credit</th>\n\
1212 <th style=\"text-align: right\">FUP</th>\n\
1213 <th style=\"text-align: right\">total</th>\n\
1214 <th style=\"text-align: right\">down</th>\n",f
);
1217 fputs("<th style=\"text-align: right\">proxy</th>\n",f
);
1219 fputs("<th style=\"text-align: right\">up</th>\n\
1220 <th style=\"text-align: right\">min</th>\n\
1221 <th style=\"text-align: right\">max</th>\n\
1222 <th style=\"text-align: right\">limit</th>\n\
1225 <th style=\"text-align: right\">#</th>\n\
1226 <th>hostname [+sharing]</th>\n\
1227 <th style=\"text-align: right\">LMS</th>\n\
1228 <th style=\"text-align: right\">MB</th>\n\
1229 <th style=\"text-align: right\">MB</th>\n\
1230 <th style=\"text-align: right\">MB</th>\n\
1231 <th style=\"text-align: right\">MB</th>\n\
1232 <th style=\"text-align: right\">MB</th>\n\
1233 <th style=\"text-align: right\">kb/s</th>\n\
1234 <th style=\"text-align: right\">kb/s</th>\n\
1235 <th style=\"text-align: right\">kb/s</th>\n\
1237 </tr></thead><tbody>\n",f
);
1240 for_each(ip
,ips
) if(!use_jquery_popups
|| !ip
->sharing
)
1242 char *f1
="", *f2
="";
1245 if(ip
->max
< ip
->desired
)
1247 f1
="<span style=\"color:red\">";
1251 else if(ip
->prio
> highest_priority
+1)
1253 f1
="<span style=\"color:brown\">";
1259 printf("%03d. %-22s %10Lu (%d/%d)\n",i
,ip
->name
, ip
->traffic
, ip
->min
, ip
->max
);
1261 /* hostnames -------------------------------------- */
1262 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",
1263 tr_odd_even(), ip
->name
, i
, log_url
, ip
->name
, ip
->name
);
1265 if(use_jquery_popups
)
1267 fprintf(f
,"<span id=\"sharing_%d\" style=\"display:none\">",i
);
1269 for_each(sharedip
, ips
) if(eq(ip
->name
, sharedip
->sharing
))
1271 fprintf(f
,"<br /><a class=\"blue\" target=\"_blank\" href=\"%s%s.log\">%s</a>\n", log_url
, sharedip
->name
, sharedip
->name
);
1274 fputs("</span>\n",f
);
1277 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>",
1278 i
, i
, i
, popup_button
);
1282 /* ----------------------------------------------- */
1286 fputs("<td style=\"text-align: right\">",f
);
1289 fprintf(f
,"<a class=\"blue\" target=\"_blank\" href=\"%s%d\">%04d</a>\n", lms_url
, ip
->lmsid
, ip
->lmsid
);
1291 else if(ip
->lmsid
== 0)
1297 fprintf(f
,"<td style=\"text-align: right\">%Lu</td>\n", ip
->credit
);
1298 fprintf(f
,"<td style=\"text-align: right\"><span style=\"color:#%s\">%Lu</span></td>",
1299 ip
->keyword
->html_color
,
1300 ip
->credit
+(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20)));
1301 fprintf(f
,"<td style=\"text-align: right\">%s%Lu%s", f1
, ip
->traffic
, f2
);
1303 /* download --------------------------------------- */
1304 fprintf(f
,"</td><td style=\"text-align: right\">%Lu", ip
->direct
);
1305 if(use_jquery_popups
)
1307 fprintf(f
,"<span id=\"download_%d\" style=\"display:none\">",i
);
1308 for_each(sharedip
, ips
) if(eq(ip
->name
, sharedip
->sharing
))
1310 fprintf(f
,"<br />%Lu", sharedip
->direct
);
1312 fputs("</span>\n",f
);
1315 /* ----------------------------------------------- */
1319 fprintf(f
,"<td style=\"text-align: right\">%Lu</td>\n", ip
->proxy
);
1321 /* upload ---------------------------------------- */
1322 fprintf(f
,"<td style=\"text-align: right\">%Lu", ip
->upload
);
1323 if(use_jquery_popups
)
1325 fprintf(f
,"<span id=\"upload_%d\" style=\"display:none\">",i
);
1326 for_each(sharedip
,ips
) if(eq(ip
->name
, sharedip
->sharing
))
1328 fprintf(f
,"<br />%Lu", sharedip
->upload
);
1330 fputs("</span>\n",f
);
1333 /* ----------------------------------------------- */
1335 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1336 <td style=\"text-align: right\">%d</td>\n\
1337 <td style=\"text-align: right\">%s%d%s</td>\n\
1338 <td>%s%d%s</td></tr>\n",
1339 ip
->min
, ip
->desired
,
1343 total_traffic
+=ip
->traffic
;
1344 total_direct
+=ip
->direct
;
1345 total_proxy
+=ip
->proxy
;
1346 total_upload
+=ip
->upload
;
1350 tmp_sum
+=ip
->traffic
;
1353 sum
->i
=active_classes
;
1354 insert(sum
,sums
,order_by
,i
);
1360 for_each(sharedip
,ips
) if(eq(ip
->name
, sharedip
->sharing
))
1362 append_log(sharedip
);
1366 fprintf(f
,"</tbody><thead><tr>\n\
1367 <th colspan=\"%d\" style=\"text-align: left\">%d CLASSES</th>", colspan
-7, i
);
1368 fprintf(f
,"<th style=\"text-align: right\">%Lu</th><th style=\"text-align: right\">%Lu</th>\n", total_traffic
, total_direct
);
1371 fprintf(f
,"<th style=\"text-align: right\">%Lu</th>\n", total_proxy
);
1373 fprintf(f
,"<th style=\"text-align: right\">%Lu</th>", total_upload
);
1374 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
);
1377 if(active_classes
>10)
1379 int top20_count
=0,top20_perc1
=0;
1380 long long top20_perc2
=0;
1381 unsigned long long top20_sum
=0l;
1383 fputs("<a name=\"erp\"></a><p><table class=\"decorated last\"><caption>Enterprise Resource Planning (ERP)</caption>\n",f
);
1384 fputs("<thead><tr>\n\
1385 <th>Analytic category</th>\n\
1386 <th colspan=\"2\" style=\"text-align: center\">Active Classes</th>\n\
1387 <th colspan=\"2\" style=\"text-align: center\">Data transfers</th>\n\
1388 </tr></thead><tbody>\n",f
);
1390 if_exists(sum
,sums
,sum
->l
>=total_traffic
/4)
1392 fprintf(f
,"%s<td>Top 25%% of traffic</td>\n", tr_odd_even());
1393 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1394 <td style=\"text-align: right\">%d %%</td>\n\
1395 <td style=\"text-align: right\">%Lu MB</td>\n\
1396 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1397 sum
->i
, (100*sum
->i
+50)/active_classes
, sum
->l
, (100*sum
->l
+50)/total_traffic
);
1400 if_exists(sum
,sums
,sum
->i
==10)
1402 fprintf(f
,"%s<td>Top 10 downloaders</td>\n", tr_odd_even());
1403 fprintf(f
,"<td style=\"text-align: right\"><strong>10</strong></td>\n\
1404 <td style=\"text-align: right\">%d %%</td>\n\
1405 <td style=\"text-align: right\">%Lu MB</td>\n\
1406 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1407 (100*sum
->i
+50)/active_classes
, sum
->l
, (100*sum
->l
+50)/total_traffic
);
1410 if_exists(sum
,sums
,sum
->l
>=total_traffic
/2)
1412 fprintf(f
,"%s<td>Top 50%% of traffic</td>\n", tr_odd_even());
1413 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1414 <td style=\"text-align: right\">%d %%</td>\n\
1415 <td style=\"text-align: right\">%Lu MB</td>\n\
1416 <td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",
1417 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1420 if_exists(sum
,sums
,sum
->l
>=4*total_traffic
/5)
1422 fprintf(f
,"%s<td>Top 80%% of traffic</td>\n", tr_odd_even());
1423 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1424 <td style=\"text-align: right\">%d %%</td>\n\
1425 <td style=\"text-align: right\">%Lu MB</td>\n\
1426 <td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",
1427 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1430 if_exists(sum
,sums
,sum
->i
>=(active_classes
+1)/5)
1432 fprintf(f
,"%s<td>Top 20%% downloaders</td>\n", tr_odd_even());
1434 top20_perc1
=(100*sum
->i
+50)/active_classes
;
1436 top20_perc2
=(100*sum
->l
+50)/total_traffic
;
1437 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1438 <td style=\"text-align: right\"><strong>%d %%</strong></td>\n\
1439 <td style=\"text-align: right\">%Lu MB</td>\n\
1440 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1441 top20_count
,top20_perc1
,top20_sum
,top20_perc2
);
1444 if_exists(sum
,sums
,sum
->i
>=(active_classes
+1)/4)
1446 fprintf(f
,"%s<td>Top 25%% downloaders</td>\n", tr_odd_even());
1447 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1448 <td style=\"text-align: right\">%d %%</td>\n\
1449 <td style=\"text-align: right\">%Lu MB</td>\n\
1450 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1451 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1454 if_exists(sum
,sums
,sum
->i
>=(active_classes
+1)/2)
1456 fprintf(f
,"%s<td>Top 50%% downloaders</td>\n", tr_odd_even());
1457 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1458 <td style=\"text-align: right\"><strong>%d %%</strong></td>\n\
1459 <td style=\"text-align: right\">%Lu MB</td>\n\
1460 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1461 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1464 if_exists(sum
,sums
,sum
->i
>=4*(active_classes
+1)/5)
1466 fprintf(f
,"%s<td>Top 80%% downloaders</td>\n", tr_odd_even());
1467 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1468 <td style=\"text-align: right\">%d %%</td>\n\
1469 <td style=\"text-align: right\">%Lu MB</td>\n\
1470 <td style=\"text-align: right\">%Ld %%</td></tr></tbody>\n",
1471 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1474 fprintf(f
,"<thead><tr><th><a class=\"blue\" target=\"_blank\" href=\"%sERP.log\">All users, all traffic</a></th>\n", log_url
);
1475 fprintf(f
,"<th style=\"text-align: right\">%d</th>\n\
1476 <th style=\"text-align: right\">100 %%</th>\n\
1477 <th style=\"text-align: right\">%Lu MB</th>\n\
1478 <th style=\"text-align: right\">100 %%</th></tr>\n",active_classes
,total_traffic
);
1479 fputs("</thead></table>\n", f
);
1481 /* write basic ERP data to log directory */
1485 sprintf(str
,"%s/ERP.log",log_dir
);
1486 iplog
=fopen(str
,"a");
1489 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",
1490 time(NULL
), top20_count
, top20_perc1
, top20_sum
, top20_perc2
,
1491 active_classes
, total_traffic
, i
, limit_count
, prio_count
, d
); /* d = date*/
1501 fprintf(f
, stats_html_signature
, version
);
1512 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar
);
1518 printf("%-22s %-15s mark\n","name","ip");
1521 printf("Writing %s ... ", classmap
);
1522 f
= fopen(classmap
, "w");
1528 /*-----------------------------------------------------------------*/
1529 puts("Generating iptables and tc classes ... ");
1530 /*-----------------------------------------------------------------*/
1532 for_each(ip
, ips
) if(ip
->mark
> 0)
1537 duplicate(ip
->addr
,buf
);
1538 buf
=index_id(ip
->addr
,32-idxtable_bitmask1
);
1540 string(chain_forward
,6+strlen(buf
));
1541 strcpy(chain_forward
,"forw_");
1542 strcat(chain_forward
,buf
);
1544 string(chain_postrouting
,6+strlen(buf
));
1545 strcpy(chain_postrouting
,"post_");
1546 strcat(chain_postrouting
,buf
);
1552 chain_forward
="FORWARD";
1553 chain_postrouting
="POSTROUTING";
1557 printf("%-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
1560 /* -------------------------------------------------------- mark download */
1562 sprintf(str
, "-A %s -d %s/32 -o %s -j %s%d",
1563 chain_postrouting
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
1564 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/
1565 /* -m limit --limit 1/s */
1570 sprintf(str
, "-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",
1571 chain_postrouting
, proxy_ip
, proxy_port
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
1572 /*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);*/
1576 sprintf(str
, "-A %s -d %s/32 -o %s -j ACCEPT",
1577 chain_postrouting
, ip
->addr
, lan
);
1580 /* -------------------------------------------------------- mark upload */
1581 sprintf(str
, "-A %s -s %s/32 -o %s -j %s%d",
1582 chain_forward
, ip
->addr
, wan
, mark_iptables
, ip
->mark
);
1583 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/
1586 sprintf(str
, "-A %s -s %s/32 -o %s -j ACCEPT",
1587 chain_forward
, ip
->addr
, wan
);
1592 /* -------------------------------------------------------- download class */
1594 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
1597 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1598 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1601 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1603 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1604 tc
, lan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1608 if(filter_type
== 1)
1610 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1611 tc
, lan
, ip
->mark
, ip
->mark
);
1615 /* -------------------------------------------------------- upload class */
1617 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1618 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1621 sprintf(str
,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1622 tc
, wan
, ip
->group
, ip
->mark
,
1623 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1624 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1627 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1629 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1630 tc
, wan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1634 if(filter_type
== 1)
1636 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1637 tc
, wan
, ip
->mark
, ip
->mark
);
1643 fprintf(f
, "%s %d\n", ip
->addr
, ip
->mark
);
1649 printf("(sharing %s)\n", ip
->sharing
);
1662 chain_forward
= "forw_common";
1663 chain_postrouting
= "post_common";
1667 chain_forward
= "FORWARD";
1668 chain_postrouting
= "POSTROUTING";
1670 /* -------------------------------- classify or reject free download */
1672 char *final_chain
= "DROP"; /* REJECT would be better, but it is impossible in mangle */
1675 final_chain
= "ACCEPT";
1681 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s%d",
1682 chain_postrouting
,proxy_ip
,proxy_port
,lan
,mark_iptables
,3);
1685 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s",
1686 chain_postrouting
,proxy_ip
,proxy_port
,lan
,final_chain
);
1691 sprintf(str
,"-A %s -o %s -j %s%d", chain_postrouting
, lan
, mark_iptables
, 3);
1694 sprintf(str
,"-A %s -o %s -j %s", chain_postrouting
, lan
, final_chain
);
1696 /* ------------------------------- classify or reject free upload */
1699 sprintf(str
,"-A %s -o %s -j %s%d", chain_forward
, wan
, mark_iptables
, 3);
1702 sprintf(str
,"-A %s -o %s -j %s", chain_forward
, wan
, final_chain
);
1706 if(free_min
) /* allocate free bandwith if it is not zero... */
1708 /*-----------------------------------------------------------------*/
1709 puts("Generating free bandwith classes ...");
1710 /*-----------------------------------------------------------------*/
1711 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1712 tc
, lan
, parent
, free_min
, free_max
,burst
, lowest_priority
);
1714 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1715 tc
, wan
, parent
, free_min
, free_max
, burst
, lowest_priority
);
1718 if(strcmpi(qos_leaf
, "none"))
1720 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, lan
, qos_leaf
);
1723 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, wan
, qos_leaf
);
1726 /* tc handle 1 fw flowid */
1727 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, lan
);
1730 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, wan
);
1733 printf("Total IP count: %d\n", i
);
1740 /* that's all folks, thank you for reading it all the way up to this point ;-) */
1741 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */
This page took 1.534695 seconds and 3 git commands to generate.