ehm
[svn/Prometheus-QoS/.git] / prometheus.c
CommitLineData
312ac2c1 1 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2 /* Prometheus QoS - you can "steal fire" from your ISP */\r
3/* "fair-per-IP" quality of service (QoS) utility */\r
4/* requires Linux 2.4.x or 2.6.x with HTB support */\r
5/* Copyright(C) 2005-2008 Michael Polak (xChaos) */\r
6/* iptables-restore support Copyright(C) 2007-2008 ludva */\r
7/* Credit: CZFree.Net,Martin Devera,Netdave,Aquarius,Gandalf */\r
8/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
9\r
a031788f 10/* Modified by: xChaos, 20080728\r
11 ludva, 20080415\r
007c44c5 12\r
13 Prometheus QoS is free software; you can redistribute it and/or\r
14 modify it under the terms of the GNU General Public License as \r
15 published by the Free Software Foundation; either version 2.1 of \r
16 the License, or (at your option) any later version.\r
17\r
18 Prometheus QoS is distributed in the hope that it will be useful,\r
19 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
21 General Public License for more details.\r
22\r
c9012978 23 You should have received a copy of the GNU General Public License\r
24 along with Prometheus Qos; if not, write to the Free Software\r
d1ae4fa7 25 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA \r
26 \r
c9012978 27 GNU General Public License is located in file COPYING */\r
007c44c5 28\r
29#define STRLEN 256\r
30#define FIRSTGROUPID 1024\r
43e07280 31#define FIRSTIPCLASS 2048\r
007c44c5 32#undef DEBUG\r
33\r
211415b9 34#include "cll1-0.6.h"\r
007c44c5 35\r
32eee498 36const char *version = "0.8.1-b"; \r
007c44c5 37\r
43cde5c3 38/* Version numbers: 0.7.9 is development releases ("beta"), 0.8.0 will be "stable" */\r
b1b59b3a 39/* Debian(RPM) package versions/patchlevels: 0.7.9-2, 0.8.0-1, 0.8.0-2, etc. */\r
40/* C source code development versions ("beta"): 0.7.9-a, 0.8.1-b, etc. */\r
41/* C source code release versions: 0.8.0, 0.8.2, 0.8.4, etc. */\r
77e71d6b 42\r
2d114137 43const 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";\r
44\r
82c702a1 45/* ======= All path names are defined here (for RPM patch) ======= */\r
ae776b10 46\r
2d114137 47char *tc = "/sbin/tc"; /* requires tc with HTB support */\r
48char *iptables = "/sbin/iptables"; /* requires iptables utility */\r
49char *iptablessave = "/sbin/iptables-save"; /* not yet required */\r
ae776b10 50char *iptablesrestore = "/sbin/iptables-restore"; /* requires iptables-restore */\r
2d114137 51char *ls = "/bin/ls"; /* this is not user configurable :-) */\r
ae776b10 52\r
2d114137 53char *config = "/etc/prometheus/prometheus.conf"; /* main configuration file */\r
54char *hosts = "/etc/prometheus/hosts"; /* per-IP bandwidth definition file */\r
ae776b10 55\r
2d114137 56char *iptablesfile = "/var/spool/prometheus.iptables"; /* temporary file for iptables-restore*/\r
57char *credit = "/var/lib/misc/prometheus.credit"; /* credit log file */\r
58char *html = "/var/www/traffic.html"; /* hall of fame filename */\r
59char *preview = "/var/www/preview.html"; /* hall of fame preview */\r
60char *cmdlog = "/var/log/prometheuslog"; /* command log filename */\r
61char *log_dir = "/var/www/logs/"; /* log directory pathname, ended with slash */\r
62char *log_url = "logs/"; /* log directory relative URI prefix (partial URL) */\r
63char *html_log_dir = "/var/www/logs/html/";\r
ae776b10 64\r
007c44c5 65/* ======= Help screen is hopefuly self-documenting part of code :-) ======= */\r
66\r
67void help(void)\r
68{\r
69 puts("Command line switches:\n\\r
70\n\\r
71-?, --help this help screen\n\\r
72-v, --version show version number of this utility and exit\n\\r
73-c filename force alternative /etc/prometheus.conf filename\n\\r
74-h filename force alternative /etc/hosts filename (overrides hosts keyword)\n\\r
75-f just flush iptables and tc classes and exit (stop shaping)\n\\r
76-9 emergency iptables flush (do not read data transfer statistics)\n\\r
77-p just generate preview of data transfer statistics and exit\n\\r
78-n no delay (overrides qos-free-delay keyword)\n\\r
79-d dry run (preview tc and iptables commands on stdout)\n\\r
5b902402 80-l Mmm YYYY generate HTML summary of traffic logs (Mmm=Jan-Dec or Year, YYYY=year)\n\\r
81-m generate HTML summary of traffic logs for yesterday's month\n\\r
82-y generate HTML summary of traffic logs for yesterday's year\n");\r
83/* not yet implemented:\r
84-s start shaping! (keep data transfer statistics - but apply shaping)\n\\r
85-r just reload configuration (...and keep data transfer statistics)\n\\r
86*/\r
007c44c5 87}\r
007c44c5 88/* === Configuraration file values defaults - stored in global variables ==== */\r
89\r
43cde5c3 90int filter_type = 1; /*1 mark, 2 classify*/\r
91char *mark = "MARK";\r
92char *mark_iptables = "MARK --set-mark ";\r
93int dry_run = 0; /* preview - use puts() instead of system() */\r
94char *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]";\r
95FILE *iptables_file = NULL;\r
96int enable_credit = 1; /* enable credit file */\r
97int use_credit = 0; /* use credit file (if enabled)*/\r
98char *title = "Hall of Fame - Greatest Suckers"; /* hall of fame title */\r
99int hall_of_fame = 1; /* enable hall of fame */\r
100char *lan = "eth0"; /* LAN interface */\r
101char *lan_medium = "100Mbit"; /* 10Mbit/100Mbit ethernet */\r
102char *wan = "eth1"; /* WAN/ISP interface */\r
103char *wan_medium = "100Mbit"; /* 10Mbit/100Mbit ethernet */\r
104char *qos_leaf = "sfq perturb 5"; /* leaf discipline */\r
105char *qos_free_zone = NULL; /* QoS free zone */\r
106int qos_proxy = 1; /* include proxy port to QoS */\r
107int include_upload = 1; /* upload+download=total traffic */\r
108char *proxy_ip = "192.168.1.1/32"; /* our IP with proxy port */\r
109int proxy_port = 3128; /* proxy port number */\r
110long long int line = 1024; /* WAN/ISP download in kbps */\r
111long long int up = 1024; /* WAN/ISP upload in kbps */\r
112int free_min = 32; /* minimum guaranted bandwidth for all undefined hosts */\r
113int free_max = 64; /* maximum allowed bandwidth for all undefined hosts */\r
114int qos_free_delay = 0; /* seconds to sleep before applying new QoS rules */\r
115int digital_divide = 2; /* controls digital divide weirdness ratio, 1...3 */ \r
116int max_nesting = 3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */\r
117int htb_r2q = 1; \r
118int burst = 8; /* HTB burst (in kbits) */\r
119int burst_main = 64;\r
120int burst_group = 32;\r
121int magic_priorities = 8; /* number of priority levels (soft shaping) */\r
122int magic_treshold = 8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */\r
123int keywordcount = 0;\r
007c44c5 124/* not yet implemented:\r
43cde5c3 125int fixed_packets = 0; maximum number of pps per IP address (not class!) \r
126int packet_limit = 5; maximum number of pps to htn CEIL, not rate !!! \r
007c44c5 127*/\r
43cde5c3 128FILE *log_file = NULL;\r
129char *kwd = "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */\r
007c44c5 130\r
0d5026c6 131const int idxtable_treshold1=24; /* this is no longer configurable */\r
132const int idxtable_treshold2=12; /* this is no longer configurable */\r
133const int idxtable_bitmask1=3; /* this is no longer configurable */\r
134const int idxtable_bitmask2=3; /* this is no longer configurable */\r
007c44c5 135\r
007c44c5 136/* ==== This is C<<1 stuff - learn C<<1 first! http://cll1.arachne.cz ==== */\r
137\r
138struct IP\r
139{\r
140 char *addr;\r
141 char *name;\r
142 char *sharing;\r
143 int min;\r
144 int desired;\r
145 int max;\r
146 int mark;\r
147 int prio;\r
148 int fixedprio;\r
149 int group;\r
150 unsigned long long direct;\r
151 unsigned long long proxy;\r
152 unsigned long long upload;\r
153 unsigned long long traffic;\r
154 unsigned long long credit;\r
155 unsigned long pktsup;\r
156 unsigned long pktsdown;\r
157 struct Keyword *keyword;\r
158 list(IP);\r
159} *ips=NULL, *ip, *sharedip;\r
160\r
161struct Group\r
162{\r
163 int min;\r
164 int count;\r
165 int desired;\r
166 int id;\r
167 list(Group);\r
168} *groups=NULL, *group;\r
169\r
170struct Index\r
171{\r
172 char *addr;\r
173 char *id;\r
174 struct Index *parent;\r
175 int bitmask;\r
176 int children;\r
177 list(Index);\r
178} *idxs=NULL, *idx, *metaindex;\r
179\r
180struct Keyword\r
181{\r
182 char *key;\r
183 \r
184 int asymetry_ratio; /* ratio for ADSL-like upload */\r
185 int asymetry_fixed; /* fixed treshold for ADSL-like upload */\r
186 int data_limit; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */\r
99127c70 187 int data_prio; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */\r
007c44c5 188 long fixed_limit; /* fixed data limit for setting lower HTB ceil */\r
189 long fixed_prio; /* fixed data lmit for setting lower HTB prio */\r
190 int reserve_min; /* bonus for nominal HTB rate bandwidth (in kbps) */\r
191 int reserve_max; /* malus for nominal HTB ceil (in kbps) */\r
192// int divide_max; /* relative malus: new_ceil=rate+(old_ceil-rate)/divide_max */\r
193// int htb_ceil_bonus_divide; /* relative bonus: new_ceil=old_ceil+old_ceil/htb_ceil_bonus_divide */\r
194 int default_prio; /* default HTB priority for this keyword */\r
195 char *html_color;\r
196 int ip_count;\r
197 char *leaf_discipline;\r
198 \r
199 list(Keyword);\r
200} *keyword,*defaultkeyword=NULL,*keywords=NULL;\r
201\r
202/* Damned, this must be object oriented! This looks almost like constructor ;-) */\r
203\r
204void TheIP(void)\r
205{\r
206 create(ip,IP);\r
207 ip->name="";\r
208 ip->addr="";\r
209 ip->sharing=NULL;\r
210 ip->prio=1;\r
211 ip->fixedprio=0;\r
212 ip->mark=ip->min=ip->max=ip->desired=ip->credit=0;\r
213 ip->upload=ip->proxy=ip->direct=ip->traffic=0;\r
214 ip->pktsup=ip->pktsdown=0;\r
215 ip->keyword=keywords;\r
216 push(ip,ips);\r
217}\r
218\r
5b902402 219/* ====== iptables indexes are used to reduce complexity to log8(N) ===== */\r
007c44c5 220\r
221char *very_ugly_ipv4_code(char *inip,int bitmask,int format_as_chainname)\r
222{\r
223 /* warning: this function was debugged only for bitmask values 20,24,28 !!!*/\r
224 int dot=0,n;\r
225 char *ip,*outip,*outptr,*fmt;\r
226\r
227 duplicate(inip,ip);\r
228 /* debug printf("(%s,%d) -> ",ip,bitmask); */\r
229\r
230 if(ip && *ip && bitmask>=0 && bitmask<=32)\r
231 string(outip,strlen(ip)+10); /*fuck unicode? assertion: 10>strlen("_%d_%d") */\r
232 else \r
233 /* should never exit here */\r
234 return "undefined";\r
235 outptr=outip;\r
236 while(ip && *ip)\r
237 {\r
238 if(*ip=='.')\r
239 {\r
240 if(dot<(bitmask/8-1)) \r
241 {\r
242 if(format_as_chainname)\r
243 *outptr='_';\r
244 else\r
245 *outptr='.';\r
246 outptr++;\r
247 dot++;\r
248 }\r
249 else\r
250 {\r
251 char *cutdot=strchr(ip+1,'.'); /*for bitmask<24*/\r
252 if(cutdot)*cutdot='\0';\r
253 if(format_as_chainname)\r
254 fmt="_%d_%d";\r
255 else\r
256 fmt=".%d";\r
257 if(bitmask%8)\r
258 n=atoi(ip+1)-atoi(ip+1)%(1<<(8-bitmask%8));\r
259 else\r
260 n=0;\r
261\r
262 /*debug printf("%d/%d => [_%d_%d]\n",atoi(ip+1),bitmask,n,bitmask); */\r
263 sprintf(outptr,fmt,n,bitmask);\r
264 if(!format_as_chainname) while(bitmask<24)\r
265 {\r
266 strcat(outip,".0");\r
267 bitmask+=8;\r
268 }\r
269 /* debug printf("[%s]\n",outip); */\r
270 return outip;\r
271 }\r
272 }\r
273 else \r
274 {\r
275 *outptr=*ip;\r
276 outptr++;\r
277 }\r
278 ip++;\r
279 }\r
280 /*should never exit here*/\r
281 *outptr='\0';\r
282 return outip;\r
283}\r
284\r
285char *hash_id(char *ip,int bitmask)\r
286{ return very_ugly_ipv4_code(ip,bitmask,1); }\r
287\r
288char *subnet_id(char *ip,int bitmask)\r
289{ return very_ugly_ipv4_code(ip,bitmask,0); }\r
290\r
291/* ================= Let's parse configuration file here =================== */\r
292\r
293void reject_config_and_exit(char *filename)\r
294{\r
295 printf("Configuration file %s rejected - abnormal exit.",filename);\r
296 exit(-1);\r
297}\r
298\r
299void get_config(char *config_filename)\r
300{\r
301 char *cnf="mark";\r
302 \r
303 printf("Configured keywords: ");\r
304 parse(config_filename)\r
305 {\r
306 option("keyword",kwd);\r
307 if(kwd)\r
308 {\r
309 printf("%s ",kwd);\r
310\r
311 create(keyword,Keyword);\r
312 keyword->key=kwd;\r
313 keyword->asymetry_ratio=1; /* ratio for ADSL-like upload */\r
314 keyword->asymetry_fixed=0; /* fixed treshold for ADSL-like upload */\r
315 keyword->data_limit=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */\r
99127c70 316 keyword->data_prio=4; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */\r
007c44c5 317 keyword->fixed_limit=0; /* fixed data limit for setting lower HTB ceil */\r
318 keyword->fixed_prio=0; /* fixed data limit for setting lower HTB prio */\r
319 keyword->reserve_min=8; /* bonus for nominal HTB rate bandwidth (in kbps) */\r
320 keyword->reserve_max=0; /* malus for nominal HTB ceil (in kbps) */\r
321/* obsolete:\r
322 keyword->divide_max=0; relative malus: new_ceil=rate+(old_ceil-rate)/divide_max\r
323 keyword->htb_ceil_bonus_divide=0; relative bonus: new_ceil=old_ceil+old_ceil/htb_ceil_bonus_divide\r
324*/\r
325 keyword->default_prio=1;\r
326 keyword->html_color="000000";\r
327 keyword->ip_count=0;\r
328 keyword->leaf_discipline="";\r
329\r
330 push(keyword,keywords);\r
331 if(!defaultkeyword) defaultkeyword=keyword;\r
332 keywordcount++;\r
333 \r
334 kwd=NULL;\r
335 }\r
336 else every(keyword,keywords)\r
337 {\r
338 int l=strlen(keyword->key);\r
339\r
340\r
341 if(!strncmp(keyword->key,_,l) && strlen(_)>l+2)\r
342 {\r
343 char *tmptr=_; /* <---- l+1 ----> */\r
344 _+=l+1; /* via-prometheus-asymetry-ratio, etc. */\r
345 ioption("asymetry-ratio",keyword->asymetry_ratio);\r
346 ioption("asymetry-treshold",keyword->asymetry_fixed);\r
347 ioption("magic-relative-limit",keyword->data_limit);\r
99127c70 348 ioption("magic-relative-prio",keyword->data_prio);\r
007c44c5 349 loption("magic-fixed-limit",keyword->fixed_limit);\r
350 loption("magic-fixed-prio",keyword->fixed_prio);\r
351 ioption("htb-default-prio",keyword->default_prio);\r
352 ioption("htb-rate-bonus",keyword->reserve_min);\r
353 ioption("htb-ceil-malus",keyword->reserve_max);\r
354/* obsolete:\r
355 ioption("htb-ceil-divide",keyword->divide_max);\r
356 ioption("htb-ceil-bonus-divide",keyword->htb_ceil_bonus_divide);\r
357*/\r
358 option("leaf-discipline",keyword->leaf_discipline);\r
359 option("html-color",keyword->html_color);\r
360 _=tmptr;\r
361 \r
362 if(keyword->data_limit || keyword->fixed_limit || \r
99127c70 363 keyword->data_prio || keyword->fixed_prio)\r
5b902402 364 use_credit=1; \r
007c44c5 365 }\r
366 }\r
367\r
368 option("tc",tc);\r
369 option("iptables",iptables);\r
370 option("iptables-save",iptablessave); /* new */\r
371 option("iptables-restore",iptablesrestore); /* new */\r
372 option("iptables-file",iptablesfile); /* new */\r
373 option("hosts",hosts);\r
374 option("lan-interface",lan);\r
375 option("wan-interface",wan);\r
376 option("lan-medium",lan_medium);\r
377 option("wan-medium",wan_medium);\r
378 lloption("wan-download",line);\r
379 lloption("wan-upload",up);\r
380 ioption("hall-of-fame-enable",hall_of_fame);\r
381 option("hall-of-fame-title",title);\r
382 option("hall-of-fame-filename",html);\r
383 option("hall-of-fame-preview",preview);\r
384 option("log-filename",cmdlog);\r
385 option("credit-filename",credit);\r
386 ioption("credit-enable",enable_credit);\r
387 option("log-traffic-directory",log_dir);\r
5b902402 388 option("log-traffic-html-directory",html_log_dir);\r
007c44c5 389 option("log-traffic-url-path",log_url);\r
390 option("qos-free-zone",qos_free_zone);\r
391 ioption("qos-free-delay",qos_free_delay);\r
392 ioption("qos-proxy-enable",qos_proxy);\r
393 option("qos-proxy-ip",proxy_ip);\r
394 option("htb-leaf-discipline",qos_leaf);\r
395 ioption("qos-proxy-port",proxy_port);\r
396 ioption("free-rate",free_min);\r
397 ioption("free-ceil",free_max);\r
398 ioption("htb-burst",burst);\r
399 ioption("htb-burst-main",burst_main);\r
400 ioption("htb-burst-group",burst_group);\r
401 ioption("htb-nesting-limit",max_nesting);\r
402 ioption("htb-r2q",htb_r2q);\r
403 ioption("magic-include-upload",include_upload);\r
404 ioption("magic-priorities",magic_priorities);\r
5b902402 405 ioption("magic-treshold",magic_treshold); \r
007c44c5 406 option("filter-type", cnf);\r
407 \r
408/* not yet implemented:\r
409 ioption("magic-fixed-packets",fixed_packets);\r
410 ioption("magic-relative-packets",packet_limit);\r
411*/\r
412 }\r
413 fail\r
414 { \r
415 perror(config_filename);\r
416 puts("Warning - using built-in defaults instead ...");\r
417 }\r
418 done;\r
419 printf("\n");\r
420 \r
421 /*leaf discipline for keywords*/\r
422 every(keyword,keywords)\r
423 {\r
424 if (!strcmpi(keyword->leaf_discipline, "")){\r
425 keyword->leaf_discipline = qos_leaf;\r
426 }\r
427 }\r
428\r
429 if (strcmpi(cnf, "mark")){\r
430 filter_type = 2;\r
431 mark = "CLASSIFY";\r
432 mark_iptables = "CLASSIFY --set-class 1:";\r
433 }else{\r
434 filter_type = 1;\r
435 mark = "MARK";\r
436 mark_iptables = "MARK --set-mark ";\r
437 }\r
438\r
439 /* are supplied values meaningful ?*/\r
440 if(line<=0 || up<=0)\r
441 {\r
b1b59b3a 442 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");\r
007c44c5 443 reject_config_and_exit(config_filename);\r
444 }\r
445}\r
446\r
447/* ===================== traffic analyser - uses iptables ================ */ \r
448\r
449void get_traffic_statistics(void)\r
450{\r
451 char *str,*cmd;\r
452 int downloadflag=0;\r
453\r
454 textfile(Pipe,str) *line,*lines=NULL;\r
455 string(str,STRLEN);\r
456 string(cmd,STRLEN);\r
457\r
458 sprintf(cmd,"%s -L -v -x -n -t mangle",iptables);\r
459 shell(cmd);\r
460 input(str,STRLEN)\r
461 {\r
462 create(line,Pipe);\r
463 line->str=str;\r
464 string(str,STRLEN);\r
465 append(line,lines);\r
466 }\r
467\r
468 every(line,lines)\r
469 {\r
470 int col, accept=0,proxyflag=0,valid=1,setchainname=0,commonflag=0; \r
471 unsigned long long traffic=0;\r
472 unsigned long pkts=0;\r
473 char *ipaddr=NULL,*ptr;\r
474 \r
475 /* debug puts(line->str); */\r
476 valid_columns(ptr,line->str,' ',col) \r
477 if(valid) switch(col)\r
478 { \r
479 case 1: if(eq(ptr,"Chain"))\r
480 setchainname=1;\r
481 else if(eq(ptr,"pkts")) \r
482 valid=0;\r
483 else\r
484 sscanf(ptr,"%lu",&pkts); \r
485 break;\r
486 case 2: if(setchainname)\r
487 {\r
488 if(!strncmp(ptr,"post_",5) || eq(ptr,"POSTROUTING"))\r
489 downloadflag=1; \r
490 else \r
491 if(!strncmp(ptr,"forw_",5) || eq(ptr,"FORWARD"))\r
492 downloadflag=0;\r
493 \r
494 if(eq(ptr,"post_common") || eq(ptr,"forw_common"))\r
495 commonflag=1;\r
496 }\r
497 else\r
498 sscanf(ptr,"%Lu",&traffic); traffic+=(1<<19); traffic>>=20;\r
499 break;\r
0045483c 500 case 3: if((strncmp(ptr,"post_",5) && strncmp(ptr,"forw_",5)) || commonflag)\r
007c44c5 501 accept=eq(ptr,mark);\r
502 /*if (filter_type==1) accept=eq(ptr,"MARK"); else accept=eq(ptr,"CLASSIFY");*/\r
503 break;\r
504 case 8: if(downloadflag)\r
505 { \r
506 if(strstr(proxy_ip,ptr))proxyflag=1; \r
507 }\r
508 else\r
509 ipaddr=ptr; \r
510 break;\r
511 case 9: if(downloadflag)ipaddr=ptr;break;\r
512 }\r
513 \r
514 if(accept && traffic>0 && ipaddr)\r
515 {\r
516 if(proxyflag)printf("(proxy) ");\r
517 else if(!downloadflag) printf("(upload) ");\r
518 printf("IP %s: %Lu M (%ld pkts)\n", ipaddr, traffic, pkts);\r
519 find(ip,ips,eq(ip->addr,ipaddr)); \r
520 else \r
521 {\r
522 TheIP();\r
523 ip->addr=ipaddr;\r
524 if(eq(ip->addr,"0.0.0.0/0"))\r
525 {\r
526 ip->name="(unregistered)";\r
527 ip->min=free_min;\r
528 ip->max=ip->desired=free_max;\r
529 }\r
530 }\r
531 \r
532 if(downloadflag)\r
533 {\r
534 if(proxyflag)\r
535 ip->proxy=traffic;\r
536 else\r
537 ip->traffic+=traffic;\r
538 ip->direct=ip->traffic-ip->upload-ip->proxy;\r
539 ip->pktsdown=pkts;\r
540 }\r
541 else\r
542 {\r
543 ip->upload=traffic;\r
544 ip->pktsup=pkts;\r
545 if(include_upload)\r
546 ip->traffic+=traffic;\r
547 else \r
548 if(traffic>ip->traffic)\r
549 ip->traffic=traffic; \r
550 }\r
551 } \r
552 }\r
553\r
007c44c5 554 free(cmd);\r
555}\r
556 \r
557/* ========== This function executes, logs OR ALSO prints command ========== */\r
558\r
559void safe_run(char *cmd)\r
560{\r
561 if(dry_run) printf("\n=>%s\n",cmd); else system(cmd);\r
562 if(log_file) fprintf(log_file,"%s\n",cmd);\r
563}\r
564\r
565void save_line(char *line)\r
566{\r
567 fprintf(iptables_file,"%s\n",line);\r
568}\r
569\r
570void run_restore(void)\r
571{\r
572 char *restor, *str;\r
573 string(restor,STRLEN);\r
abe9b855 574\r
575 /*-----------------------------------------------------------------*/\r
576 printf("Running %s <%s ...\n",iptablesrestore,iptablesfile);\r
577 /*-----------------------------------------------------------------*/\r
007c44c5 578 \r
579 save_line("COMMIT");\r
580 fclose(iptables_file);\r
ae776b10 581 if(dry_run) \r
582 {\r
007c44c5 583 parse(iptablesfile)\r
584 {\r
585 str=_;\r
586 printf("%s\n", str);\r
587 }done;\r
ae776b10 588 }\r
589\r
590 sprintf(restor,"%s <%s",iptablesrestore, iptablesfile);\r
591 safe_run(restor);\r
007c44c5 592 \r
593 free(restor);\r
594}\r
595\r
596/* == This function strips extra characters after IP address and stores it = */\r
597\r
598void parse_ip(char *str)\r
599{\r
600 char *ptr=str,*ipaddr=NULL,*ipname=NULL;;\r
601 \r
602 while(*ptr && *ptr!=' ' && *ptr!=9)\r
603 ptr++;\r
604 \r
605 *ptr=0;\r
606 ipaddr=str;\r
607 ptr++;\r
608 while(*ptr && (*ptr==' ' || *ptr==9))\r
609 ptr++;\r
610 ipname=ptr; \r
611 while(*ptr && *ptr!=' ' && *ptr!=9)\r
612 ptr++;\r
613 *ptr=0;\r
614\r
615 find(ip,ips,eq(ip->addr,ipaddr)); else TheIP();\r
616 ip->addr=ipaddr;\r
617 ip->name=ipname;\r
618}\r
619\r
620char *parse_datafile_line(char *str)\r
621{\r
622 char *ptr=strchr(str,' ');\r
623\r
624 if(ptr)\r
625 {\r
626 *ptr=0;\r
627 ptr++;\r
628 return ptr;\r
629 } \r
630 else \r
631 return NULL;\r
632}\r
633\r
c9012978 634struct IpLog\r
635{\r
636 char *name;\r
637 long traffic;\r
5a8f2e77 638 long guaranted;\r
c9012978 639 list(IpLog);\r
640} *iplog,*iplogs;\r
641\r
642void parse_ip_log(int argc, char **argv) \r
643{\r
9da6a279 644 char *month, *year, *str, *name, *ptr, *ptr2, *filename;\r
5a8f2e77 645 long traffic, traffic_month, total=0, guaranted;\r
646 int col, col2, y_ok, m_ok, accept_month, i=1, any_month=0;\r
647 char mstr[4], ystr[5];\r
648 FILE *f; \r
c9012978 649 string(str,STRLEN);\r
9da6a279 650 string(filename,STRLEN);\r
c9012978 651\r
5b902402 652 if(argv[1][1]=='l') /* -l */\r
653 {\r
c9012978 654 if(argc<4)\r
655 {\r
656 puts("Missing parameter(s)!\nUsage: prometheus -l Mmm YYYY (Mmm=Jan-Dec or Year, YYYY=year)");\r
657 exit(-1);\r
658 }\r
659 else\r
660 {\r
661 month=argv[2];\r
662 if(eq(month,"Year")) any_month=1;\r
663 year=argv[3];\r
5b902402 664 }\r
665 }\r
666 else\r
667 { \r
668 time_t t = time(NULL) - 3600*24 ; /* yesterday's timestamp*/\r
669 struct tm *timep = localtime(&t); \r
670 \r
671 if(argv[1][1]=='m') /* -m yestarday - month */\r
672 {\r
673 strftime(mstr, 4, "%b", timep);\r
674 month=mstr;\r
675 strftime(ystr, 5, "%Y", timep);\r
676 year=ystr; \r
677 }\r
678 else /* -y yesterday - year */\r
679 {\r
680 month="Year";\r
681 any_month=1;\r
682 strftime(ystr, 5, "%Y", timep);\r
683 year=ystr;\r
684 }\r
685 }\r
686 printf("Analysing traffic for %s %s ...\n",month,year);\r
c9012978 687\r
493e1ccd 688 /* sorry... next release of C<<1 header file will include for_path_files(name,path) { } macro */\r
689 sprintf(str,"%s %s/",ls,log_dir);\r
c9012978 690 shell(str);\r
493e1ccd 691 input(str,STRLEN) \r
c9012978 692 {\r
493e1ccd 693 if(strstr(str,".log"))\r
9da6a279 694 {\r
493e1ccd 695 ptr=strrchr(str,'\n');\r
696 if(ptr) *ptr='\0';\r
9da6a279 697 sprintf(filename,"%s/%s",log_dir,str);\r
698 printf("Parsing %s ...",filename);\r
493e1ccd 699 accept_month=0;\r
700 traffic_month=0;\r
701 guaranted = 0;\r
9da6a279 702 parse(filename)\r
493e1ccd 703 {\r
704 y_ok=m_ok=0; \r
705 valid_columns(ptr,_,'\t',col) switch(col)\r
706 {\r
707 case 2: name = ptr;break;\r
708 case 3: traffic = atol(ptr);break;\r
709 /* column number - was 7, now 10...*/\r
710 case 7:\r
711 case 8:\r
712 case 9:\r
713 case 10: if (isalpha(*ptr)) /* character, not numeric string = date, just one*/\r
5a8f2e77 714 {\r
493e1ccd 715 valid_columns(ptr2,ptr,' ',col2) switch(col2)\r
716 {\r
717 case 2: if(any_month || eq(ptr2,month)) m_ok = 1; break;\r
718 case 5: if(eq(ptr2,year)) y_ok = 1; break;\r
719 }\r
5a8f2e77 720 }\r
493e1ccd 721 else\r
722 {\r
723 if(col == 7) guaranted = atol(ptr);\r
724 }\r
725 }\r
726 \r
727 if(y_ok && m_ok) \r
728 {\r
729 traffic_month += traffic;\r
730 accept_month = 1;\r
731 }\r
732 }\r
733 done;\r
b1b59b3a 734\r
493e1ccd 735 if(accept_month)\r
736 {\r
737 create(iplog,IpLog);\r
738 iplog->name = name;\r
739 iplog->guaranted = guaranted;\r
740 iplog->traffic = traffic_month;\r
741 insert(iplog,iplogs,desc_order_by,traffic);\r
742 printf(" %ld MB\n",iplog->traffic);\r
743 }\r
744 else\r
745 puts(" no records.");\r
9da6a279 746 }\r
c9012978 747 }\r
748 sprintf(str,"%s/%s-%s.html",html_log_dir,year,month);\r
749 printf("Writing %s ...",str);\r
750 f=fopen(str,"w");\r
751 if(f)\r
752 {\r
f5707e28 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);\r
c9012978 754 every(iplog,iplogs)\r
755 if(iplog->traffic)\r
756 {\r
f5707e28 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",\r
5a8f2e77 758 i++, iplog->name, iplog->traffic, iplog->traffic>>10, iplog->guaranted);\r
c9012978 759 total+=iplog->traffic>>10;\r
760 }\r
5a8f2e77 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);\r
2d114137 762 fputs("</table>\n", f);\r
763 fprintf(f, stats_html_signature, version);\r
c9012978 764 fclose(f);\r
765 puts(" done.");\r
766 }\r
767}\r
5b902402 768\r
769\r
007c44c5 770/*-----------------------------------------------------------------*/\r
493e1ccd 771/* Are you looking for int main(int argc, char **argv) ? :-)) */\r
007c44c5 772/*-----------------------------------------------------------------*/\r
773\r
774program\r
775{\r
776 int i=0;\r
777 FILE *f=NULL;\r
778 char *str, *ptr, *d;\r
779 char *substring;\r
780 int class_count=0,ip_count=0;\r
781 int parent=1;\r
782 int just_flush=0;\r
783 int nodelay=0;\r
33ec95ab 784 int just_preview=0; /* preview - generate just stats */\r
785 int just_logs=0; /* just parse logs */\r
786 \r
007c44c5 787 char *chain_forward, *chain_postrouting;\r
788 char *althosts=NULL;\r
789 \r
790 printf("\n\\r
791Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\\r
ab85aff7 792Version %s - Copyright (C)2005-2008 Michael Polak (xChaos)\n\\r
43cde5c3 793iptables-restore & burst tunning & classify modification by Ludva\n\\r
0d5026c6 794Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version);\r
007c44c5 795\r
796 /*----- Boring... we have to check command line options first: ----*/\r
797 \r
798 arguments\r
799 {\r
800 argument("-c") { nextargument(config); }\r
801 argument("-h") { nextargument(althosts);}\r
802 argument("-d") { dry_run=1; }\r
803 argument("-f") { just_flush=1; }\r
804 argument("-9") { just_flush=9; }\r
805 argument("-p") { just_preview=1; }\r
806 argument("-n") { nodelay=1; }\r
33ec95ab 807 argument("-l") { just_logs=1; }\r
808 argument("-m") { just_logs=1; }\r
809 argument("-y") { just_logs=1; }\r
007c44c5 810 argument("-?") { help(); exit(0); }\r
811 argument("--help") { help(); exit(0); }\r
812 argument("-v") { exit(0); } \r
813 argument("--version") { exit(0); } \r
814 }\r
815\r
816 if(dry_run)\r
817 puts("*** THIS IS JUST DRY RUN ! ***\n");\r
818\r
819 date(d); /* this is typical cll1.h macro */\r
820\r
821 /*-----------------------------------------------------------------*/\r
822 printf("Parsing configuration file %s ...\n", config);\r
823 /*-----------------------------------------------------------------*/\r
824 get_config(config);\r
c9012978 825 \r
33ec95ab 826 if(just_logs)\r
c9012978 827 {\r
33ec95ab 828 parse_ip_log(argc,argv);\r
829 exit(0);\r
c9012978 830 }\r
007c44c5 831\r
832 if(althosts) hosts=althosts;\r
833\r
834 if(just_flush<9)\r
835 {\r
836 /*-----------------------------------------------------------------*/\r
837 puts("Parsing iptables verbose output ...");\r
838 /*-----------------------------------------------------------------*/\r
839 get_traffic_statistics();\r
840 }\r
841\r
842 /*-----------------------------------------------------------------*/\r
843 printf("Parsing class defintion file %s ...\n", hosts);\r
844 /*-----------------------------------------------------------------*/\r
845 int groupidx = FIRSTGROUPID;\r
846 parse(hosts)\r
847 {\r
848 str=_;\r
849\r
850 if(*str<'0' || *str>'9')\r
851 continue;\r
852 \r
853 //Does this IP share QoS class with some other ?\r
854 substring=strstr(str,"sharing-");\r
855 if(substring)\r
856 { \r
857 substring+=8; //"sharing-"\r
858 parse_ip(str);\r
859 ip_count++;\r
860 ip->sharing=substring;\r
861 ip->keyword=defaultkeyword; /* settings for default keyword */\r
862 while(*substring && *substring!='\n')\r
863 substring++;\r
864 *substring=0; \r
865 }\r
866 else\r
867 {\r
868 //Do we have to create new QoS class for this IP ?\r
869\r
870 find(keyword,keywords,(substring=strstr(str,keyword->key)))\r
871 {\r
872 parse_ip(str);\r
873 ip_count++;\r
874 ip->keyword=keyword;\r
875 keyword->ip_count++;\r
876 ip->prio=keyword->default_prio;\r
877 substring+=strlen(keyword->key)+1;\r
878 ptr=substring;\r
879 while(*ptr && *ptr!='-')\r
880 ptr++;\r
881 if(*ptr=='-')\r
882 {\r
883 *ptr=0;\r
884 ip->max=ip->desired=atoi(ptr+1);\r
885 }\r
886 ip->min=atoi(substring);\r
887 if(ip->min<=0)\r
888 {\r
312ac2c1 889 printf(" %s: Illegal value of minimum bandwidth 0 kbps, using %d kbps\n",str,free_min);\r
c312f6a9 890 ip->min=free_min;\r
007c44c5 891 }\r
892 if(ip->max<=ip->min)\r
893 {\r
894 ip->fixedprio=1;\r
895 ip->max=ip->min+ip->keyword->reserve_min;\r
896 }\r
897 else \r
898 {\r
899 ip->max-=ip->keyword->reserve_max;\r
900\r
901/*\r
902 if(ip->keyword->divide_max>1)\r
903 ip->max=ip->min+(ip->max-ip->min)/ip->keyword->divide_max;\r
904 if(ip->keyword->htb_ceil_bonus_divide>0)\r
905 ip->max+=ip->max/ip->keyword->htb_ceil_bonus_divide;\r
906*/\r
907 if(ip->max<ip->min)\r
908 ip->max=ip->min;\r
909 }\r
43e07280 910 ip->mark=FIRSTIPCLASS+1+class_count++;\r
007c44c5 911\r
912 find(group,groups,group->min==ip->min) \r
913 { \r
914 group->count++; \r
915 group->desired+=ip->min;\r
916 ip->group = group->id; \r
917 }\r
918 else\r
919 {\r
920 create(group,Group);\r
921 group->min=ip->min;\r
922 group->id = groupidx++;\r
923 ip->group = group->id;\r
924\r
925 if(group->min<8) group->min=8;\r
926 /* Warning - this is maybe because of primitive tc namespace, can be fixed */\r
927 /* it is because class IDs are derived from min. bandwidth. - xCh */\r
928 //if(group->min>MAX_GUARANTED_KBPS) group->min=MAX_GUARANTED_KBPS;\r
929 \r
930 group->count=1;\r
931 group->desired=ip->min; \r
932 insert(group,groups,desc_order_by,min);\r
933 }\r
934 }//endif keyword-\r
935 }//endif sharing-\r
936 }\r
937 fail\r
938 {\r
939 perror(hosts);\r
940 exit(-1);\r
941 }\r
942 done;\r
943\r
944 /*-----------------------------------------------------------------*/\r
945 /* cll1.h - let's allocate brand new character buffer... */\r
946 /*-----------------------------------------------------------------*/\r
947 string(str,STRLEN); \r
948\r
949 /*-----------------------------------------------------------------*/\r
950 puts("Resolving shared connections ...");\r
951 /*-----------------------------------------------------------------*/\r
952 search(ip,ips,ip->sharing)\r
953 {\r
954 search(sharedip,ips,eq(sharedip->name,ip->sharing))\r
955 {\r
956 sharedip->traffic+=ip->traffic;\r
957 ip->traffic=0;\r
958 ip->mark=sharedip->mark; \r
959 break;\r
960 }\r
961 if(!sharedip)\r
962 printf("Unresolved shared connection: %s %s sharing-%s\n",ip->addr,ip->name,ip->sharing);\r
963 }\r
964\r
965 if(enable_credit && just_flush<9)\r
966 {\r
967 /*-----------------------------------------------------------------*/\r
968 printf("Parsing credit file %s ...\n", credit);\r
969 /*-----------------------------------------------------------------*/\r
970 parse(credit)\r
971 {\r
972 ptr=parse_datafile_line(_);\r
973 if(ptr)\r
974 {\r
975 find(ip,ips,eq(ip->addr,_))\r
976 sscanf(ptr,"%Lu",&(ip->credit));\r
977 }\r
978 }\r
979 done;\r
980 }\r
981\r
982 if(!just_preview)\r
983 {\r
984 /*-----------------------------------------------------------------*/\r
985 puts("Initializing iptables and tc classes ...");\r
986 /*-----------------------------------------------------------------*/\r
987 \r
988 iptables_file=fopen(iptablesfile,"w");\r
989 if (iptables_file == NULL) {\r
990 puts("Cannot open iptablesfile!");\r
991 exit(-1);\r
992 }\r
993 \r
994 log_file=fopen(cmdlog,"w");\r
995 if (log_file == NULL) {\r
996 puts("Cannot open logfile!");\r
997 exit(-1);\r
998 }\r
999 \r
1000 save_line(iptablespreamble);\r
1001 run_restore();\r
1002 \r
1003 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,lan);\r
1004 safe_run(str);\r
1005\r
1006 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,wan);\r
1007 safe_run(str);\r
1008 \r
1009 iptables_file=fopen(iptablesfile,"w");\r
1010 save_line(iptablespreamble);\r
1011\r
1012 if(qos_free_zone && *qos_free_zone!='0')\r
1013 {\r
1014 char *chain;\r
1015 \r
1016 sprintf(str,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone, wan);\r
1017 save_line(str);\r
1018 \r
1019 if(qos_proxy)\r
1020 {\r
1021 save_line(":post_noproxy - [0:0]");\r
1022 sprintf(str,"-A POSTROUTING -p ! tcp -o %s -j post_noproxy", lan);\r
1023 save_line(str); \r
1024 sprintf(str,"-A POSTROUTING -s ! %s -o %s -j post_noproxy", proxy_ip, lan);\r
1025 save_line(str); \r
1026 sprintf(str,"-A POSTROUTING -s %s -p tcp --sport ! %d -o %s -j post_noproxy", proxy_ip, proxy_port, lan);\r
1027 save_line(str); \r
1028\r
1029 chain="post_noproxy"; \r
1030 }\r
1031 else\r
1032 chain="POSTROUTING";\r
1033 \r
1034 sprintf(str,"-A %s -s %s -o %s -j ACCEPT", chain, qos_free_zone, lan);\r
1035 save_line(str);\r
1036 }\r
1037 \r
1038 if(ip_count>idxtable_treshold1 && !just_flush)\r
1039 {\r
1040 int idxcount=0, bitmask=32-idxtable_bitmask1; /* default net mask: 255.255.255.240 */\r
e0161edb 1041 char *subnet, *buf;\r
007c44c5 1042 /*-----------------------------------------------------------------*/\r
1043 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count);\r
1044 /*-----------------------------------------------------------------*/\r
1045\r
1046 save_line(":post_common - [0:0]");\r
1047 save_line(":forw_common - [0:0]");\r
1048\r
1049 search(ip,ips,ip->addr && *(ip->addr) && !eq(ip->addr,"0.0.0.0/0"))\r
1050 {\r
1051 buf=hash_id(ip->addr,bitmask);\r
1052 find(idx,idxs,eq(idx->id,buf))\r
1053 idx->children++;\r
1054 else\r
1055 {\r
1056 create(idx,Index);\r
1057 idx->addr=ip->addr;\r
1058 idx->id=buf;\r
1059 idx->bitmask=bitmask;\r
1060 idx->parent=NULL;\r
1061 idx->children=0;\r
1062 idxcount++;\r
1063 push(idx,idxs);\r
1064 }\r
1065 }\r
1066\r
1067 /* brutal perfomance optimalization */\r
1068 while(idxcount>idxtable_treshold2 && bitmask>2*idxtable_bitmask2)\r
1069 {\r
1070 bitmask-=idxtable_bitmask2;\r
1071 idxcount=0;\r
1072 search(idx,idxs,idx->parent==NULL)\r
1073 {\r
1074 buf=hash_id(idx->addr,bitmask);\r
1075 find(metaindex,idxs,eq(metaindex->id,buf))\r
1076 metaindex->children++; \r
1077 else\r
1078 {\r
1079 create(metaindex,Index);\r
1080 metaindex->addr=idx->addr;\r
1081 metaindex->id=buf;\r
1082 metaindex->bitmask=bitmask;\r
1083 metaindex->parent=NULL;\r
1084 metaindex->children=0;\r
1085 idxcount++;\r
1086 push(metaindex,idxs);\r
1087 }\r
1088 idx->parent=metaindex;\r
1089 }\r
1090 }\r
1091\r
1092 /* this should slightly optimize throughout ... */\r
1093 sort(idx,idxs,desc_order_by,children);\r
1094 sort(idx,idxs,order_by,bitmask);\r
1095\r
1096 i=0;\r
1097 every(idx,idxs)\r
1098 {\r
1099 subnet=subnet_id(idx->addr,idx->bitmask);\r
1100 printf("%d: %s/%d\n",++i,subnet,idx->bitmask);\r
1101 \r
1102 sprintf(str,":post_%s - [0:0]", idx->id);\r
1103 save_line(str);\r
1104\r
1105 sprintf(str,":forw_%s - [0:0]", idx->id);\r
1106 save_line(str);\r
1107\r
1108 if(idx->parent)\r
1109 {\r
1110 string(buf,strlen(idx->parent->id)+6);\r
1111 sprintf(buf,"post_%s",idx->parent->id);\r
1112 }\r
1113 else\r
1114 buf="POSTROUTING";\r
1115\r
1116 sprintf(str,"-A %s -d %s/%d -o %s -j post_%s", buf, subnet, idx->bitmask, lan, idx->id);\r
1117 save_line(str);\r
1118\r
1119 sprintf(str,"-A %s -d %s/%d -o %s -j post_common", buf, subnet, idx->bitmask, lan);\r
1120 save_line(str);\r
1121\r
1122 if(idx->parent)\r
1123 {\r
1124 string(buf,strlen(idx->parent->id)+6);\r
1125 sprintf(buf,"forw_%s",idx->parent->id);\r
1126 }\r
1127 else\r
1128 buf="FORWARD";\r
1129\r
1130 sprintf(str,"-A %s -s %s/%d -o %s -j forw_%s", buf, subnet, idx->bitmask, wan, idx->id);\r
1131 save_line(str);\r
1132\r
1133 sprintf(str,"-A %s -s %s/%d -o %s -j forw_common", buf, subnet, idx->bitmask, wan);\r
1134 save_line(str);\r
1135 }\r
1136 printf("Total indexed iptables chains created: %d\n", i);\r
1137\r
1138 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);\r
1139 save_line(str);\r
1140 \r
1141 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);\r
1142 save_line(str);\r
1143 }\r
1144 \r
1145 }\r
1146\r
1147 if(just_flush)\r
1148 {\r
1149 fclose(iptables_file);\r
1150 if (log_file) fclose(log_file);\r
1151 puts("Just flushed iptables and tc classes - now exiting ...");\r
1152 exit(0);\r
1153 }\r
1154\r
1155 if(!just_preview)\r
1156 {\r
1157 if(!dry_run && !nodelay && qos_free_delay)\r
1158 {\r
1159 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay);\r
1160 sleep(qos_free_delay);\r
1161 }\r
1162\r
1163 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc,lan,htb_r2q);\r
1164 safe_run(str);\r
1165\r
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);\r
1167 safe_run(str);\r
1168\r
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);\r
1170 safe_run(str);\r
1171\r
1172 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc,wan,htb_r2q);\r
1173 safe_run(str);\r
1174\r
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);\r
1176 safe_run(str);\r
1177\r
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);\r
1179 safe_run(str);\r
1180 }\r
1181\r
1182 /*-----------------------------------------------------------------*/\r
1183 puts("Locating suckers and generating root classes ...");\r
1184 /*-----------------------------------------------------------------*/\r
1185 sort(ip,ips,desc_order_by,traffic);\r
1186 \r
1187\r
1188 /*-----------------------------------------------------------------*/\r
1189 /* sub-scope - local variables */ \r
1190 {\r
1191 long long int rate=line;\r
1192 long long int max=line;\r
1193 int group_count=0;\r
1194 FILE *credit_file=NULL;\r
1195 \r
1196 if(!just_preview && !dry_run && enable_credit) credit_file=fopen(credit,"w");\r
1197 \r
1198 every(group,groups)\r
1199 {\r
1200 if(!just_preview)\r
1201 {\r
1202 \r
1203 //download\r
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", \r
1205 tc, lan, parent, group->id, rate, max, burst_group, group->desired);\r
1206 safe_run(str);\r
1207 \r
1208 //upload\r
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", \r
1210 tc, wan, parent, group->id, rate*up/line, max*up/line, burst_group, group->desired);\r
1211 safe_run(str);\r
1212 }\r
1213 \r
1214 if(group_count++<max_nesting) parent=group->id;\r
1215 \r
1216 rate-=digital_divide*group->min;\r
1217 if(rate<group->min)rate=group->min;\r
1218 \r
1219 /*shaping of aggresive downloaders, with credit file support */\r
1220 if(use_credit)\r
1221 {\r
1222 int group_rate=group->min, priority_sequence=magic_priorities+1;\r
1223 \r
1224 search(ip, ips, ip->min==group->min && ip->max>ip->min)\r
1225 {\r
99127c70 1226 if( ip->keyword->data_limit && !ip->fixedprio &&\r
007c44c5 1227 ip->traffic>ip->credit+\r
99127c70 1228 (ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20)) )\r
007c44c5 1229 {\r
1230 if(group_rate<ip->max) ip->max=group_rate;\r
1231 group_rate+=magic_treshold;\r
1232 ip->prio=magic_priorities+2;\r
1233 if(ip->prio<3) ip->prio=3;\r
1234 }\r
1235 else\r
1236 {\r
abe9b855 1237 if( ip->keyword->data_prio && !ip->fixedprio &&\r
99127c70 1238 ip->traffic>ip->credit+\r
1239 (ip->min*ip->keyword->data_prio+(ip->keyword->fixed_prio<<20)) )\r
007c44c5 1240 {\r
1241 ip->prio=priority_sequence--;\r
1242 if(ip->prio<2) ip->prio=2;\r
1243 }\r
1244 \r
1245 if(credit_file)\r
1246 {\r
1247 unsigned long long lcredit=0;\r
99127c70 1248 \r
007c44c5 1249 if((ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))>ip->traffic) \r
1250 lcredit=(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))-ip->traffic;\r
1251 fprintf(credit_file,"%s %Lu\n",ip->addr,lcredit);\r
1252 }\r
1253 }\r
1254 }\r
1255 \r
1256 }\r
1257 }\r
1258 if(credit_file)fclose(credit_file);\r
1259 }\r
1260\r
1261 if(just_preview)\r
1262 {\r
1263 f=fopen(preview,"w");\r
1264 ptr=preview; \r
1265 }\r
1266 else if(!dry_run && !just_flush)\r
1267 {\r
1268 /*-----------------------------------------------------------------*/\r
1269 printf("Writing data transfer database ...\n");\r
1270 /*-----------------------------------------------------------------*/\r
1271 f=fopen("/var/run/prometheus.previous","w");\r
1272 if(f)\r
1273 {\r
1274 search(ip,ips,ip->traffic || ip->direct || ip->proxy ||ip->upload)\r
1275 fprintf(f,"%s %Lu %Lu %Lu %Lu\n",ip->addr,ip->traffic,ip->direct,ip->proxy,ip->upload);\r
1276 fclose(f);\r
1277 }\r
1278\r
1279 f=fopen(html,"w");\r
1280 ptr=html;\r
1281 }\r
1282\r
1283 if(f)\r
1284 {\r
1285 int total=0;\r
1286 int count=1;\r
1287 i=0;\r
1288\r
1289 /*-----------------------------------------------------------------*/\r
1290 printf("Sorting data and generating statistics page %s ...\n",ptr);\r
1291 /*-----------------------------------------------------------------*/\r
1292\r
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);\r
1294 fprintf(f,"<th colspan=\"%d\">data limits</th>\n",keywordcount);\r
1295 fputs("</tr>\n",f);\r
1296 every(group,groups) \r
1297 { \r
1298#ifdef DEBUG\r
1299 printf("%d k group: %d bandwidth requested: %d k\n",group->min,group->count,group->desired);\r
1300#endif\r
1301 fprintf(f,"<tr><td align=\"right\">%d</td><td align=\"right\">%d k</td>",count,group->min);\r
1302 fprintf(f,"<td align=\"right\">%d</td><td align=\"right\">%d k</td>",group->count,group->desired);\r
1303\r
1304 every(keyword,keywords)\r
1305 fprintf(f,"<td align=\"right\"><font color=\"#%s\">%d M</font></td>",keyword->html_color,group->min*keyword->data_limit); \r
1306 \r
1307 i+=group->desired; \r
1308 total+=group->count;\r
1309 count++; \r
1310 }\r
1311#ifdef DEBUG\r
1312 printf("Total groups: %d Total bandwidth requested: %d k\nAGGREGATION: 1/%d\n",count,i,i/line);\r
1313#endif\r
e0161edb 1314 fprintf(f,"<tr><th colspan=\"2\" align=\"left\">Line %Ld k</td>",line);\r
007c44c5 1315 fprintf(f,"<th align=\"right\">%d</td><th align=\"right\">%d k</td>",total,i);\r
1316\r
1317 every(keyword,keywords)\r
1318 fprintf(f,"<th align=\"right\">%d IPs</th>",keyword->ip_count); \r
1319\r
1320 fprintf(f,"</tr><tr><th colspan=\"4\">Aggregation 1/%d</th>\n",(int)(0.5+i/line));\r
1321 fprintf(f,"<th colspan=\"%d\">%d traffic classes</th></tr>\n",keywordcount,total);\r
1322\r
1323 fputs("</table>\n",f);\r
1324 }\r
1325 else if(!dry_run && !just_flush) \r
1326 perror(html);\r
1327\r
1328 i=1;\r
1329 if(f)\r
1330 {\r
1331 unsigned long long total=0, total_direct=0, total_proxy=0, total_upload=0, tmp_sum=0;\r
1332 int active_classes=0;\r
1333 int colspan;\r
1334 FILE *iplog;\r
1335 struct Sum {unsigned long long l; int i; list(Sum);} *sum,*sums=NULL;\r
1336\r
1337 if(qos_proxy)\r
1338 colspan=12;\r
1339 else \r
1340 colspan=11;\r
1341 \r
1342 fprintf(f,"<p><table border>\n<tr><th colspan=\"%d\">%s",colspan,title);\r
1343 fprintf(f," (%s)</th></tr>\n", d);\r
1344 fputs("<tr><td align=\"right\">#</td><td>hostname</td>\\r
1345 <td align=\"right\">credit</td>\\r
1346 <td align=\"right\">limit</td>\\r
1347 <td align=\"right\">total</td>\\r
1348 <td align=\"right\">direct</td>\n",f);\r
1349 if(qos_proxy)\r
1350 fputs("<td align=\"right\">proxy</td>\n",f);\r
1351 fputs("<td align=\"right\">upload</td>\\r
1352 <td align=\"right\">minimum</td>\\r
1353 <td align=\"right\">desired</td>\\r
1354 <td align=\"right\">maximum</td>\\r
1355 <td>prio</td></tr>\n",f); \r
1356\r
1357 every(ip,ips)\r
1358 {\r
1359 char *f1="", *f2="";\r
1360 if(ip->max<ip->desired)\r
1361 {\r
1362 f1="<font color=\"red\">";\r
1363 f2="</font>";\r
1364 }\r
1365 else if(ip->prio>1)\r
1366 {\r
1367 f1="<font color=\"brown\">";\r
1368 f2="</font>";\r
1369 }\r
1370\r
1371#ifdef DEBUG\r
1372 printf("%03d. %-22s %10Lu (%d/%d)\n",i ,ip->name, ip->traffic, ip->min, ip->max); \r
1373#endif\r
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",\r
1375 ip->name, i, log_url, ip->name, ip->name, ip->credit);\r
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)));\r
1377 fprintf(f,"<td align=\"right\">%s%Lu M%s</td><td align=\"right\">%Lu M</td>\n", f1, ip->traffic, f2, ip->direct);\r
1378 if(qos_proxy)\r
1379 fprintf(f,"<td align=\"right\">%Lu M</td>\n", ip->proxy);\r
1380 fprintf(f,"<td align=\"right\">%Lu M</td>\n", ip->upload);\r
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);\r
1382 total+=ip->traffic;\r
1383 total_direct+=ip->direct;\r
1384 total_proxy+=ip->proxy;\r
1385 total_upload+=ip->upload;\r
1386 if(ip->traffic>0)\r
1387 {\r
1388 active_classes++;\r
1389 tmp_sum+=ip->traffic;\r
1390 create(sum,Sum);\r
1391 sum->l=tmp_sum;\r
1392 sum->i=active_classes;\r
1393 insert(sum,sums,order_by,i);\r
1394 }\r
1395 \r
1396 i++;\r
1397 \r
1398 if(!just_preview)\r
1399 {\r
5b902402 1400 sprintf(str,"%s/%s.log",log_dir,ip->name);\r
007c44c5 1401 iplog=fopen(str,"a");\r
1402 if(iplog)\r
1403 {\r
c0718973 1404 fprintf(iplog,"%ld\t%s\t%Lu\t%Lu\t%Lu\t%Lu\t%d\t%d\t%d\t%s",\r
1405 time(NULL),ip->name,ip->traffic,ip->direct,ip->proxy,ip->upload,ip->min,ip->max,ip->desired,d); /* d = date*/\r
007c44c5 1406 fclose(iplog);\r
1407 }\r
1408 }\r
1409\r
1410 }\r
1411 fprintf(f,"<tr><th colspan=\"4 \"align=\"left\">SUMMARY:</td>");\r
1412 fprintf(f,"<th align=\"right\">%Lu M</th>\\r
1413 <th align=\"right\">%Lu M</th>\n", total, total_direct);\r
1414 if(qos_proxy)\r
1415 fprintf(f,"<th align=\"right\">%Lu M</th>\n", total_proxy);\r
1416 fprintf(f,"<th align=\"right\">%Lu M</th>", total_upload);\r
1417 fputs("<td colspan=\"4\"></td></th>\n</table>\n",f);\r
1418\r
1419 if(active_classes>10)\r
c9012978 1420 {\r
1421 fputs("<a name=\"erp\"></a><p><table border><tr><th colspan=\"5\">Enterprise Research and Planning (ERP)</th></tr>\n",f);\r
1422 fputs("<tr><td>Analytic category</td>\n",f);\r
1423 fputs("<td colspan=\"2\" align=\"center\">Active Classes</td><td colspan=\"2\" align=\"center\">Data transfers</td></tr>\n",f);\r
1424\r
1425 find(sum,sums,sum->l>=total/4)\r
1426 {\r
1427 fprintf(f,"<tr><td>Top 25%% of traffic</td>\n");\r
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);\r
1429 }\r
1430 \r
1431 find(sum,sums,sum->i==10)\r
1432 {\r
1433 fprintf(f,"<tr><td>Top 10 downloaders</td>\n");\r
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);\r
1435 }\r
1436\r
1437 find(sum,sums,sum->l>=total/2)\r
1438 {\r
1439 fprintf(f,"<tr><td>Top 50%% of traffic</td>\n");\r
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);\r
1441 }\r
1442\r
1443 find(sum,sums,sum->l>=4*total/5)\r
1444 {\r
1445 fprintf(f,"<tr><td>Top 80%% of traffic</td>\n");\r
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);\r
1447 }\r
1448\r
1449 find (sum,sums,sum->i>=(active_classes+1)/5)\r
1450 {\r
1451 fprintf(f,"<tr><td>Top 20%% downloaders</td>\n");\r
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);\r
1453 }\r
1454\r
1455 find(sum,sums,sum->i>=(active_classes+1)/4)\r
1456 {\r
1457 fprintf(f,"<tr><td>Top 25%% downloaders</td>\n");\r
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);\r
1459 }\r
1460\r
1461 find(sum,sums,sum->i>=(active_classes+1)/2)\r
1462 {\r
1463 fprintf(f,"<tr><td>Top 50%% downloaders</td>\n");\r
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);\r
1465 }\r
1466\r
1467 find(sum,sums,sum->i>=4*(active_classes+1)/5)\r
1468 {\r
1469 fprintf(f,"<tr><td>Top 80%% downloaders</td>\n");\r
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);\r
1471 }\r
1472\r
1473 fprintf(f,"<tr><td>All users, all traffic</td>\n");\r
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);\r
2d114137 1475 fputs("</table>\n", f);\r
c9012978 1476 }\r
2d114137 1477 fprintf(f, stats_html_signature, version);\r
007c44c5 1478 fclose(f);\r
1479 }\r
1480\r
1481 if(just_preview)\r
1482 {\r
1483 puts("Statistics preview generated (-p switch) - now exiting ...");\r
1484 exit(0);\r
1485 }\r
1486 \r
1487 /*-----------------------------------------------------------------*/\r
1488 puts("Generating iptables and tc classes ...");\r
1489 /*-----------------------------------------------------------------*/\r
1490\r
1491 i=0;\r
1492 printf("%-22s %-15s mark\n","name","ip");\r
1493 search(ip,ips,ip->mark>0)\r
1494 { \r
1495 \r
1496 if(idxs)\r
1497 {\r
1498 char *buf;\r
1499 duplicate(ip->addr,buf);\r
1500 buf=hash_id(ip->addr,32-idxtable_bitmask1); \r
1501 \r
1502 string(chain_forward,6+strlen(buf));\r
1503 strcpy(chain_forward,"forw_");\r
1504 strcat(chain_forward,buf);\r
1505\r
1506 string(chain_postrouting,6+strlen(buf));\r
1507 strcpy(chain_postrouting,"post_");\r
1508 strcat(chain_postrouting,buf);\r
1509 \r
1510 free(buf);\r
1511 }\r
1512 else\r
1513 {\r
1514 chain_forward="FORWARD";\r
1515 chain_postrouting="POSTROUTING";\r
1516 }\r
1517\r
1518 printf("%-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
1519\r
1520 /* -------------------------------------------------------- mark download */\r
1521 \r
1522 sprintf(str,"-A %s -d %s/32 -o %s -j %s%d",chain_postrouting,ip->addr,lan,mark_iptables,ip->mark);\r
1523 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/\r
1524 /* -m limit --limit 1/s */ \r
1525 save_line(str);\r
1526\r
1527 if(qos_proxy)\r
1528 {\r
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);\r
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);*/\r
1531 save_line(str);\r
1532 }\r
1533\r
1534 sprintf(str,"-A %s -d %s/32 -o %s -j ACCEPT",chain_postrouting,ip->addr,lan);\r
1535 save_line(str);\r
1536\r
1537 /* -------------------------------------------------------- mark upload */\r
1538 sprintf(str,"-A %s -s %s/32 -o %s -j %s%d",chain_forward,ip->addr,wan,mark_iptables,ip->mark);\r
1539 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/\r
1540 save_line(str);\r
1541\r
1542 sprintf(str,"-A %s -s %s/32 -o %s -j ACCEPT",chain_forward,ip->addr,wan);\r
1543 save_line(str);\r
1544\r
1545 if(ip->min)\r
1546 {\r
1547 /* -------------------------------------------------------- download class */\r
1548 printf("(down: %dk-%dk ", ip->min, ip->max); \r
1549\r
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);\r
1551 safe_run(str);\r
1552\r
dee5592e 1553 if (strcmpi(ip->keyword->leaf_discipline, "none"))\r
1554 {\r
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*/\r
1556 safe_run(str);\r
1557 } \r
1558 if (filter_type == 1)\r
1559 {\r
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);\r
1561 safe_run(str);\r
007c44c5 1562 }\r
1563\r
1564 /* -------------------------------------------------------- upload class */\r
1565 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1566 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
1567\r
1568 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1569 tc, wan, ip->group, ip->mark,\r
1570 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1571 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1572 safe_run(str);\r
1573 \r
dee5592e 1574 if (strcmpi(ip->keyword->leaf_discipline, "none"))\r
1575 {\r
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*/\r
1577 safe_run(str);\r
1578 } \r
1579 if (filter_type == 1)\r
1580 {\r
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);\r
1582 safe_run(str);\r
007c44c5 1583 }\r
1584 }\r
1585 else\r
1586 printf("(sharing %s)\n", ip->sharing);\r
1587 i++;\r
1588 }\r
1589\r
007c44c5 1590 if(idxs)\r
1591 {\r
dee5592e 1592 chain_forward = "forw_common";\r
1593 chain_postrouting = "post_common";\r
007c44c5 1594 }\r
1595 else\r
1596 {\r
dee5592e 1597 chain_forward = "FORWARD";\r
1598 chain_postrouting = "POSTROUTING";\r
007c44c5 1599 }\r
dee5592e 1600 /* -------------------------------- classify or reject free download */\r
007c44c5 1601 {\r
b6a8d473 1602 char *final_chain = "DROP"; /* REJECT would be better, but it is impossible in mangle */\r
dee5592e 1603 if(free_min) final_chain = "ACCEPT";\r
1604 if(qos_proxy)\r
1605 {\r
1606 if(free_min)\r
1607 {\r
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);\r
1609 save_line(str);\r
1610 }\r
1611 sprintf(str,"-A %s -s %s -p tcp --sport %d -o %s -j %s",chain_postrouting,proxy_ip,proxy_port,lan,final_chain);\r
1612 save_line(str);\r
1613 }\r
1614 if(free_min)\r
1615 {\r
1616 sprintf(str,"-A %s -o %s -j %s%d",chain_postrouting,lan,mark_iptables,3);\r
1617 save_line(str);\r
1618 }\r
1619 sprintf(str,"-A %s -o %s -j %s",chain_postrouting,lan,final_chain);\r
1620 save_line(str);\r
1621 /* ------------------------------- classify or reject free upload */\r
1622 if(free_min)\r
1623 {\r
1624 sprintf(str,"-A %s -o %s -j %s%d",chain_forward,wan,mark_iptables,3);\r
1625 save_line(str);\r
1626 }\r
1627 sprintf(str,"-A %s -o %s -j %s",chain_forward,wan,final_chain);\r
1628 save_line(str);\r
007c44c5 1629 }\r
abe9b855 1630\r
dee5592e 1631 if(free_min) /* allocate free bandwith if it is not zero... */ \r
1632 {\r
1633 /*-----------------------------------------------------------------*/\r
1634 puts("Generating free bandwith classes ...");\r
1635 /*-----------------------------------------------------------------*/\r
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);\r
1637 safe_run(str);\r
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);\r
1639 safe_run(str);\r
1640 /* tc SFQ */\r
1641 if (strcmpi(qos_leaf, "none"))\r
1642 {\r
1643 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s",tc,lan,qos_leaf);\r
1644 safe_run(str);\r
1645 \r
1646 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s",tc,wan,qos_leaf);\r
1647 safe_run(str);\r
1648 } \r
1649 /* tc handle 1 fw flowid */\r
1650 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3",tc,lan);\r
1651 safe_run(str);\r
007c44c5 1652\r
dee5592e 1653 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3",tc,wan);\r
1654 safe_run(str);\r
007c44c5 1655 }\r
dee5592e 1656 printf("Total IP count: %d\n", i);\r
1657 run_restore(); \r
007c44c5 1658 if (log_file) fclose(log_file);\r
1659 return 0;\r
007c44c5 1660 /* that's all folks, thank you for reading it all the way up to this point ;-) */\r
1661 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */\r
1662}\r
This page took 1.531418 seconds and 4 git commands to generate.