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