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-2008 Michael Polak (xChaos) */
6 /* iptables-restore support Copyright(C) 2007-2008 ludva */
7 /* Credit: CZFree.Net,Martin Devera,Netdave,Aquarius,Gandalf */
8 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
10 /* Modified by: xChaos, 20080728
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
36 const char *version
= "0.8.1-b";
38 /* Version numbers: 0.7.9 is development releases ("beta"), 0.8.0 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
= "<small>Statistics generated by Prometheus QoS version %s<br>GPL+Copyright(C)2005-2008 Michael Polak, <a href=\"http://www.arachne.cz/\">Arachne Labs</a></small>\n";
45 /* ======= All path names are defined here (for RPM patch) ======= */
47 char *tc
= "/sbin/tc"; /* requires tc with HTB support */
48 char *iptables
= "/sbin/iptables"; /* requires iptables utility */
49 char *iptablessave
= "/sbin/iptables-save"; /* not yet required */
50 char *iptablesrestore
= "/sbin/iptables-restore"; /* requires iptables-restore */
51 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 *html
= "/var/www/traffic.html"; /* hall of fame filename */
59 char *preview
= "/var/www/preview.html"; /* hall of fame preview */
60 char *cmdlog
= "/var/log/prometheuslog"; /* command log filename */
61 char *log_dir
= "/var/www/logs/"; /* log directory pathname, ended with slash */
62 char *log_url
= "logs/"; /* log directory relative URI prefix (partial URL) */
63 char *html_log_dir
= "/var/www/logs/html/";
65 /* ======= Help screen is hopefuly self-documenting part of code :-) ======= */
69 puts("Command line switches:\n\
71 -?, --help this help screen\n\
72 -v, --version show version number of this utility and exit\n\
73 -c filename force alternative /etc/prometheus.conf filename\n\
74 -h filename force alternative /etc/hosts filename (overrides hosts keyword)\n\
75 -f just flush iptables and tc classes and exit (stop shaping)\n\
76 -9 emergency iptables flush (do not read data transfer statistics)\n\
77 -p just generate preview of data transfer statistics and exit\n\
78 -n no delay (overrides qos-free-delay keyword)\n\
79 -d dry run (preview tc and iptables commands on stdout)\n\
80 -l Mmm YYYY generate HTML summary of traffic logs (Mmm=Jan-Dec or Year, YYYY=year)\n\
81 -m generate HTML summary of traffic logs for yesterday's month\n\
82 -y generate HTML summary of traffic logs for yesterday's year\n");
83 /* not yet implemented:
84 -s start shaping! (keep data transfer statistics - but apply shaping)\n\
85 -r just reload configuration (...and keep data transfer statistics)\n\
88 /* === Configuraration file values defaults - stored in global variables ==== */
90 int filter_type
= 1; /*1 mark, 2 classify*/
92 char *mark_iptables
= "MARK --set-mark ";
93 int dry_run
= 0; /* preview - use puts() instead of system() */
94 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]";
95 FILE *iptables_file
= NULL
;
96 int enable_credit
= 1; /* enable credit file */
97 int use_credit
= 0; /* use credit file (if enabled)*/
98 char *title
= "Hall of Fame - Greatest Suckers"; /* hall of fame title */
99 int hall_of_fame
= 1; /* enable hall of fame */
100 char *lan
= "eth0"; /* LAN interface */
101 char *lan_medium
= "100Mbit"; /* 10Mbit/100Mbit ethernet */
102 char *wan
= "eth1"; /* WAN/ISP interface */
103 char *wan_medium
= "100Mbit"; /* 10Mbit/100Mbit ethernet */
104 char *qos_leaf
= "sfq perturb 5"; /* leaf discipline */
105 char *qos_free_zone
= NULL
; /* QoS free zone */
106 int qos_proxy
= 1; /* include proxy port to QoS */
107 int include_upload
= 1; /* upload+download=total traffic */
108 char *proxy_ip
= "192.168.1.1/32"; /* our IP with proxy port */
109 int proxy_port
= 3128; /* proxy port number */
110 long long int line
= 1024; /* WAN/ISP download in kbps */
111 long long int up
= 1024; /* WAN/ISP upload in kbps */
112 int free_min
= 32; /* minimum guaranted bandwidth for all undefined hosts */
113 int free_max
= 64; /* maximum allowed bandwidth for all undefined hosts */
114 int qos_free_delay
= 0; /* seconds to sleep before applying new QoS rules */
115 int digital_divide
= 2; /* controls digital divide weirdness ratio, 1...3 */
116 int max_nesting
= 3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */
118 int burst
= 8; /* HTB burst (in kbits) */
120 int burst_group
= 32;
121 int magic_priorities
= 8; /* number of priority levels (soft shaping) */
122 int magic_treshold
= 8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */
123 int keywordcount
= 0;
124 /* not yet implemented:
125 int fixed_packets = 0; maximum number of pps per IP address (not class!)
126 int packet_limit = 5; maximum number of pps to htn CEIL, not rate !!!
128 FILE *log_file
= NULL
;
129 char *kwd
= "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */
131 const int idxtable_treshold1
=24; /* this is no longer configurable */
132 const int idxtable_treshold2
=12; /* this is no longer configurable */
133 const int idxtable_bitmask1
=3; /* this is no longer configurable */
134 const int idxtable_bitmask2
=3; /* this is no longer configurable */
136 /* ==== This is C<<1 stuff - learn C<<1 first! http://cll1.arachne.cz ==== */
150 unsigned long long direct
;
151 unsigned long long proxy
;
152 unsigned long long upload
;
153 unsigned long long traffic
;
154 unsigned long long credit
;
155 unsigned long pktsup
;
156 unsigned long pktsdown
;
157 struct Keyword
*keyword
;
159 } *ips
=NULL
, *ip
, *sharedip
;
168 } *groups
=NULL
, *group
;
174 struct Index
*parent
;
178 } *idxs
=NULL
, *idx
, *metaindex
;
184 int asymetry_ratio
; /* ratio for ADSL-like upload */
185 int asymetry_fixed
; /* fixed treshold for ADSL-like upload */
186 int data_limit
; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */
187 int data_prio
; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */
188 long fixed_limit
; /* fixed data limit for setting lower HTB ceil */
189 long fixed_prio
; /* fixed data lmit for setting lower HTB prio */
190 int reserve_min
; /* bonus for nominal HTB rate bandwidth (in kbps) */
191 int reserve_max
; /* malus for nominal HTB ceil (in kbps) */
192 // int divide_max; /* relative malus: new_ceil=rate+(old_ceil-rate)/divide_max */
193 // int htb_ceil_bonus_divide; /* relative bonus: new_ceil=old_ceil+old_ceil/htb_ceil_bonus_divide */
194 int default_prio
; /* default HTB priority for this keyword */
197 char *leaf_discipline
;
200 } *keyword
,*defaultkeyword
=NULL
,*keywords
=NULL
;
202 /* Damned, this must be object oriented! This looks almost like constructor ;-) */
212 ip
->mark
=ip
->min
=ip
->max
=ip
->desired
=ip
->credit
=0;
213 ip
->upload
=ip
->proxy
=ip
->direct
=ip
->traffic
=0;
214 ip
->pktsup
=ip
->pktsdown
=0;
215 ip
->keyword
=keywords
;
219 /* ====== iptables indexes are used to reduce complexity to log8(N) ===== */
221 char *very_ugly_ipv4_code(char *inip
,int bitmask
,int format_as_chainname
)
223 /* warning: this function was debugged only for bitmask values 20,24,28 !!!*/
225 char *ip
,*outip
,*outptr
,*fmt
;
228 /* debug printf("(%s,%d) -> ",ip,bitmask); */
230 if(ip
&& *ip
&& bitmask
>=0 && bitmask
<=32)
231 string(outip
,strlen(ip
)+10); /*fuck unicode? assertion: 10>strlen("_%d_%d") */
233 /* should never exit here */
240 if(dot
<(bitmask
/8-1))
242 if(format_as_chainname
)
251 char *cutdot
=strchr(ip
+1,'.'); /*for bitmask<24*/
252 if(cutdot
)*cutdot
='\0';
253 if(format_as_chainname
)
258 n
=atoi(ip
+1)-atoi(ip
+1)%(1<<(8-bitmask
%8));
262 /*debug printf("%d/%d => [_%d_%d]\n",atoi(ip+1),bitmask,n,bitmask); */
263 sprintf(outptr
,fmt
,n
,bitmask
);
264 if(!format_as_chainname
) while(bitmask
<24)
269 /* debug printf("[%s]\n",outip); */
280 /*should never exit here*/
285 char *hash_id(char *ip
,int bitmask
)
286 { return very_ugly_ipv4_code(ip
,bitmask
,1); }
288 char *subnet_id(char *ip
,int bitmask
)
289 { return very_ugly_ipv4_code(ip
,bitmask
,0); }
291 /* ================= Let's parse configuration file here =================== */
293 void reject_config_and_exit(char *filename
)
295 printf("Configuration file %s rejected - abnormal exit.",filename
);
299 void get_config(char *config_filename
)
303 printf("Configured keywords: ");
304 parse(config_filename
)
306 option("keyword",kwd
);
311 create(keyword
,Keyword
);
313 keyword
->asymetry_ratio
=1; /* ratio for ADSL-like upload */
314 keyword
->asymetry_fixed
=0; /* fixed treshold for ADSL-like upload */
315 keyword
->data_limit
=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */
316 keyword
->data_prio
=4; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */
317 keyword
->fixed_limit
=0; /* fixed data limit for setting lower HTB ceil */
318 keyword
->fixed_prio
=0; /* fixed data limit for setting lower HTB prio */
319 keyword
->reserve_min
=8; /* bonus for nominal HTB rate bandwidth (in kbps) */
320 keyword
->reserve_max
=0; /* malus for nominal HTB ceil (in kbps) */
322 keyword->divide_max=0; relative malus: new_ceil=rate+(old_ceil-rate)/divide_max
323 keyword->htb_ceil_bonus_divide=0; relative bonus: new_ceil=old_ceil+old_ceil/htb_ceil_bonus_divide
325 keyword
->default_prio
=1;
326 keyword
->html_color
="000000";
328 keyword
->leaf_discipline
="";
330 push(keyword
,keywords
);
331 if(!defaultkeyword
) defaultkeyword
=keyword
;
336 else every(keyword
,keywords
)
338 int l
=strlen(keyword
->key
);
341 if(!strncmp(keyword
->key
,_
,l
) && strlen(_
)>l
+2)
343 char *tmptr
=_
; /* <---- l+1 ----> */
344 _
+=l
+1; /* via-prometheus-asymetry-ratio, etc. */
345 ioption("asymetry-ratio",keyword
->asymetry_ratio
);
346 ioption("asymetry-treshold",keyword
->asymetry_fixed
);
347 ioption("magic-relative-limit",keyword
->data_limit
);
348 ioption("magic-relative-prio",keyword
->data_prio
);
349 loption("magic-fixed-limit",keyword
->fixed_limit
);
350 loption("magic-fixed-prio",keyword
->fixed_prio
);
351 ioption("htb-default-prio",keyword
->default_prio
);
352 ioption("htb-rate-bonus",keyword
->reserve_min
);
353 ioption("htb-ceil-malus",keyword
->reserve_max
);
355 ioption("htb-ceil-divide",keyword->divide_max);
356 ioption("htb-ceil-bonus-divide",keyword->htb_ceil_bonus_divide);
358 option("leaf-discipline",keyword
->leaf_discipline
);
359 option("html-color",keyword
->html_color
);
362 if(keyword
->data_limit
|| keyword
->fixed_limit
||
363 keyword
->data_prio
|| keyword
->fixed_prio
)
369 option("iptables",iptables
);
370 option("iptables-save",iptablessave
); /* new */
371 option("iptables-restore",iptablesrestore
); /* new */
372 option("iptables-file",iptablesfile
); /* new */
373 option("hosts",hosts
);
374 option("lan-interface",lan
);
375 option("wan-interface",wan
);
376 option("lan-medium",lan_medium
);
377 option("wan-medium",wan_medium
);
378 lloption("wan-download",line
);
379 lloption("wan-upload",up
);
380 ioption("hall-of-fame-enable",hall_of_fame
);
381 option("hall-of-fame-title",title
);
382 option("hall-of-fame-filename",html
);
383 option("hall-of-fame-preview",preview
);
384 option("log-filename",cmdlog
);
385 option("credit-filename",credit
);
386 ioption("credit-enable",enable_credit
);
387 option("log-traffic-directory",log_dir
);
388 option("log-traffic-html-directory",html_log_dir
);
389 option("log-traffic-url-path",log_url
);
390 option("qos-free-zone",qos_free_zone
);
391 ioption("qos-free-delay",qos_free_delay
);
392 ioption("qos-proxy-enable",qos_proxy
);
393 option("qos-proxy-ip",proxy_ip
);
394 option("htb-leaf-discipline",qos_leaf
);
395 ioption("qos-proxy-port",proxy_port
);
396 ioption("free-rate",free_min
);
397 ioption("free-ceil",free_max
);
398 ioption("htb-burst",burst
);
399 ioption("htb-burst-main",burst_main
);
400 ioption("htb-burst-group",burst_group
);
401 ioption("htb-nesting-limit",max_nesting
);
402 ioption("htb-r2q",htb_r2q
);
403 ioption("magic-include-upload",include_upload
);
404 ioption("magic-priorities",magic_priorities
);
405 ioption("magic-treshold",magic_treshold
);
406 option("filter-type", cnf
);
408 /* not yet implemented:
409 ioption("magic-fixed-packets",fixed_packets);
410 ioption("magic-relative-packets",packet_limit);
415 perror(config_filename
);
416 puts("Warning - using built-in defaults instead ...");
421 /*leaf discipline for keywords*/
422 every(keyword
,keywords
)
424 if (!strcmpi(keyword
->leaf_discipline
, "")){
425 keyword
->leaf_discipline
= qos_leaf
;
429 if (strcmpi(cnf
, "mark")){
432 mark_iptables
= "CLASSIFY --set-class 1:";
436 mark_iptables
= "MARK --set-mark ";
439 /* are supplied values meaningful ?*/
442 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");
443 reject_config_and_exit(config_filename
);
447 /* ===================== traffic analyser - uses iptables ================ */
449 void get_traffic_statistics(void)
454 textfile(Pipe
,str
) *line
,*lines
=NULL
;
458 sprintf(cmd
,"%s -L -v -x -n -t mangle",iptables
);
470 int col
, accept
=0,proxyflag
=0,valid
=1,setchainname
=0,commonflag
=0;
471 unsigned long long traffic
=0;
472 unsigned long pkts
=0;
473 char *ipaddr
=NULL
,*ptr
;
475 /* debug puts(line->str); */
476 valid_columns(ptr
,line
->str
,' ',col
)
477 if(valid
) switch(col
)
479 case 1: if(eq(ptr
,"Chain"))
481 else if(eq(ptr
,"pkts"))
484 sscanf(ptr
,"%lu",&pkts
);
486 case 2: if(setchainname
)
488 if(!strncmp(ptr
,"post_",5) || eq(ptr
,"POSTROUTING"))
491 if(!strncmp(ptr
,"forw_",5) || eq(ptr
,"FORWARD"))
494 if(eq(ptr
,"post_common") || eq(ptr
,"forw_common"))
498 sscanf(ptr
,"%Lu",&traffic
); traffic
+=(1<<19); traffic
>>=20;
500 case 3: if((strncmp(ptr
,"post_",5) && strncmp(ptr
,"forw_",5)) || commonflag
)
502 /*if (filter_type==1) accept=eq(ptr,"MARK"); else accept=eq(ptr,"CLASSIFY");*/
504 case 8: if(downloadflag
)
506 if(strstr(proxy_ip
,ptr
))proxyflag
=1;
511 case 9: if(downloadflag
)ipaddr
=ptr
;break;
514 if(accept
&& traffic
>0 && ipaddr
)
516 if(proxyflag
)printf("(proxy) ");
517 else if(!downloadflag
) printf("(upload) ");
518 printf("IP %s: %Lu M (%ld pkts)\n", ipaddr
, traffic
, pkts
);
519 find(ip
,ips
,eq(ip
->addr
,ipaddr
));
524 if(eq(ip
->addr
,"0.0.0.0/0"))
526 ip
->name
="(unregistered)";
528 ip
->max
=ip
->desired
=free_max
;
537 ip
->traffic
+=traffic
;
538 ip
->direct
=ip
->traffic
-ip
->upload
-ip
->proxy
;
546 ip
->traffic
+=traffic
;
548 if(traffic
>ip
->traffic
)
557 /* ========== This function executes, logs OR ALSO prints command ========== */
559 void safe_run(char *cmd
)
561 if(dry_run
) printf("\n=>%s\n",cmd
); else system(cmd
);
562 if(log_file
) fprintf(log_file
,"%s\n",cmd
);
565 void save_line(char *line
)
567 fprintf(iptables_file
,"%s\n",line
);
570 void run_restore(void)
573 string(restor
,STRLEN
);
575 /*-----------------------------------------------------------------*/
576 printf("Running %s <%s ...\n",iptablesrestore
,iptablesfile
);
577 /*-----------------------------------------------------------------*/
580 fclose(iptables_file
);
590 sprintf(restor
,"%s <%s",iptablesrestore
, iptablesfile
);
596 /* == This function strips extra characters after IP address and stores it = */
598 void parse_ip(char *str
)
600 char *ptr
=str
,*ipaddr
=NULL
,*ipname
=NULL
;;
602 while(*ptr
&& *ptr
!=' ' && *ptr
!=9)
608 while(*ptr
&& (*ptr
==' ' || *ptr
==9))
611 while(*ptr
&& *ptr
!=' ' && *ptr
!=9)
615 find(ip
,ips
,eq(ip
->addr
,ipaddr
)); else TheIP();
620 char *parse_datafile_line(char *str
)
622 char *ptr
=strchr(str
,' ');
642 void parse_ip_log(int argc
, char **argv
)
644 char *month
, *year
, *str
, *name
, *ptr
, *ptr2
, *filename
;
645 long traffic
, traffic_month
, total
=0, guaranted
;
646 int col
, col2
, y_ok
, m_ok
, accept_month
, i
=1, any_month
=0;
647 char mstr
[4], ystr
[5];
650 string(filename
,STRLEN
);
652 if(argv
[1][1]=='l') /* -l */
656 puts("Missing parameter(s)!\nUsage: prometheus -l Mmm YYYY (Mmm=Jan-Dec or Year, YYYY=year)");
662 if(eq(month
,"Year")) any_month
=1;
668 time_t t
= time(NULL
) - 3600*24 ; /* yesterday's timestamp*/
669 struct tm
*timep
= localtime(&t
);
671 if(argv
[1][1]=='m') /* -m yestarday - month */
673 strftime(mstr
, 4, "%b", timep
);
675 strftime(ystr
, 5, "%Y", timep
);
678 else /* -y yesterday - year */
682 strftime(ystr
, 5, "%Y", timep
);
686 printf("Analysing traffic for %s %s ...\n",month
,year
);
688 /* sorry... next release of C<<1 header file will include for_path_files(name,path) { } macro */
689 sprintf(str
,"%s %s/",ls
,log_dir
);
693 if(strstr(str
,".log"))
695 ptr
=strrchr(str
,'\n');
697 sprintf(filename
,"%s/%s",log_dir
,str
);
698 printf("Parsing %s ...",filename
);
705 valid_columns(ptr
,_
,'\t',col
) switch(col
)
707 case 2: name
= ptr
;break;
708 case 3: traffic
= atol(ptr
);break;
709 /* column number - was 7, now 10...*/
713 case 10: if (isalpha(*ptr
)) /* character, not numeric string = date, just one*/
715 valid_columns(ptr2
,ptr
,' ',col2
) switch(col2
)
717 case 2: if(any_month
|| eq(ptr2
,month
)) m_ok
= 1; break;
718 case 5: if(eq(ptr2
,year
)) y_ok
= 1; break;
723 if(col
== 7) guaranted
= atol(ptr
);
729 traffic_month
+= traffic
;
739 iplog
->guaranted
= guaranted
;
740 iplog
->traffic
= traffic_month
;
741 insert(iplog
,iplogs
,desc_order_by
,traffic
);
742 printf(" %ld MB\n",iplog
->traffic
);
745 puts(" no records.");
748 sprintf(str
,"%s/%s-%s.html",html_log_dir
,year
,month
);
749 printf("Writing %s ...",str
);
753 fprintf(f
,"<table border><tr><th colspan=\"2\">%s %s</th><th colspan=\"2\">Data transfers</th><th align=\"right\">Min.speed</th></tr>\n ",month
,year
);
757 fprintf(f
,"<tr><td align=\"right\">%d</td><th align=\"left\">%s</td><td align=\"right\">%ld MB</td><th align=\"right\">%ld GB</th><td align=\"right\">%ld kbps</th></tr>\n",
758 i
++, iplog
->name
, iplog
->traffic
, iplog
->traffic
>>10, iplog
->guaranted
);
759 total
+=iplog
->traffic
>>10;
761 fprintf(f
,"<tr><th colspan=\"3\" align=\"left\">Total:</th><th align=\"right\">%ld GB</th><th align=\"right\">%Ld kbps</th></tr>\n", total
, line
);
762 fputs("</table>\n", f
);
763 fprintf(f
, stats_html_signature
, version
);
770 /*-----------------------------------------------------------------*/
771 /* Are you looking for int main(int argc, char **argv) ? :-)) */
772 /*-----------------------------------------------------------------*/
780 int class_count
=0,ip_count
=0;
784 int just_preview
=0; /* preview - generate just stats */
785 int just_logs
=0; /* just parse logs */
787 char *chain_forward
, *chain_postrouting
;
791 Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\
792 Version %s - Copyright (C)2005-2008 Michael Polak (xChaos)\n\
793 iptables-restore & burst tunning & classify modification by Ludva\n\
794 Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version
);
796 /*----- Boring... we have to check command line options first: ----*/
800 argument("-c") { nextargument(config
); }
801 argument("-h") { nextargument(althosts
);}
802 argument("-d") { dry_run
=1; }
803 argument("-f") { just_flush
=1; }
804 argument("-9") { just_flush
=9; }
805 argument("-p") { just_preview
=1; }
806 argument("-n") { nodelay
=1; }
807 argument("-l") { just_logs
=1; }
808 argument("-m") { just_logs
=1; }
809 argument("-y") { just_logs
=1; }
810 argument("-?") { help(); exit(0); }
811 argument("--help") { help(); exit(0); }
812 argument("-v") { exit(0); }
813 argument("--version") { exit(0); }
817 puts("*** THIS IS JUST DRY RUN ! ***\n");
819 date(d
); /* this is typical cll1.h macro */
821 /*-----------------------------------------------------------------*/
822 printf("Parsing configuration file %s ...\n", config
);
823 /*-----------------------------------------------------------------*/
828 parse_ip_log(argc
,argv
);
832 if(althosts
) hosts
=althosts
;
836 /*-----------------------------------------------------------------*/
837 puts("Parsing iptables verbose output ...");
838 /*-----------------------------------------------------------------*/
839 get_traffic_statistics();
842 /*-----------------------------------------------------------------*/
843 printf("Parsing class defintion file %s ...\n", hosts
);
844 /*-----------------------------------------------------------------*/
845 int groupidx
= FIRSTGROUPID
;
850 if(*str
<'0' || *str
>'9')
853 //Does this IP share QoS class with some other ?
854 substring
=strstr(str
,"sharing-");
857 substring
+=8; //"sharing-"
860 ip
->sharing
=substring
;
861 ip
->keyword
=defaultkeyword
; /* settings for default keyword */
862 while(*substring
&& *substring
!='\n')
868 //Do we have to create new QoS class for this IP ?
870 find(keyword
,keywords
,(substring
=strstr(str
,keyword
->key
)))
876 ip
->prio
=keyword
->default_prio
;
877 substring
+=strlen(keyword
->key
)+1;
879 while(*ptr
&& *ptr
!='-')
884 ip
->max
=ip
->desired
=atoi(ptr
+1);
886 ip
->min
=atoi(substring
);
889 printf(" %s: Illegal value of minimum bandwidth 0 kbps, using %d kbps\n",str
,free_min
);
895 ip
->max
=ip
->min
+ip
->keyword
->reserve_min
;
899 ip
->max
-=ip
->keyword
->reserve_max
;
902 if(ip->keyword->divide_max>1)
903 ip->max=ip->min+(ip->max-ip->min)/ip->keyword->divide_max;
904 if(ip->keyword->htb_ceil_bonus_divide>0)
905 ip->max+=ip->max/ip->keyword->htb_ceil_bonus_divide;
910 ip
->mark
=FIRSTIPCLASS
+1+class_count
++;
912 find(group
,groups
,group
->min
==ip
->min
)
915 group
->desired
+=ip
->min
;
916 ip
->group
= group
->id
;
922 group
->id
= groupidx
++;
923 ip
->group
= group
->id
;
925 if(group
->min
<8) group
->min
=8;
926 /* Warning - this is maybe because of primitive tc namespace, can be fixed */
927 /* it is because class IDs are derived from min. bandwidth. - xCh */
928 //if(group->min>MAX_GUARANTED_KBPS) group->min=MAX_GUARANTED_KBPS;
931 group
->desired
=ip
->min
;
932 insert(group
,groups
,desc_order_by
,min
);
944 /*-----------------------------------------------------------------*/
945 /* cll1.h - let's allocate brand new character buffer... */
946 /*-----------------------------------------------------------------*/
949 /*-----------------------------------------------------------------*/
950 puts("Resolving shared connections ...");
951 /*-----------------------------------------------------------------*/
952 search(ip
,ips
,ip
->sharing
)
954 search(sharedip
,ips
,eq(sharedip
->name
,ip
->sharing
))
956 sharedip
->traffic
+=ip
->traffic
;
958 ip
->mark
=sharedip
->mark
;
962 printf("Unresolved shared connection: %s %s sharing-%s\n",ip
->addr
,ip
->name
,ip
->sharing
);
965 if(enable_credit
&& just_flush
<9)
967 /*-----------------------------------------------------------------*/
968 printf("Parsing credit file %s ...\n", credit
);
969 /*-----------------------------------------------------------------*/
972 ptr
=parse_datafile_line(_
);
975 find(ip
,ips
,eq(ip
->addr
,_
))
976 sscanf(ptr
,"%Lu",&(ip
->credit
));
984 /*-----------------------------------------------------------------*/
985 puts("Initializing iptables and tc classes ...");
986 /*-----------------------------------------------------------------*/
988 iptables_file
=fopen(iptablesfile
,"w");
989 if (iptables_file
== NULL
) {
990 puts("Cannot open iptablesfile!");
994 log_file
=fopen(cmdlog
,"w");
995 if (log_file
== NULL
) {
996 puts("Cannot open logfile!");
1000 save_line(iptablespreamble
);
1003 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,lan
);
1006 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null",tc
,wan
);
1009 iptables_file
=fopen(iptablesfile
,"w");
1010 save_line(iptablespreamble
);
1012 if(qos_free_zone
&& *qos_free_zone
!='0')
1016 sprintf(str
,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone
, wan
);
1021 save_line(":post_noproxy - [0:0]");
1022 sprintf(str
,"-A POSTROUTING -p ! tcp -o %s -j post_noproxy", lan
);
1024 sprintf(str
,"-A POSTROUTING -s ! %s -o %s -j post_noproxy", proxy_ip
, lan
);
1026 sprintf(str
,"-A POSTROUTING -s %s -p tcp --sport ! %d -o %s -j post_noproxy", proxy_ip
, proxy_port
, lan
);
1029 chain
="post_noproxy";
1032 chain
="POSTROUTING";
1034 sprintf(str
,"-A %s -s %s -o %s -j ACCEPT", chain
, qos_free_zone
, lan
);
1038 if(ip_count
>idxtable_treshold1
&& !just_flush
)
1040 int idxcount
=0, bitmask
=32-idxtable_bitmask1
; /* default net mask: 255.255.255.240 */
1042 /*-----------------------------------------------------------------*/
1043 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count
);
1044 /*-----------------------------------------------------------------*/
1046 save_line(":post_common - [0:0]");
1047 save_line(":forw_common - [0:0]");
1049 search(ip
,ips
,ip
->addr
&& *(ip
->addr
) && !eq(ip
->addr
,"0.0.0.0/0"))
1051 buf
=hash_id(ip
->addr
,bitmask
);
1052 find(idx
,idxs
,eq(idx
->id
,buf
))
1059 idx
->bitmask
=bitmask
;
1067 /* brutal perfomance optimalization */
1068 while(idxcount
>idxtable_treshold2
&& bitmask
>2*idxtable_bitmask2
)
1070 bitmask
-=idxtable_bitmask2
;
1072 search(idx
,idxs
,idx
->parent
==NULL
)
1074 buf
=hash_id(idx
->addr
,bitmask
);
1075 find(metaindex
,idxs
,eq(metaindex
->id
,buf
))
1076 metaindex
->children
++;
1079 create(metaindex
,Index
);
1080 metaindex
->addr
=idx
->addr
;
1082 metaindex
->bitmask
=bitmask
;
1083 metaindex
->parent
=NULL
;
1084 metaindex
->children
=0;
1086 push(metaindex
,idxs
);
1088 idx
->parent
=metaindex
;
1092 /* this should slightly optimize throughout ... */
1093 sort(idx
,idxs
,desc_order_by
,children
);
1094 sort(idx
,idxs
,order_by
,bitmask
);
1099 subnet
=subnet_id(idx
->addr
,idx
->bitmask
);
1100 printf("%d: %s/%d\n",++i
,subnet
,idx
->bitmask
);
1102 sprintf(str
,":post_%s - [0:0]", idx
->id
);
1105 sprintf(str
,":forw_%s - [0:0]", idx
->id
);
1110 string(buf
,strlen(idx
->parent
->id
)+6);
1111 sprintf(buf
,"post_%s",idx
->parent
->id
);
1116 sprintf(str
,"-A %s -d %s/%d -o %s -j post_%s", buf
, subnet
, idx
->bitmask
, lan
, idx
->id
);
1119 sprintf(str
,"-A %s -d %s/%d -o %s -j post_common", buf
, subnet
, idx
->bitmask
, lan
);
1124 string(buf
,strlen(idx
->parent
->id
)+6);
1125 sprintf(buf
,"forw_%s",idx
->parent
->id
);
1130 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_%s", buf
, subnet
, idx
->bitmask
, wan
, idx
->id
);
1133 sprintf(str
,"-A %s -s %s/%d -o %s -j forw_common", buf
, subnet
, idx
->bitmask
, wan
);
1136 printf("Total indexed iptables chains created: %d\n", i
);
1138 sprintf(str
,"-A FORWARD -o %s -j forw_common", wan
);
1141 sprintf(str
,"-A POSTROUTING -o %s -j post_common", lan
);
1149 fclose(iptables_file
);
1150 if (log_file
) fclose(log_file
);
1151 puts("Just flushed iptables and tc classes - now exiting ...");
1157 if(!dry_run
&& !nodelay
&& qos_free_delay
)
1159 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay
);
1160 sleep(qos_free_delay
);
1163 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc
,lan
,htb_r2q
);
1166 sprintf(str
,"%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio 0",tc
,lan
,lan_medium
,lan_medium
,burst_main
);
1169 sprintf(str
,"%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio 0",tc
,lan
,line
,line
,burst_main
);
1172 sprintf(str
,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc
,wan
,htb_r2q
);
1175 sprintf(str
,"%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio 0",tc
,wan
,wan_medium
,wan_medium
,burst_main
);
1178 sprintf(str
,"%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio 0",tc
,wan
,up
,up
,burst_main
);
1182 /*-----------------------------------------------------------------*/
1183 puts("Locating suckers and generating root classes ...");
1184 /*-----------------------------------------------------------------*/
1185 sort(ip
,ips
,desc_order_by
,traffic
);
1188 /*-----------------------------------------------------------------*/
1189 /* sub-scope - local variables */
1191 long long int rate
=line
;
1192 long long int max
=line
;
1194 FILE *credit_file
=NULL
;
1196 if(!just_preview
&& !dry_run
&& enable_credit
) credit_file
=fopen(credit
,"w");
1204 sprintf(str
,"%s class add dev %s parent 1:%d classid 1:%d htb rate %Ldkbit ceil %Ldkbit burst %dk prio 1 #down desired %d",
1205 tc
, lan
, parent
, group
->id
, rate
, max
, burst_group
, group
->desired
);
1209 sprintf(str
,"%s class add dev %s parent 1:%d classid 1:%d htb rate %Ldkbit ceil %Ldkbit burst %dk prio 1 #up desired %d",
1210 tc
, wan
, parent
, group
->id
, rate
*up
/line
, max
*up
/line
, burst_group
, group
->desired
);
1214 if(group_count
++<max_nesting
) parent
=group
->id
;
1216 rate
-=digital_divide
*group
->min
;
1217 if(rate
<group
->min
)rate
=group
->min
;
1219 /*shaping of aggresive downloaders, with credit file support */
1222 int group_rate
=group
->min
, priority_sequence
=magic_priorities
+1;
1224 search(ip
, ips
, ip
->min
==group
->min
&& ip
->max
>ip
->min
)
1226 if( ip
->keyword
->data_limit
&& !ip
->fixedprio
&&
1227 ip
->traffic
>ip
->credit
+
1228 (ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20)) )
1230 if(group_rate
<ip
->max
) ip
->max
=group_rate
;
1231 group_rate
+=magic_treshold
;
1232 ip
->prio
=magic_priorities
+2;
1233 if(ip
->prio
<3) ip
->prio
=3;
1237 if( ip
->keyword
->data_prio
&& !ip
->fixedprio
&&
1238 ip
->traffic
>ip
->credit
+
1239 (ip
->min
*ip
->keyword
->data_prio
+(ip
->keyword
->fixed_prio
<<20)) )
1241 ip
->prio
=priority_sequence
--;
1242 if(ip
->prio
<2) ip
->prio
=2;
1247 unsigned long long lcredit
=0;
1249 if((ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))>ip
->traffic
)
1250 lcredit
=(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20))-ip
->traffic
;
1251 fprintf(credit_file
,"%s %Lu\n",ip
->addr
,lcredit
);
1258 if(credit_file
)fclose(credit_file
);
1263 f
=fopen(preview
,"w");
1266 else if(!dry_run
&& !just_flush
)
1268 /*-----------------------------------------------------------------*/
1269 printf("Writing data transfer database ...\n");
1270 /*-----------------------------------------------------------------*/
1271 f
=fopen("/var/run/prometheus.previous","w");
1274 search(ip
,ips
,ip
->traffic
|| ip
->direct
|| ip
->proxy
||ip
->upload
)
1275 fprintf(f
,"%s %Lu %Lu %Lu %Lu\n",ip
->addr
,ip
->traffic
,ip
->direct
,ip
->proxy
,ip
->upload
);
1289 /*-----------------------------------------------------------------*/
1290 printf("Sorting data and generating statistics page %s ...\n",ptr
);
1291 /*-----------------------------------------------------------------*/
1293 fputs("<table border>\n<tr><th align=\"right\">#</th><th align=\"right\">group</th><th align=\"right\">IPs</th><th align=\"right\">requested</th>\n",f
);
1294 fprintf(f
,"<th colspan=\"%d\">data limits</th>\n",keywordcount
);
1299 printf("%d k group: %d bandwidth requested: %d k\n",group
->min
,group
->count
,group
->desired
);
1301 fprintf(f
,"<tr><td align=\"right\">%d</td><td align=\"right\">%d k</td>",count
,group
->min
);
1302 fprintf(f
,"<td align=\"right\">%d</td><td align=\"right\">%d k</td>",group
->count
,group
->desired
);
1304 every(keyword
,keywords
)
1305 fprintf(f
,"<td align=\"right\"><font color=\"#%s\">%d M</font></td>",keyword
->html_color
,group
->min
*keyword
->data_limit
);
1308 total
+=group
->count
;
1312 printf("Total groups: %d Total bandwidth requested: %d k\nAGGREGATION: 1/%d\n",count
,i
,i
/line
);
1314 fprintf(f
,"<tr><th colspan=\"2\" align=\"left\">Line %Ld k</td>",line
);
1315 fprintf(f
,"<th align=\"right\">%d</td><th align=\"right\">%d k</td>",total
,i
);
1317 every(keyword
,keywords
)
1318 fprintf(f
,"<th align=\"right\">%d IPs</th>",keyword
->ip_count
);
1320 fprintf(f
,"</tr><tr><th colspan=\"4\">Aggregation 1/%d</th>\n",(int)(0.5+i
/line
));
1321 fprintf(f
,"<th colspan=\"%d\">%d traffic classes</th></tr>\n",keywordcount
,total
);
1323 fputs("</table>\n",f
);
1325 else if(!dry_run
&& !just_flush
)
1331 unsigned long long total
=0, total_direct
=0, total_proxy
=0, total_upload
=0, tmp_sum
=0;
1332 int active_classes
=0;
1335 struct Sum
{unsigned long long l
; int i
; list(Sum
);} *sum
,*sums
=NULL
;
1342 fprintf(f
,"<p><table border>\n<tr><th colspan=\"%d\">%s",colspan
,title
);
1343 fprintf(f
," (%s)</th></tr>\n", d
);
1344 fputs("<tr><td align=\"right\">#</td><td>hostname</td>\
1345 <td align=\"right\">credit</td>\
1346 <td align=\"right\">limit</td>\
1347 <td align=\"right\">total</td>\
1348 <td align=\"right\">direct</td>\n",f
);
1350 fputs("<td align=\"right\">proxy</td>\n",f
);
1351 fputs("<td align=\"right\">upload</td>\
1352 <td align=\"right\">minimum</td>\
1353 <td align=\"right\">desired</td>\
1354 <td align=\"right\">maximum</td>\
1355 <td>prio</td></tr>\n",f
);
1359 char *f1
="", *f2
="";
1360 if(ip
->max
<ip
->desired
)
1362 f1
="<font color=\"red\">";
1367 f1
="<font color=\"brown\">";
1372 printf("%03d. %-22s %10Lu (%d/%d)\n",i
,ip
->name
, ip
->traffic
, ip
->min
, ip
->max
);
1374 fprintf(f
,"<tr><td align=\"right\"><a name=\"%s\"></a>%d</td><td><a href=\"%s%s.log\">%s</a></td><td align=\"right\">%Lu M</td>\n",
1375 ip
->name
, i
, log_url
, ip
->name
, ip
->name
, ip
->credit
);
1376 fprintf(f
,"<td align=\"right\"><font color=\"#%s\">%Lu M</font></td>",ip
->keyword
->html_color
,ip
->credit
+(ip
->min
*ip
->keyword
->data_limit
+(ip
->keyword
->fixed_limit
<<20)));
1377 fprintf(f
,"<td align=\"right\">%s%Lu M%s</td><td align=\"right\">%Lu M</td>\n", f1
, ip
->traffic
, f2
, ip
->direct
);
1379 fprintf(f
,"<td align=\"right\">%Lu M</td>\n", ip
->proxy
);
1380 fprintf(f
,"<td align=\"right\">%Lu M</td>\n", ip
->upload
);
1381 fprintf(f
,"<td align=\"right\">%d k</td><td align=\"right\">%d k</td><td align=\"right\">%s%d k%s</td><td>%s%d%s</td></tr>\n",ip
->min
,ip
->desired
,f1
,ip
->max
,f2
,f1
,ip
->prio
,f2
);
1383 total_direct
+=ip
->direct
;
1384 total_proxy
+=ip
->proxy
;
1385 total_upload
+=ip
->upload
;
1389 tmp_sum
+=ip
->traffic
;
1392 sum
->i
=active_classes
;
1393 insert(sum
,sums
,order_by
,i
);
1400 sprintf(str
,"%s/%s.log",log_dir
,ip
->name
);
1401 iplog
=fopen(str
,"a");
1404 fprintf(iplog
,"%ld\t%s\t%Lu\t%Lu\t%Lu\t%Lu\t%d\t%d\t%d\t%s",
1405 time(NULL
),ip
->name
,ip
->traffic
,ip
->direct
,ip
->proxy
,ip
->upload
,ip
->min
,ip
->max
,ip
->desired
,d
); /* d = date*/
1411 fprintf(f
,"<tr><th colspan=\"4 \"align=\"left\">SUMMARY:</td>");
1412 fprintf(f
,"<th align=\"right\">%Lu M</th>\
1413 <th align=\"right\">%Lu M</th>\n", total
, total_direct
);
1415 fprintf(f
,"<th align=\"right\">%Lu M</th>\n", total_proxy
);
1416 fprintf(f
,"<th align=\"right\">%Lu M</th>", total_upload
);
1417 fputs("<td colspan=\"4\"></td></th>\n</table>\n",f
);
1419 if(active_classes
>10)
1421 fputs("<a name=\"erp\"></a><p><table border><tr><th colspan=\"5\">Enterprise Research and Planning (ERP)</th></tr>\n",f
);
1422 fputs("<tr><td>Analytic category</td>\n",f
);
1423 fputs("<td colspan=\"2\" align=\"center\">Active Classes</td><td colspan=\"2\" align=\"center\">Data transfers</td></tr>\n",f
);
1425 find(sum
,sums
,sum
->l
>=total
/4)
1427 fprintf(f
,"<tr><td>Top 25%% of traffic</td>\n");
1428 fprintf(f
,"<td align=\"right\">%d</td><td align=\"right\">%d %%</td><td align=\"right\">%Lu M</td><td align=\"right\">%Ld %%</td></tr>\n",sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total
);
1431 find(sum
,sums
,sum
->i
==10)
1433 fprintf(f
,"<tr><td>Top 10 downloaders</td>\n");
1434 fprintf(f
,"<th align=\"right\">10</th><td align=\"right\">%d %%</td><td align=\"right\">%Lu M</td><td align=\"right\">%Ld %%</td></tr>\n",(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total
);
1437 find(sum
,sums
,sum
->l
>=total
/2)
1439 fprintf(f
,"<tr><td>Top 50%% of traffic</td>\n");
1440 fprintf(f
,"<td align=\"right\">%d</td><td align=\"right\">%d %%</td><td align=\"right\">%Lu M</td><th align=\"right\">%Ld %%</th></tr>\n",sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total
);
1443 find(sum
,sums
,sum
->l
>=4*total
/5)
1445 fprintf(f
,"<tr><td>Top 80%% of traffic</td>\n");
1446 fprintf(f
,"<td align=\"right\">%d</td><td align=\"right\">%d %%</td><td align=\"right\">%Lu M</td><th align=\"right\">%Ld %%</th></tr>\n",sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total
);
1449 find (sum
,sums
,sum
->i
>=(active_classes
+1)/5)
1451 fprintf(f
,"<tr><td>Top 20%% downloaders</td>\n");
1452 fprintf(f
,"<td align=\"right\">%d</td><th align=\"right\">%d %%</th><td align=\"right\">%Lu M</td><td align=\"right\">%Ld %%</td></tr>\n",sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total
);
1455 find(sum
,sums
,sum
->i
>=(active_classes
+1)/4)
1457 fprintf(f
,"<tr><td>Top 25%% downloaders</td>\n");
1458 fprintf(f
,"<td align=\"right\">%d</td><td align=\"right\">%d %%</td><td align=\"right\">%Lu M</td><td align=\"right\">%Ld %%</td></tr>\n",sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total
);
1461 find(sum
,sums
,sum
->i
>=(active_classes
+1)/2)
1463 fprintf(f
,"<tr><td>Top 50%% downloaders</td>\n");
1464 fprintf(f
,"<td align=\"right\">%d</td><th align=\"right\">%d %%</th><td align=\"right\">%Lu M</td><td align=\"right\">%Ld %%</td></tr>\n",sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total
);
1467 find(sum
,sums
,sum
->i
>=4*(active_classes
+1)/5)
1469 fprintf(f
,"<tr><td>Top 80%% downloaders</td>\n");
1470 fprintf(f
,"<td align=\"right\">%d</td><td align=\"right\">%d %%</td><td align=\"right\">%Lu M</td><td align=\"right\">%Ld %%</td></tr>\n",sum
->i
,(100*sum
->i
+50)/active_classes
,sum
->l
,(100*sum
->l
+50)/total
);
1473 fprintf(f
,"<tr><td>All users, all traffic</td>\n");
1474 fprintf(f
,"<th align=\"right\">%d</th><th align=\"right\">100 %%</th><th align=\"right\">%Lu M</th><th align=\"right\">100 %%</th></tr>\n",active_classes
,total
);
1475 fputs("</table>\n", f
);
1477 fprintf(f
, stats_html_signature
, version
);
1483 puts("Statistics preview generated (-p switch) - now exiting ...");
1487 /*-----------------------------------------------------------------*/
1488 puts("Generating iptables and tc classes ...");
1489 /*-----------------------------------------------------------------*/
1492 printf("%-22s %-15s mark\n","name","ip");
1493 search(ip
,ips
,ip
->mark
>0)
1499 duplicate(ip
->addr
,buf
);
1500 buf
=hash_id(ip
->addr
,32-idxtable_bitmask1
);
1502 string(chain_forward
,6+strlen(buf
));
1503 strcpy(chain_forward
,"forw_");
1504 strcat(chain_forward
,buf
);
1506 string(chain_postrouting
,6+strlen(buf
));
1507 strcpy(chain_postrouting
,"post_");
1508 strcat(chain_postrouting
,buf
);
1514 chain_forward
="FORWARD";
1515 chain_postrouting
="POSTROUTING";
1518 printf("%-22s %-16s %04d ", ip
->name
, ip
->addr
, ip
->mark
);
1520 /* -------------------------------------------------------- mark download */
1522 sprintf(str
,"-A %s -d %s/32 -o %s -j %s%d",chain_postrouting
,ip
->addr
,lan
,mark_iptables
,ip
->mark
);
1523 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/
1524 /* -m limit --limit 1/s */
1529 sprintf(str
,"-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",chain_postrouting
,proxy_ip
,proxy_port
,ip
->addr
,lan
,mark_iptables
,ip
->mark
);
1530 /*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);*/
1534 sprintf(str
,"-A %s -d %s/32 -o %s -j ACCEPT",chain_postrouting
,ip
->addr
,lan
);
1537 /* -------------------------------------------------------- mark upload */
1538 sprintf(str
,"-A %s -s %s/32 -o %s -j %s%d",chain_forward
,ip
->addr
,wan
,mark_iptables
,ip
->mark
);
1539 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/
1542 sprintf(str
,"-A %s -s %s/32 -o %s -j ACCEPT",chain_forward
,ip
->addr
,wan
);
1547 /* -------------------------------------------------------- download class */
1548 printf("(down: %dk-%dk ", ip
->min
, ip
->max
);
1550 sprintf(str
,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", tc
, lan
, ip
->group
, ip
->mark
,ip
->min
,ip
->max
, burst
, ip
->prio
);
1553 if (strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1555 sprintf(str
,"%s qdisc add dev %s parent 1:%d handle %d %s", tc
, lan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1558 if (filter_type
== 1)
1560 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d", tc
, lan
, ip
->mark
, ip
->mark
);
1564 /* -------------------------------------------------------- upload class */
1565 printf("up: %dk-%dk)\n", (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1566 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1568 sprintf(str
,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1569 tc
, wan
, ip
->group
, ip
->mark
,
1570 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1571 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1574 if (strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1576 sprintf(str
,"%s qdisc add dev %s parent 1:%d handle %d %s",tc
, wan
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1579 if (filter_type
== 1)
1581 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",tc
, wan
, ip
->mark
, ip
->mark
);
1586 printf("(sharing %s)\n", ip
->sharing
);
1592 chain_forward
= "forw_common";
1593 chain_postrouting
= "post_common";
1597 chain_forward
= "FORWARD";
1598 chain_postrouting
= "POSTROUTING";
1600 /* -------------------------------- classify or reject free download */
1602 char *final_chain
= "DROP"; /* REJECT would be better, but it is impossible in mangle */
1603 if(free_min
) final_chain
= "ACCEPT";
1608 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s%d",chain_postrouting
,proxy_ip
,proxy_port
,lan
,mark_iptables
,3);
1611 sprintf(str
,"-A %s -s %s -p tcp --sport %d -o %s -j %s",chain_postrouting
,proxy_ip
,proxy_port
,lan
,final_chain
);
1616 sprintf(str
,"-A %s -o %s -j %s%d",chain_postrouting
,lan
,mark_iptables
,3);
1619 sprintf(str
,"-A %s -o %s -j %s",chain_postrouting
,lan
,final_chain
);
1621 /* ------------------------------- classify or reject free upload */
1624 sprintf(str
,"-A %s -o %s -j %s%d",chain_forward
,wan
,mark_iptables
,3);
1627 sprintf(str
,"-A %s -o %s -j %s",chain_forward
,wan
,final_chain
);
1631 if(free_min
) /* allocate free bandwith if it is not zero... */
1633 /*-----------------------------------------------------------------*/
1634 puts("Generating free bandwith classes ...");
1635 /*-----------------------------------------------------------------*/
1636 sprintf(str
,"%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio 2",tc
,lan
,parent
,free_min
,free_max
,burst
);
1638 sprintf(str
,"%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio 2",tc
,wan
,parent
,free_min
,free_max
,burst
);
1641 if (strcmpi(qos_leaf
, "none"))
1643 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s",tc
,lan
,qos_leaf
);
1646 sprintf(str
,"%s qdisc add dev %s parent 1:3 handle 3 %s",tc
,wan
,qos_leaf
);
1649 /* tc handle 1 fw flowid */
1650 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3",tc
,lan
);
1653 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3",tc
,wan
);
1656 printf("Total IP count: %d\n", i
);
1658 if (log_file
) fclose(log_file
);
1660 /* that's all folks, thank you for reading it all the way up to this point ;-) */
1661 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */
This page took 1.320084 seconds and 4 git commands to generate.