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