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, 20120612
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 */
30 #define FIRSTGROUPID 1024
31 #define FIRSTIPCLASS 2048
34 #include "cll1-0.6.2.h"
36 const char *version
= "0.8.3-f";
38 /* Version numbers: 0.8.3 is development releases ("beta"), 0.8.4 will be "stable" */
39 /* Debian(RPM) package versions/patchlevels: 0.7.9-2, 0.8.0-1, 0.8.0-2, etc. */
40 /* C source code development versions ("beta"): 0.7.9-a, 0.8.1-b, etc. */
41 /* C source code release versions: 0.8.0, 0.8.2, 0.8.4, etc. */
43 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";
45 /* ======= All path names are defined here (for RPM patch) ======= */
47 const char *tc
= "/sbin/tc"; /* requires tc with HTB support */
48 const char *iptables
= "/sbin/iptables"; /* requires iptables utility */
49 const char *iptablessave
= "/sbin/iptables-save"; /* not yet required */
50 const char *iptablesrestore
= "/sbin/iptables-restore"; /* requires iptables-restore */
51 const char *ls
= "/bin/ls"; /* this is not user configurable :-) */
53 char *config
= "/etc/prometheus/prometheus.conf"; /* main configuration file */
54 char *hosts
= "/etc/prometheus/hosts"; /* per-IP bandwidth definition file */
56 char *iptablesfile
= "/var/spool/prometheus.iptables"; /* temporary file for iptables-restore*/
57 char *credit
= "/var/lib/misc/prometheus.credit"; /* credit log file */
58 char *classmap
= "/var/lib/misc/prometheus.classes"; /* credit log file */
59 char *html
= "/var/www/traffic.html"; /* hall of fame - html version */
60 char *preview
= "/var/www/preview.html"; /* hall of fame preview - html version */
61 char *json
= "/var/www/logs/traffic.json"; /* hall of fame - json version */
62 char *json_preview
= "/var/www/logs/preview.json"; /* hall of fame preview - json version */
63 char *cmdlog
= "/var/log/prometheuslog"; /* command log filename */
64 char *log_dir
= "/var/www/logs/"; /* log directory pathname, ended with slash */
65 char *log_url
= "/logs/"; /* log directory relative URI prefix (partial URL) */
66 char *html_log_dir
= "/var/www/logs/html/";
68 char *jquery_url
= "http://code.jquery.com/jquery-latest.js";
69 char *lms_url
= "/lms/?m=customerinfo&id=";
70 int use_jquery_popups
= 1;
71 int row_odd_even
= 0; /*<tr class="odd/even"> */
74 void parse_ip_log(int argc
, char **argv
);
75 /* implementid in parselog.c */
77 const char *tr_odd_even(void)
79 row_odd_even
= 1 - row_odd_even
;
82 return "<tr class=\"even\">\n";
86 return "<tr class=\"odd\">\n";
90 /* ======= Help screen is hopefuly self-documenting part of code :-) ======= */
94 puts("Command line switches:\n\
96 -d Dry run (preview tc and iptables commands on stdout)\n\
97 -r Run (reset all statistics and start shaping - daily usage)\n\
98 -p just generate Preview of data transfer statistics and exit (after -r)\n\
99 -s start Shaping FUP limits (keeps data transfer stat like -p) (after -r)\n\
100 -n run Now (like -r delay - overrides qos-free-delay keyword, after boot)\n\
101 -f just Flush iptables and tc classes and exit (stop shaping, no QiS)\n\
102 -9 emergency iptables flush (like -f, but dumps data transfer statistics)\n\
104 -c filename force alternative /etc/prometheus/prometheus.conf filename\n\
105 -h filename force alternative /etc/hosts filename (overrides hosts keyword)\n\
106 -l Mmm YYYY generate HTML summary of Logged traffic (Mmm=Jan-Dec) (and exit)\n\
107 -m generate HTML summary of traffic for yesterday's Month (and exit)\n\
108 -y generate HTML summary of traffic for yesterday's Year (and exit)\n\
109 -? --help show this help scree (and exit)\n\
110 -v --version show Version number of this utility (and exit)\n");
113 /* === Configuraration file values defaults - stored in global variables ==== */
115 int filter_type
= 1; /*1 mark, 2 classify*/
117 char *mark_iptables
= "MARK --set-mark ";
118 int dry_run
= 0; /* preview - use puts() instead of system() */
119 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]";
120 FILE *iptables_file
= NULL
;
121 int enable_credit
= 1; /* enable credit file */
122 int use_credit
= 0; /* use credit file (if enabled)*/
123 char *title
= "Hall of Fame - Greatest Suckers"; /* hall of fame title */
124 int hall_of_fame
= 1; /* enable hall of fame */
125 char *lan
= "eth0"; /* LAN interface */
126 char *lan_medium
= "100Mbit"; /* 10Mbit/100Mbit ethernet */
127 char *wan
= "eth1"; /* WAN/ISP interface */
128 char *wan_medium
= "100Mbit"; /* 10Mbit/100Mbit ethernet */
129 char *qos_leaf
= "sfq perturb 5"; /* leaf discipline */
130 char *qos_free_zone
= NULL
; /* QoS free zone */
131 int qos_proxy
= 1; /* include proxy port to QoS */
132 int found_lmsid
= 0; /* show links to users in LMS information system */
133 int include_upload
= 1; /* upload+download=total traffic */
134 char *proxy_ip
= "192.168.1.1/32"; /* our IP with proxy port */
135 int proxy_port
= 3128; /* proxy port number */
136 long long int line
= 1024; /* WAN/ISP download in kbps */
137 long long int up
= 1024; /* WAN/ISP upload in kbps */
138 int free_min
= 32; /* minimum guaranted bandwidth for all undefined hosts */
139 int free_max
= 64; /* maximum allowed bandwidth for all undefined hosts */
140 int qos_free_delay
= 0; /* seconds to sleep before applying new QoS rules */
141 int digital_divide
= 2; /* controls digital divide weirdness ratio, 1...3 */
142 int max_nesting
= 3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */
143 int htb_r2q
= 256; /* should work for leaf values 512 kbps to 8 Mbps */
144 int burst
= 8; /* HTB burst (in kbits) */
146 int burst_group
= 32;
147 int magic_treshold
= 8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */
148 int keywordcount
= 0;
149 /* not yet implemented:
150 int fixed_packets = 0; maximum number of pps per IP address (not class!)
151 int packet_limit = 5; maximum number of pps to htn CEIL, not rate !!!
153 FILE *log_file
= NULL
;
154 char *kwd
= "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */
156 const int highest_priority
= 0; /* highest HTB priority (HTB built-in value is 0) */
157 const int lowest_priority
= 7; /* lowest HTB priority (HTB built-in value is 7) */
158 const int idxtable_treshold1
= 24; /* this is no longer configurable */
159 const int idxtable_treshold2
= 12; /* this is no longer configurable */
160 const int idxtable_bitmask1
= 3; /* this is no longer configurable */
161 const int idxtable_bitmask2
= 3; /* this is no longer configurable */
163 /* ==== This is C<<1 stuff - learn C<<1 first! https://dev.arachne.cz/svn/cll1h ==== */
178 unsigned long long direct
;
179 unsigned long long proxy
;
180 unsigned long long upload
;
181 unsigned long long traffic
;
182 unsigned long long credit
;
183 unsigned long pktsup
;
184 unsigned long pktsdown
;
185 struct Keyword
*keyword
;
187 } *ips
=NULL
, *ip
, *sharedip
;
196 } *groups
=NULL
, *group
;
202 struct Index
*parent
;
206 } *idxs
=NULL
, *idx
, *metaindex
;
212 int asymetry_ratio
; /* ratio for ADSL-like upload */
213 int asymetry_fixed
; /* fixed treshold for ADSL-like upload */
214 int data_limit
; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */
215 int data_prio
; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */
216 long fixed_limit
; /* fixed data limit for setting lower HTB ceil */
217 long fixed_prio
; /* fixed data lmit for setting lower HTB prio */
218 int reserve_min
; /* bonus for nominal HTB rate bandwidth (in kbps) */
219 int reserve_max
; /* malus for nominal HTB ceil (in kbps) */
220 // int divide_max; /* relative malus: new_ceil=rate+(old_ceil-rate)/divide_max */
221 // int htb_ceil_bonus_divide; /* relative bonus: new_ceil=old_ceil+old_ceil/htb_ceil_bonus_divide */
222 int default_prio
; /* default HTB priority for this keyword */
225 char *leaf_discipline
;
228 } *keyword
,*defaultkeyword
=NULL
,*keywords
=NULL
;
230 /* Damned, this must be object oriented! This looks almost like constructor ;-) */
238 ip
->prio
= highest_priority
+1;
252 ip
->keyword
= keywords
;
256 /* ====== iptables indexes are used to reduce complexity to log8(N) ===== */
258 char *very_ugly_ipv4_code(char *inip
,int bitmask
,int format_as_chainname
)
260 /* warning: this function was debugged only for bitmask values 20,24,28 !!!*/
262 char *ip
,*outip
,*outptr
,*fmt
;
265 /* debug printf("(%s,%d) -> ",ip,bitmask); */
267 if(ip
&& *ip
&& bitmask
>=0 && bitmask
<=32)
269 string(outip
,strlen(ip
)+10); /*fuck unicode? assertion: 10>strlen("_%d_%d") */
273 /* should never exit here */
281 if(dot
<(bitmask
/8-1))
283 if(format_as_chainname
)
296 char *cutdot
=strchr(ip
+1,'.'); /*for bitmask<24*/
302 if(format_as_chainname
)
313 n
= atoi(ip
+1)-atoi(ip
+1)%(1<<(8-bitmask
%8));
320 /*debug printf("%d/%d => [_%d_%d]\n",atoi(ip+1),bitmask,n,bitmask); */
321 sprintf(outptr
,fmt
,n
,bitmask
);
322 if(!format_as_chainname
)
330 /* debug printf("[%s]\n",outip); */
341 /*should never exit here*/
346 char *hash_id(char *ip
,int bitmask
)
348 return very_ugly_ipv4_code(ip
,bitmask
,1);
351 char *subnet_id(char *ip
,int bitmask
)
353 return very_ugly_ipv4_code(ip
,bitmask
,0);
356 /* ================= Let's parse configuration file here =================== */
358 void reject_config_and_exit(char *filename
)
360 printf("Configuration file %s rejected - abnormal exit.",filename
);
364 void get_config(char *config_filename
)
368 printf("Configured keywords: ");
369 parse(config_filename
)
371 option("keyword",kwd
);
376 create(keyword
,Keyword
);
378 keyword
->asymetry_ratio
=1; /* ratio for ADSL-like upload */
379 keyword
->asymetry_fixed
=0; /* fixed treshold for ADSL-like upload */
380 keyword
->data_limit
=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */
381 keyword
->data_prio
=4; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */
382 keyword
->fixed_limit
=0; /* fixed data limit for setting lower HTB ceil */
383 keyword
->fixed_prio
=0; /* fixed data limit for setting lower HTB prio */
384 keyword
->reserve_min
=8; /* bonus for nominal HTB rate bandwidth (in kbps) */
385 keyword
->reserve_max
=0; /* malus for nominal HTB ceil (in kbps) */
386 keyword
->default_prio
=highest_priority
+1;
387 keyword
->html_color
="000000";
389 keyword
->leaf_discipline
="";
391 push(keyword
,keywords
);
392 if(!defaultkeyword
) defaultkeyword
=keyword
;
399 for_each(keyword
,keywords
)
401 int l
=strlen(keyword
->key
);
403 if(!strncmp(keyword
->key
,_
,l
) && strlen(_
)>l
+2)
405 char *tmptr
=_
; /* <---- l+1 ----> */
406 _
+=l
+1; /* via-prometheus-asymetry-ratio, etc. */
407 ioption("asymetry-ratio",keyword
->asymetry_ratio
);
408 ioption("asymetry-treshold",keyword
->asymetry_fixed
);
409 ioption("magic-relative-limit",keyword
->data_limit
);
410 ioption("magic-relative-prio",keyword
->data_prio
);
411 loption("magic-fixed-limit",keyword
->fixed_limit
);
412 loption("magic-fixed-prio",keyword
->fixed_prio
);
413 ioption("htb-default-prio",keyword
->default_prio
);
414 ioption("htb-rate-bonus",keyword
->reserve_min
);
415 ioption("htb-ceil-malus",keyword
->reserve_max
);
416 option("leaf-discipline",keyword
->leaf_discipline
);
417 option("html-color",keyword
->html_color
);
420 if(keyword
->data_limit
|| keyword
->fixed_limit
||
421 keyword
->data_prio
|| keyword
->fixed_prio
)
430 option("iptables",iptables
);
431 option("iptables-save",iptablessave
); /* new */
432 option("iptables-restore",iptablesrestore
); /* new */
433 option("iptables-in-filename",iptablesfile
); /* new */
434 option("hosts",hosts
);
435 option("lan-interface",lan
);
436 option("wan-interface",wan
);
437 option("lan-medium",lan_medium
);
438 option("wan-medium",wan_medium
);
439 lloption("wan-download",line
);
440 lloption("wan-upload",up
);
441 ioption("hall-of-fame-enable",hall_of_fame
);
442 option("hall-of-fame-title",title
);
443 option("hall-of-fame-filename",html
);
444 option("json-filename",json
);
445 option("hall-of-fame-preview",preview
);
446 option("json-preview",json_preview
);
447 option("log-filename",cmdlog
);
448 option("credit-filename",credit
);
449 option("classmap-filename",classmap
);
450 ioption("credit-enable",enable_credit
);
451 option("log-traffic-directory",log_dir
);
452 option("log-traffic-html-directory",html_log_dir
);
453 option("log-traffic-url-path",log_url
);
454 option("jquery-url",jquery_url
);
455 option("lms-url",lms_url
);
456 ioption("use-jquery-popups",use_jquery_popups
);
457 option("qos-free-zone",qos_free_zone
);
458 ioption("qos-free-delay",qos_free_delay
);
459 ioption("qos-proxy-enable",qos_proxy
);
460 option("qos-proxy-ip",proxy_ip
);
461 option("htb-leaf-discipline",qos_leaf
);
462 ioption("qos-proxy-port",proxy_port
);
463 ioption("free-rate",free_min
);
464 ioption("free-ceil",free_max
);
465 ioption("htb-burst",burst
);
466 ioption("htb-burst-main",burst_main
);
467 ioption("htb-burst-group",burst_group
);
468 ioption("htb-nesting-limit",max_nesting
);
469 ioption("htb-r2q",htb_r2q
);
470 ioption("magic-include-upload",include_upload
);
471 ioption("magic-treshold",magic_treshold
);
472 option("filter-type", cnf
);
473 /* not yet implemented:
474 ioption("magic-fixed-packets",fixed_packets);
475 ioption("magic-relative-packets",packet_limit);
480 perror(config_filename
);
481 puts("Warning - using built-in defaults instead ...");
483 done
; /* ugly macro end */
486 /* leaf discipline for keywords */
487 for_each(keyword
,keywords
)
489 if(!strcmpi(keyword
->leaf_discipline
, ""))
491 keyword
->leaf_discipline
= qos_leaf
;
495 if(strcmpi(cnf
, "mark"))
499 mark_iptables
= "CLASSIFY --set-class 1:";
505 mark_iptables
= "MARK --set-mark ";
508 /* are supplied values meaningful ?*/
511 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");
512 reject_config_and_exit(config_filename
);
516 /* ===================== traffic analyser - uses iptables ================ */
518 void get_traffic_statistics(void)
523 textfile(Pipe
,str
) *line
,*lines
=NULL
;
527 sprintf(cmd
,"%s -L -v -x -n -t mangle",iptables
);
539 int col
, accept
=0,proxyflag
=0,valid
=1,setchainname
=0,commonflag
=0;
540 unsigned long long traffic
=0;
541 unsigned long pkts
=0;
542 char *ipaddr
=NULL
,*ptr
;
544 /* debug puts(line->str); */
545 valid_columns(ptr
,line
->str
,' ',col
)
546 if(valid
) switch(col
)
548 case 1: if(eq(ptr
,"Chain"))
552 else if(eq(ptr
,"pkts"))
558 sscanf(ptr
,"%lu",&pkts
);
561 case 2: if(setchainname
)
563 if(!strncmp(ptr
,"post_",5) || eq(ptr
,"POSTROUTING"))
569 if(!strncmp(ptr
,"forw_",5) || eq(ptr
,"FORWARD"))
574 if(eq(ptr
,"post_common") || eq(ptr
,"forw_common"))
581 sscanf(ptr
,"%Lu",&traffic
);
586 case 3: if((strncmp(ptr
,"post_",5) && strncmp(ptr
,"forw_",5)) || commonflag
)
590 /*if(filter_type==1) accept=eq(ptr,"MARK"); else accept=eq(ptr,"CLASSIFY");*/
592 case 8: if(downloadflag
)
594 if(strstr(proxy_ip
,ptr
))
604 case 9: if(downloadflag
)ipaddr
=ptr
;break;
607 if(accept
&& traffic
>0 && ipaddr
)
613 else if(!downloadflag
)
617 printf("IP %s: %Lu MB (%ld pkts)\n", ipaddr
, traffic
, pkts
);
619 if_exists(ip
,ips
,eq(ip
->addr
,ipaddr
));
624 if(eq(ip
->addr
,"0.0.0.0/0"))
626 ip
->name
="(unregistered)";
628 ip
->max
=ip
->desired
=free_max
;
640 ip
->traffic
+=traffic
;
642 ip
->direct
=ip
->traffic
-ip
->upload
-ip
->proxy
;
651 ip
->traffic
+=traffic
;
655 if(traffic
>ip
->traffic
)
666 /* ========== This function executes, logs OR ALSO prints command ========== */
668 void safe_run(char *cmd
)
672 printf("\n=>%s\n",cmd
);
680 fprintf(log_file
,"%s\n",cmd
);
684 void save_line(char *line
)
686 fprintf(iptables_file
,"%s\n",line
);
689 void run_restore(void)
692 string(restor
,STRLEN
);
694 /*-----------------------------------------------------------------*/
695 printf("Running %s <%s ...\n", iptablesrestore
, iptablesfile
);
696 /*-----------------------------------------------------------------*/
699 fclose(iptables_file
);
706 done
; /* ugly macro end */
709 sprintf(restor
,"%s <%s",iptablesrestore
, iptablesfile
);
715 /* == This function strips extra characters after IP address and stores it = */
717 void parse_ip(char *str
)
719 char *ptr
,*ipaddr
=NULL
,*ipname
=NULL
,*lmsid
=NULL
;
725 while(*ptr
&& *ptr
!='}')
733 while(*ptr
&& *ptr
!=' ' && *ptr
!=9)
741 while(*ptr
&& (*ptr
==' ' || *ptr
==9))
746 while(*ptr
&& *ptr
!=' ' && *ptr
!=9)
752 if_exists(ip
,ips
,eq(ip
->addr
,ipaddr
));
761 ip
->lmsid
=atoi(lmsid
);
766 char *parse_datafile_line(char *str
)
768 char *ptr
=strchr(str
,' ');
785 void append_log(struct IP
*self
) /*using global variables*/
790 date(d
); /* this is typical cll1.h macro - prints current date */
792 sprintf(str
,"%s/%s.log", log_dir
, self
->name
);
796 fprintf(f
,"%ld\t%s\t%Lu\t%Lu\t%Lu\t%Lu\t%d\t%d\t%d\t%d\t%s",
797 time(NULL
), self
->name
, self
->traffic
, self
->direct
, self
->proxy
,
798 self
->upload
, self
->min
, self
->max
, self
->desired
, self
->lmsid
, d
); /* d = date*/
808 /*-----------------------------------------------------------------*/
809 /* Are you looking for int main(int argc, char **argv) ? :-)) */
810 /*-----------------------------------------------------------------*/
814 int i
=0; /* just plain old Fortran style integer :-) */
815 FILE *f
=NULL
; /* everything is just stream of bytes... */
816 char *str
, *ptr
, *d
; /* LET A$=B$ :-) */
818 int class_count
=0,ip_count
=0;
820 int just_flush
=FALSE
; /* deactivates all previous actions */
822 int just_preview
=FALSE
; /* preview - generate just stats */
823 int start_shaping
=FALSE
; /* apply FUP - requires classmap file */
824 int just_logs
=FALSE
; /* just parse logs */
828 char *chain_forward
, *chain_postrouting
;
832 Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\
833 Version %s - Copyright (C)2005-2012 Michael Polak, Arachne Labs\n\
834 iptables-restore & burst tunning & classify modification by Ludva\n\
835 Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version
);
837 /*----- Boring... we have to check command line options first: ----*/
840 argument("-c") { nextargument(config
); }
841 argument("-h") { nextargument(althosts
);}
842 argument("-d") { run
=TRUE
; dry_run
=TRUE
; }
843 argument("-f") { run
=TRUE
; just_flush
=TRUE
; }
844 argument("-9") { run
=TRUE
; just_flush
=9; }
845 argument("-p") { run
=TRUE
; just_preview
=TRUE
; }
846 argument("-s") { run
=TRUE
; just_preview
=TRUE
; start_shaping
=TRUE
; }
847 argument("-r") { run
=TRUE
; }
848 argument("-n") { run
=TRUE
; nodelay
=TRUE
; }
849 argument("-l") { just_logs
=TRUE
; }
850 argument("-m") { just_logs
=TRUE
; }
851 argument("-y") { just_logs
=TRUE
; }
852 argument("-?") { help(); exit(0); }
853 argument("--help") { help(); exit(0); }
854 argument("-v") { exit(0); }
855 argument("--version") { exit(0); }
860 puts("*** THIS IS JUST DRY RUN ! ***\n");
863 date(d
); /* this is typical cll1.h macro - prints current date */
865 /*-----------------------------------------------------------------*/
866 printf("Parsing configuration file %s ...\n", config
);
867 /*-----------------------------------------------------------------*/
872 parse_ip_log(argc
,argv
);
888 /*-----------------------------------------------------------------*/
889 puts("Parsing iptables verbose output ...");
890 /*-----------------------------------------------------------------*/
891 get_traffic_statistics();
894 /*-----------------------------------------------------------------*/
895 printf("Parsing class defintion file %s ...\n", hosts
);
896 /*-----------------------------------------------------------------*/
897 int groupidx
= FIRSTGROUPID
;
902 if(*str
<'0' || *str
>'9')
904 /* any line starting with non-number is comment ...*/
908 //Does this IP share QoS class with some other ?
909 substring
=strstr(str
,"sharing-");
912 substring
+=8; //"sharing-"
915 ip
->sharing
=substring
;
916 ip
->keyword
=defaultkeyword
; /* settings for default keyword */
917 while(*substring
&& *substring
!='\n')
925 //Do we have to create new QoS class for this IP ?
927 if_exists(keyword
,keywords
,(substring
=strstr(str
,keyword
->key
)))
933 ip
->prio
=keyword
->default_prio
;
934 substring
+=strlen(keyword
->key
)+1;
936 while(*ptr
&& *ptr
!='-')
943 ip
->max
= ip
->desired
=atoi(ptr
+1);
945 ip
->min
= atoi(substring
);
948 printf(" %s: Illegal value of minimum bandwidth 0 kbps, using %d kb/s\n",
952 if(ip
->max
<= ip
->min
)
955 ip
->max
= ip
->min
+ip
->keyword
->reserve_min
;
959 ip
->max
-= ip
->keyword
->reserve_max
;
965 ip
->mark
=FIRSTIPCLASS
+1+class_count
++;
967 if_exists(group
,groups
,group
->min
==ip
->min
)
970 group
->desired
+= ip
->min
;
971 ip
->group
= group
->id
;
976 group
->min
= ip
->min
;
977 group
->id
= groupidx
++;
978 ip
->group
= group
->id
;
980 if(group
->min
<8) group
->min
=8;
981 /* Warning - this is maybe because of primitive tc namespace, can be fixed */
982 /* it is because class IDs are derived from min. bandwidth. - xCh */
983 //if(group->min>MAX_GUARANTED_KBPS) group->min=MAX_GUARANTED_KBPS;
986 group
->desired
=ip
->min
;
987 insert(group
,groups
,desc_order_by
,min
);
997 done
; /* ugly macro end */
999 /*-----------------------------------------------------------------*/
1000 /* cll1.h - let's allocate brand new character buffer... */
1001 /*-----------------------------------------------------------------*/
1004 /*-----------------------------------------------------------------*/
1005 puts("Resolving shared connections ...");
1006 /*-----------------------------------------------------------------*/
1007 for_each(ip
,ips
) if(ip
->sharing
)
1009 for_each(sharedip
,ips
) if(eq(sharedip
->name
,ip
->sharing
))
1011 sharedip
->traffic
+=ip
->traffic
;
1013 ip
->mark
=sharedip
->mark
;
1014 ip
->lmsid
=sharedip
->lmsid
;
1019 printf("Unresolved shared connection: %s %s sharing-%s\n",
1020 ip
->addr
, ip
->name
, ip
->sharing
);
1024 if(enable_credit
&& just_flush
<9)
1026 /*-----------------------------------------------------------------*/
1027 printf("Parsing credit file %s ...\n", credit
);
1028 /*-----------------------------------------------------------------*/
1031 ptr
=parse_datafile_line(_
);
1034 if_exists(ip
,ips
,eq(ip
->addr
,_
))
1036 sscanf(ptr
,"%Lu",&(ip
->credit
));
1040 done
; /* ugly macro end */
1045 /*-----------------------------------------------------------------*/
1046 puts("Initializing iptables and tc classes ...");
1047 /*-----------------------------------------------------------------*/
1049 iptables_file
=fopen(iptablesfile
,"w");
1050 if(iptables_file
== NULL
)
1052 puts("Cannot open iptablesfile!");
1056 log_file
=fopen(cmdlog
,"w");
1057 if(log_file
== NULL
)
1059 puts("Cannot open logfile!");
1063 save_line(iptablespreamble
);
1066 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,lan
);
1069 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,wan
);
1072 iptables_file
=fopen(iptablesfile
,"w");
1073 save_line(iptablespreamble
);
1075 if(qos_free_zone
&& *qos_free_zone
!='0')
1079 sprintf(str
,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone
, wan
);
1084 save_line(":post_noproxy - [0:0]");
1085 sprintf(str
,"-A POSTROUTING -p ! tcp -o %s -j post_noproxy", lan
);
1087 sprintf(str
,"-A POSTROUTING -s ! %s -o %s -j post_noproxy", proxy_ip
, lan
);
1089 sprintf(str
,"-A POSTROUTING -s %s -p tcp --sport ! %d -o %s -j post_noproxy", proxy_ip
, proxy_port
, lan
);
1092 chain
="post_noproxy";
1096 chain
="POSTROUTING";
1099 sprintf(str
,"-A %s -s %s -o %s -j ACCEPT", chain
, qos_free_zone
, lan
);
1103 if(ip_count
>idxtable_treshold1
&& !just_flush
)
1105 int idxcount
=0, bitmask
=32-idxtable_bitmask1
; /* default net mask: 255.255.255.240 */
1107 /*-----------------------------------------------------------------*/
1108 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count
);
1109 /*-----------------------------------------------------------------*/
1111 save_line(":post_common - [0:0]");
1112 save_line(":forw_common - [0:0]");
1114 for_each(ip
,ips
) if(ip
->addr
&& *(ip
->addr
) && !eq(ip
->addr
,"0.0.0.0/0"))
1116 buf
=hash_id(ip
->addr
,bitmask
);
1117 if_exists(idx
,idxs
,eq(idx
->id
,buf
))
1126 idx
->bitmask
=bitmask
;
1134 /* brutal perfomance optimalization */
1135 while(idxcount
>idxtable_treshold2
&& bitmask
>2*idxtable_bitmask2
)
1137 bitmask
-=idxtable_bitmask2
;
1140 for_each(idx
,idxs
) if(idx
->parent
== NULL
)
1142 buf
=hash_id(idx
->addr
,bitmask
);
1143 if_exists(metaindex
,idxs
,eq(metaindex
->id
,buf
))
1145 metaindex
->children
++;
1149 create(metaindex
,Index
);
1150 metaindex
->addr
=idx
->addr
;
1152 metaindex
->bitmask
=bitmask
;
1153 metaindex
->parent
=NULL
;
1154 metaindex
->children
=0;
1156 push(metaindex
,idxs
);
1158 idx
->parent
=metaindex
;
1162 /* this should slightly optimize throughout ... */
1163 sort(idx
,idxs
,desc_order_by
,children
);
1164 sort(idx
,idxs
,order_by
,bitmask
);
1169 subnet
=subnet_id(idx
->addr
,idx
->bitmask
);
1170 printf("%d: %s/%d\n",
1171 ++i
, subnet
, idx
->bitmask
);
1173 sprintf(str
,":post_%s - [0:0]", idx
->id
);
1176 sprintf(str
,":forw_%s - [0:0]", idx
->id
);
1181 string(buf
,strlen(idx
->parent
->id
)+6);
1182 sprintf(buf
,"post_%s",idx
->parent
->id
);
1189 sprintf(str
,"-A %s -d %s/%d -o %s -j post_%s", buf
, subnet
, idx
->bitmask
, lan
, idx
->id
);
1192 sprintf(str
,"-A %s -d %s/%d -o %s -j post_common", buf
, subnet
, idx
->bitmask
, lan
);
1197 string(buf
,strlen(idx
->parent
->id
)+6);
1198 sprintf(buf
,"forw_%s",idx
->parent
->id
);
1205 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_%s", buf
, subnet
, idx
->bitmask
, wan
, idx
->id
);
1208 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_common", buf
, subnet
, idx
->bitmask
, wan
);
1211 printf("Total indexed iptables chains created: %d\n", i
);
1213 sprintf(str
,"-A FORWARD -o %s -j forw_common", wan
);
1216 sprintf(str
,"-A POSTROUTING -o %s -j post_common", lan
);
1224 fclose(iptables_file
);
1229 puts("Just flushed iptables and tc classes - now exiting ...");
1235 if(!dry_run
&& !nodelay
&& qos_free_delay
)
1237 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay
);
1238 sleep(qos_free_delay
);
1241 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",
1245 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
1246 tc
,lan
,lan_medium
,lan_medium
,burst_main
,highest_priority
);
1249 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
1250 tc
,lan
,line
,line
,burst_main
,highest_priority
);
1253 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc
,wan
,htb_r2q
);
1256 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
1257 tc
,wan
,wan_medium
,wan_medium
,burst_main
,highest_priority
);
1260 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
1261 tc
,wan
,up
,up
,burst_main
,highest_priority
);
1265 /*-----------------------------------------------------------------*/
1266 puts("Locating heavy downloaders and generating root classes ...");
1267 /*-----------------------------------------------------------------*/
1268 sort(ip
,ips
,desc_order_by
,traffic
);
1270 /*-----------------------------------------------------------------*/
1271 /* sub-scope - local variables */
1273 long long int rate
= line
;
1274 long long int max
= line
;
1275 int group_count
= 0;
1276 FILE *credit_file
= NULL
;
1278 if(!just_preview
&& !dry_run
&& enable_credit
)
1280 credit_file
= fopen(credit
,"w");
1283 for_each(group
,groups
)
1288 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",
1289 tc
, lan
, parent
, group
->id
, rate
, max
, burst_group
, highest_priority
+1, group
->desired
);
1293 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",
1294 tc
, wan
, parent
, group
->id
, rate
*up
/line
, max
*up
/line
, burst_group
, highest_priority
+1, group
->desired
);
1298 if(group_count
++ < max_nesting
)
1303 rate
-= digital_divide
*group
->min
;
1304 if(rate
< group
->min
)
1309 /*shaping of aggresive downloaders, with credit file support */
1312 int group_rate
= group
->min
, priority_sequence
= lowest_priority
;
1314 for_each(ip
, ips
) if(ip
->min
== group
->min
&& ip
->max
> ip
->min
)
1316 if( ip
->keyword
->data_limit
&& !ip
->fixedprio
1317 && ( ip
->traffic
>ip
->credit
1318 + (ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))) )
1320 if(group_rate
<ip
->max
)
1324 group_rate
+=magic_treshold
;
1325 ip
->prio
=lowest_priority
;
1326 if(ip
->prio
<highest_priority
+2)
1328 ip
->prio
=highest_priority
+2;
1333 if( ip
->keyword
->data_prio
1335 && ( ip
->traffic
>ip
->credit
1336 + (ip
->min
*ip
->keyword
->data_prio
+(ip
->keyword
->fixed_prio
<<20))) )
1338 ip
->prio
=priority_sequence
--;
1339 if(ip
->prio
<highest_priority
+1)
1341 ip
->prio
=highest_priority
+1;
1347 unsigned long long lcredit
=0;
1349 if((ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))>ip
->traffic
)
1351 lcredit
=(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))-ip
->traffic
;
1353 fprintf(credit_file
,"%s %Lu\n",ip
->addr
,lcredit
);
1361 fclose(credit_file
);
1369 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap
);
1377 if_exists(ip
,ips
,eq(ip
->addr
,_
))
1380 if(ip
->max
< ip
->desired
) /* apply FUP limit immediately.... */
1382 printf("Applying limit for %-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
1383 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
1384 sprintf(str
, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1385 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1387 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1388 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1389 sprintf(str
,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1390 tc
, wan
, ip
->group
, ip
->mark
,
1391 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1392 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1401 puts("Warning - classmap file not fund, just generating preview ...");
1402 start_shaping
=FALSE
;
1404 done
; /* ugly macro end */
1410 if(!dry_run
&& !just_flush
)
1412 /*-----------------------------------------------------------------*/
1413 printf("Writing json overview %s ... ", json
);
1414 /*-----------------------------------------------------------------*/
1423 && (ip
->traffic
|| ip
->direct
|| ip
->proxy
|| ip
->upload
))
1429 fprintf(f
, " \"%s\":{ \"lms\": %d, \"ip\":\"%s\", \"total\":%Lu, \"down\":%Lu, \"proxy\":%Lu, \"up\":%Lu, \"min\":%d, \"max\":%d, \"limit\":%d }",
1430 ip
->name
, ip
->lmsid
, ip
->addr
, ip
->traffic
, ip
->direct
, ip
->proxy
, ip
->upload
, ip
->min
, ip
->desired
, ip
->max
);
1450 /*-----------------------------------------------------------------*/
1451 printf("Sorting data and generating statistics page %s ...\n", html
);
1452 /*-----------------------------------------------------------------*/
1454 if(use_jquery_popups
)
1456 fprintf(f
,"<script type=\"text/javascript\" src=\"%s\"></script>\n", jquery_url
);
1458 fputs("<table class=\"decorated last\">\n\
1459 <caption>Bandwidth classes</caption>\n\
1461 <th style=\"text-align: right\">#</th>\n\
1462 <th style=\"text-align: right\">group</th>\n\
1463 <th style=\"text-align: right\">IPs</th>\n\
1464 <th style=\"text-align: right\">requested</th>\n",f
);
1465 fprintf(f
,"<th colspan=\"%d\">data limits</th>\n", keywordcount
);
1466 fputs("</tr></thead><tbody>\n",f
);
1469 for_each(group
, groups
)
1472 printf("%d kb/s group: %d bandwidth requested: %d kb/s\n",group
->min
,group
->count
,group
->desired
);
1474 fprintf(f
, "%s<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d kb/s</td>",
1475 tr_odd_even(), count
, group
->min
);
1476 fprintf(f
, "<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d kb/s</td>",
1477 group
->count
, group
->desired
);
1479 for_each(keyword
, keywords
) if(keyword
->ip_count
)
1481 fprintf(f
,"<td style=\"text-align: right\"><span style=\"color:#%s\">%d MB</span></td>",
1482 keyword
->html_color
, group
->min
*keyword
->data_limit
);
1484 i
+= group
->desired
;
1485 total
+= group
->count
;
1489 printf("Total groups: %d Total bandwidth requested: %d kb/s\nAGGREGATION: 1/%d\n",
1492 fprintf(f
,"</tr></tbody>\n\
1494 <th colspan=\"2\" style=\"text-align: left\">Line %Ld kb/s</td>",line
);
1495 fprintf(f
,"<th style=\"text-align: right\">%d</td><th style=\"text-align: right\">%d kb/s</td>",total
,i
);
1497 for_each(keyword
, keywords
) if(keyword
->ip_count
)
1499 fprintf(f
,"<th style=\"text-align: right\">%d IPs</th>",keyword
->ip_count
);
1501 fprintf(f
,"</tr><tr><th colspan=\"4\">Aggregation 1/%d</th>\n", (int)(0.5+i
/line
));
1502 fprintf(f
,"<th colspan=\"%d\">%d traffic classes</th></tr>\n", keywordcount
, total
);
1504 fputs("</thead></table>\n",f
);
1506 else if(!dry_run
&& !just_flush
)
1514 unsigned long long total_traffic
=0, total_direct
=0, total_proxy
=0, total_upload
=0, tmp_sum
=0;
1515 int active_classes
=0;
1517 struct Sum
{unsigned long long l
; int i
; list(Sum
);} *sum
,*sums
=NULL
;
1518 int limit_count
=0, prio_count
=0;
1526 fprintf(f
,"<p><table class=\"decorated last\">\n<caption>%s",title
);
1527 fprintf(f
," (%s)</caption>\n", d
);
1528 fputs("<thead><tr>\n<th colspan=\"3\"> </th>\n",f
);
1529 fputs("<th style=\"text-align: right\">credit</th>\n\
1530 <th style=\"text-align: right\">FUP</th>\n\
1531 <th style=\"text-align: right\">total</th>\n\
1532 <th style=\"text-align: right\">down</th>\n",f
);
1535 fputs("<th style=\"text-align: right\">proxy</th>\n",f
);
1537 fputs("<th style=\"text-align: right\">up</th>\n\
1538 <th style=\"text-align: right\">min</th>\n\
1539 <th style=\"text-align: right\">max</th>\n\
1540 <th style=\"text-align: right\">limit</th>\n\
1543 <th style=\"text-align: right\">#</th>\n\
1544 <th>hostname [+sharing]</th>\n\
1545 <th style=\"text-align: right\">LMS</th>\n\
1546 <th style=\"text-align: right\">MB</th>\n\
1547 <th style=\"text-align: right\">MB</th>\n\
1548 <th style=\"text-align: right\">MB</th>\n\
1549 <th style=\"text-align: right\">MB</th>\n\
1550 <th style=\"text-align: right\">MB</th>\n\
1551 <th style=\"text-align: right\">kb/s</th>\n\
1552 <th style=\"text-align: right\">kb/s</th>\n\
1553 <th style=\"text-align: right\">kb/s</th>\n\
1555 </tr></thead><tbody>\n",f
);
1558 for_each(ip
,ips
) if(!use_jquery_popups
|| !ip
->sharing
)
1560 char *f1
="", *f2
="";
1563 if(ip
->max
< ip
->desired
)
1565 f1
="<span style=\"color:red\">";
1569 else if(ip
->prio
> highest_priority
+1)
1571 f1
="<span style=\"color:brown\">";
1577 printf("%03d. %-22s %10Lu (%d/%d)\n",i
,ip
->name
, ip
->traffic
, ip
->min
, ip
->max
);
1579 /* hostnames -------------------------------------- */
1580 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",
1581 tr_odd_even(), ip
->name
, i
, log_url
, ip
->name
, ip
->name
);
1583 if(use_jquery_popups
)
1585 fprintf(f
,"<span id=\"sharing_%d\" style=\"display:none\">",i
);
1587 for_each(sharedip
, ips
) if(eq(ip
->name
, sharedip
->sharing
))
1589 fprintf(f
,"<br /><a class=\"blue\" target=\"_blank\" href=\"%s%s.log\">%s</a>\n", log_url
, sharedip
->name
, sharedip
->name
);
1592 fputs("</span>\n",f
);
1595 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>",
1596 i
, i
, i
, popup_button
);
1600 /* ----------------------------------------------- */
1604 fputs("<td style=\"text-align: right\">",f
);
1607 fprintf(f
,"<a class=\"blue\" target=\"_blank\" href=\"%s%d\">%04d</a>\n", lms_url
, ip
->lmsid
, ip
->lmsid
);
1609 else if(ip
->lmsid
== 0)
1615 fprintf(f
,"<td style=\"text-align: right\">%Lu</td>\n", ip
->credit
);
1616 fprintf(f
,"<td style=\"text-align: right\"><span style=\"color:#%s\">%Lu</span></td>",
1617 ip
->keyword
->html_color
,
1618 ip
->credit
+(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20)));
1619 fprintf(f
,"<td style=\"text-align: right\">%s%Lu%s", f1
, ip
->traffic
, f2
);
1621 /* download --------------------------------------- */
1622 fprintf(f
,"</td><td style=\"text-align: right\">%Lu", ip
->direct
);
1623 if(use_jquery_popups
)
1625 fprintf(f
,"<span id=\"download_%d\" style=\"display:none\">",i
);
1626 for_each(sharedip
, ips
) if(eq(ip
->name
, sharedip
->sharing
))
1628 fprintf(f
,"<br />%Lu", sharedip
->direct
);
1630 fputs("</span>\n",f
);
1633 /* ----------------------------------------------- */
1637 fprintf(f
,"<td style=\"text-align: right\">%Lu</td>\n", ip
->proxy
);
1639 /* upload ---------------------------------------- */
1640 fprintf(f
,"<td style=\"text-align: right\">%Lu", ip
->upload
);
1641 if(use_jquery_popups
)
1643 fprintf(f
,"<span id=\"upload_%d\" style=\"display:none\">",i
);
1644 for_each(sharedip
,ips
) if(eq(ip
->name
, sharedip
->sharing
))
1646 fprintf(f
,"<br />%Lu", sharedip
->upload
);
1648 fputs("</span>\n",f
);
1651 /* ----------------------------------------------- */
1653 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1654 <td style=\"text-align: right\">%d</td>\n\
1655 <td style=\"text-align: right\">%s%d%s</td>\n\
1656 <td>%s%d%s</td></tr>\n",
1657 ip
->min
, ip
->desired
,
1661 total_traffic
+=ip
->traffic
;
1662 total_direct
+=ip
->direct
;
1663 total_proxy
+=ip
->proxy
;
1664 total_upload
+=ip
->upload
;
1668 tmp_sum
+=ip
->traffic
;
1671 sum
->i
=active_classes
;
1672 insert(sum
,sums
,order_by
,i
);
1678 for_each(sharedip
,ips
) if(eq(ip
->name
, sharedip
->sharing
))
1680 append_log(sharedip
);
1684 fprintf(f
,"</tbody><thead><tr>\n\
1685 <th colspan=\"%d\" style=\"text-align: left\">%d CLASSES</th>", colspan
-7, i
);
1686 fprintf(f
,"<th style=\"text-align: right\">%Lu</th><th style=\"text-align: right\">%Lu</th>\n", total_traffic
, total_direct
);
1689 fprintf(f
,"<th style=\"text-align: right\">%Lu</th>\n", total_proxy
);
1691 fprintf(f
,"<th style=\"text-align: right\">%Lu</th>", total_upload
);
1692 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
);
1695 if(active_classes
>10)
1697 int top20_count
=0,top20_perc1
=0;
1698 long long top20_perc2
=0;
1699 unsigned long long top20_sum
=0l;
1701 fputs("<a name=\"erp\"></a><p><table class=\"decorated last\"><caption>Enterprise Resource Planning (ERP)</caption>\n",f
);
1702 fputs("<thead><tr>\n\
1703 <th>Analytic category</th>\n\
1704 <th colspan=\"2\" style=\"text-align: center\">Active Classes</th>\n\
1705 <th colspan=\"2\" style=\"text-align: center\">Data transfers</th>\n\
1706 </tr></thead><tbody>\n",f
);
1708 if_exists(sum
,sums
,sum
->l
>=total_traffic
/4)
1710 fprintf(f
,"%s<td>Top 25%% of traffic</td>\n", tr_odd_even());
1711 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1712 <td style=\"text-align: right\">%d %%</td>\n\
1713 <td style=\"text-align: right\">%Lu MB</td>\n\
1714 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1715 sum
->i
, (100*sum
->i
+50)/active_classes
, sum
->l
, (100*sum
->l
+50)/total_traffic
);
1718 if_exists(sum
,sums
,sum
->i
==10)
1720 fprintf(f
,"%s<td>Top 10 downloaders</td>\n", tr_odd_even());
1721 fprintf(f
,"<td style=\"text-align: right\"><strong>10</strong></td>\n\
1722 <td style=\"text-align: right\">%d %%</td>\n\
1723 <td style=\"text-align: right\">%Lu MB</td>\n\
1724 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1725 (100*sum
->i
+50)/active_classes
, sum
->l
, (100*sum
->l
+50)/total_traffic
);
1728 if_exists(sum
,sums
,sum
->l
>=total_traffic
/2)
1730 fprintf(f
,"%s<td>Top 50%% of traffic</td>\n", tr_odd_even());
1731 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1732 <td style=\"text-align: right\">%d %%</td>\n\
1733 <td style=\"text-align: right\">%Lu MB</td>\n\
1734 <td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",
1735 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1738 if_exists(sum
,sums
,sum
->l
>=4*total_traffic
/5)
1740 fprintf(f
,"%s<td>Top 80%% of traffic</td>\n", tr_odd_even());
1741 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1742 <td style=\"text-align: right\">%d %%</td>\n\
1743 <td style=\"text-align: right\">%Lu MB</td>\n\
1744 <td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",
1745 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1748 if_exists(sum
,sums
,sum
->i
>=(active_classes
+1)/5)
1750 fprintf(f
,"%s<td>Top 20%% downloaders</td>\n", tr_odd_even());
1752 top20_perc1
=(100*sum
->i
+50)/active_classes
;
1754 top20_perc2
=(100*sum
->l
+50)/total_traffic
;
1755 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1756 <td style=\"text-align: right\"><strong>%d %%</strong></td>\n\
1757 <td style=\"text-align: right\">%Lu MB</td>\n\
1758 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1759 top20_count
,top20_perc1
,top20_sum
,top20_perc2
);
1762 if_exists(sum
,sums
,sum
->i
>=(active_classes
+1)/4)
1764 fprintf(f
,"%s<td>Top 25%% downloaders</td>\n", tr_odd_even());
1765 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1766 <td style=\"text-align: right\">%d %%</td>\n\
1767 <td style=\"text-align: right\">%Lu MB</td>\n\
1768 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1769 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1772 if_exists(sum
,sums
,sum
->i
>=(active_classes
+1)/2)
1774 fprintf(f
,"%s<td>Top 50%% downloaders</td>\n", tr_odd_even());
1775 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1776 <td style=\"text-align: right\"><strong>%d %%</strong></td>\n\
1777 <td style=\"text-align: right\">%Lu MB</td>\n\
1778 <td style=\"text-align: right\">%Ld %%</td></tr>\n",
1779 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1782 if_exists(sum
,sums
,sum
->i
>=4*(active_classes
+1)/5)
1784 fprintf(f
,"%s<td>Top 80%% downloaders</td>\n", tr_odd_even());
1785 fprintf(f
,"<td style=\"text-align: right\">%d</td>\n\
1786 <td style=\"text-align: right\">%d %%</td>\n\
1787 <td style=\"text-align: right\">%Lu MB</td>\n\
1788 <td style=\"text-align: right\">%Ld %%</td></tr></tbody>\n",
1789 sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total_traffic
);
1792 fprintf(f
,"<thead><tr><th><a class=\"blue\" target=\"_blank\" href=\"%sERP.log\">All users, all traffic</a></th>\n", log_url
);
1793 fprintf(f
,"<th style=\"text-align: right\">%d</th>\n\
1794 <th style=\"text-align: right\">100 %%</th>\n\
1795 <th style=\"text-align: right\">%Lu MB</th>\n\
1796 <th style=\"text-align: right\">100 %%</th></tr>\n",active_classes
,total_traffic
);
1797 fputs("</thead></table>\n", f
);
1799 /* write basic ERP data to log directory */
1803 sprintf(str
,"%s/ERP.log",log_dir
);
1804 iplog
=fopen(str
,"a");
1807 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",
1808 time(NULL
), top20_count
, top20_perc1
, top20_sum
, top20_perc2
,
1809 active_classes
, total_traffic
, i
, limit_count
, prio_count
, d
); /* d = date*/
1819 fprintf(f
, stats_html_signature
, version
);
1830 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar
);
1836 printf("%-22s %-15s mark\n","name","ip");
1839 printf("Writing %s ... ", classmap
);
1840 f
= fopen(classmap
, "w");
1846 /*-----------------------------------------------------------------*/
1847 puts("Generating iptables and tc classes ... ");
1848 /*-----------------------------------------------------------------*/
1850 for_each(ip
, ips
) if(ip
->mark
> 0)
1855 duplicate(ip
->addr
,buf
);
1856 buf
=hash_id(ip
->addr
,32-idxtable_bitmask1
);
1858 string(chain_forward
,6+strlen(buf
));
1859 strcpy(chain_forward
,"forw_");
1860 strcat(chain_forward
,buf
);
1862 string(chain_postrouting
,6+strlen(buf
));
1863 strcpy(chain_postrouting
,"post_");
1864 strcat(chain_postrouting
,buf
);
1870 chain_forward
="FORWARD";
1871 chain_postrouting
="POSTROUTING";
1875 printf("%-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
1878 /* -------------------------------------------------------- mark download */
1880 sprintf(str
, "-A %s -d %s/32 -o %s -j %s%d",
1881 chain_postrouting
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
1882 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/
1883 /* -m limit --limit 1/s */
1888 sprintf(str
, "-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",
1889 chain_postrouting
, proxy_ip
, proxy_port
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
1890 /*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);*/
1894 sprintf(str
, "-A %s -d %s/32 -o %s -j ACCEPT",
1895 chain_postrouting
, ip
->addr
, lan
);
1898 /* -------------------------------------------------------- mark upload */
1899 sprintf(str
, "-A %s -s %s/32 -o %s -j %s%d",
1900 chain_forward
, ip
->addr
, wan
, mark_iptables
, ip
->mark
);
1901 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/
1904 sprintf(str
, "-A %s -s %s/32 -o %s -j ACCEPT",
1905 chain_forward
, ip
->addr
, wan
);
1910 /* -------------------------------------------------------- download class */
1912 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
1915 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1916 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1919 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1921 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1922 tc
, lan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1926 if(filter_type
== 1)
1928 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1929 tc
, lan
, ip
->mark
, ip
->mark
);
1933 /* -------------------------------------------------------- upload class */
1935 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1936 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1939 sprintf(str
,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1940 tc
, wan
, ip
->group
, ip
->mark
,
1941 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1942 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1945 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1947 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1948 tc
, wan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1952 if(filter_type
== 1)
1954 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1955 tc
, wan
, ip
->mark
, ip
->mark
);
1961 fprintf(f
, "%s %d\n", ip
->addr
, ip
->mark
);
1967 printf("(sharing %s)\n", ip
->sharing
);
1980 chain_forward
= "forw_common";
1981 chain_postrouting
= "post_common";
1985 chain_forward
= "FORWARD";
1986 chain_postrouting
= "POSTROUTING";
1988 /* -------------------------------- classify or reject free download */
1990 char *final_chain
= "DROP"; /* REJECT would be better, but it is impossible in mangle */
1993 final_chain
= "ACCEPT";
1999 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s%d",
2000 chain_postrouting
,proxy_ip
,proxy_port
,lan
,mark_iptables
,3);
2003 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s",
2004 chain_postrouting
,proxy_ip
,proxy_port
,lan
,final_chain
);
2009 sprintf(str
,"-A %s -o %s -j %s%d", chain_postrouting
, lan
, mark_iptables
, 3);
2012 sprintf(str
,"-A %s -o %s -j %s", chain_postrouting
, lan
, final_chain
);
2014 /* ------------------------------- classify or reject free upload */
2017 sprintf(str
,"-A %s -o %s -j %s%d", chain_forward
, wan
, mark_iptables
, 3);
2020 sprintf(str
,"-A %s -o %s -j %s", chain_forward
, wan
, final_chain
);
2024 if(free_min
) /* allocate free bandwith if it is not zero... */
2026 /*-----------------------------------------------------------------*/
2027 puts("Generating free bandwith classes ...");
2028 /*-----------------------------------------------------------------*/
2029 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
2030 tc
, lan
, parent
, free_min
, free_max
,burst
, lowest_priority
);
2032 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
2033 tc
, wan
, parent
, free_min
, free_max
, burst
, lowest_priority
);
2036 if(strcmpi(qos_leaf
, "none"))
2038 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, lan
, qos_leaf
);
2041 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, wan
, qos_leaf
);
2044 /* tc handle 1 fw flowid */
2045 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, lan
);
2048 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, wan
);
2051 printf("Total IP count: %d\n", i
);
2058 /* that's all folks, thank you for reading it all the way up to this point ;-) */
2059 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */
This page took 1.765787 seconds and 4 git commands to generate.