094008789cd56e3029e1e57641805463d2fb09bd
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-2013 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, 20130107
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-2013 Michael Polak, <a target=\"_blank\" href=\"http://www.arachne.cz/\">Arachne Labs</a></span>\n";
44 /* ======= Help screen is hopefuly self-documenting part of code :-) ======= */
48 puts("Command line switches:\n\
50 -d Dry run (preview tc and iptables commands on stdout)\n\
51 -r Run (reset all statistics and start shaping - daily usage)\n\
52 -p just generate Preview of data transfer statistics and exit (after -r)\n\
53 -s start Shaping FUP limits (keeps data transfer stat like -p) (after -r)\n\
54 -n run Now (like -r delay - overrides qos-free-delay keyword, after boot)\n\
55 -f just Flush iptables and tc classes and exit (stop shaping, no QiS)\n\
56 -9 emergency iptables flush (like -f, but dumps data transfer statistics)\n\
58 -c filename force alternative /etc/prometheus/prometheus.conf filename\n\
59 -h filename force alternative /etc/hosts filename (overrides hosts keyword)\n\
60 -l Mmm YYYY generate HTML summary of Logged traffic (Mmm=Jan-Dec) (and exit)\n\
61 -m generate HTML summary of traffic for yesterday's Month (and exit)\n\
62 -y generate HTML summary of traffic for yesterday's Year (and exit)\n\
63 -? --help show this help scree (and exit)\n\
64 -v --version show Version number of this utility (and exit)\n");
67 /* ======= All path names are defined here (for RPM patch) ======= */
69 const char *tc
= "/sbin/tc"; /* requires tc with HTB support */
70 const char *iptables
= "/sbin/iptables"; /* requires iptables utility */
71 const char *iptablessave
= "/sbin/iptables-save"; /* not yet required */
72 const char *iptablesrestore
= "/sbin/iptables-restore"; /* requires iptables-restore */
73 const char *ls
= "/bin/ls"; /* this is not user configurable :-) */
75 char *config
= "/etc/prometheus/prometheus.conf"; /* main configuration file */
76 char *hosts
= "/etc/prometheus/hosts"; /* per-IP bandwidth definition file */
78 char *iptablesfile
= "/var/spool/prometheus.iptables"; /* temporary file for iptables-restore*/
79 char *credit
= "/var/lib/misc/prometheus.credit"; /* credit log file */
80 char *classmap
= "/var/lib/misc/prometheus.classes"; /* credit log file */
81 char *html
= "/var/www/traffic.html"; /* hall of fame - html version */
82 char *preview
= "/var/www/preview.html"; /* hall of fame preview - html version */
83 char *json_traffic
= "/var/www/logs/traffic.json"; /* hall of fame - json version */
84 char *json_preview
= "/var/www/logs/preview.json"; /* hall of fame preview - json version */
85 char *cmdlog
= "/var/log/prometheuslog"; /* command log filename */
86 char *log_dir
= "/var/www/logs/"; /* log directory pathname, ended with slash */
87 char *log_url
= "/logs/"; /* log directory relative URI prefix (partial URL) */
88 char *html_log_dir
= "/var/www/logs/html/";
90 char *jquery_url
= "http://code.jquery.com/jquery-latest.js";
91 char *lms_url
= "/lms/?m=customerinfo&id=";
92 int use_jquery_popups
= TRUE
;
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
= FALSE
; /* 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
= TRUE
; /* enable credit file */
104 int use_credit
= FALSE
; /* use credit file (if enabled)*/
105 char *title
= "Hall of Fame - Greatest Suckers"; /* hall of fame title */
106 int hall_of_fame
= TRUE
; /* 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
= TRUE
; /* include proxy port to QoS */
114 int found_lmsid
= FALSE
; /* show links to users in LMS information system */
115 int include_upload
= TRUE
; /* upload+download=total traffic */
116 char *proxy_ip
= "192.168.1.1/32"; /* our IP with proxy port */
117 int proxy_port
= 3128; /* proxy port number */
118 long long int line
= 1024; /* WAN/ISP download in kbps */
119 long long int up
= 1024; /* WAN/ISP upload in kbps */
120 int free_min
= 32; /* minimum guaranted bandwidth for all undefined hosts */
121 int free_max
= 64; /* maximum allowed bandwidth for all undefined hosts */
122 int qos_free_delay
= 0; /* seconds to sleep before applying new QoS rules */
123 int digital_divide
= 2; /* controls digital divide weirdness ratio, 1...3 */
124 int max_nesting
= 3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */
125 int htb_r2q
= 256; /* should work for leaf values 512 kbps to 8 Mbps */
126 int burst
= 8; /* HTB burst (in kbits) */
128 int burst_group
= 32;
129 int magic_treshold
= 8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */
130 int keywordcount
= 0;
133 /* not yet implemented:
134 int fixed_packets = 0; maximum number of pps per IP address (not class!)
135 int packet_limit = 5; maximum number of pps to htn CEIL, not rate !!!
137 FILE *log_file
= NULL
;
138 char *kwd
= "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */
140 const int highest_priority
= 0; /* highest HTB priority (HTB built-in value is 0) */
141 const int lowest_priority
= 7; /* lowest HTB priority (HTB built-in value is 7) */
142 const int idxtable_treshold1
= 24; /* this is no longer configurable */
143 const int idxtable_treshold2
= 12; /* this is no longer configurable */
144 const int idxtable_bitmask1
= 3; /* this is no longer configurable */
145 const int idxtable_bitmask2
= 3; /* this is no longer configurable */
147 struct IP
*ips
= NULL
, *ip
, *sharedip
;
148 struct Group
*groups
= NULL
, *group
;
149 struct Keyword
*keyword
, *defaultkeyword
=NULL
, *keywords
=NULL
;
151 void parse_ip_log(int argc
, char **argv
);
152 /* implemented in parselog.c */
154 void parse_hosts(char *hosts
);
155 /* implemented in parsehosts.c */
157 void write_json_traffic(char *json
);
158 /* implemented in json.c */
160 void write_htmlandlogs(char *html
, char *d
, int total
, int just_preview
);
161 /* implemented in htmlandlogs.c */
163 const char *tr_odd_even(void)
165 row_odd_even
= 1 - row_odd_even
;
168 return "<tr class=\"even\">\n";
172 return "<tr class=\"odd\">\n";
176 /* ==== This is C<<1 stuff - learn C<<1 first! https://dev.arachne.cz/svn/cll1h ==== */
182 struct Index
*parent
;
186 } *idxs
=NULL
, *idx
, *metaindex
;
189 /* function implemented in parsehosts.c */
191 /* ====== iptables indexes are used to reduce complexity to log8(N) ===== */
193 char *index_id(char *ip
, int bitmask
);
194 /* function implemented in ipv4subnets.c */
196 char *subnet_id(char *ip
, int bitmask
);
197 /* function implemented in ipv4subnets.c */
199 /* ================= Let's parse configuration file here ================ */
201 void reject_config_and_exit(char *filename
)
203 printf("Configuration file %s rejected - abnormal exit.",filename
);
207 void get_config(char *config_filename
)
211 printf("Configured keywords: ");
212 parse(config_filename
)
214 option("keyword",kwd
);
219 create(keyword
,Keyword
);
221 keyword
->asymetry_ratio
=1; /* ratio for ADSL-like upload */
222 keyword
->asymetry_fixed
=0; /* fixed treshold for ADSL-like upload */
223 keyword
->data_limit
=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */
224 keyword
->data_prio
=4; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */
225 keyword
->fixed_limit
=0; /* fixed data limit for setting lower HTB ceil */
226 keyword
->fixed_prio
=0; /* fixed data limit for setting lower HTB prio */
227 keyword
->reserve_min
=8; /* bonus for nominal HTB rate bandwidth (in kbps) */
228 keyword
->reserve_max
=0; /* malus for nominal HTB ceil (in kbps) */
229 keyword
->default_prio
=highest_priority
+1;
230 keyword
->html_color
="000000";
232 keyword
->leaf_discipline
="";
234 push(keyword
,keywords
);
237 defaultkeyword
=keyword
;
245 for_each(keyword
,keywords
)
247 int l
=strlen(keyword
->key
);
249 if(!strncmp(keyword
->key
,_
,l
) && strlen(_
)>l
+2)
251 char *tmptr
=_
; /* <---- l+1 ----> */
252 _
+=l
+1; /* via-prometheus-asymetry-ratio, etc. */
253 ioption("asymetry-ratio",keyword
->asymetry_ratio
);
254 ioption("asymetry-treshold",keyword
->asymetry_fixed
);
255 ioption("magic-relative-limit",keyword
->data_limit
);
256 ioption("magic-relative-prio",keyword
->data_prio
);
257 loption("magic-fixed-limit",keyword
->fixed_limit
);
258 loption("magic-fixed-prio",keyword
->fixed_prio
);
259 ioption("htb-default-prio",keyword
->default_prio
);
260 ioption("htb-rate-bonus",keyword
->reserve_min
);
261 ioption("htb-ceil-malus",keyword
->reserve_max
);
262 option("leaf-discipline",keyword
->leaf_discipline
);
263 option("html-color",keyword
->html_color
);
266 if(keyword
->data_limit
|| keyword
->fixed_limit
||
267 keyword
->data_prio
|| keyword
->fixed_prio
)
276 option("iptables",iptables
);
277 option("iptables-save",iptablessave
); /* new */
278 option("iptables-restore",iptablesrestore
); /* new */
279 option("iptables-in-filename",iptablesfile
); /* new */
280 option("hosts",hosts
);
281 option("lan-interface",lan
);
282 option("wan-interface",wan
);
283 option("lan-medium",lan_medium
);
284 option("wan-medium",wan_medium
);
285 lloption("wan-download",line
);
286 lloption("wan-upload",up
);
287 ioption("hall-of-fame-enable",hall_of_fame
);
288 option("hall-of-fame-title",title
);
289 option("hall-of-fame-filename",html
);
290 option("json-filename",json_traffic
);
291 option("hall-of-fame-preview",preview
);
292 option("json-preview",json_preview
);
293 option("log-filename",cmdlog
);
294 option("credit-filename",credit
);
295 option("classmap-filename",classmap
);
296 ioption("credit-enable",enable_credit
);
297 option("log-traffic-directory",log_dir
);
298 option("log-traffic-html-directory",html_log_dir
);
299 option("log-traffic-url-path",log_url
);
300 option("jquery-url",jquery_url
);
301 option("lms-url",lms_url
);
302 ioption("use-jquery-popups",use_jquery_popups
);
303 option("qos-free-zone",qos_free_zone
);
304 ioption("qos-free-delay",qos_free_delay
);
305 ioption("qos-proxy-enable",qos_proxy
);
306 option("qos-proxy-ip",proxy_ip
);
307 option("htb-leaf-discipline",qos_leaf
);
308 ioption("qos-proxy-port",proxy_port
);
309 ioption("free-rate",free_min
);
310 ioption("free-ceil",free_max
);
311 ioption("htb-burst",burst
);
312 ioption("htb-burst-main",burst_main
);
313 ioption("htb-burst-group",burst_group
);
314 ioption("htb-nesting-limit",max_nesting
);
315 ioption("htb-r2q",htb_r2q
);
316 ioption("magic-include-upload",include_upload
);
317 ioption("magic-treshold",magic_treshold
);
318 option("filter-type", cnf
);
319 /* not yet implemented:
320 ioption("magic-fixed-packets",fixed_packets);
321 ioption("magic-relative-packets",packet_limit);
326 perror(config_filename
);
327 puts("Warning - using built-in defaults instead ...");
329 done
; /* ugly macro end */
332 /* leaf discipline for keywords */
333 for_each(keyword
,keywords
)
335 if(!strcmpi(keyword
->leaf_discipline
, ""))
337 keyword
->leaf_discipline
= qos_leaf
;
341 if(strcmpi(cnf
, "mark"))
345 mark_iptables
= "CLASSIFY --set-class 1:";
351 mark_iptables
= "MARK --set-mark ";
354 /* are supplied values meaningful ?*/
357 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");
358 reject_config_and_exit(config_filename
);
362 /* ===================== traffic analyser - uses iptables ================ */
364 void get_traffic_statistics(void)
369 textfile(Pipe
,str
) *line
,*lines
=NULL
;
373 sprintf(cmd
,"%s -L -v -x -n -t mangle",iptables
);
385 int col
, accept
=0,proxyflag
=0,valid
=1,setchainname
=0,commonflag
=0;
386 unsigned long long traffic
=0;
387 unsigned long pkts
=0;
388 char *ipaddr
=NULL
,*ptr
;
390 /* debug puts(line->str); */
391 valid_columns(ptr
,line
->str
,' ',col
)
392 if(valid
) switch(col
)
394 case 1: if(eq(ptr
,"Chain"))
398 else if(eq(ptr
,"pkts"))
404 sscanf(ptr
,"%lu",&pkts
);
407 case 2: if(setchainname
)
409 if(!strncmp(ptr
,"post_",5) || eq(ptr
,"POSTROUTING"))
415 if(!strncmp(ptr
,"forw_",5) || eq(ptr
,"FORWARD"))
420 if(eq(ptr
,"post_common") || eq(ptr
,"forw_common"))
427 sscanf(ptr
,"%Lu",&traffic
);
432 case 3: if((strncmp(ptr
,"post_",5) && strncmp(ptr
,"forw_",5)) || commonflag
)
436 /*if(filter_type==1) accept=eq(ptr,"MARK"); else accept=eq(ptr,"CLASSIFY");*/
438 case 8: if(downloadflag
)
440 if(strstr(proxy_ip
,ptr
))
450 case 9: if(downloadflag
)ipaddr
=ptr
;break;
453 if(accept
&& traffic
>0 && ipaddr
)
459 else if(!downloadflag
)
463 printf("IP %s: %Lu MB (%ld pkts)\n", ipaddr
, traffic
, pkts
);
465 if_exists(ip
,ips
,eq(ip
->addr
,ipaddr
));
470 if(eq(ip
->addr
,"0.0.0.0/0"))
472 ip
->name
= "(unregistered)";
474 ip
->max
= ip
->desired
=free_max
;
490 ip
->traffic
+=traffic
;
492 ip
->direct
=ip
->traffic
-ip
->upload
-ip
->proxy
;
501 ip
->traffic
+=traffic
;
505 if(traffic
>ip
->traffic
)
516 /* ========== This function executes, logs OR ALSO prints command ========== */
518 void safe_run(char *cmd
)
522 printf("\n=>%s\n",cmd
);
530 fprintf(log_file
,"%s\n",cmd
);
534 void save_line(char *line
)
536 fprintf(iptables_file
,"%s\n",line
);
539 void run_restore(void)
542 string(restor
,STRLEN
);
544 /*-----------------------------------------------------------------*/
545 printf("Running %s <%s ...\n", iptablesrestore
, iptablesfile
);
546 /*-----------------------------------------------------------------*/
549 fclose(iptables_file
);
556 done
; /* ugly macro end */
559 sprintf(restor
,"%s <%s",iptablesrestore
, iptablesfile
);
565 char *parse_datafile_line(char *str
)
567 char *ptr
=strchr(str
,' ');
582 /*-----------------------------------------------------------------*/
583 /* Are you looking for int main(int argc, char **argv) ? :-)) */
584 /*-----------------------------------------------------------------*/
588 int i
=0; /* just plain old Fortran style integer :-) */
589 FILE *f
=NULL
; /* everything is just stream of bytes... */
590 char *str
, *ptr
, *d
; /* LET A$=B$ :-) */
594 int just_flush
= FALSE
; /* deactivates all previous actions */
596 int just_preview
= FALSE
; /* preview - generate just stats */
597 int start_shaping
= FALSE
; /* apply FUP - requires classmap file */
598 int just_logs
= FALSE
; /* just parse logs */
602 char *chain_forward
, *chain_postrouting
;
606 Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\
607 Version %s - Copyright (C)2005-2012 Michael Polak, Arachne Labs\n\
608 iptables-restore & burst tunning & classify modification by Ludva\n\
609 Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version
);
611 /*----- Boring... we have to check command line options first: ----*/
614 argument("-c") { nextargument(config
); }
615 argument("-h") { nextargument(althosts
);}
616 argument("-d") { run
=TRUE
; dry_run
=TRUE
; }
617 argument("-f") { run
=TRUE
; just_flush
=TRUE
; }
618 argument("-9") { run
=TRUE
; just_flush
=9; }
619 argument("-p") { run
=TRUE
; just_preview
=TRUE
; }
620 argument("-s") { run
=TRUE
; just_preview
=TRUE
; start_shaping
=TRUE
; }
621 argument("-r") { run
=TRUE
; }
622 argument("-n") { run
=TRUE
; nodelay
=TRUE
; }
623 argument("-l") { just_logs
=TRUE
; }
624 argument("-m") { just_logs
=TRUE
; }
625 argument("-y") { just_logs
=TRUE
; }
626 argument("-?") { help(); exit(0); }
627 argument("--help") { help(); exit(0); }
628 argument("-v") { exit(0); }
629 argument("--version") { exit(0); }
634 puts("*** THIS IS JUST DRY RUN ! ***\n");
637 date(d
); /* this is typical cll1.h macro - prints current date */
639 /*-----------------------------------------------------------------*/
640 printf("Parsing configuration file %s ...\n", config
);
641 /*-----------------------------------------------------------------*/
646 parse_ip_log(argc
,argv
);
662 /*-----------------------------------------------------------------*/
663 puts("Parsing iptables verbose output ...");
664 /*-----------------------------------------------------------------*/
665 get_traffic_statistics();
668 /*-----------------------------------------------------------------*/
669 printf("Parsing class defintion file %s ...\n", hosts
);
670 /*-----------------------------------------------------------------*/
673 /*-----------------------------------------------------------------*/
674 /* cll1.h - let's allocate brand new character buffer... */
675 /*-----------------------------------------------------------------*/
678 /*-----------------------------------------------------------------*/
679 puts("Resolving shared connections ...");
680 /*-----------------------------------------------------------------*/
681 for_each(ip
,ips
) if(ip
->sharing
)
683 for_each(sharedip
,ips
) if(eq(sharedip
->name
,ip
->sharing
))
685 sharedip
->traffic
+=ip
->traffic
;
687 ip
->mark
=sharedip
->mark
;
688 ip
->lmsid
=sharedip
->lmsid
;
693 printf("Unresolved shared connection: %s %s sharing-%s\n",
694 ip
->addr
, ip
->name
, ip
->sharing
);
698 if(enable_credit
&& just_flush
<9)
700 /*-----------------------------------------------------------------*/
701 printf("Parsing credit file %s ...\n", credit
);
702 /*-----------------------------------------------------------------*/
705 ptr
=parse_datafile_line(_
);
708 if_exists(ip
,ips
,eq(ip
->addr
,_
))
710 sscanf(ptr
,"%Lu",&(ip
->credit
));
714 done
; /* ugly macro end */
719 /*-----------------------------------------------------------------*/
720 puts("Initializing iptables and tc classes ...");
721 /*-----------------------------------------------------------------*/
723 iptables_file
=fopen(iptablesfile
,"w");
724 if(iptables_file
== NULL
)
726 puts("Cannot open iptablesfile!");
730 log_file
=fopen(cmdlog
,"w");
733 puts("Cannot open logfile!");
737 save_line(iptablespreamble
);
740 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,lan
);
743 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,wan
);
746 iptables_file
=fopen(iptablesfile
,"w");
747 save_line(iptablespreamble
);
749 if(qos_free_zone
&& *qos_free_zone
!='0')
753 sprintf(str
,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone
, wan
);
758 save_line(":post_noproxy - [0:0]");
759 sprintf(str
,"-A POSTROUTING ! -p tcp -o %s -j post_noproxy", lan
);
761 sprintf(str
,"-A POSTROUTING ! -s %s -o %s -j post_noproxy", proxy_ip
, lan
);
763 sprintf(str
,"-A POSTROUTING -s %s -p tcp ! --sport %d -o %s -j post_noproxy", proxy_ip
, proxy_port
, lan
);
766 chain
="post_noproxy";
773 sprintf(str
,"-A %s -s %s -o %s -j ACCEPT", chain
, qos_free_zone
, lan
);
777 if(ip_count
>idxtable_treshold1
&& !just_flush
)
779 int idxcount
=0, bitmask
=32-idxtable_bitmask1
; /* default net mask: 255.255.255.240 */
781 /*-----------------------------------------------------------------*/
782 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count
);
783 /*-----------------------------------------------------------------*/
785 save_line(":post_common - [0:0]");
786 save_line(":forw_common - [0:0]");
788 for_each(ip
,ips
) if(ip
->addr
&& *(ip
->addr
) && !eq(ip
->addr
,"0.0.0.0/0"))
790 buf
=index_id(ip
->addr
,bitmask
);
791 if_exists(idx
,idxs
,eq(idx
->id
,buf
))
800 idx
->bitmask
=bitmask
;
808 /* brutal perfomance optimalization */
809 while(idxcount
>idxtable_treshold2
&& bitmask
>2*idxtable_bitmask2
)
811 bitmask
-=idxtable_bitmask2
;
814 for_each(idx
,idxs
) if(idx
->parent
== NULL
)
816 buf
=index_id(idx
->addr
,bitmask
);
817 if_exists(metaindex
,idxs
,eq(metaindex
->id
,buf
))
819 metaindex
->children
++;
823 create(metaindex
,Index
);
824 metaindex
->addr
=idx
->addr
;
826 metaindex
->bitmask
=bitmask
;
827 metaindex
->parent
=NULL
;
828 metaindex
->children
=0;
830 push(metaindex
,idxs
);
832 idx
->parent
=metaindex
;
836 /* this should slightly optimize throughout ... */
837 sort(idx
,idxs
,desc_order_by
,children
);
838 sort(idx
,idxs
,order_by
,bitmask
);
843 subnet
=subnet_id(idx
->addr
,idx
->bitmask
);
844 printf("%d: %s/%d\n",
845 ++i
, subnet
, idx
->bitmask
);
847 sprintf(str
,":post_%s - [0:0]", idx
->id
);
850 sprintf(str
,":forw_%s - [0:0]", idx
->id
);
855 string(buf
,strlen(idx
->parent
->id
)+6);
856 sprintf(buf
,"post_%s",idx
->parent
->id
);
863 sprintf(str
,"-A %s -d %s/%d -o %s -j post_%s", buf
, subnet
, idx
->bitmask
, lan
, idx
->id
);
866 sprintf(str
,"-A %s -d %s/%d -o %s -j post_common", buf
, subnet
, idx
->bitmask
, lan
);
871 string(buf
,strlen(idx
->parent
->id
)+6);
872 sprintf(buf
,"forw_%s",idx
->parent
->id
);
879 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_%s", buf
, subnet
, idx
->bitmask
, wan
, idx
->id
);
882 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_common", buf
, subnet
, idx
->bitmask
, wan
);
885 printf("Total indexed iptables chains created: %d\n", i
);
887 sprintf(str
,"-A FORWARD -o %s -j forw_common", wan
);
890 sprintf(str
,"-A POSTROUTING -o %s -j post_common", lan
);
898 fclose(iptables_file
);
903 puts("Just flushed iptables and tc classes - now exiting ...");
909 if(!dry_run
&& !nodelay
&& qos_free_delay
)
911 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay
);
912 sleep(qos_free_delay
);
915 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",
919 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
920 tc
,lan
,lan_medium
,lan_medium
,burst_main
,highest_priority
);
923 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
924 tc
,lan
,line
,line
,burst_main
,highest_priority
);
927 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc
,wan
,htb_r2q
);
930 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
931 tc
,wan
,wan_medium
,wan_medium
,burst_main
,highest_priority
);
934 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
935 tc
,wan
,up
,up
,burst_main
,highest_priority
);
939 /*-----------------------------------------------------------------*/
940 puts("Locating heavy downloaders and generating root classes ...");
941 /*-----------------------------------------------------------------*/
942 sort(ip
,ips
,desc_order_by
,traffic
);
944 /*-----------------------------------------------------------------*/
945 /* sub-scope - local variables */
947 long long int rate
= line
;
948 long long int max
= line
;
950 FILE *credit_file
= NULL
;
952 if(!just_preview
&& !dry_run
&& enable_credit
)
954 credit_file
= fopen(credit
,"w");
957 for_each(group
,groups
)
962 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",
963 tc
, lan
, parent
, group
->id
, rate
, max
, burst_group
, highest_priority
+1, group
->desired
);
967 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",
968 tc
, wan
, parent
, group
->id
, rate
*up
/line
, max
*up
/line
, burst_group
, highest_priority
+1, group
->desired
);
972 if(group_count
++ < max_nesting
)
977 rate
-= digital_divide
*group
->min
;
978 if(rate
< group
->min
)
983 /*shaping of aggresive downloaders, with credit file support */
986 int group_rate
= group
->min
, priority_sequence
= lowest_priority
;
988 for_each(ip
, ips
) if(ip
->min
== group
->min
&& ip
->max
> ip
->min
)
990 ip
->realquota
=ip
->credit
+(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20));
991 if( ip
->keyword
->data_limit
992 and not ip
->fixedprio
993 and ip
->traffic
> ip
->realquota
)
995 if(group_rate
< ip
->max
)
997 ip
->max
= group_rate
;
999 group_rate
+=magic_treshold
;
1000 ip
->prio
=lowest_priority
;
1001 if(ip
->prio
<highest_priority
+2)
1003 ip
->prio
=highest_priority
+2;
1008 if( ip
->keyword
->data_prio
1010 && ( ip
->traffic
>ip
->credit
1011 + (ip
->min
*ip
->keyword
->data_prio
+(ip
->keyword
->fixed_prio
<<20))) )
1013 ip
->prio
=priority_sequence
--;
1014 if(ip
->prio
<highest_priority
+1)
1016 ip
->prio
=highest_priority
+1;
1022 unsigned long long lcredit
=0;
1024 if((ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))>ip
->traffic
)
1026 lcredit
=(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))-ip
->traffic
;
1028 fprintf(credit_file
,"%s %Lu\n",ip
->addr
,lcredit
);
1036 fclose(credit_file
);
1044 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap
);
1052 if_exists(ip
,ips
,eq(ip
->addr
,_
))
1055 if(ip
->max
< ip
->desired
) /* apply FUP limit immediately.... */
1057 printf("Applying limit for %-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
1058 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
1059 sprintf(str
, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1060 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1062 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1063 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1064 sprintf(str
,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1065 tc
, wan
, ip
->group
, ip
->mark
,
1066 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1067 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1076 puts("Warning - classmap file not fund, just generating preview ...");
1077 start_shaping
=FALSE
;
1079 done
; /* ugly macro end */
1082 json_traffic
=json_preview
;
1085 if(!dry_run
&& !just_flush
)
1087 /*-----------------------------------------------------------------*/
1088 printf("Writing json traffic overview %s ... ", json_traffic
);
1089 /*-----------------------------------------------------------------*/
1090 write_json_traffic(json_traffic
);
1093 /*-----------------------------------------------------------------*/
1094 printf("Writing statistics into HTML page %s ...\n", html
);
1095 /*-----------------------------------------------------------------*/
1096 write_htmlandlogs(html
, d
,total
, just_preview
);
1105 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar
);
1111 printf("%-22s %-15s mark\n","name","ip");
1114 printf("Writing %s ... ", classmap
);
1115 f
= fopen(classmap
, "w");
1121 /*-----------------------------------------------------------------*/
1122 puts("Generating iptables and tc classes ... ");
1123 /*-----------------------------------------------------------------*/
1125 for_each(ip
, ips
) if(ip
->mark
> 0)
1130 duplicate(ip
->addr
,buf
);
1131 buf
=index_id(ip
->addr
,32-idxtable_bitmask1
);
1133 string(chain_forward
,6+strlen(buf
));
1134 strcpy(chain_forward
,"forw_");
1135 strcat(chain_forward
,buf
);
1137 string(chain_postrouting
,6+strlen(buf
));
1138 strcpy(chain_postrouting
,"post_");
1139 strcat(chain_postrouting
,buf
);
1145 chain_forward
="FORWARD";
1146 chain_postrouting
="POSTROUTING";
1150 printf("%-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
1153 /* -------------------------------------------------------- mark download */
1155 sprintf(str
, "-A %s -d %s/32 -o %s -j %s%d",
1156 chain_postrouting
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
1157 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/
1158 /* -m limit --limit 1/s */
1163 sprintf(str
, "-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",
1164 chain_postrouting
, proxy_ip
, proxy_port
, ip
->addr
, lan
, mark_iptables
, ip
->mark
);
1165 /*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);*/
1169 sprintf(str
, "-A %s -d %s/32 -o %s -j ACCEPT",
1170 chain_postrouting
, ip
->addr
, lan
);
1173 /* -------------------------------------------------------- mark upload */
1174 sprintf(str
, "-A %s -s %s/32 -o %s -j %s%d",
1175 chain_forward
, ip
->addr
, wan
, mark_iptables
, ip
->mark
);
1176 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/
1179 sprintf(str
, "-A %s -s %s/32 -o %s -j ACCEPT",
1180 chain_forward
, ip
->addr
, wan
);
1185 /* -------------------------------------------------------- download class */
1187 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
1190 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1191 tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1194 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1196 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1197 tc
, lan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1201 if(filter_type
== 1)
1203 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1204 tc
, lan
, ip
->mark
, ip
->mark
);
1208 /* -------------------------------------------------------- upload class */
1210 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1211 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1214 sprintf(str
,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1215 tc
, wan
, ip
->group
, ip
->mark
,
1216 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1217 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1220 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1222 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1223 tc
, wan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1227 if(filter_type
== 1)
1229 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1230 tc
, wan
, ip
->mark
, ip
->mark
);
1236 fprintf(f
, "%s %d\n", ip
->addr
, ip
->mark
);
1242 printf("(sharing %s)\n", ip
->sharing
);
1255 chain_forward
= "forw_common";
1256 chain_postrouting
= "post_common";
1260 chain_forward
= "FORWARD";
1261 chain_postrouting
= "POSTROUTING";
1263 /* -------------------------------- classify or reject free download */
1265 char *final_chain
= "DROP"; /* REJECT would be better, but it is impossible in mangle */
1268 final_chain
= "ACCEPT";
1274 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s%d",
1275 chain_postrouting
,proxy_ip
,proxy_port
,lan
,mark_iptables
,3);
1278 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s",
1279 chain_postrouting
,proxy_ip
,proxy_port
,lan
,final_chain
);
1284 sprintf(str
,"-A %s -o %s -j %s%d", chain_postrouting
, lan
, mark_iptables
, 3);
1287 sprintf(str
,"-A %s -o %s -j %s", chain_postrouting
, lan
, final_chain
);
1289 /* ------------------------------- classify or reject free upload */
1292 sprintf(str
,"-A %s -o %s -j %s%d", chain_forward
, wan
, mark_iptables
, 3);
1295 sprintf(str
,"-A %s -o %s -j %s", chain_forward
, wan
, final_chain
);
1299 if(free_min
) /* allocate free bandwith if it is not zero... */
1301 /*-----------------------------------------------------------------*/
1302 puts("Generating free bandwith classes ...");
1303 /*-----------------------------------------------------------------*/
1304 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1305 tc
, lan
, parent
, free_min
, free_max
,burst
, lowest_priority
);
1307 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1308 tc
, wan
, parent
, free_min
, free_max
, burst
, lowest_priority
);
1311 if(strcmpi(qos_leaf
, "none"))
1313 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, lan
, qos_leaf
);
1316 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc
, wan
, qos_leaf
);
1319 /* tc handle 1 fw flowid */
1320 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, lan
);
1323 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc
, wan
);
1326 printf("Total IP count: %d\n", i
);
1333 /* that's all folks, thank you for reading it all the way up to this point ;-) */
1334 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */
This page took 0.944973 seconds and 3 git commands to generate.