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