cleanup
[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
43cde5c3 10/* Modified: xChaos, 20080504\r
33ec95ab 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
2d114137 36const char *version = "0.7.9-c"; \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
5a8f2e77 644 char *month, *year, *str, *name, *ptr, *ptr2;\r
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
650\r
5b902402 651 if(argv[1][1]=='l') /* -l */\r
652 {\r
c9012978 653 if(argc<4)\r
654 {\r
655 puts("Missing parameter(s)!\nUsage: prometheus -l Mmm YYYY (Mmm=Jan-Dec or Year, YYYY=year)");\r
656 exit(-1);\r
657 }\r
658 else\r
659 {\r
660 month=argv[2];\r
661 if(eq(month,"Year")) any_month=1;\r
662 year=argv[3];\r
5b902402 663 }\r
664 }\r
665 else\r
666 { \r
667 time_t t = time(NULL) - 3600*24 ; /* yesterday's timestamp*/\r
668 struct tm *timep = localtime(&t); \r
669 \r
670 if(argv[1][1]=='m') /* -m yestarday - month */\r
671 {\r
672 strftime(mstr, 4, "%b", timep);\r
673 month=mstr;\r
674 strftime(ystr, 5, "%Y", timep);\r
675 year=ystr; \r
676 }\r
677 else /* -y yesterday - year */\r
678 {\r
679 month="Year";\r
680 any_month=1;\r
681 strftime(ystr, 5, "%Y", timep);\r
682 year=ystr;\r
683 }\r
684 }\r
685 printf("Analysing traffic for %s %s ...\n",month,year);\r
c9012978 686\r
687 sprintf(str,"%s %s/*.log",ls,log_dir);\r
688 shell(str);\r
b1b59b3a 689\r
c9012978 690 input(str,STRLEN)\r
691 {\r
692 ptr=strrchr(str,'\n');\r
693 if(ptr) *ptr='\0';\r
694 printf("Parsing %s ...",str);\r
695 accept_month=0;\r
696 traffic_month=0;\r
5a8f2e77 697 guaranted = 0;\r
c9012978 698 parse(str)\r
699 {\r
700 y_ok=m_ok=0; \r
701 valid_columns(ptr,_,'\t',col) switch(col)\r
702 {\r
5a8f2e77 703 case 2: name = ptr;break;\r
704 case 3: traffic = atol(ptr);break;\r
705 /* column number - was 7, now 10...*/\r
b1b59b3a 706 case 7:\r
707 case 8:\r
5a8f2e77 708 case 9:\r
2d114137 709 case 10: if (isalpha(*ptr)) /* character, not numeric string = date, just one*/\r
5a8f2e77 710 {\r
711 valid_columns(ptr2,ptr,' ',col2) switch(col2)\r
712 {\r
713 case 2: if(any_month || eq(ptr2,month)) m_ok = 1; break;\r
714 case 5: if(eq(ptr2,year)) y_ok = 1; break;\r
715 }\r
716 }\r
717 else\r
718 {\r
719 if(col == 7) guaranted = atol(ptr);\r
720 }\r
c9012978 721 }\r
b1b59b3a 722 \r
c9012978 723 if(y_ok && m_ok) \r
724 {\r
5a8f2e77 725 traffic_month += traffic;\r
726 accept_month = 1;\r
c9012978 727 }\r
728 }\r
729 done;\r
b1b59b3a 730\r
c9012978 731 if(accept_month)\r
732 {\r
733 create(iplog,IpLog);\r
5a8f2e77 734 iplog->name = name;\r
735 iplog->guaranted = guaranted;\r
736 iplog->traffic = traffic_month;\r
c9012978 737 insert(iplog,iplogs,desc_order_by,traffic);\r
738 printf(" %ld MB\n",iplog->traffic);\r
739 }\r
740 else\r
741 puts(" no records.");\r
742 }\r
743 sprintf(str,"%s/%s-%s.html",html_log_dir,year,month);\r
744 printf("Writing %s ...",str);\r
745 f=fopen(str,"w");\r
746 if(f)\r
747 {\r
5a8f2e77 748 fprintf(f,"<table border><tr><th colspan=\"4\">Data transfers - %s %s</th><th align=\"right\">Min.speed</th></tr>\n ",month,year);\r
c9012978 749 every(iplog,iplogs)\r
750 if(iplog->traffic)\r
751 {\r
5a8f2e77 752 fprintf(f,"<tr><td align=\"right\">%d</td><th>%s</td><td align=\"right\">%ld MB</td><th align=\"right\">%ld GB</th><th align=\"right\">%ld kbps</th></tr>\n",\r
753 i++, iplog->name, iplog->traffic, iplog->traffic>>10, iplog->guaranted);\r
c9012978 754 total+=iplog->traffic>>10;\r
755 }\r
5a8f2e77 756 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 757 fputs("</table>\n", f);\r
758 fprintf(f, stats_html_signature, version);\r
c9012978 759 fclose(f);\r
760 puts(" done.");\r
761 }\r
762}\r
5b902402 763\r
764\r
007c44c5 765/*-----------------------------------------------------------------*/\r
766/* Are you looking for int main (int argc, char **argv) ? :-)) */\r
767/*-----------------------------------------------------------------*/\r
768\r
769program\r
770{\r
771 int i=0;\r
772 FILE *f=NULL;\r
773 char *str, *ptr, *d;\r
774 char *substring;\r
775 int class_count=0,ip_count=0;\r
776 int parent=1;\r
777 int just_flush=0;\r
778 int nodelay=0;\r
33ec95ab 779 int just_preview=0; /* preview - generate just stats */\r
780 int just_logs=0; /* just parse logs */\r
781 \r
007c44c5 782 char *chain_forward, *chain_postrouting;\r
783 char *althosts=NULL;\r
784 \r
785 printf("\n\\r
786Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\\r
ab85aff7 787Version %s - Copyright (C)2005-2008 Michael Polak (xChaos)\n\\r
43cde5c3 788iptables-restore & burst tunning & classify modification by Ludva\n\\r
0d5026c6 789Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version);\r
007c44c5 790\r
791 /*----- Boring... we have to check command line options first: ----*/\r
792 \r
793 arguments\r
794 {\r
795 argument("-c") { nextargument(config); }\r
796 argument("-h") { nextargument(althosts);}\r
797 argument("-d") { dry_run=1; }\r
798 argument("-f") { just_flush=1; }\r
799 argument("-9") { just_flush=9; }\r
800 argument("-p") { just_preview=1; }\r
801 argument("-n") { nodelay=1; }\r
33ec95ab 802 argument("-l") { just_logs=1; }\r
803 argument("-m") { just_logs=1; }\r
804 argument("-y") { just_logs=1; }\r
007c44c5 805 argument("-?") { help(); exit(0); }\r
806 argument("--help") { help(); exit(0); }\r
807 argument("-v") { exit(0); } \r
808 argument("--version") { exit(0); } \r
809 }\r
810\r
811 if(dry_run)\r
812 puts("*** THIS IS JUST DRY RUN ! ***\n");\r
813\r
814 date(d); /* this is typical cll1.h macro */\r
815\r
816 /*-----------------------------------------------------------------*/\r
817 printf("Parsing configuration file %s ...\n", config);\r
818 /*-----------------------------------------------------------------*/\r
819 get_config(config);\r
c9012978 820 \r
33ec95ab 821 if(just_logs)\r
c9012978 822 {\r
33ec95ab 823 parse_ip_log(argc,argv);\r
824 exit(0);\r
c9012978 825 }\r
007c44c5 826\r
827 if(althosts) hosts=althosts;\r
828\r
829 if(just_flush<9)\r
830 {\r
831 /*-----------------------------------------------------------------*/\r
832 puts("Parsing iptables verbose output ...");\r
833 /*-----------------------------------------------------------------*/\r
834 get_traffic_statistics();\r
835 }\r
836\r
837 /*-----------------------------------------------------------------*/\r
838 printf("Parsing class defintion file %s ...\n", hosts);\r
839 /*-----------------------------------------------------------------*/\r
840 int groupidx = FIRSTGROUPID;\r
841 parse(hosts)\r
842 {\r
843 str=_;\r
844\r
845 if(*str<'0' || *str>'9')\r
846 continue;\r
847 \r
848 //Does this IP share QoS class with some other ?\r
849 substring=strstr(str,"sharing-");\r
850 if(substring)\r
851 { \r
852 substring+=8; //"sharing-"\r
853 parse_ip(str);\r
854 ip_count++;\r
855 ip->sharing=substring;\r
856 ip->keyword=defaultkeyword; /* settings for default keyword */\r
857 while(*substring && *substring!='\n')\r
858 substring++;\r
859 *substring=0; \r
860 }\r
861 else\r
862 {\r
863 //Do we have to create new QoS class for this IP ?\r
864\r
865 find(keyword,keywords,(substring=strstr(str,keyword->key)))\r
866 {\r
867 parse_ip(str);\r
868 ip_count++;\r
869 ip->keyword=keyword;\r
870 keyword->ip_count++;\r
871 ip->prio=keyword->default_prio;\r
872 substring+=strlen(keyword->key)+1;\r
873 ptr=substring;\r
874 while(*ptr && *ptr!='-')\r
875 ptr++;\r
876 if(*ptr=='-')\r
877 {\r
878 *ptr=0;\r
879 ip->max=ip->desired=atoi(ptr+1);\r
880 }\r
881 ip->min=atoi(substring);\r
882 if(ip->min<=0)\r
883 {\r
312ac2c1 884 printf(" %s: Illegal value of minimum bandwidth 0 kbps, using %d kbps\n",str,free_min);\r
c312f6a9 885 ip->min=free_min;\r
007c44c5 886 }\r
887 if(ip->max<=ip->min)\r
888 {\r
889 ip->fixedprio=1;\r
890 ip->max=ip->min+ip->keyword->reserve_min;\r
891 }\r
892 else \r
893 {\r
894 ip->max-=ip->keyword->reserve_max;\r
895\r
896/*\r
897 if(ip->keyword->divide_max>1)\r
898 ip->max=ip->min+(ip->max-ip->min)/ip->keyword->divide_max;\r
899 if(ip->keyword->htb_ceil_bonus_divide>0)\r
900 ip->max+=ip->max/ip->keyword->htb_ceil_bonus_divide;\r
901*/\r
902 if(ip->max<ip->min)\r
903 ip->max=ip->min;\r
904 }\r
43e07280 905 ip->mark=FIRSTIPCLASS+1+class_count++;\r
007c44c5 906\r
907 find(group,groups,group->min==ip->min) \r
908 { \r
909 group->count++; \r
910 group->desired+=ip->min;\r
911 ip->group = group->id; \r
912 }\r
913 else\r
914 {\r
915 create(group,Group);\r
916 group->min=ip->min;\r
917 group->id = groupidx++;\r
918 ip->group = group->id;\r
919\r
920 if(group->min<8) group->min=8;\r
921 /* Warning - this is maybe because of primitive tc namespace, can be fixed */\r
922 /* it is because class IDs are derived from min. bandwidth. - xCh */\r
923 //if(group->min>MAX_GUARANTED_KBPS) group->min=MAX_GUARANTED_KBPS;\r
924 \r
925 group->count=1;\r
926 group->desired=ip->min; \r
927 insert(group,groups,desc_order_by,min);\r
928 }\r
929 }//endif keyword-\r
930 }//endif sharing-\r
931 }\r
932 fail\r
933 {\r
934 perror(hosts);\r
935 exit(-1);\r
936 }\r
937 done;\r
938\r
939 /*-----------------------------------------------------------------*/\r
940 /* cll1.h - let's allocate brand new character buffer... */\r
941 /*-----------------------------------------------------------------*/\r
942 string(str,STRLEN); \r
943\r
944 /*-----------------------------------------------------------------*/\r
945 puts("Resolving shared connections ...");\r
946 /*-----------------------------------------------------------------*/\r
947 search(ip,ips,ip->sharing)\r
948 {\r
949 search(sharedip,ips,eq(sharedip->name,ip->sharing))\r
950 {\r
951 sharedip->traffic+=ip->traffic;\r
952 ip->traffic=0;\r
953 ip->mark=sharedip->mark; \r
954 break;\r
955 }\r
956 if(!sharedip)\r
957 printf("Unresolved shared connection: %s %s sharing-%s\n",ip->addr,ip->name,ip->sharing);\r
958 }\r
959\r
960 if(enable_credit && just_flush<9)\r
961 {\r
962 /*-----------------------------------------------------------------*/\r
963 printf("Parsing credit file %s ...\n", credit);\r
964 /*-----------------------------------------------------------------*/\r
965 parse(credit)\r
966 {\r
967 ptr=parse_datafile_line(_);\r
968 if(ptr)\r
969 {\r
970 find(ip,ips,eq(ip->addr,_))\r
971 sscanf(ptr,"%Lu",&(ip->credit));\r
972 }\r
973 }\r
974 done;\r
975 }\r
976\r
977 if(!just_preview)\r
978 {\r
979 /*-----------------------------------------------------------------*/\r
980 puts("Initializing iptables and tc classes ...");\r
981 /*-----------------------------------------------------------------*/\r
982 \r
983 iptables_file=fopen(iptablesfile,"w");\r
984 if (iptables_file == NULL) {\r
985 puts("Cannot open iptablesfile!");\r
986 exit(-1);\r
987 }\r
988 \r
989 log_file=fopen(cmdlog,"w");\r
990 if (log_file == NULL) {\r
991 puts("Cannot open logfile!");\r
992 exit(-1);\r
993 }\r
994 \r
995 save_line(iptablespreamble);\r
996 run_restore();\r
997 \r
998 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,lan);\r
999 safe_run(str);\r
1000\r
1001 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,wan);\r
1002 safe_run(str);\r
1003 \r
1004 iptables_file=fopen(iptablesfile,"w");\r
1005 save_line(iptablespreamble);\r
1006\r
1007 if(qos_free_zone && *qos_free_zone!='0')\r
1008 {\r
1009 char *chain;\r
1010 \r
1011 sprintf(str,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone, wan);\r
1012 save_line(str);\r
1013 \r
1014 if(qos_proxy)\r
1015 {\r
1016 save_line(":post_noproxy - [0:0]");\r
1017 sprintf(str,"-A POSTROUTING -p ! tcp -o %s -j post_noproxy", lan);\r
1018 save_line(str); \r
1019 sprintf(str,"-A POSTROUTING -s ! %s -o %s -j post_noproxy", proxy_ip, lan);\r
1020 save_line(str); \r
1021 sprintf(str,"-A POSTROUTING -s %s -p tcp --sport ! %d -o %s -j post_noproxy", proxy_ip, proxy_port, lan);\r
1022 save_line(str); \r
1023\r
1024 chain="post_noproxy"; \r
1025 }\r
1026 else\r
1027 chain="POSTROUTING";\r
1028 \r
1029 sprintf(str,"-A %s -s %s -o %s -j ACCEPT", chain, qos_free_zone, lan);\r
1030 save_line(str);\r
1031 }\r
1032 \r
1033 if(ip_count>idxtable_treshold1 && !just_flush)\r
1034 {\r
1035 int idxcount=0, bitmask=32-idxtable_bitmask1; /* default net mask: 255.255.255.240 */\r
e0161edb 1036 char *subnet, *buf;\r
007c44c5 1037 /*-----------------------------------------------------------------*/\r
1038 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count);\r
1039 /*-----------------------------------------------------------------*/\r
1040\r
1041 save_line(":post_common - [0:0]");\r
1042 save_line(":forw_common - [0:0]");\r
1043\r
1044 search(ip,ips,ip->addr && *(ip->addr) && !eq(ip->addr,"0.0.0.0/0"))\r
1045 {\r
1046 buf=hash_id(ip->addr,bitmask);\r
1047 find(idx,idxs,eq(idx->id,buf))\r
1048 idx->children++;\r
1049 else\r
1050 {\r
1051 create(idx,Index);\r
1052 idx->addr=ip->addr;\r
1053 idx->id=buf;\r
1054 idx->bitmask=bitmask;\r
1055 idx->parent=NULL;\r
1056 idx->children=0;\r
1057 idxcount++;\r
1058 push(idx,idxs);\r
1059 }\r
1060 }\r
1061\r
1062 /* brutal perfomance optimalization */\r
1063 while(idxcount>idxtable_treshold2 && bitmask>2*idxtable_bitmask2)\r
1064 {\r
1065 bitmask-=idxtable_bitmask2;\r
1066 idxcount=0;\r
1067 search(idx,idxs,idx->parent==NULL)\r
1068 {\r
1069 buf=hash_id(idx->addr,bitmask);\r
1070 find(metaindex,idxs,eq(metaindex->id,buf))\r
1071 metaindex->children++; \r
1072 else\r
1073 {\r
1074 create(metaindex,Index);\r
1075 metaindex->addr=idx->addr;\r
1076 metaindex->id=buf;\r
1077 metaindex->bitmask=bitmask;\r
1078 metaindex->parent=NULL;\r
1079 metaindex->children=0;\r
1080 idxcount++;\r
1081 push(metaindex,idxs);\r
1082 }\r
1083 idx->parent=metaindex;\r
1084 }\r
1085 }\r
1086\r
1087 /* this should slightly optimize throughout ... */\r
1088 sort(idx,idxs,desc_order_by,children);\r
1089 sort(idx,idxs,order_by,bitmask);\r
1090\r
1091 i=0;\r
1092 every(idx,idxs)\r
1093 {\r
1094 subnet=subnet_id(idx->addr,idx->bitmask);\r
1095 printf("%d: %s/%d\n",++i,subnet,idx->bitmask);\r
1096 \r
1097 sprintf(str,":post_%s - [0:0]", idx->id);\r
1098 save_line(str);\r
1099\r
1100 sprintf(str,":forw_%s - [0:0]", idx->id);\r
1101 save_line(str);\r
1102\r
1103 if(idx->parent)\r
1104 {\r
1105 string(buf,strlen(idx->parent->id)+6);\r
1106 sprintf(buf,"post_%s",idx->parent->id);\r
1107 }\r
1108 else\r
1109 buf="POSTROUTING";\r
1110\r
1111 sprintf(str,"-A %s -d %s/%d -o %s -j post_%s", buf, subnet, idx->bitmask, lan, idx->id);\r
1112 save_line(str);\r
1113\r
1114 sprintf(str,"-A %s -d %s/%d -o %s -j post_common", buf, subnet, idx->bitmask, lan);\r
1115 save_line(str);\r
1116\r
1117 if(idx->parent)\r
1118 {\r
1119 string(buf,strlen(idx->parent->id)+6);\r
1120 sprintf(buf,"forw_%s",idx->parent->id);\r
1121 }\r
1122 else\r
1123 buf="FORWARD";\r
1124\r
1125 sprintf(str,"-A %s -s %s/%d -o %s -j forw_%s", buf, subnet, idx->bitmask, wan, idx->id);\r
1126 save_line(str);\r
1127\r
1128 sprintf(str,"-A %s -s %s/%d -o %s -j forw_common", buf, subnet, idx->bitmask, wan);\r
1129 save_line(str);\r
1130 }\r
1131 printf("Total indexed iptables chains created: %d\n", i);\r
1132\r
1133 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);\r
1134 save_line(str);\r
1135 \r
1136 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);\r
1137 save_line(str);\r
1138 }\r
1139 \r
1140 }\r
1141\r
1142 if(just_flush)\r
1143 {\r
1144 fclose(iptables_file);\r
1145 if (log_file) fclose(log_file);\r
1146 puts("Just flushed iptables and tc classes - now exiting ...");\r
1147 exit(0);\r
1148 }\r
1149\r
1150 if(!just_preview)\r
1151 {\r
1152 if(!dry_run && !nodelay && qos_free_delay)\r
1153 {\r
1154 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay);\r
1155 sleep(qos_free_delay);\r
1156 }\r
1157\r
1158 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc,lan,htb_r2q);\r
1159 safe_run(str);\r
1160\r
1161 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
1162 safe_run(str);\r
1163\r
1164 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
1165 safe_run(str);\r
1166\r
1167 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc,wan,htb_r2q);\r
1168 safe_run(str);\r
1169\r
1170 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
1171 safe_run(str);\r
1172\r
1173 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
1174 safe_run(str);\r
1175 }\r
1176\r
1177 /*-----------------------------------------------------------------*/\r
1178 puts("Locating suckers and generating root classes ...");\r
1179 /*-----------------------------------------------------------------*/\r
1180 sort(ip,ips,desc_order_by,traffic);\r
1181 \r
1182\r
1183 /*-----------------------------------------------------------------*/\r
1184 /* sub-scope - local variables */ \r
1185 {\r
1186 long long int rate=line;\r
1187 long long int max=line;\r
1188 int group_count=0;\r
1189 FILE *credit_file=NULL;\r
1190 \r
1191 if(!just_preview && !dry_run && enable_credit) credit_file=fopen(credit,"w");\r
1192 \r
1193 every(group,groups)\r
1194 {\r
1195 if(!just_preview)\r
1196 {\r
1197 \r
1198 //download\r
1199 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
1200 tc, lan, parent, group->id, rate, max, burst_group, group->desired);\r
1201 safe_run(str);\r
1202 \r
1203 //upload\r
1204 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
1205 tc, wan, parent, group->id, rate*up/line, max*up/line, burst_group, group->desired);\r
1206 safe_run(str);\r
1207 }\r
1208 \r
1209 if(group_count++<max_nesting) parent=group->id;\r
1210 \r
1211 rate-=digital_divide*group->min;\r
1212 if(rate<group->min)rate=group->min;\r
1213 \r
1214 /*shaping of aggresive downloaders, with credit file support */\r
1215 if(use_credit)\r
1216 {\r
1217 int group_rate=group->min, priority_sequence=magic_priorities+1;\r
1218 \r
1219 search(ip, ips, ip->min==group->min && ip->max>ip->min)\r
1220 {\r
99127c70 1221 if( ip->keyword->data_limit && !ip->fixedprio &&\r
007c44c5 1222 ip->traffic>ip->credit+\r
99127c70 1223 (ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20)) )\r
007c44c5 1224 {\r
1225 if(group_rate<ip->max) ip->max=group_rate;\r
1226 group_rate+=magic_treshold;\r
1227 ip->prio=magic_priorities+2;\r
1228 if(ip->prio<3) ip->prio=3;\r
1229 }\r
1230 else\r
1231 {\r
abe9b855 1232 if( ip->keyword->data_prio && !ip->fixedprio &&\r
99127c70 1233 ip->traffic>ip->credit+\r
1234 (ip->min*ip->keyword->data_prio+(ip->keyword->fixed_prio<<20)) )\r
007c44c5 1235 {\r
1236 ip->prio=priority_sequence--;\r
1237 if(ip->prio<2) ip->prio=2;\r
1238 }\r
1239 \r
1240 if(credit_file)\r
1241 {\r
1242 unsigned long long lcredit=0;\r
99127c70 1243 \r
007c44c5 1244 if((ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))>ip->traffic) \r
1245 lcredit=(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))-ip->traffic;\r
1246 fprintf(credit_file,"%s %Lu\n",ip->addr,lcredit);\r
1247 }\r
1248 }\r
1249 }\r
1250 \r
1251 }\r
1252 }\r
1253 if(credit_file)fclose(credit_file);\r
1254 }\r
1255\r
1256 if(just_preview)\r
1257 {\r
1258 f=fopen(preview,"w");\r
1259 ptr=preview; \r
1260 }\r
1261 else if(!dry_run && !just_flush)\r
1262 {\r
1263 /*-----------------------------------------------------------------*/\r
1264 printf("Writing data transfer database ...\n");\r
1265 /*-----------------------------------------------------------------*/\r
1266 f=fopen("/var/run/prometheus.previous","w");\r
1267 if(f)\r
1268 {\r
1269 search(ip,ips,ip->traffic || ip->direct || ip->proxy ||ip->upload)\r
1270 fprintf(f,"%s %Lu %Lu %Lu %Lu\n",ip->addr,ip->traffic,ip->direct,ip->proxy,ip->upload);\r
1271 fclose(f);\r
1272 }\r
1273\r
1274 f=fopen(html,"w");\r
1275 ptr=html;\r
1276 }\r
1277\r
1278 if(f)\r
1279 {\r
1280 int total=0;\r
1281 int count=1;\r
1282 i=0;\r
1283\r
1284 /*-----------------------------------------------------------------*/\r
1285 printf("Sorting data and generating statistics page %s ...\n",ptr);\r
1286 /*-----------------------------------------------------------------*/\r
1287\r
1288 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
1289 fprintf(f,"<th colspan=\"%d\">data limits</th>\n",keywordcount);\r
1290 fputs("</tr>\n",f);\r
1291 every(group,groups) \r
1292 { \r
1293#ifdef DEBUG\r
1294 printf("%d k group: %d bandwidth requested: %d k\n",group->min,group->count,group->desired);\r
1295#endif\r
1296 fprintf(f,"<tr><td align=\"right\">%d</td><td align=\"right\">%d k</td>",count,group->min);\r
1297 fprintf(f,"<td align=\"right\">%d</td><td align=\"right\">%d k</td>",group->count,group->desired);\r
1298\r
1299 every(keyword,keywords)\r
1300 fprintf(f,"<td align=\"right\"><font color=\"#%s\">%d M</font></td>",keyword->html_color,group->min*keyword->data_limit); \r
1301 \r
1302 i+=group->desired; \r
1303 total+=group->count;\r
1304 count++; \r
1305 }\r
1306#ifdef DEBUG\r
1307 printf("Total groups: %d Total bandwidth requested: %d k\nAGGREGATION: 1/%d\n",count,i,i/line);\r
1308#endif\r
e0161edb 1309 fprintf(f,"<tr><th colspan=\"2\" align=\"left\">Line %Ld k</td>",line);\r
007c44c5 1310 fprintf(f,"<th align=\"right\">%d</td><th align=\"right\">%d k</td>",total,i);\r
1311\r
1312 every(keyword,keywords)\r
1313 fprintf(f,"<th align=\"right\">%d IPs</th>",keyword->ip_count); \r
1314\r
1315 fprintf(f,"</tr><tr><th colspan=\"4\">Aggregation 1/%d</th>\n",(int)(0.5+i/line));\r
1316 fprintf(f,"<th colspan=\"%d\">%d traffic classes</th></tr>\n",keywordcount,total);\r
1317\r
1318 fputs("</table>\n",f);\r
1319 }\r
1320 else if(!dry_run && !just_flush) \r
1321 perror(html);\r
1322\r
1323 i=1;\r
1324 if(f)\r
1325 {\r
1326 unsigned long long total=0, total_direct=0, total_proxy=0, total_upload=0, tmp_sum=0;\r
1327 int active_classes=0;\r
1328 int colspan;\r
1329 FILE *iplog;\r
1330 struct Sum {unsigned long long l; int i; list(Sum);} *sum,*sums=NULL;\r
1331\r
1332 if(qos_proxy)\r
1333 colspan=12;\r
1334 else \r
1335 colspan=11;\r
1336 \r
1337 fprintf(f,"<p><table border>\n<tr><th colspan=\"%d\">%s",colspan,title);\r
1338 fprintf(f," (%s)</th></tr>\n", d);\r
1339 fputs("<tr><td align=\"right\">#</td><td>hostname</td>\\r
1340 <td align=\"right\">credit</td>\\r
1341 <td align=\"right\">limit</td>\\r
1342 <td align=\"right\">total</td>\\r
1343 <td align=\"right\">direct</td>\n",f);\r
1344 if(qos_proxy)\r
1345 fputs("<td align=\"right\">proxy</td>\n",f);\r
1346 fputs("<td align=\"right\">upload</td>\\r
1347 <td align=\"right\">minimum</td>\\r
1348 <td align=\"right\">desired</td>\\r
1349 <td align=\"right\">maximum</td>\\r
1350 <td>prio</td></tr>\n",f); \r
1351\r
1352 every(ip,ips)\r
1353 {\r
1354 char *f1="", *f2="";\r
1355 if(ip->max<ip->desired)\r
1356 {\r
1357 f1="<font color=\"red\">";\r
1358 f2="</font>";\r
1359 }\r
1360 else if(ip->prio>1)\r
1361 {\r
1362 f1="<font color=\"brown\">";\r
1363 f2="</font>";\r
1364 }\r
1365\r
1366#ifdef DEBUG\r
1367 printf("%03d. %-22s %10Lu (%d/%d)\n",i ,ip->name, ip->traffic, ip->min, ip->max); \r
1368#endif\r
1369 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
1370 ip->name, i, log_url, ip->name, ip->name, ip->credit);\r
1371 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
1372 fprintf(f,"<td align=\"right\">%s%Lu M%s</td><td align=\"right\">%Lu M</td>\n", f1, ip->traffic, f2, ip->direct);\r
1373 if(qos_proxy)\r
1374 fprintf(f,"<td align=\"right\">%Lu M</td>\n", ip->proxy);\r
1375 fprintf(f,"<td align=\"right\">%Lu M</td>\n", ip->upload);\r
1376 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
1377 total+=ip->traffic;\r
1378 total_direct+=ip->direct;\r
1379 total_proxy+=ip->proxy;\r
1380 total_upload+=ip->upload;\r
1381 if(ip->traffic>0)\r
1382 {\r
1383 active_classes++;\r
1384 tmp_sum+=ip->traffic;\r
1385 create(sum,Sum);\r
1386 sum->l=tmp_sum;\r
1387 sum->i=active_classes;\r
1388 insert(sum,sums,order_by,i);\r
1389 }\r
1390 \r
1391 i++;\r
1392 \r
1393 if(!just_preview)\r
1394 {\r
5b902402 1395 sprintf(str,"%s/%s.log",log_dir,ip->name);\r
007c44c5 1396 iplog=fopen(str,"a");\r
1397 if(iplog)\r
1398 {\r
c0718973 1399 fprintf(iplog,"%ld\t%s\t%Lu\t%Lu\t%Lu\t%Lu\t%d\t%d\t%d\t%s",\r
1400 time(NULL),ip->name,ip->traffic,ip->direct,ip->proxy,ip->upload,ip->min,ip->max,ip->desired,d); /* d = date*/\r
007c44c5 1401 fclose(iplog);\r
1402 }\r
1403 }\r
1404\r
1405 }\r
1406 fprintf(f,"<tr><th colspan=\"4 \"align=\"left\">SUMMARY:</td>");\r
1407 fprintf(f,"<th align=\"right\">%Lu M</th>\\r
1408 <th align=\"right\">%Lu M</th>\n", total, total_direct);\r
1409 if(qos_proxy)\r
1410 fprintf(f,"<th align=\"right\">%Lu M</th>\n", total_proxy);\r
1411 fprintf(f,"<th align=\"right\">%Lu M</th>", total_upload);\r
1412 fputs("<td colspan=\"4\"></td></th>\n</table>\n",f);\r
1413\r
1414 if(active_classes>10)\r
c9012978 1415 {\r
1416 fputs("<a name=\"erp\"></a><p><table border><tr><th colspan=\"5\">Enterprise Research and Planning (ERP)</th></tr>\n",f);\r
1417 fputs("<tr><td>Analytic category</td>\n",f);\r
1418 fputs("<td colspan=\"2\" align=\"center\">Active Classes</td><td colspan=\"2\" align=\"center\">Data transfers</td></tr>\n",f);\r
1419\r
1420 find(sum,sums,sum->l>=total/4)\r
1421 {\r
1422 fprintf(f,"<tr><td>Top 25%% of traffic</td>\n");\r
1423 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
1424 }\r
1425 \r
1426 find(sum,sums,sum->i==10)\r
1427 {\r
1428 fprintf(f,"<tr><td>Top 10 downloaders</td>\n");\r
1429 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
1430 }\r
1431\r
1432 find(sum,sums,sum->l>=total/2)\r
1433 {\r
1434 fprintf(f,"<tr><td>Top 50%% of traffic</td>\n");\r
1435 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
1436 }\r
1437\r
1438 find(sum,sums,sum->l>=4*total/5)\r
1439 {\r
1440 fprintf(f,"<tr><td>Top 80%% of traffic</td>\n");\r
1441 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
1442 }\r
1443\r
1444 find (sum,sums,sum->i>=(active_classes+1)/5)\r
1445 {\r
1446 fprintf(f,"<tr><td>Top 20%% downloaders</td>\n");\r
1447 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
1448 }\r
1449\r
1450 find(sum,sums,sum->i>=(active_classes+1)/4)\r
1451 {\r
1452 fprintf(f,"<tr><td>Top 25%% downloaders</td>\n");\r
1453 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
1454 }\r
1455\r
1456 find(sum,sums,sum->i>=(active_classes+1)/2)\r
1457 {\r
1458 fprintf(f,"<tr><td>Top 50%% downloaders</td>\n");\r
1459 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
1460 }\r
1461\r
1462 find(sum,sums,sum->i>=4*(active_classes+1)/5)\r
1463 {\r
1464 fprintf(f,"<tr><td>Top 80%% downloaders</td>\n");\r
1465 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
1466 }\r
1467\r
1468 fprintf(f,"<tr><td>All users, all traffic</td>\n");\r
1469 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 1470 fputs("</table>\n", f);\r
c9012978 1471 }\r
2d114137 1472 fprintf(f, stats_html_signature, version);\r
007c44c5 1473 fclose(f);\r
1474 }\r
1475\r
1476 if(just_preview)\r
1477 {\r
1478 puts("Statistics preview generated (-p switch) - now exiting ...");\r
1479 exit(0);\r
1480 }\r
1481 \r
1482 /*-----------------------------------------------------------------*/\r
1483 puts("Generating iptables and tc classes ...");\r
1484 /*-----------------------------------------------------------------*/\r
1485\r
1486 i=0;\r
1487 printf("%-22s %-15s mark\n","name","ip");\r
1488 search(ip,ips,ip->mark>0)\r
1489 { \r
1490 \r
1491 if(idxs)\r
1492 {\r
1493 char *buf;\r
1494 duplicate(ip->addr,buf);\r
1495 buf=hash_id(ip->addr,32-idxtable_bitmask1); \r
1496 \r
1497 string(chain_forward,6+strlen(buf));\r
1498 strcpy(chain_forward,"forw_");\r
1499 strcat(chain_forward,buf);\r
1500\r
1501 string(chain_postrouting,6+strlen(buf));\r
1502 strcpy(chain_postrouting,"post_");\r
1503 strcat(chain_postrouting,buf);\r
1504 \r
1505 free(buf);\r
1506 }\r
1507 else\r
1508 {\r
1509 chain_forward="FORWARD";\r
1510 chain_postrouting="POSTROUTING";\r
1511 }\r
1512\r
1513 printf("%-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
1514\r
1515 /* -------------------------------------------------------- mark download */\r
1516 \r
1517 sprintf(str,"-A %s -d %s/32 -o %s -j %s%d",chain_postrouting,ip->addr,lan,mark_iptables,ip->mark);\r
1518 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/\r
1519 /* -m limit --limit 1/s */ \r
1520 save_line(str);\r
1521\r
1522 if(qos_proxy)\r
1523 {\r
1524 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
1525 /*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
1526 save_line(str);\r
1527 }\r
1528\r
1529 sprintf(str,"-A %s -d %s/32 -o %s -j ACCEPT",chain_postrouting,ip->addr,lan);\r
1530 save_line(str);\r
1531\r
1532 /* -------------------------------------------------------- mark upload */\r
1533 sprintf(str,"-A %s -s %s/32 -o %s -j %s%d",chain_forward,ip->addr,wan,mark_iptables,ip->mark);\r
1534 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/\r
1535 save_line(str);\r
1536\r
1537 sprintf(str,"-A %s -s %s/32 -o %s -j ACCEPT",chain_forward,ip->addr,wan);\r
1538 save_line(str);\r
1539\r
1540 if(ip->min)\r
1541 {\r
1542 /* -------------------------------------------------------- download class */\r
1543 printf("(down: %dk-%dk ", ip->min, ip->max); \r
1544\r
1545 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
1546 safe_run(str);\r
1547\r
1548 if (strcmpi(ip->keyword->leaf_discipline, "none")){\r
1549 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
1550 safe_run(str);\r
1551 }\r
1552 \r
1553 if (filter_type == 1){\r
1554 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
1555 safe_run(str);\r
1556 }\r
1557\r
1558 /* -------------------------------------------------------- upload class */\r
1559 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1560 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
1561\r
1562 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1563 tc, wan, ip->group, ip->mark,\r
1564 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1565 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1566 safe_run(str);\r
1567 \r
1568 if (strcmpi(ip->keyword->leaf_discipline, "none")){\r
1569 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
1570 safe_run(str);\r
1571 }\r
1572 \r
1573 if (filter_type == 1){\r
1574 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
1575 safe_run(str);\r
1576 }\r
1577 }\r
1578 else\r
1579 printf("(sharing %s)\n", ip->sharing);\r
1580 i++;\r
1581 }\r
1582\r
1583\r
1584 if(idxs)\r
1585 {\r
1586 chain_forward="forw_common";\r
1587 chain_postrouting="post_common";\r
1588 }\r
1589 else\r
1590 {\r
1591 chain_forward="FORWARD";\r
1592 chain_postrouting="POSTROUTING";\r
1593 }\r
1594\r
1595 /* -------------------------------------------------------- mark download */\r
1596\r
1597 if(qos_proxy)\r
1598 {\r
c9012978 1599 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
007c44c5 1600 save_line(str);\r
1601 sprintf(str,"-A %s -s %s -p tcp --sport %d -o %s -j ACCEPT",chain_postrouting,proxy_ip,proxy_port,lan);\r
1602 save_line(str);\r
1603 }\r
c9012978 1604 sprintf(str,"-A %s -o %s -j %s%d",chain_postrouting,lan,mark_iptables,3);\r
007c44c5 1605 save_line(str);\r
1606 sprintf(str,"-A %s -o %s -j ACCEPT",chain_postrouting,lan);\r
1607 save_line(str);\r
1608\r
1609 /* -------------------------------------------------------- mark upload */\r
c9012978 1610 sprintf(str,"-A %s -o %s -j %s%d",chain_forward,wan,mark_iptables,3);\r
007c44c5 1611 save_line(str);\r
1612 sprintf(str,"-A %s -o %s -j ACCEPT",chain_forward,wan);\r
1613 save_line(str);\r
1614\r
1615 printf("Total IP count: %d\n", i);\r
1616\r
abe9b855 1617 /*-----------------------------------------------------------------*/\r
1618 puts("Generating free bandwith classes ...");\r
1619 /*-----------------------------------------------------------------*/\r
1620\r
007c44c5 1621 /* ---------------------------------------- tc - free bandwith shared class */\r
1622 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
1623 safe_run(str);\r
1624\r
1625 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
1626 safe_run(str);\r
1627\r
1628 /* tc SFQ */\r
1629 if (strcmpi(qos_leaf, "none")){\r
1630 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s",tc,lan,qos_leaf);\r
1631 safe_run(str);\r
1632 \r
1633 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s",tc,wan,qos_leaf);\r
1634 safe_run(str);\r
1635 }\r
1636 \r
1637 /* tc handle 1 fw flowid */\r
1638 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3",tc,lan);\r
1639 safe_run(str);\r
1640\r
1641 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3",tc,wan);\r
1642 safe_run(str);\r
abe9b855 1643\r
007c44c5 1644 run_restore();\r
1645 \r
1646 if (log_file) fclose(log_file);\r
1647 return 0;\r
1648\r
1649 /* that's all folks, thank you for reading it all the way up to this point ;-) */\r
1650 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */\r
1651}\r
This page took 1.955771 seconds and 4 git commands to generate.