source code + html output formatting
[svn/Prometheus-QoS/.git] / prometheus.c
CommitLineData
312ac2c1 1 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2 /* Prometheus QoS - you can "steal fire" from your ISP */\r
3/* "fair-per-IP" quality of service (QoS) utility */\r
4/* requires Linux 2.4.x or 2.6.x with HTB support */\r
5/* Copyright(C) 2005-2008 Michael Polak (xChaos) */\r
6/* iptables-restore support Copyright(C) 2007-2008 ludva */\r
7/* Credit: CZFree.Net,Martin Devera,Netdave,Aquarius,Gandalf */\r
8/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
9\r
be96b71b 10/* Modified by: xChaos, 20120516\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
be96b71b 36const char *version = "0.8.3-d";\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
be96b71b 61char *json = "/var/www/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
92-?, --help this help screen\n\\r
208112af 93-v, --version show Version number of this utility and exit\n\\r
94-c filename force alternative /etc/prometheus.Conf filename\n\\r
95-h filename force alternative /etc/Hosts filename (overrides hosts keyword)\n\\r
96-f just Flush iptables and tc classes and exit (stop shaping)\n\\r
007c44c5 97-9 emergency iptables flush (do not read data transfer statistics)\n\\r
208112af 98-p just generate Preview of data transfer statistics and exit\n\\r
99-d Dry run (preview tc and iptables commands on stdout)\n\\r
100-r Run (reset all statistics and start shaping)\n\\r
101-n run Now (start shaping without delay - overrides qos-free-delay keyword)\n\\r
102-l Mmm YYYY generate HTML summary of traffic Logs (Mmm=Jan-Dec or Year, YYYY=year)\n\\r
103-m generate HTML summary of traffic logs for yesterday's Month\n\\r
104-y generate HTML summary of traffic logs for yesterday's Year\n");\r
5b902402 105/* not yet implemented:\r
106-s start shaping! (keep data transfer statistics - but apply shaping)\n\\r
5b902402 107*/\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
443 option("log-filename",cmdlog);\r
444 option("credit-filename",credit);\r
be96b71b 445 option("classmap-filename",classmap);\r
007c44c5 446 ioption("credit-enable",enable_credit);\r
447 option("log-traffic-directory",log_dir);\r
5b902402 448 option("log-traffic-html-directory",html_log_dir);\r
007c44c5 449 option("log-traffic-url-path",log_url);\r
6cc38f96 450 option("jquery-url",jquery_url);\r
451 option("lms-url",lms_url);\r
452 ioption("use-jquery-popups",use_jquery_popups);\r
007c44c5 453 option("qos-free-zone",qos_free_zone);\r
454 ioption("qos-free-delay",qos_free_delay);\r
455 ioption("qos-proxy-enable",qos_proxy);\r
456 option("qos-proxy-ip",proxy_ip);\r
457 option("htb-leaf-discipline",qos_leaf);\r
458 ioption("qos-proxy-port",proxy_port);\r
459 ioption("free-rate",free_min);\r
460 ioption("free-ceil",free_max);\r
461 ioption("htb-burst",burst);\r
462 ioption("htb-burst-main",burst_main);\r
463 ioption("htb-burst-group",burst_group);\r
464 ioption("htb-nesting-limit",max_nesting);\r
465 ioption("htb-r2q",htb_r2q);\r
466 ioption("magic-include-upload",include_upload);\r
5b902402 467 ioption("magic-treshold",magic_treshold); \r
260c2719 468 option("filter-type", cnf); \r
007c44c5 469/* not yet implemented:\r
470 ioption("magic-fixed-packets",fixed_packets);\r
471 ioption("magic-relative-packets",packet_limit);\r
472*/\r
473 }\r
474 fail\r
475 { \r
476 perror(config_filename);\r
477 puts("Warning - using built-in defaults instead ...");\r
478 }\r
479 done;\r
480 printf("\n");\r
481 \r
be96b71b 482 /* leaf discipline for keywords */\r
208112af 483 for_each(keyword,keywords)\r
007c44c5 484 {\r
260c2719 485 if(!strcmpi(keyword->leaf_discipline, ""))\r
208112af 486 {\r
007c44c5 487 keyword->leaf_discipline = qos_leaf;\r
488 }\r
489 }\r
490\r
260c2719 491 if(strcmpi(cnf, "mark"))\r
bb9e11ee 492 {\r
493 filter_type = 2;\r
494 mark = "CLASSIFY";\r
495 mark_iptables = "CLASSIFY --set-class 1:";\r
496 }\r
497 else\r
498 {\r
499 filter_type = 1;\r
500 mark = "MARK";\r
501 mark_iptables = "MARK --set-mark ";\r
007c44c5 502 }\r
503\r
504 /* are supplied values meaningful ?*/\r
505 if(line<=0 || up<=0)\r
506 {\r
b1b59b3a 507 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");\r
007c44c5 508 reject_config_and_exit(config_filename);\r
509 }\r
510}\r
511\r
512/* ===================== traffic analyser - uses iptables ================ */ \r
513\r
514void get_traffic_statistics(void)\r
515{\r
516 char *str,*cmd;\r
517 int downloadflag=0;\r
518\r
519 textfile(Pipe,str) *line,*lines=NULL;\r
520 string(str,STRLEN);\r
521 string(cmd,STRLEN);\r
522\r
523 sprintf(cmd,"%s -L -v -x -n -t mangle",iptables);\r
524 shell(cmd);\r
525 input(str,STRLEN)\r
526 {\r
527 create(line,Pipe);\r
528 line->str=str;\r
529 string(str,STRLEN);\r
530 append(line,lines);\r
531 }\r
532\r
208112af 533 for_each(line,lines)\r
007c44c5 534 {\r
535 int col, accept=0,proxyflag=0,valid=1,setchainname=0,commonflag=0; \r
536 unsigned long long traffic=0;\r
537 unsigned long pkts=0;\r
538 char *ipaddr=NULL,*ptr;\r
539 \r
540 /* debug puts(line->str); */\r
541 valid_columns(ptr,line->str,' ',col) \r
542 if(valid) switch(col)\r
543 { \r
544 case 1: if(eq(ptr,"Chain"))\r
260c2719 545 {\r
007c44c5 546 setchainname=1;\r
260c2719 547 }\r
007c44c5 548 else if(eq(ptr,"pkts")) \r
260c2719 549 {\r
007c44c5 550 valid=0;\r
260c2719 551 }\r
007c44c5 552 else\r
260c2719 553 {\r
007c44c5 554 sscanf(ptr,"%lu",&pkts); \r
260c2719 555 }\r
007c44c5 556 break;\r
557 case 2: if(setchainname)\r
558 {\r
559 if(!strncmp(ptr,"post_",5) || eq(ptr,"POSTROUTING"))\r
260c2719 560 {\r
561 downloadflag = 1; \r
562 }\r
007c44c5 563 else \r
260c2719 564 {\r
565 if(!strncmp(ptr,"forw_",5) || eq(ptr,"FORWARD"))\r
566 {\r
567 downloadflag = 0;\r
568 }\r
569 } \r
007c44c5 570 if(eq(ptr,"post_common") || eq(ptr,"forw_common"))\r
260c2719 571 {\r
572 commonflag = 1;\r
573 }\r
007c44c5 574 }\r
575 else\r
260c2719 576 {\r
577 sscanf(ptr,"%Lu",&traffic); \r
578 traffic += (1<<19);\r
579 traffic >>= 20;\r
580 }\r
007c44c5 581 break;\r
0045483c 582 case 3: if((strncmp(ptr,"post_",5) && strncmp(ptr,"forw_",5)) || commonflag)\r
260c2719 583 {\r
007c44c5 584 accept=eq(ptr,mark);\r
260c2719 585 }\r
586 /*if(filter_type==1) accept=eq(ptr,"MARK"); else accept=eq(ptr,"CLASSIFY");*/\r
007c44c5 587 break;\r
588 case 8: if(downloadflag)\r
589 { \r
260c2719 590 if(strstr(proxy_ip,ptr))\r
591 {\r
592 proxyflag=1; \r
593 }\r
007c44c5 594 }\r
595 else\r
260c2719 596 {\r
007c44c5 597 ipaddr=ptr; \r
260c2719 598 }\r
599 break;\r
007c44c5 600 case 9: if(downloadflag)ipaddr=ptr;break;\r
601 }\r
602 \r
603 if(accept && traffic>0 && ipaddr)\r
604 {\r
a1d21464 605 if(proxyflag)\r
606 {\r
607 printf("(proxy) ");\r
608 }\r
609 else if(!downloadflag)\r
610 {\r
611 printf("(upload) ");\r
612 }\r
007c44c5 613 printf("IP %s: %Lu M (%ld pkts)\n", ipaddr, traffic, pkts);\r
208112af 614\r
615 if_exists(ip,ips,eq(ip->addr,ipaddr)); \r
007c44c5 616 else \r
617 {\r
618 TheIP();\r
619 ip->addr=ipaddr;\r
620 if(eq(ip->addr,"0.0.0.0/0"))\r
621 {\r
622 ip->name="(unregistered)";\r
623 ip->min=free_min;\r
624 ip->max=ip->desired=free_max;\r
625 }\r
626 }\r
627 \r
628 if(downloadflag)\r
629 {\r
630 if(proxyflag)\r
a1d21464 631 {\r
007c44c5 632 ip->proxy=traffic;\r
a1d21464 633 }\r
007c44c5 634 else\r
a1d21464 635 {\r
007c44c5 636 ip->traffic+=traffic;\r
a1d21464 637 }\r
007c44c5 638 ip->direct=ip->traffic-ip->upload-ip->proxy;\r
639 ip->pktsdown=pkts;\r
640 }\r
641 else\r
642 {\r
643 ip->upload=traffic;\r
644 ip->pktsup=pkts;\r
645 if(include_upload)\r
bb9e11ee 646 {\r
007c44c5 647 ip->traffic+=traffic;\r
bb9e11ee 648 }\r
007c44c5 649 else \r
bb9e11ee 650 {\r
007c44c5 651 if(traffic>ip->traffic)\r
bb9e11ee 652 {\r
007c44c5 653 ip->traffic=traffic; \r
bb9e11ee 654 }\r
655 }\r
007c44c5 656 }\r
657 } \r
658 }\r
1c004f15 659 free(cmd);\r
007c44c5 660}\r
661 \r
662/* ========== This function executes, logs OR ALSO prints command ========== */\r
663\r
664void safe_run(char *cmd)\r
665{\r
a1d21464 666 if(dry_run)\r
667 {\r
668 printf("\n=>%s\n",cmd);\r
669 }\r
670 else\r
671 {\r
672 system(cmd);\r
673 }\r
674 if(log_file)\r
675 {\r
676 fprintf(log_file,"%s\n",cmd);\r
677 }\r
007c44c5 678}\r
679\r
680void save_line(char *line)\r
681{\r
682 fprintf(iptables_file,"%s\n",line);\r
683}\r
684\r
685void run_restore(void)\r
686{\r
5da44508 687 char *restor;\r
007c44c5 688 string(restor,STRLEN);\r
abe9b855 689\r
690 /*-----------------------------------------------------------------*/\r
1c004f15 691 printf("Running %s <%s ...\n", iptablesrestore, iptablesfile);\r
abe9b855 692 /*-----------------------------------------------------------------*/\r
007c44c5 693 \r
694 save_line("COMMIT");\r
695 fclose(iptables_file);\r
ae776b10 696 if(dry_run) \r
697 {\r
a1d21464 698 parse(iptablesfile)\r
699 {\r
700 printf("%s\n",_);\r
701 }\r
702 done;\r
ae776b10 703 }\r
704\r
705 sprintf(restor,"%s <%s",iptablesrestore, iptablesfile);\r
706 safe_run(restor);\r
007c44c5 707 \r
708 free(restor);\r
709}\r
710\r
711/* == This function strips extra characters after IP address and stores it = */\r
712\r
0eb8bc04 713void parse_ip(char *str)\r
007c44c5 714{\r
4358455e 715 char *ptr,*ipaddr=NULL,*ipname=NULL,*lmsid=NULL;\r
716\r
717 ptr=strchr(str,'{');\r
718 if(ptr)\r
719 {\r
720 lmsid=++ptr;\r
721 while(*ptr && *ptr!='}')\r
a1d21464 722 {\r
4358455e 723 ptr++;\r
a1d21464 724 }\r
4358455e 725 *ptr=0;\r
726 }\r
007c44c5 727 \r
4358455e 728 ptr=str;\r
007c44c5 729 while(*ptr && *ptr!=' ' && *ptr!=9)\r
a1d21464 730 {\r
007c44c5 731 ptr++;\r
a1d21464 732 }\r
007c44c5 733 \r
734 *ptr=0;\r
735 ipaddr=str;\r
736 ptr++;\r
737 while(*ptr && (*ptr==' ' || *ptr==9))\r
a1d21464 738 {\r
007c44c5 739 ptr++;\r
a1d21464 740 }\r
007c44c5 741 ipname=ptr; \r
742 while(*ptr && *ptr!=' ' && *ptr!=9)\r
a1d21464 743 {\r
007c44c5 744 ptr++;\r
a1d21464 745 }\r
007c44c5 746 *ptr=0;\r
747\r
208112af 748 if_exists(ip,ips,eq(ip->addr,ipaddr));\r
749 else\r
750 {\r
751 TheIP();\r
752 }\r
007c44c5 753 ip->addr=ipaddr;\r
754 ip->name=ipname;\r
4358455e 755 if(lmsid)\r
756 {\r
757 ip->lmsid=atoi(lmsid);\r
758 found_lmsid=1;\r
759 }\r
007c44c5 760}\r
761\r
762char *parse_datafile_line(char *str)\r
763{\r
764 char *ptr=strchr(str,' ');\r
765\r
766 if(ptr)\r
767 {\r
768 *ptr=0;\r
769 ptr++;\r
770 return ptr;\r
771 } \r
772 else \r
4358455e 773 {\r
007c44c5 774 return NULL;\r
4358455e 775 }\r
007c44c5 776}\r
777\r
c9012978 778struct IpLog\r
779{\r
780 char *name;\r
781 long traffic;\r
5a8f2e77 782 long guaranted;\r
208112af 783 int i;\r
a1d21464 784 int lmsid;\r
208112af 785 long l;\r
c9012978 786 list(IpLog);\r
787} *iplog,*iplogs;\r
788\r
789void parse_ip_log(int argc, char **argv) \r
790{\r
208112af 791 char *month, *year, *str, *name="(undefined)", *ptr, *ptr2, *filename;\r
792 long traffic=0l, traffic_month, total=0, guaranted;\r
4358455e 793 int col, col2, y_ok, m_ok, accept_month, i=1, any_month=0, lmsid;\r
5a8f2e77 794 char mstr[4], ystr[5];\r
795 FILE *f; \r
c9012978 796 string(str,STRLEN);\r
9da6a279 797 string(filename,STRLEN);\r
c9012978 798\r
5b902402 799 if(argv[1][1]=='l') /* -l */\r
800 {\r
208112af 801 if(argc<4)\r
802 {\r
803 puts("Missing parameter(s)!\nUsage: prometheus -l Mmm YYYY (Mmm=Jan-Dec or Year, YYYY=year)");\r
804 exit(-1);\r
805 }\r
806 else\r
807 {\r
808 month=argv[2];\r
809 if(eq(month,"Year")) any_month=1;\r
810 year=argv[3];\r
811 }\r
5b902402 812 }\r
813 else\r
814 { \r
208112af 815 time_t t = time(NULL) - 3600*24 ; /* yesterday's timestamp*/\r
816 struct tm *timep = localtime(&t); \r
817\r
818 if(argv[1][1]=='m') /* -m yestarday - month */\r
819 {\r
820 strftime(mstr, 4, "%b", timep);\r
821 month=mstr;\r
822 strftime(ystr, 5, "%Y", timep);\r
823 year=ystr; \r
824 }\r
825 else /* -y yesterday - year */\r
826 {\r
827 month="Year";\r
828 any_month=1;\r
829 strftime(ystr, 5, "%Y", timep);\r
830 year=ystr;\r
831 }\r
5b902402 832 }\r
833 printf("Analysing traffic for %s %s ...\n",month,year);\r
c9012978 834\r
493e1ccd 835 /* sorry... next release of C<<1 header file will include for_path_files(name,path) { } macro */\r
836 sprintf(str,"%s %s/",ls,log_dir);\r
c9012978 837 shell(str);\r
493e1ccd 838 input(str,STRLEN) \r
c9012978 839 {\r
493e1ccd 840 if(strstr(str,".log"))\r
9da6a279 841 {\r
493e1ccd 842 ptr=strrchr(str,'\n');\r
843 if(ptr) *ptr='\0';\r
9da6a279 844 sprintf(filename,"%s/%s",log_dir,str);\r
845 printf("Parsing %s ...",filename);\r
493e1ccd 846 accept_month=0;\r
847 traffic_month=0;\r
4358455e 848 guaranted=0;\r
a1d21464 849 lmsid=-1;\r
9da6a279 850 parse(filename)\r
493e1ccd 851 {\r
852 y_ok=m_ok=0; \r
853 valid_columns(ptr,_,'\t',col) switch(col)\r
854 {\r
855 case 2: name = ptr;break;\r
856 case 3: traffic = atol(ptr);break;\r
4358455e 857 /* column number - was 7, now 11...*/\r
493e1ccd 858 case 7:\r
859 case 8:\r
860 case 9:\r
4358455e 861 case 10:\r
260c2719 862 case 11: if(isalpha(*ptr)) /* character, not numeric string = date, just one*/\r
5a8f2e77 863 {\r
208112af 864 valid_columns(ptr2,ptr,' ',col2) switch(col2)\r
865 {\r
866 case 2: if(any_month || eq(ptr2,month)) m_ok = 1; break;\r
867 case 5: if(eq(ptr2,year)) y_ok = 1; break;\r
868 }\r
5a8f2e77 869 }\r
493e1ccd 870 else\r
871 {\r
872 if(col == 7) guaranted = atol(ptr);\r
4358455e 873 if(col == 10) lmsid = atoi(ptr);\r
493e1ccd 874 }\r
875 }\r
876 \r
877 if(y_ok && m_ok) \r
878 {\r
879 traffic_month += traffic;\r
880 accept_month = 1;\r
881 }\r
882 }\r
883 done;\r
b1b59b3a 884\r
493e1ccd 885 if(accept_month)\r
886 {\r
887 create(iplog,IpLog);\r
888 iplog->name = name;\r
889 iplog->guaranted = guaranted;\r
890 iplog->traffic = traffic_month;\r
a1d21464 891 iplog->lmsid = lmsid;\r
493e1ccd 892 insert(iplog,iplogs,desc_order_by,traffic);\r
893 printf(" %ld MB\n",iplog->traffic);\r
894 }\r
895 else\r
208112af 896 {\r
493e1ccd 897 puts(" no records.");\r
208112af 898 }\r
9da6a279 899 }\r
c9012978 900 }\r
901 sprintf(str,"%s/%s-%s.html",html_log_dir,year,month);\r
add90548 902 printf("Writing %s ... ",str);\r
c9012978 903 f=fopen(str,"w");\r
be96b71b 904 if(f > 0)\r
c9012978 905 {\r
103d292c 906 fprintf(f, "<table class=\"decorated last\"><thead>\n\\r
907<tr><th colspan=\"2\">%s %s</th>\n\\r
908<th style=\"text-align: right\">lms</th>\n\\r
909<th colspan=\"2\">Data transfers</th>\n\\r
910<th style=\"text-align: right\">Min.speed</th>\n\\r
911</tr></thead><tbody>\n ",\r
6cc38f96 912 month, year);\r
208112af 913\r
9aa195f6 914 row_odd_even = 0;\r
6cc38f96 915 for_each(iplog, iplogs)\r
208112af 916 {\r
c9012978 917 if(iplog->traffic)\r
918 {\r
103d292c 919 fprintf(f, "%s<td style=\"text-align: right\">%d</td>\n\\r
4f4d1820 920<td style=\"text-align: left\"><a class=\"blue\" target=\"_blank\" href=\"%s%s.log\">%s</td>\n\\r
103d292c 921<td style=\"text-align: right\">", \r
9aa195f6 922 tr_odd_even(), i++, log_url, iplog->name, iplog->name); \r
ad4cb129 923 if(iplog->lmsid > 0)\r
924 {\r
925 /*base URL will be configurable soon ... */\r
4f4d1820 926 fprintf(f, "<a class=\"blue\" target=\"_blank\" href=\"%s%d\">%04d</a>\n", lms_url, iplog->lmsid, iplog->lmsid);\r
ad4cb129 927 }\r
928 else if(iplog->lmsid == 0)\r
929 {\r
930 fputs("-------",f);\r
931 } \r
3ece6581 932 fprintf(f, "<td style=\"text-align: right\">%ld&nbsp;MB</td>\n\\r
933 <td style=\"text-align: right\"><strong>%ld&nbsp;GB</strong></td>\n\\r
934 <td style=\"text-align: right\">%ld&nbsp;kb/s</th></tr>\n",\r
6cc38f96 935 iplog->traffic, iplog->traffic>>10, iplog->guaranted);\r
c9012978 936 total+=iplog->traffic>>10;\r
208112af 937 iplog->i=i;\r
938 iplog->l=total;\r
c9012978 939 }\r
208112af 940 }\r
be96b71b 941 fprintf(f,"</tbody><thead><tr>\\r
4f4d1820 942 <th colspan=\"3\" style=\"text-align: left\">Total:</th>\\r
943 <th colspan=\"2\" style=\"text-align: right\"><strong>%ld&nbsp;GB</strong></th>\\r
944 <th style=\"text-align: right\"><strong>%Ld&nbsp;kb/s</strong></th></tr>\n", total, line);\r
be96b71b 945 fputs("</thead></table>\n", f);\r
208112af 946\r
9aa195f6 947 row_odd_even = 0;\r
208112af 948 if(i>10)\r
949 {\r
3ece6581 950 fputs("<a name=\"erp\"></a><p><table class=\"decorated last\">\n\\r
951<caption>Enterprise Resource Planning (ERP)</caption>\n\\r
952<thead><tr>\n\\r
953<th>Analytic category</th>\n\\r
954<th colspan=\"2\" style=\"text-align: center\">Active Classes</th>\n\\r
955<th colspan=\"2\" style=\"text-align: center\">Data transfers</th>\n\\r
956</tr></thead><tbody>\n",f);\r
208112af 957\r
958 if_exists(iplog,iplogs,iplog->l>=total/4)\r
959 {\r
9aa195f6 960 fprintf(f,"%s<td>Top 25%% of traffic</td>\n", tr_odd_even());\r
9690db8e 961 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
962<td style=\"text-align: right\">%d %%</td>\n\\r
963<td style=\"text-align: right\">%ld GB</td>\n\\r
964<td style=\"text-align: right\">%d %%</td></tr>\n",\r
965 iplog->i, (100*iplog->i+50)/i, iplog->l, (int)((100*iplog->l+50)/total));\r
208112af 966 }\r
967 \r
968 if_exists(iplog,iplogs,iplog->i==10)\r
969 {\r
9aa195f6 970 fprintf(f,"%s<td>Top 10 downloaders</td>\n", tr_odd_even());\r
3ece6581 971 fprintf(f,"<td style=\"text-align: right\"><strong>10</strong></td>\n\\r
972<td style=\"text-align: right\">%d %%</td>\n\\r
9690db8e 973<td style=\"text-align: right\">%ld GB</td>\n\\r
3ece6581 974<td style=\"text-align: right\">%d %%</td></tr>\n",\r
9690db8e 975 (100*iplog->i+50)/i, iplog->l, (int)((100*iplog->l+50)/total));\r
208112af 976 }\r
977\r
978 if_exists(iplog,iplogs,iplog->l>=total/2)\r
979 {\r
9aa195f6 980 fprintf(f,"%s<td>Top 50%% of traffic</td>\n", tr_odd_even());\r
3ece6581 981 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
982<td style=\"text-align: right\">%d %%</td>\n\\r
9690db8e 983<td style=\"text-align: right\">%ld GB</td>\n\\r
3ece6581 984<td style=\"text-align: right\"><strong>%d %%</strong></td></tr>\n",\r
985 iplog->i,(100*iplog->i+50)/i,iplog->l,(int)((100*iplog->l+50)/total));\r
208112af 986 }\r
987\r
988 if_exists(iplog,iplogs,iplog->l>=4*total/5)\r
989 {\r
9aa195f6 990 fprintf(f,"%s<td>Top 80%% of traffic</td>\n",tr_odd_even());\r
3ece6581 991 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
992<td style=\"text-align: right\">%d %%</td>\n\\r
9690db8e 993<td style=\"text-align: right\">%ld GB</td>\n\\r
3ece6581 994<td style=\"text-align: right\"><strong>%d %%</strong></td></tr>\n",\r
9690db8e 995 iplog->i, (100*iplog->i+50)/i, iplog->l, (int)((100*iplog->l+50)/total));\r
208112af 996 }\r
997\r
998 if_exists (iplog,iplogs,iplog->i>=i/5)\r
999 {\r
9aa195f6 1000 fprintf(f,"%s<td>Top 20%% downloaders</td>\n",tr_odd_even());\r
3ece6581 1001 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1002<td style=\"text-align: right\"><strong>%d %%</strong></td>\n\\r
9690db8e 1003<td style=\"text-align: right\">%ld GB</td>\n\\r
3ece6581 1004<td style=\"text-align: right\">%d %%</td></tr>\n",\r
9690db8e 1005 iplog->i, (100*iplog->i+50)/i, iplog->l, (int)((100*iplog->l+50)/total));\r
208112af 1006 }\r
1007\r
1008 if_exists(iplog,iplogs,iplog->i>=i/4)\r
1009 {\r
9aa195f6 1010 fprintf(f,"%s<td>Top 25%% downloaders</td>\n", tr_odd_even());\r
9690db8e 1011 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1012<td style=\"text-align: right\">%d %%</td>\n\\r
1013<td style=\"text-align: right\">%ld GB</td>\n\\r
1014<td style=\"text-align: right\">%d %%</td></tr>\n",\r
1015 iplog->i, (100*iplog->i+50)/i, iplog->l, (int)((100*iplog->l+50)/total));\r
208112af 1016 }\r
1017\r
1018 if_exists(iplog,iplogs,iplog->i>=i/2)\r
1019 {\r
9aa195f6 1020 fprintf(f,"%s<td>Top 50%% downloaders</td>\n",tr_odd_even());\r
3ece6581 1021 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1022<td style=\"text-align: right\"><strong>%d %%</strong></td>\n\\r
9690db8e 1023<td style=\"text-align: right\">%ld GB</td>\n\\r
1024<td style=\"text-align: right\">%d %%</td></tr>\n",\r
1025 iplog->i, (100*iplog->i+50)/i, iplog->l, (int)((100*iplog->l+50)/total));\r
208112af 1026 }\r
1027\r
1028 if_exists(iplog,iplogs,iplog->i>=4*i/5)\r
1029 {\r
9aa195f6 1030 fprintf(f,"%s<td>Top 80%% downloaders</td>\n",tr_odd_even());\r
9690db8e 1031 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1032<td style=\"text-align: right\">%d %%</td>\n\\r
1033<td style=\"text-align: right\">%ld GB</td>\n\\r
1034<td style=\"text-align: right\">%d %%</td></tr>\n",\r
1035 iplog->i, (100*iplog->i+50)/i, iplog->l, (int)((100*iplog->l+50)/total));\r
208112af 1036 }\r
1037\r
4f4d1820 1038 fprintf(f,"</tbody><thead><tr><th><a class=\"blue\" target=\"_blank\" href=\"%sERP.log\">All users, all traffic</a></th>\n", log_url);\r
1039 fprintf(f,"<th style=\"text-align: right\">%d</th>\n\\r
3ece6581 1040<th style=\"text-align: right\">100 %%</th>\n\\r
9690db8e 1041<th style=\"text-align: right\">%ld GB</th>\n\\r
3ece6581 1042<th style=\"text-align: right\">100 %%</th></tr>\n",i-1,total);\r
1043 fputs("</thead></table>\n", f);\r
208112af 1044 }\r
1045\r
2d114137 1046 fprintf(f, stats_html_signature, version);\r
c9012978 1047 fclose(f);\r
be96b71b 1048 puts("done.");\r
c9012978 1049 }\r
add90548 1050 else\r
1051 {\r
1052 perror(str);\r
1053 }\r
1054}\r
1055\r
1056void append_log(struct IP *self) /*using global variables*/\r
1057{\r
1058 char *d, *str;\r
1059 FILE *f; \r
1060\r
1061 date(d); /* this is typical cll1.h macro - prints current date */ \r
1062 string(str,STRLEN); \r
1063 sprintf(str,"%s/%s.log", log_dir, self->name);\r
1064 f=fopen(str,"a");\r
be96b71b 1065 if(f > 0)\r
add90548 1066 {\r
1067 fprintf(f,"%ld\t%s\t%Lu\t%Lu\t%Lu\t%Lu\t%d\t%d\t%d\t%d\t%s",\r
1068 time(NULL), self->name, self->traffic, self->direct, self->proxy,\r
1069 self->upload, self->min, self->max, self->desired, self->lmsid, d); /* d = date*/\r
1070 fclose(f);\r
1071 }\r
1072 else\r
1073 {\r
1074 perror(str);\r
1075 }\r
c9012978 1076}\r
5b902402 1077\r
add90548 1078\r
007c44c5 1079/*-----------------------------------------------------------------*/\r
493e1ccd 1080/* Are you looking for int main(int argc, char **argv) ? :-)) */\r
007c44c5 1081/*-----------------------------------------------------------------*/\r
1082\r
1083program\r
1084{\r
1085 int i=0;\r
1086 FILE *f=NULL;\r
1087 char *str, *ptr, *d;\r
1088 char *substring;\r
1089 int class_count=0,ip_count=0;\r
1090 int parent=1;\r
208112af 1091 int just_flush=FALSE;\r
1092 int nodelay=FALSE;\r
1093 int just_preview=FALSE; /* preview - generate just stats */\r
1094 int just_logs=FALSE; /* just parse logs */\r
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
260c2719 1103Version %s - Copyright (C)2005-2012 Michael Polak (xChaos)\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
1107 /*----- Boring... we have to check command line options first: ----*/\r
1108 \r
1109 arguments\r
1110 {\r
1111 argument("-c") { nextargument(config); }\r
1112 argument("-h") { nextargument(althosts);}\r
208112af 1113 argument("-d") { run=TRUE; dry_run=TRUE; }\r
1114 argument("-f") { run=TRUE; just_flush=TRUE; }\r
1115 argument("-9") { run=TRUE; just_flush=9; }\r
1116 argument("-p") { run=TRUE; just_preview=TRUE; }\r
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
1267 done;\r
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
1310 done;\r
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
1637 f=fopen(preview,"w");\r
1638 ptr=preview; \r
1639 }\r
1640 else if(!dry_run && !just_flush)\r
1641 {\r
1642 /*-----------------------------------------------------------------*/\r
be96b71b 1643 printf("Writing daily statistics %s ... ", json);\r
007c44c5 1644 /*-----------------------------------------------------------------*/\r
be96b71b 1645 f=fopen(json, "w");\r
1646 if(f > 0)\r
007c44c5 1647 {\r
be96b71b 1648 int jsoncount=0;\r
1649 fprintf(f, "{\n");\r
1650 for_each(ip, ips)\r
6cc38f96 1651 {\r
be96b71b 1652 if(jsoncount)\r
1653 {\r
1654 fprintf(f, ",\n");\r
1655 }\r
260c2719 1656 if(ip->traffic || ip->direct || ip->proxy || ip->upload)\r
1657 {\r
1c004f15 1658 fprintf(f, " %d:{ \"ip\":\"%s\", \"total\":%Lu, \"down\":%Lu, \"proxy\":%Lu, \"up\":%Lu }",\r
be96b71b 1659 ip->lmsid, ip->addr, ip->traffic, ip->direct, ip->proxy, ip->upload);\r
260c2719 1660 }\r
be96b71b 1661 jsoncount++;\r
6cc38f96 1662 }\r
be96b71b 1663 fprintf(f, "}\n");\r
007c44c5 1664 fclose(f);\r
be96b71b 1665 puts("done.");\r
add90548 1666 }\r
1667 else\r
1668 {\r
be96b71b 1669 perror(json);\r
007c44c5 1670 }\r
007c44c5 1671 f=fopen(html,"w");\r
1672 ptr=html;\r
1673 }\r
1674\r
1675 if(f)\r
1676 {\r
007c44c5 1677 int count=1;\r
1678 i=0;\r
1679\r
1680 /*-----------------------------------------------------------------*/\r
6cc38f96 1681 printf("Sorting data and generating statistics page %s ...\n", ptr);\r
007c44c5 1682 /*-----------------------------------------------------------------*/\r
1683\r
6cc38f96 1684 if(use_jquery_popups)\r
1685 {\r
1686 fprintf(f,"<script type=\"text/javascript\" src=\"%s\"></script>\n", jquery_url);\r
1687 }\r
3ece6581 1688 fputs("<table class=\"decorated last\">\n\\r
1689<caption>Bandwidth classes</caption>\n\\r
1690<thead><tr>\n\\r
1691<th style=\"text-align: right\">#</th>\n\\r
103d292c 1692<th style=\"text-align: right\">group</th>\n\\r
1693<th style=\"text-align: right\">IPs</th>\n\\r
1694<th style=\"text-align: right\">requested</th>\n",f);\r
6cc38f96 1695 fprintf(f,"<th colspan=\"%d\">data limits</th>\n", keywordcount);\r
9aa195f6 1696 fputs("</tr></thead><tbody>\n",f);\r
208112af 1697\r
9aa195f6 1698 row_odd_even = 0;\r
6cc38f96 1699 for_each(group, groups) \r
007c44c5 1700 { \r
1701#ifdef DEBUG\r
3ece6581 1702 printf("%d kb/s group: %d bandwidth requested: %d kb/s\n",group->min,group->count,group->desired);\r
007c44c5 1703#endif\r
3ece6581 1704 fprintf(f, "%s<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d&nbsp;kb/s</td>",\r
9aa195f6 1705 tr_odd_even(), count, group->min);\r
3ece6581 1706 fprintf(f, "<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d&nbsp;kb/s</td>",\r
9aa195f6 1707 group->count, group->desired);\r
007c44c5 1708\r
c864e623 1709 for_each(keyword, keywords) if(keyword->ip_count)\r
208112af 1710 {\r
c864e623 1711 fprintf(f,"<td style=\"text-align: right\"><span style=\"color:#%s\">%d&nbsp;MB</span></td>",\r
6cc38f96 1712 keyword->html_color, group->min*keyword->data_limit);\r
208112af 1713 } \r
6cc38f96 1714 i += group->desired; \r
1715 total += group->count;\r
007c44c5 1716 count++; \r
1717 }\r
1718#ifdef DEBUG\r
3ece6581 1719 printf("Total groups: %d Total bandwidth requested: %d kb/s\nAGGREGATION: 1/%d\n",\r
6cc38f96 1720 count, i, i/line);\r
007c44c5 1721#endif\r
e64e760d 1722 fprintf(f,"</tr></tbody>\n\\r
1723<thead><tr>\n\\r
1724<th colspan=\"2\" style=\"text-align: left\">Line %Ld kb/s</td>",line);\r
3ece6581 1725 fprintf(f,"<th style=\"text-align: right\">%d</td><th style=\"text-align: right\">%d kb/s</td>",total,i);\r
007c44c5 1726\r
c864e623 1727 for_each(keyword, keywords) if(keyword->ip_count)\r
208112af 1728 {\r
103d292c 1729 fprintf(f,"<th style=\"text-align: right\">%d IPs</th>",keyword->ip_count);\r
208112af 1730 }\r
6cc38f96 1731 fprintf(f,"</tr><tr><th colspan=\"4\">Aggregation 1/%d</th>\n", (int)(0.5+i/line));\r
1732 fprintf(f,"<th colspan=\"%d\">%d traffic classes</th></tr>\n", keywordcount, total);\r
007c44c5 1733\r
e64e760d 1734 fputs("</thead></table>\n",f);\r
007c44c5 1735 }\r
6cc38f96 1736 else if(!dry_run && !just_flush)\r
1737 {\r
007c44c5 1738 perror(html);\r
6cc38f96 1739 }\r
007c44c5 1740\r
6cc38f96 1741 i=0;\r
007c44c5 1742 if(f)\r
1743 {\r
b014f181 1744 unsigned long long total_traffic=0, total_direct=0, total_proxy=0, total_upload=0, tmp_sum=0;\r
007c44c5 1745 int active_classes=0;\r
3ece6581 1746 int colspan=12;\r
007c44c5 1747 struct Sum {unsigned long long l; int i; list(Sum);} *sum,*sums=NULL;\r
78884bad 1748 int limit_count=0, prio_count=0;\r
4a1b62ea 1749 int popup_button=0;\r
007c44c5 1750\r
1751 if(qos_proxy)\r
4358455e 1752 {\r
1753 colspan++;\r
1754 }\r
007c44c5 1755 \r
3ece6581 1756 fprintf(f,"<p><table class=\"decorated last\">\n<caption>%s",title);\r
9aa195f6 1757 fprintf(f," (%s)</caption>\n", d);\r
3ece6581 1758 fputs("<thead><tr>\n<th colspan=\"3\">&nbsp;</th>\n",f);\r
1759 fputs("<th style=\"text-align: right\">credit</th>\n\\r
1760<th style=\"text-align: right\">FUP</th>\n\\r
1761<th style=\"text-align: right\">total</th>\n\\r
1762<th style=\"text-align: right\">down</th>\n",f);\r
007c44c5 1763 if(qos_proxy)\r
4358455e 1764 {\r
103d292c 1765 fputs("<th style=\"text-align: right\">proxy</th>\n",f);\r
4358455e 1766 }\r
3ece6581 1767 fputs("<th style=\"text-align: right\">up</th>\n\\r
1768<th style=\"text-align: right\">min</th>\n\\r
1769<th style=\"text-align: right\">max</th>\n\\r
1770<th style=\"text-align: right\">limit</th>\n\\r
e64e760d 1771<th>&nbsp;</th>\n\\r
1772</tr><tr>\n\\r
3ece6581 1773<th style=\"text-align: right\">#</th>\n\\r
1774<th>hostname [+sharing]</th>\n\\r
1775<th style=\"text-align: right\">LMS</th>\n\\r
1776<th style=\"text-align: right\">MB</th>\n\\r
1777<th style=\"text-align: right\">MB</th>\n\\r
1778<th style=\"text-align: right\">MB</th>\n\\r
1779<th style=\"text-align: right\">MB</th>\n\\r
1780<th style=\"text-align: right\">MB</th>\n\\r
1781<th style=\"text-align: right\">kb/s</th>\n\\r
1782<th style=\"text-align: right\">kb/s</th>\n\\r
1783<th style=\"text-align: right\">kb/s</th>\n\\r
e64e760d 1784<th>prio</th>\n\\r
3ece6581 1785</tr></thead><tbody>\n",f); \r
007c44c5 1786\r
9aa195f6 1787 row_odd_even = 0;\r
6cc38f96 1788 for_each(ip,ips) if(!use_jquery_popups || !ip->sharing)\r
007c44c5 1789 {\r
1790 char *f1="", *f2="";\r
6cc38f96 1791 i++;\r
1792 \r
1793 if(ip->max < ip->desired)\r
007c44c5 1794 {\r
78884bad 1795 f1="<span style=\"color:red\">";\r
1796 f2="</span>";\r
1797 limit_count++;\r
007c44c5 1798 }\r
6cc38f96 1799 else if(ip->prio > highest_priority+1)\r
007c44c5 1800 {\r
78884bad 1801 f1="<span style=\"color:brown\">";\r
1802 f2="</span>";\r
1803 prio_count++;\r
007c44c5 1804 }\r
1805\r
1806#ifdef DEBUG\r
1807 printf("%03d. %-22s %10Lu (%d/%d)\n",i ,ip->name, ip->traffic, ip->min, ip->max); \r
1808#endif\r
4a1b62ea 1809 /* hostnames -------------------------------------- */\r
4f4d1820 1810 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 1811 tr_odd_even(), ip->name, i, log_url, ip->name, ip->name);\r
3ece6581 1812\r
6cc38f96 1813 if(use_jquery_popups)\r
4a1b62ea 1814 {\r
6cc38f96 1815 fprintf(f,"<span id=\"sharing_%d\" style=\"display:none\">",i);\r
1816 popup_button=0;\r
1817 for_each(sharedip, ips) if(eq(ip->name, sharedip->sharing))\r
1818 {\r
4f4d1820 1819 fprintf(f,"<br /><a class=\"blue\" target=\"_blank\" href=\"%s%s.log\">%s</a>\n", log_url, sharedip->name, sharedip->name);\r
6cc38f96 1820 popup_button++;\r
1821 }\r
1822 fputs("</span>\n",f);\r
1823 if(popup_button)\r
1824 {\r
103d292c 1825 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 1826 i, i, i, popup_button);\r
1827 }\r
4a1b62ea 1828 }\r
1829 fputs("</td>\n",f);\r
1830 /* ----------------------------------------------- */\r
1831\r
4358455e 1832 if(found_lmsid)\r
1833 {\r
103d292c 1834 fputs("<td style=\"text-align: right\">",f);\r
a1d21464 1835 if(ip->lmsid > 0)\r
4358455e 1836 {\r
4f4d1820 1837 fprintf(f,"<a class=\"blue\" target=\"_blank\" href=\"%s%d\">%04d</a>\n", lms_url, ip->lmsid, ip->lmsid);\r
4358455e 1838 }\r
a1d21464 1839 else if(ip->lmsid == 0)\r
1840 {\r
ad4cb129 1841 fputs("-------",f);\r
a1d21464 1842 }\r
4a1b62ea 1843 fputs("</td>\n",f);\r
4358455e 1844 }\r
3ece6581 1845 fprintf(f,"<td style=\"text-align: right\">%Lu</td>\n", ip->credit);\r
1846 fprintf(f,"<td style=\"text-align: right\"><span style=\"color:#%s\">%Lu</span></td>",\r
4a1b62ea 1847 ip->keyword->html_color,\r
1848 ip->credit+(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20)));\r
3ece6581 1849 fprintf(f,"<td style=\"text-align: right\">%s%Lu%s", f1, ip->traffic, f2);\r
4a1b62ea 1850\r
1851 /* download --------------------------------------- */\r
3ece6581 1852 fprintf(f,"</td><td style=\"text-align: right\">%Lu", ip->direct);\r
6cc38f96 1853 if(use_jquery_popups)\r
4a1b62ea 1854 {\r
6cc38f96 1855 fprintf(f,"<span id=\"download_%d\" style=\"display:none\">",i);\r
1856 for_each(sharedip, ips) if(eq(ip->name, sharedip->sharing))\r
1857 {\r
3ece6581 1858 fprintf(f,"<br />%Lu", sharedip->direct);\r
6cc38f96 1859 }\r
1860 fputs("</span>\n",f);\r
4a1b62ea 1861 }\r
6cc38f96 1862 fputs("</td>\n",f);\r
4a1b62ea 1863 /* ----------------------------------------------- */\r
1864\r
007c44c5 1865 if(qos_proxy)\r
4358455e 1866 {\r
3ece6581 1867 fprintf(f,"<td style=\"text-align: right\">%Lu</td>\n", ip->proxy);\r
4358455e 1868 }\r
4a1b62ea 1869 /* upload ---------------------------------------- */\r
3ece6581 1870 fprintf(f,"<td style=\"text-align: right\">%Lu", ip->upload);\r
6cc38f96 1871 if(use_jquery_popups)\r
4a1b62ea 1872 {\r
6cc38f96 1873 fprintf(f,"<span id=\"upload_%d\" style=\"display:none\">",i);\r
1874 for_each(sharedip,ips) if(eq(ip->name, sharedip->sharing))\r
1875 {\r
3ece6581 1876 fprintf(f,"<br />%Lu", sharedip->upload);\r
6cc38f96 1877 }\r
1878 fputs("</span>\n",f);\r
4a1b62ea 1879 }\r
6cc38f96 1880 fputs("</td>\n",f);\r
4a1b62ea 1881 /* ----------------------------------------------- */\r
1882\r
3ece6581 1883 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1884<td style=\"text-align: right\">%d</td>\n\\r
1885<td style=\"text-align: right\">%s%d%s</td>\n\\r
1886<td>%s%d%s</td></tr>\n",\r
1887 ip->min, ip->desired, \r
1888 f1, ip->max, f2, \r
1889 f1, ip->prio, f2);\r
6cc38f96 1890\r
b014f181 1891 total_traffic+=ip->traffic;\r
007c44c5 1892 total_direct+=ip->direct;\r
1893 total_proxy+=ip->proxy;\r
1894 total_upload+=ip->upload;\r
1895 if(ip->traffic>0)\r
1896 {\r
1897 active_classes++;\r
1898 tmp_sum+=ip->traffic;\r
1899 create(sum,Sum);\r
1900 sum->l=tmp_sum;\r
1901 sum->i=active_classes;\r
1902 insert(sum,sums,order_by,i);\r
1903 }\r
6cc38f96 1904\r
007c44c5 1905 if(!just_preview)\r
1906 {\r
add90548 1907 append_log(ip);\r
52e8df5d 1908 for_each(sharedip,ips) if(eq(ip->name, sharedip->sharing))\r
1909 {\r
1910 append_log(sharedip);\r
1911 }\r
007c44c5 1912 }\r
007c44c5 1913 }\r
e64e760d 1914 fprintf(f,"</tbody><thead><tr>\n\\r
1915<th colspan=\"%d\" style=\"text-align: left\">%d CLASSES</th>", colspan-7, i);\r
3ece6581 1916 fprintf(f,"<th style=\"text-align: right\">%Lu</th><th style=\"text-align: right\">%Lu</th>\n", total_traffic, total_direct);\r
007c44c5 1917 if(qos_proxy)\r
4358455e 1918 {\r
3ece6581 1919 fprintf(f,"<th style=\"text-align: right\">%Lu</th>\n", total_proxy);\r
4358455e 1920 }\r
3ece6581 1921 fprintf(f,"<th style=\"text-align: right\">%Lu</th>", total_upload);\r
e64e760d 1922 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 1923\r
9aa195f6 1924 row_odd_even = 0;\r
007c44c5 1925 if(active_classes>10)\r
c9012978 1926 {\r
60a8251d 1927 int top20_count=0,top20_perc1=0;\r
1928 long long top20_perc2=0;\r
1929 unsigned long long top20_sum=0l;\r
1930 \r
3ece6581 1931 fputs("<a name=\"erp\"></a><p><table class=\"decorated last\"><caption>Enterprise Resource Planning (ERP)</caption>\n",f);\r
1932 fputs("<thead><tr>\n\\r
1933<th>Analytic category</th>\n\\r
1934<th colspan=\"2\" style=\"text-align: center\">Active Classes</th>\n\\r
1935<th colspan=\"2\" style=\"text-align: center\">Data transfers</th>\n\\r
1936</tr></thead><tbody>\n",f);\r
c9012978 1937\r
b014f181 1938 if_exists(sum,sums,sum->l>=total_traffic/4)\r
c9012978 1939 {\r
9aa195f6 1940 fprintf(f,"%s<td>Top 25%% of traffic</td>\n", tr_odd_even());\r
9690db8e 1941 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1942<td style=\"text-align: right\">%d %%</td>\n\\r
1943<td style=\"text-align: right\">%Lu MB</td>\n\\r
1944<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
1945 sum->i, (100*sum->i+50)/active_classes, sum->l, (100*sum->l+50)/total_traffic);\r
c9012978 1946 }\r
1947 \r
208112af 1948 if_exists(sum,sums,sum->i==10)\r
c9012978 1949 {\r
9aa195f6 1950 fprintf(f,"%s<td>Top 10 downloaders</td>\n", tr_odd_even());\r
3ece6581 1951 fprintf(f,"<td style=\"text-align: right\"><strong>10</strong></td>\n\\r
1952<td style=\"text-align: right\">%d %%</td>\n\\r
1953<td style=\"text-align: right\">%Lu MB</td>\n\\r
1954<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
9690db8e 1955 (100*sum->i+50)/active_classes, sum->l, (100*sum->l+50)/total_traffic);\r
c9012978 1956 }\r
1957\r
b014f181 1958 if_exists(sum,sums,sum->l>=total_traffic/2)\r
c9012978 1959 {\r
9aa195f6 1960 fprintf(f,"%s<td>Top 50%% of traffic</td>\n", tr_odd_even());\r
3ece6581 1961 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1962<td style=\"text-align: right\">%d %%</td>\n\\r
1963<td style=\"text-align: right\">%Lu MB</td>\n\\r
1964<td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",\r
1965 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
c9012978 1966 }\r
1967\r
b014f181 1968 if_exists(sum,sums,sum->l>=4*total_traffic/5)\r
c9012978 1969 {\r
9aa195f6 1970 fprintf(f,"%s<td>Top 80%% of traffic</td>\n", tr_odd_even());\r
3ece6581 1971 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1972<td style=\"text-align: right\">%d %%</td>\n\\r
1973<td style=\"text-align: right\">%Lu MB</td>\n\\r
1974<td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",\r
1975 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
c9012978 1976 }\r
1977\r
60a8251d 1978 if_exists(sum,sums,sum->i>=(active_classes+1)/5)\r
c9012978 1979 {\r
9aa195f6 1980 fprintf(f,"%s<td>Top 20%% downloaders</td>\n", tr_odd_even());\r
60a8251d 1981 top20_count=sum->i;\r
1982 top20_perc1=(100*sum->i+50)/active_classes;\r
1983 top20_sum=sum->l;\r
b014f181 1984 top20_perc2=(100*sum->l+50)/total_traffic;\r
3ece6581 1985 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1986<td style=\"text-align: right\"><strong>%d %%</strong></td>\n\\r
1987<td style=\"text-align: right\">%Lu MB</td>\n\\r
1988<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
1989 top20_count,top20_perc1,top20_sum,top20_perc2);\r
c9012978 1990 }\r
1991\r
208112af 1992 if_exists(sum,sums,sum->i>=(active_classes+1)/4)\r
c9012978 1993 {\r
9aa195f6 1994 fprintf(f,"%s<td>Top 25%% downloaders</td>\n", tr_odd_even());\r
3ece6581 1995 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1996<td style=\"text-align: right\">%d %%</td>\n\\r
1997<td style=\"text-align: right\">%Lu MB</td>\n\\r
1998<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
1999 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
c9012978 2000 }\r
2001\r
208112af 2002 if_exists(sum,sums,sum->i>=(active_classes+1)/2)\r
c9012978 2003 {\r
9aa195f6 2004 fprintf(f,"%s<td>Top 50%% downloaders</td>\n", tr_odd_even());\r
3ece6581 2005 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
2006<td style=\"text-align: right\"><strong>%d %%</strong></td>\n\\r
2007<td style=\"text-align: right\">%Lu MB</td>\n\\r
2008<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
2009 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
c9012978 2010 }\r
2011\r
208112af 2012 if_exists(sum,sums,sum->i>=4*(active_classes+1)/5)\r
c9012978 2013 {\r
9aa195f6 2014 fprintf(f,"%s<td>Top 80%% downloaders</td>\n", tr_odd_even());\r
3ece6581 2015 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
2016<td style=\"text-align: right\">%d %%</td>\n\\r
2017<td style=\"text-align: right\">%Lu MB</td>\n\\r
2018<td style=\"text-align: right\">%Ld %%</td></tr></tbody>\n",\r
2019 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
c9012978 2020 }\r
2021\r
4f4d1820 2022 fprintf(f,"<thead><tr><th><a class=\"blue\" target=\"_blank\" href=\"%sERP.log\">All users, all traffic</a></th>\n", log_url);\r
103d292c 2023 fprintf(f,"<th style=\"text-align: right\">%d</th>\n\\r
2024<th style=\"text-align: right\">100 %%</th>\n\\r
9690db8e 2025<th style=\"text-align: right\">%Lu MB</th>\n\\r
103d292c 2026<th style=\"text-align: right\">100 %%</th></tr>\n",active_classes,total_traffic);\r
3ece6581 2027 fputs("</thead></table>\n", f);\r
60a8251d 2028\r
5da44508 2029 /* write basic ERP data to log directory */\r
60a8251d 2030 if(!just_preview)\r
2031 {\r
add90548 2032 FILE *iplog;\r
60a8251d 2033 sprintf(str,"%s/ERP.log",log_dir);\r
2034 iplog=fopen(str,"a");\r
2035 if(iplog)\r
2036 {\r
78884bad 2037 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 2038 time(NULL), top20_count, top20_perc1, top20_sum, top20_perc2, \r
6cc38f96 2039 active_classes, total_traffic, i, limit_count, prio_count, d); /* d = date*/\r
60a8251d 2040 fclose(iplog);\r
2041 }\r
add90548 2042 else\r
2043 {\r
2044 perror(str);\r
2045 }\r
60a8251d 2046 }\r
c9012978 2047 }\r
60a8251d 2048\r
2d114137 2049 fprintf(f, stats_html_signature, version);\r
007c44c5 2050 fclose(f);\r
2051 }\r
2052\r
2053 if(just_preview)\r
2054 {\r
2055 puts("Statistics preview generated (-p switch) - now exiting ...");\r
2056 exit(0);\r
be96b71b 2057 } \r
007c44c5 2058\r
2059 i=0;\r
260c2719 2060#ifdef DEBUG\r
007c44c5 2061 printf("%-22s %-15s mark\n","name","ip");\r
260c2719 2062#endif\r
208112af 2063\r
be96b71b 2064 printf("Writing %s ... ", classmap); \r
2065 f = fopen(classmap, "w"); \r
2066 if(f < 0)\r
2067 {\r
2068 perror(classmap);\r
2069 }\r
2070\r
2071 /*-----------------------------------------------------------------*/\r
2072 puts("Generating iptables and tc classes ... ");\r
2073 /*-----------------------------------------------------------------*/\r
2074\r
2075 for_each(ip, ips) if(ip->mark > 0)\r
2076 {\r
007c44c5 2077 if(idxs)\r
2078 {\r
2079 char *buf;\r
2080 duplicate(ip->addr,buf);\r
2081 buf=hash_id(ip->addr,32-idxtable_bitmask1); \r
2082 \r
2083 string(chain_forward,6+strlen(buf));\r
2084 strcpy(chain_forward,"forw_");\r
2085 strcat(chain_forward,buf);\r
2086\r
2087 string(chain_postrouting,6+strlen(buf));\r
2088 strcpy(chain_postrouting,"post_");\r
2089 strcat(chain_postrouting,buf);\r
2090 \r
2091 free(buf);\r
2092 }\r
2093 else\r
2094 {\r
2095 chain_forward="FORWARD";\r
2096 chain_postrouting="POSTROUTING";\r
2097 }\r
2098\r
260c2719 2099#ifdef DEBUG\r
007c44c5 2100 printf("%-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
260c2719 2101#endif\r
007c44c5 2102\r
2103 /* -------------------------------------------------------- mark download */\r
2104 \r
be96b71b 2105 sprintf(str, "-A %s -d %s/32 -o %s -j %s%d",\r
2106 chain_postrouting, ip->addr, lan, mark_iptables, ip->mark);\r
007c44c5 2107 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/\r
2108 /* -m limit --limit 1/s */ \r
2109 save_line(str);\r
2110\r
2111 if(qos_proxy)\r
2112 {\r
be96b71b 2113 sprintf(str, "-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",\r
2114 chain_postrouting, proxy_ip, proxy_port, ip->addr, lan, mark_iptables, ip->mark);\r
007c44c5 2115 /*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
2116 save_line(str);\r
2117 }\r
2118\r
be96b71b 2119 sprintf(str, "-A %s -d %s/32 -o %s -j ACCEPT",\r
2120 chain_postrouting, ip->addr, lan);\r
007c44c5 2121 save_line(str);\r
2122\r
2123 /* -------------------------------------------------------- mark upload */\r
be96b71b 2124 sprintf(str, "-A %s -s %s/32 -o %s -j %s%d", \r
2125 chain_forward, ip->addr, wan, mark_iptables, ip->mark);\r
007c44c5 2126 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/\r
2127 save_line(str);\r
2128\r
be96b71b 2129 sprintf(str, "-A %s -s %s/32 -o %s -j ACCEPT",\r
2130 chain_forward, ip->addr, wan);\r
007c44c5 2131 save_line(str);\r
2132\r
2133 if(ip->min)\r
2134 {\r
2135 /* -------------------------------------------------------- download class */\r
260c2719 2136#ifdef DEBUG\r
007c44c5 2137 printf("(down: %dk-%dk ", ip->min, ip->max); \r
260c2719 2138#endif\r
007c44c5 2139\r
be96b71b 2140 sprintf(str, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
2141 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
007c44c5 2142 safe_run(str);\r
2143\r
260c2719 2144 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
dee5592e 2145 {\r
be96b71b 2146 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s", \r
2147 tc, lan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
dee5592e 2148 safe_run(str);\r
be96b71b 2149 }\r
2150\r
260c2719 2151 if(filter_type == 1)\r
dee5592e 2152 {\r
be96b71b 2153 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
2154 tc, lan, ip->mark, ip->mark);\r
dee5592e 2155 safe_run(str);\r
007c44c5 2156 }\r
2157\r
2158 /* -------------------------------------------------------- upload class */\r
260c2719 2159#ifdef DEBUG\r
007c44c5 2160 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
2161 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
260c2719 2162#endif\r
007c44c5 2163\r
2164 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
2165 tc, wan, ip->group, ip->mark,\r
2166 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
2167 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
2168 safe_run(str);\r
2169 \r
260c2719 2170 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
dee5592e 2171 {\r
be96b71b 2172 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s",\r
2173 tc, wan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
dee5592e 2174 safe_run(str);\r
2175 } \r
be96b71b 2176\r
260c2719 2177 if(filter_type == 1)\r
dee5592e 2178 {\r
be96b71b 2179 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
2180 tc, wan, ip->mark, ip->mark);\r
dee5592e 2181 safe_run(str);\r
007c44c5 2182 }\r
be96b71b 2183 \r
2184 if(f)\r
2185 {\r
2186 fprintf(f, "%s %d", ip->addr, ip->mark);\r
2187 }\r
007c44c5 2188 }\r
2189 else\r
260c2719 2190 {\r
2191#ifdef DEBUG\r
007c44c5 2192 printf("(sharing %s)\n", ip->sharing);\r
260c2719 2193#endif\r
2194 }\r
007c44c5 2195 i++;\r
2196 }\r
be96b71b 2197 if(f)\r
2198 {\r
2199 puts("done.");\r
2200 fclose(f);\r
2201 }\r
2202 \r
007c44c5 2203 if(idxs)\r
2204 {\r
dee5592e 2205 chain_forward = "forw_common";\r
2206 chain_postrouting = "post_common";\r
007c44c5 2207 }\r
2208 else\r
2209 {\r
dee5592e 2210 chain_forward = "FORWARD";\r
2211 chain_postrouting = "POSTROUTING";\r
007c44c5 2212 }\r
dee5592e 2213 /* -------------------------------- classify or reject free download */\r
007c44c5 2214 {\r
b6a8d473 2215 char *final_chain = "DROP"; /* REJECT would be better, but it is impossible in mangle */\r
be96b71b 2216 if(free_min)\r
2217 {\r
2218 final_chain = "ACCEPT";\r
2219 }\r
dee5592e 2220 if(qos_proxy)\r
2221 {\r
2222 if(free_min)\r
2223 {\r
be96b71b 2224 sprintf(str,"-A %s -s %s -p tcp --sport %d -o %s -j %s%d",\r
2225 chain_postrouting,proxy_ip,proxy_port,lan,mark_iptables,3);\r
dee5592e 2226 save_line(str);\r
2227 }\r
be96b71b 2228 sprintf(str,"-A %s -s %s -p tcp --sport %d -o %s -j %s",\r
2229 chain_postrouting,proxy_ip,proxy_port,lan,final_chain);\r
dee5592e 2230 save_line(str);\r
2231 }\r
2232 if(free_min)\r
2233 {\r
be96b71b 2234 sprintf(str,"-A %s -o %s -j %s%d", chain_postrouting, lan, mark_iptables, 3);\r
dee5592e 2235 save_line(str);\r
2236 }\r
be96b71b 2237 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
dee5592e 2238 save_line(str);\r
2239 /* ------------------------------- classify or reject free upload */\r
2240 if(free_min)\r
2241 {\r
be96b71b 2242 sprintf(str,"-A %s -o %s -j %s%d", chain_forward, wan, mark_iptables, 3);\r
dee5592e 2243 save_line(str);\r
2244 }\r
be96b71b 2245 sprintf(str,"-A %s -o %s -j %s", chain_forward, wan, final_chain);\r
dee5592e 2246 save_line(str);\r
007c44c5 2247 }\r
abe9b855 2248\r
dee5592e 2249 if(free_min) /* allocate free bandwith if it is not zero... */ \r
2250 {\r
2251 /*-----------------------------------------------------------------*/\r
2252 puts("Generating free bandwith classes ...");\r
2253 /*-----------------------------------------------------------------*/\r
208112af 2254 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
be96b71b 2255 tc, lan, parent, free_min, free_max,burst, lowest_priority);\r
dee5592e 2256 safe_run(str);\r
208112af 2257 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
be96b71b 2258 tc, wan, parent, free_min, free_max, burst, lowest_priority);\r
dee5592e 2259 safe_run(str);\r
2260 /* tc SFQ */\r
260c2719 2261 if(strcmpi(qos_leaf, "none"))\r
dee5592e 2262 {\r
be96b71b 2263 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, lan, qos_leaf);\r
dee5592e 2264 safe_run(str);\r
2265 \r
be96b71b 2266 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, wan, qos_leaf);\r
dee5592e 2267 safe_run(str);\r
2268 } \r
2269 /* tc handle 1 fw flowid */\r
be96b71b 2270 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, lan);\r
dee5592e 2271 safe_run(str);\r
007c44c5 2272\r
be96b71b 2273 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, wan);\r
dee5592e 2274 safe_run(str);\r
007c44c5 2275 }\r
dee5592e 2276 printf("Total IP count: %d\n", i);\r
2277 run_restore(); \r
260c2719 2278 if(log_file)\r
2279 {\r
2280 fclose(log_file);\r
2281 }\r
007c44c5 2282 return 0;\r
007c44c5 2283 /* that's all folks, thank you for reading it all the way up to this point ;-) */\r
2284 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */\r
2285}\r
This page took 2.220014 seconds and 4 git commands to generate.