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