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