aktualni prenosy jako json a soubor classmap pro prubezny shaping
[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
103d292c 43const char *stats_html_signature = "<span class=\"small\">Statistics generated by Prometheus QoS version %s<br />GPL+Copyright(C)2005-2012 Michael Polak, <a href=\"http://www.arachne.cz/\">Arachne Labs</a></span>\n";\r
2d114137 44\r
82c702a1 45/* ======= All path names are defined here (for RPM patch) ======= */\r
ae776b10 46\r
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
659\r
007c44c5 660 free(cmd);\r
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
692 printf("Running %s <%s ...\n",iptablesrestore,iptablesfile);\r
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
703 done;\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
884 done;\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
921<td style=\"text-align: left\"><a class=\"blue\" href=\"%s%s.log\">%s</td>\n\\r
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
103d292c 927 fprintf(f, "<a class=\"blue\" 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
103d292c 943 <td colspan=\"4\" style=\"text-align: left\">Total:</td>\\r
3ece6581 944 <td style=\"text-align: right\"><strong>%ld&nbsp;GB</strong></td>\\r
945 <td style=\"text-align: right\"><strong>%Ld&nbsp;kb/s</strong></td></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
103d292c 962 fprintf(f,"<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d %%</td><td style=\"text-align: right\">%ld G</td><td style=\"text-align: right\">%d %%</td></tr>\n",iplog->i,(100*iplog->i+50)/i,iplog->l,(int)((100*iplog->l+50)/total));\r
208112af 963 }\r
964 \r
965 if_exists(iplog,iplogs,iplog->i==10)\r
966 {\r
9aa195f6 967 fprintf(f,"%s<td>Top 10 downloaders</td>\n", tr_odd_even());\r
3ece6581 968 fprintf(f,"<td style=\"text-align: right\"><strong>10</strong></td>\n\\r
969<td style=\"text-align: right\">%d %%</td>\n\\r
970<td style=\"text-align: right\">%ld G</td>\n\\r
971<td style=\"text-align: right\">%d %%</td></tr>\n",\r
972 (100*iplog->i+50)/i,iplog->l,(int)((100*iplog->l+50)/total));\r
208112af 973 }\r
974\r
975 if_exists(iplog,iplogs,iplog->l>=total/2)\r
976 {\r
9aa195f6 977 fprintf(f,"%s<td>Top 50%% of traffic</td>\n", tr_odd_even());\r
3ece6581 978 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
979<td style=\"text-align: right\">%d %%</td>\n\\r
980<td style=\"text-align: right\">%ld G</td>\n\\r
981<td style=\"text-align: right\"><strong>%d %%</strong></td></tr>\n",\r
982 iplog->i,(100*iplog->i+50)/i,iplog->l,(int)((100*iplog->l+50)/total));\r
208112af 983 }\r
984\r
985 if_exists(iplog,iplogs,iplog->l>=4*total/5)\r
986 {\r
9aa195f6 987 fprintf(f,"%s<td>Top 80%% of traffic</td>\n",tr_odd_even());\r
3ece6581 988 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
989<td style=\"text-align: right\">%d %%</td>\n\\r
990<td style=\"text-align: right\">%ld G</td>\n\\r
991<td style=\"text-align: right\"><strong>%d %%</strong></td></tr>\n",\r
992 iplog->i,(100*iplog->i+50)/i,iplog->l,(int)((100*iplog->l+50)/total));\r
208112af 993 }\r
994\r
995 if_exists (iplog,iplogs,iplog->i>=i/5)\r
996 {\r
9aa195f6 997 fprintf(f,"%s<td>Top 20%% downloaders</td>\n",tr_odd_even());\r
3ece6581 998 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
999<td style=\"text-align: right\"><strong>%d %%</strong></td>\n\\r
1000<td style=\"text-align: right\">%ld G</td>\n\\r
1001<td style=\"text-align: right\">%d %%</td></tr>\n",\r
1002 iplog->i,(100*iplog->i+50)/i,iplog->l,(int)((100*iplog->l+50)/total));\r
208112af 1003 }\r
1004\r
1005 if_exists(iplog,iplogs,iplog->i>=i/4)\r
1006 {\r
9aa195f6 1007 fprintf(f,"%s<td>Top 25%% downloaders</td>\n", tr_odd_even());\r
103d292c 1008 fprintf(f,"<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d %%</td><td style=\"text-align: right\">%ld G</td><td style=\"text-align: right\">%d %%</td></tr>\n",iplog->i,(100*iplog->i+50)/i,iplog->l,(int)((100*iplog->l+50)/total));\r
208112af 1009 }\r
1010\r
1011 if_exists(iplog,iplogs,iplog->i>=i/2)\r
1012 {\r
9aa195f6 1013 fprintf(f,"%s<td>Top 50%% downloaders</td>\n",tr_odd_even());\r
3ece6581 1014 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1015<td style=\"text-align: right\"><strong>%d %%</strong></td>\n\\r
1016<td style=\"text-align: right\">%ld G</td><td style=\"text-align: right\">%d %%</td></tr>\n",iplog->i,(100*iplog->i+50)/i,iplog->l,(int)((100*iplog->l+50)/total));\r
208112af 1017 }\r
1018\r
1019 if_exists(iplog,iplogs,iplog->i>=4*i/5)\r
1020 {\r
9aa195f6 1021 fprintf(f,"%s<td>Top 80%% downloaders</td>\n",tr_odd_even());\r
103d292c 1022 fprintf(f,"<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d %%</td><td style=\"text-align: right\">%ld G</td><td style=\"text-align: right\">%d %%</td></tr>\n",iplog->i,(100*iplog->i+50)/i,iplog->l,(int)((100*iplog->l+50)/total));\r
208112af 1023 }\r
1024\r
3ece6581 1025 fprintf(f,"</tbody><thead><tr>\n\\r
1026<th>All users, all traffic</th>\n\\r
1027<th style=\"text-align: right\">%d</th>\n\\r
1028<th style=\"text-align: right\">100 %%</th>\n\\r
1029<th style=\"text-align: right\">%ld G</th>\n\\r
1030<th style=\"text-align: right\">100 %%</th></tr>\n",i-1,total);\r
1031 fputs("</thead></table>\n", f);\r
208112af 1032 }\r
1033\r
2d114137 1034 fprintf(f, stats_html_signature, version);\r
c9012978 1035 fclose(f);\r
be96b71b 1036 puts("done.");\r
c9012978 1037 }\r
add90548 1038 else\r
1039 {\r
1040 perror(str);\r
1041 }\r
1042}\r
1043\r
1044void append_log(struct IP *self) /*using global variables*/\r
1045{\r
1046 char *d, *str;\r
1047 FILE *f; \r
1048\r
1049 date(d); /* this is typical cll1.h macro - prints current date */ \r
1050 string(str,STRLEN); \r
1051 sprintf(str,"%s/%s.log", log_dir, self->name);\r
1052 f=fopen(str,"a");\r
be96b71b 1053 if(f > 0)\r
add90548 1054 {\r
1055 fprintf(f,"%ld\t%s\t%Lu\t%Lu\t%Lu\t%Lu\t%d\t%d\t%d\t%d\t%s",\r
1056 time(NULL), self->name, self->traffic, self->direct, self->proxy,\r
1057 self->upload, self->min, self->max, self->desired, self->lmsid, d); /* d = date*/\r
1058 fclose(f);\r
1059 }\r
1060 else\r
1061 {\r
1062 perror(str);\r
1063 }\r
c9012978 1064}\r
5b902402 1065\r
add90548 1066\r
007c44c5 1067/*-----------------------------------------------------------------*/\r
493e1ccd 1068/* Are you looking for int main(int argc, char **argv) ? :-)) */\r
007c44c5 1069/*-----------------------------------------------------------------*/\r
1070\r
1071program\r
1072{\r
1073 int i=0;\r
1074 FILE *f=NULL;\r
1075 char *str, *ptr, *d;\r
1076 char *substring;\r
1077 int class_count=0,ip_count=0;\r
1078 int parent=1;\r
208112af 1079 int just_flush=FALSE;\r
1080 int nodelay=FALSE;\r
1081 int just_preview=FALSE; /* preview - generate just stats */\r
1082 int just_logs=FALSE; /* just parse logs */\r
1083 int run=FALSE;\r
b014f181 1084 int total=0;\r
33ec95ab 1085 \r
007c44c5 1086 char *chain_forward, *chain_postrouting;\r
1087 char *althosts=NULL;\r
1088 \r
1089 printf("\n\\r
1090Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\\r
260c2719 1091Version %s - Copyright (C)2005-2012 Michael Polak (xChaos)\n\\r
43cde5c3 1092iptables-restore & burst tunning & classify modification by Ludva\n\\r
0d5026c6 1093Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version);\r
007c44c5 1094\r
1095 /*----- Boring... we have to check command line options first: ----*/\r
1096 \r
1097 arguments\r
1098 {\r
1099 argument("-c") { nextargument(config); }\r
1100 argument("-h") { nextargument(althosts);}\r
208112af 1101 argument("-d") { run=TRUE; dry_run=TRUE; }\r
1102 argument("-f") { run=TRUE; just_flush=TRUE; }\r
1103 argument("-9") { run=TRUE; just_flush=9; }\r
1104 argument("-p") { run=TRUE; just_preview=TRUE; }\r
1105 argument("-r") { run=TRUE; }\r
1106 argument("-n") { run=TRUE; nodelay=TRUE; }\r
1107 argument("-l") { just_logs=TRUE; }\r
1108 argument("-m") { just_logs=TRUE; }\r
1109 argument("-y") { just_logs=TRUE; }\r
007c44c5 1110 argument("-?") { help(); exit(0); }\r
1111 argument("--help") { help(); exit(0); }\r
1112 argument("-v") { exit(0); } \r
1113 argument("--version") { exit(0); } \r
1114 }\r
208112af 1115 \r
007c44c5 1116 if(dry_run)\r
208112af 1117 {\r
007c44c5 1118 puts("*** THIS IS JUST DRY RUN ! ***\n");\r
208112af 1119 }\r
007c44c5 1120\r
208112af 1121 date(d); /* this is typical cll1.h macro - prints current date */\r
007c44c5 1122\r
1123 /*-----------------------------------------------------------------*/\r
1124 printf("Parsing configuration file %s ...\n", config);\r
1125 /*-----------------------------------------------------------------*/\r
1126 get_config(config);\r
c9012978 1127 \r
33ec95ab 1128 if(just_logs)\r
c9012978 1129 {\r
208112af 1130 parse_ip_log(argc,argv);\r
1131 exit(0);\r
1132 }\r
1133 else if(not run)\r
1134 {\r
1135 help();\r
1136 exit(0);\r
c9012978 1137 }\r
007c44c5 1138\r
208112af 1139 if(althosts)\r
1140 {\r
1141 hosts=althosts;\r
1142 }\r
007c44c5 1143\r
1144 if(just_flush<9)\r
1145 {\r
1146 /*-----------------------------------------------------------------*/\r
1147 puts("Parsing iptables verbose output ...");\r
1148 /*-----------------------------------------------------------------*/\r
1149 get_traffic_statistics();\r
1150 }\r
1151\r
1152 /*-----------------------------------------------------------------*/\r
1153 printf("Parsing class defintion file %s ...\n", hosts);\r
1154 /*-----------------------------------------------------------------*/\r
1155 int groupidx = FIRSTGROUPID;\r
1156 parse(hosts)\r
1157 {\r
1158 str=_;\r
1159\r
1160 if(*str<'0' || *str>'9')\r
4358455e 1161 {\r
1162 /* any line starting with non-number is comment ...*/\r
007c44c5 1163 continue;\r
4358455e 1164 }\r
007c44c5 1165 \r
1166 //Does this IP share QoS class with some other ?\r
1167 substring=strstr(str,"sharing-");\r
1168 if(substring)\r
1169 { \r
1170 substring+=8; //"sharing-"\r
0eb8bc04 1171 parse_ip(str);\r
007c44c5 1172 ip_count++;\r
1173 ip->sharing=substring;\r
1174 ip->keyword=defaultkeyword; /* settings for default keyword */\r
1175 while(*substring && *substring!='\n')\r
4358455e 1176 {\r
007c44c5 1177 substring++;\r
4358455e 1178 }\r
007c44c5 1179 *substring=0; \r
1180 }\r
1181 else\r
1182 {\r
1183 //Do we have to create new QoS class for this IP ?\r
1184\r
208112af 1185 if_exists(keyword,keywords,(substring=strstr(str,keyword->key)))\r
007c44c5 1186 {\r
0eb8bc04 1187 parse_ip(str);\r
007c44c5 1188 ip_count++;\r
1189 ip->keyword=keyword;\r
1190 keyword->ip_count++;\r
1191 ip->prio=keyword->default_prio;\r
1192 substring+=strlen(keyword->key)+1;\r
1193 ptr=substring;\r
1194 while(*ptr && *ptr!='-')\r
bb9e11ee 1195 {\r
007c44c5 1196 ptr++;\r
bb9e11ee 1197 }\r
007c44c5 1198 if(*ptr=='-')\r
1199 {\r
1200 *ptr=0;\r
260c2719 1201 ip->max = ip->desired=atoi(ptr+1);\r
007c44c5 1202 }\r
260c2719 1203 ip->min = atoi(substring);\r
1204 if(ip->min <= 0)\r
007c44c5 1205 {\r
3ece6581 1206 printf(" %s: Illegal value of minimum bandwidth 0 kbps, using %d kb/s\n",\r
260c2719 1207 str, free_min);\r
1208 ip->min = free_min;\r
007c44c5 1209 }\r
260c2719 1210 if(ip->max <= ip->min)\r
007c44c5 1211 {\r
260c2719 1212 ip->fixedprio = 1;\r
1213 ip->max = ip->min+ip->keyword->reserve_min;\r
007c44c5 1214 }\r
1215 else \r
1216 {\r
260c2719 1217 ip->max -= ip->keyword->reserve_max;\r
007c44c5 1218 if(ip->max<ip->min)\r
bb9e11ee 1219 {\r
007c44c5 1220 ip->max=ip->min;\r
bb9e11ee 1221 }\r
007c44c5 1222 }\r
43e07280 1223 ip->mark=FIRSTIPCLASS+1+class_count++;\r
007c44c5 1224\r
208112af 1225 if_exists(group,groups,group->min==ip->min) \r
007c44c5 1226 { \r
1227 group->count++; \r
260c2719 1228 group->desired += ip->min;\r
007c44c5 1229 ip->group = group->id; \r
1230 }\r
1231 else\r
1232 {\r
1233 create(group,Group);\r
260c2719 1234 group->min = ip->min;\r
007c44c5 1235 group->id = groupidx++;\r
1236 ip->group = group->id;\r
1237\r
1238 if(group->min<8) group->min=8;\r
1239 /* Warning - this is maybe because of primitive tc namespace, can be fixed */\r
1240 /* it is because class IDs are derived from min. bandwidth. - xCh */\r
1241 //if(group->min>MAX_GUARANTED_KBPS) group->min=MAX_GUARANTED_KBPS;\r
1242 \r
1243 group->count=1;\r
1244 group->desired=ip->min; \r
1245 insert(group,groups,desc_order_by,min);\r
1246 }\r
1247 }//endif keyword-\r
1248 }//endif sharing-\r
1249 }\r
1250 fail\r
1251 {\r
1252 perror(hosts);\r
1253 exit(-1);\r
1254 }\r
1255 done;\r
1256\r
1257 /*-----------------------------------------------------------------*/\r
1258 /* cll1.h - let's allocate brand new character buffer... */\r
1259 /*-----------------------------------------------------------------*/\r
1260 string(str,STRLEN); \r
1261\r
1262 /*-----------------------------------------------------------------*/\r
1263 puts("Resolving shared connections ...");\r
1264 /*-----------------------------------------------------------------*/\r
6cc38f96 1265 for_each(ip,ips) if(ip->sharing)\r
007c44c5 1266 {\r
6cc38f96 1267 for_each(sharedip,ips) if(eq(sharedip->name,ip->sharing))\r
007c44c5 1268 {\r
1269 sharedip->traffic+=ip->traffic;\r
1270 ip->traffic=0;\r
1271 ip->mark=sharedip->mark; \r
b3175d62 1272 ip->lmsid=sharedip->lmsid;\r
007c44c5 1273 break;\r
1274 }\r
1275 if(!sharedip)\r
bb9e11ee 1276 {\r
260c2719 1277 printf("Unresolved shared connection: %s %s sharing-%s\n",\r
1278 ip->addr, ip->name, ip->sharing);\r
bb9e11ee 1279 }\r
007c44c5 1280 }\r
1281\r
1282 if(enable_credit && just_flush<9)\r
1283 {\r
1284 /*-----------------------------------------------------------------*/\r
1285 printf("Parsing credit file %s ...\n", credit);\r
1286 /*-----------------------------------------------------------------*/\r
1287 parse(credit)\r
1288 {\r
1289 ptr=parse_datafile_line(_);\r
1290 if(ptr)\r
1291 {\r
208112af 1292 if_exists(ip,ips,eq(ip->addr,_))\r
1293 {\r
007c44c5 1294 sscanf(ptr,"%Lu",&(ip->credit));\r
208112af 1295 }\r
007c44c5 1296 }\r
1297 }\r
1298 done;\r
1299 }\r
1300\r
1301 if(!just_preview)\r
1302 {\r
1303 /*-----------------------------------------------------------------*/\r
1304 puts("Initializing iptables and tc classes ...");\r
1305 /*-----------------------------------------------------------------*/\r
1306 \r
1307 iptables_file=fopen(iptablesfile,"w");\r
260c2719 1308 if(iptables_file == NULL)\r
bb9e11ee 1309 {\r
007c44c5 1310 puts("Cannot open iptablesfile!");\r
1311 exit(-1);\r
1312 }\r
1313 \r
1314 log_file=fopen(cmdlog,"w");\r
260c2719 1315 if(log_file == NULL) \r
bb9e11ee 1316 {\r
007c44c5 1317 puts("Cannot open logfile!");\r
1318 exit(-1);\r
1319 }\r
1320 \r
1321 save_line(iptablespreamble);\r
1322 run_restore();\r
1323 \r
1324 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,lan);\r
1325 safe_run(str);\r
1326\r
1327 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,wan);\r
1328 safe_run(str);\r
1329 \r
1330 iptables_file=fopen(iptablesfile,"w");\r
1331 save_line(iptablespreamble);\r
1332\r
1333 if(qos_free_zone && *qos_free_zone!='0')\r
1334 {\r
1335 char *chain;\r
1336 \r
1337 sprintf(str,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone, wan);\r
1338 save_line(str);\r
1339 \r
1340 if(qos_proxy)\r
1341 {\r
1342 save_line(":post_noproxy - [0:0]");\r
1343 sprintf(str,"-A POSTROUTING -p ! tcp -o %s -j post_noproxy", lan);\r
1344 save_line(str); \r
1345 sprintf(str,"-A POSTROUTING -s ! %s -o %s -j post_noproxy", proxy_ip, lan);\r
1346 save_line(str); \r
1347 sprintf(str,"-A POSTROUTING -s %s -p tcp --sport ! %d -o %s -j post_noproxy", proxy_ip, proxy_port, lan);\r
1348 save_line(str); \r
1349\r
1350 chain="post_noproxy"; \r
1351 }\r
1352 else\r
bb9e11ee 1353 {\r
007c44c5 1354 chain="POSTROUTING";\r
bb9e11ee 1355 }\r
007c44c5 1356 \r
1357 sprintf(str,"-A %s -s %s -o %s -j ACCEPT", chain, qos_free_zone, lan);\r
1358 save_line(str);\r
1359 }\r
1360 \r
1361 if(ip_count>idxtable_treshold1 && !just_flush)\r
1362 {\r
1363 int idxcount=0, bitmask=32-idxtable_bitmask1; /* default net mask: 255.255.255.240 */\r
e0161edb 1364 char *subnet, *buf;\r
007c44c5 1365 /*-----------------------------------------------------------------*/\r
1366 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count);\r
1367 /*-----------------------------------------------------------------*/\r
1368\r
1369 save_line(":post_common - [0:0]");\r
1370 save_line(":forw_common - [0:0]");\r
1371\r
260c2719 1372 for_each(ip,ips) if(ip->addr && *(ip->addr) && !eq(ip->addr,"0.0.0.0/0"))\r
007c44c5 1373 {\r
1374 buf=hash_id(ip->addr,bitmask);\r
208112af 1375 if_exists(idx,idxs,eq(idx->id,buf))\r
1376 {\r
007c44c5 1377 idx->children++;\r
208112af 1378 }\r
007c44c5 1379 else\r
1380 {\r
1381 create(idx,Index);\r
1382 idx->addr=ip->addr;\r
1383 idx->id=buf;\r
1384 idx->bitmask=bitmask;\r
1385 idx->parent=NULL;\r
1386 idx->children=0;\r
1387 idxcount++;\r
1388 push(idx,idxs);\r
1389 }\r
1390 }\r
1391\r
1392 /* brutal perfomance optimalization */\r
1393 while(idxcount>idxtable_treshold2 && bitmask>2*idxtable_bitmask2)\r
1394 {\r
1395 bitmask-=idxtable_bitmask2;\r
1396 idxcount=0;\r
208112af 1397\r
6cc38f96 1398 for_each(idx,idxs) if(idx->parent == NULL)\r
007c44c5 1399 {\r
1400 buf=hash_id(idx->addr,bitmask);\r
208112af 1401 if_exists(metaindex,idxs,eq(metaindex->id,buf))\r
1402 {\r
1403 metaindex->children++;\r
1404 }\r
007c44c5 1405 else\r
1406 {\r
1407 create(metaindex,Index);\r
1408 metaindex->addr=idx->addr;\r
1409 metaindex->id=buf;\r
1410 metaindex->bitmask=bitmask;\r
1411 metaindex->parent=NULL;\r
1412 metaindex->children=0;\r
1413 idxcount++;\r
1414 push(metaindex,idxs);\r
1415 }\r
1416 idx->parent=metaindex;\r
1417 }\r
1418 }\r
1419\r
1420 /* this should slightly optimize throughout ... */\r
1421 sort(idx,idxs,desc_order_by,children);\r
1422 sort(idx,idxs,order_by,bitmask);\r
1423\r
1424 i=0;\r
208112af 1425 for_each(idx,idxs)\r
007c44c5 1426 {\r
1427 subnet=subnet_id(idx->addr,idx->bitmask);\r
260c2719 1428 printf("%d: %s/%d\n",\r
1429 ++i, subnet, idx->bitmask);\r
007c44c5 1430 \r
1431 sprintf(str,":post_%s - [0:0]", idx->id);\r
1432 save_line(str);\r
1433\r
1434 sprintf(str,":forw_%s - [0:0]", idx->id);\r
1435 save_line(str);\r
1436\r
1437 if(idx->parent)\r
1438 {\r
1439 string(buf,strlen(idx->parent->id)+6);\r
1440 sprintf(buf,"post_%s",idx->parent->id);\r
1441 }\r
1442 else\r
bb9e11ee 1443 {\r
007c44c5 1444 buf="POSTROUTING";\r
bb9e11ee 1445 }\r
007c44c5 1446\r
1447 sprintf(str,"-A %s -d %s/%d -o %s -j post_%s", buf, subnet, idx->bitmask, lan, idx->id);\r
1448 save_line(str);\r
1449\r
1450 sprintf(str,"-A %s -d %s/%d -o %s -j post_common", buf, subnet, idx->bitmask, lan);\r
1451 save_line(str);\r
1452\r
1453 if(idx->parent)\r
1454 {\r
1455 string(buf,strlen(idx->parent->id)+6);\r
1456 sprintf(buf,"forw_%s",idx->parent->id);\r
1457 }\r
1458 else\r
bb9e11ee 1459 {\r
007c44c5 1460 buf="FORWARD";\r
bb9e11ee 1461 }\r
007c44c5 1462\r
1463 sprintf(str,"-A %s -s %s/%d -o %s -j forw_%s", buf, subnet, idx->bitmask, wan, idx->id);\r
1464 save_line(str);\r
1465\r
1466 sprintf(str,"-A %s -s %s/%d -o %s -j forw_common", buf, subnet, idx->bitmask, wan);\r
1467 save_line(str);\r
1468 }\r
1469 printf("Total indexed iptables chains created: %d\n", i);\r
1470\r
1471 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);\r
1472 save_line(str);\r
1473 \r
1474 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);\r
1475 save_line(str);\r
1476 }\r
1477 \r
1478 }\r
1479\r
1480 if(just_flush)\r
1481 {\r
1482 fclose(iptables_file);\r
add90548 1483 if(log_file)\r
1484 { \r
1485 fclose(log_file);\r
1486 }\r
007c44c5 1487 puts("Just flushed iptables and tc classes - now exiting ...");\r
1488 exit(0);\r
1489 }\r
1490\r
1491 if(!just_preview)\r
1492 {\r
1493 if(!dry_run && !nodelay && qos_free_delay)\r
1494 {\r
1495 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay);\r
1496 sleep(qos_free_delay);\r
1497 }\r
1498\r
6cc38f96 1499 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",\r
1500 tc,lan,htb_r2q);\r
007c44c5 1501 safe_run(str);\r
1502\r
208112af 1503 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
1504 tc,lan,lan_medium,lan_medium,burst_main,highest_priority);\r
007c44c5 1505 safe_run(str);\r
1506\r
208112af 1507 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
1508 tc,lan,line,line,burst_main,highest_priority);\r
007c44c5 1509 safe_run(str);\r
1510\r
1511 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc,wan,htb_r2q);\r
1512 safe_run(str);\r
1513\r
208112af 1514 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
1515 tc,wan,wan_medium,wan_medium,burst_main,highest_priority);\r
007c44c5 1516 safe_run(str);\r
1517\r
208112af 1518 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
1519 tc,wan,up,up,burst_main,highest_priority);\r
007c44c5 1520 safe_run(str);\r
1521 }\r
1522\r
1523 /*-----------------------------------------------------------------*/\r
208112af 1524 puts("Locating heavy downloaders and generating root classes ...");\r
007c44c5 1525 /*-----------------------------------------------------------------*/\r
bb9e11ee 1526 sort(ip,ips,desc_order_by,traffic); \r
007c44c5 1527\r
1528 /*-----------------------------------------------------------------*/\r
1529 /* sub-scope - local variables */ \r
1530 {\r
6cc38f96 1531 long long int rate = line;\r
1532 long long int max = line;\r
1533 int group_count = 0;\r
1534 FILE *credit_file = NULL;\r
007c44c5 1535 \r
4358455e 1536 if(!just_preview && !dry_run && enable_credit)\r
1537 {\r
6cc38f96 1538 credit_file = fopen(credit,"w");\r
4358455e 1539 }\r
007c44c5 1540 \r
208112af 1541 for_each(group,groups)\r
007c44c5 1542 {\r
1543 if(!just_preview)\r
1544 {\r
007c44c5 1545 //download\r
208112af 1546 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
1547 tc, lan, parent, group->id, rate, max, burst_group, highest_priority+1, group->desired);\r
007c44c5 1548 safe_run(str);\r
1549 \r
1550 //upload\r
208112af 1551 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
1552 tc, wan, parent, group->id, rate*up/line, max*up/line, burst_group, highest_priority+1, group->desired);\r
007c44c5 1553 safe_run(str);\r
1554 }\r
1555 \r
6cc38f96 1556 if(group_count++ < max_nesting)\r
bb9e11ee 1557 {\r
6cc38f96 1558 parent = group->id;\r
bb9e11ee 1559 }\r
007c44c5 1560 \r
6cc38f96 1561 rate -= digital_divide*group->min;\r
1562 if(rate < group->min)\r
4358455e 1563 {\r
6cc38f96 1564 rate = group->min;\r
4358455e 1565 }\r
007c44c5 1566 \r
1567 /*shaping of aggresive downloaders, with credit file support */\r
1568 if(use_credit)\r
1569 {\r
6cc38f96 1570 int group_rate = group->min, priority_sequence = lowest_priority;\r
007c44c5 1571 \r
6cc38f96 1572 for_each(ip, ips) if(ip->min == group->min && ip->max > ip->min)\r
007c44c5 1573 {\r
6cc38f96 1574 if( ip->keyword->data_limit && !ip->fixedprio \r
1575 && ( ip->traffic>ip->credit\r
1576 + (ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))) )\r
007c44c5 1577 {\r
4358455e 1578 if(group_rate<ip->max)\r
1579 {\r
1580 ip->max=group_rate;\r
1581 }\r
007c44c5 1582 group_rate+=magic_treshold;\r
208112af 1583 ip->prio=lowest_priority;\r
4358455e 1584 if(ip->prio<highest_priority+2)\r
1585 {\r
1586 ip->prio=highest_priority+2;\r
1587 }\r
007c44c5 1588 }\r
1589 else\r
1590 {\r
6cc38f96 1591 if( ip->keyword->data_prio \r
1592 && !ip->fixedprio \r
1593 && ( ip->traffic>ip->credit\r
1594 + (ip->min*ip->keyword->data_prio+(ip->keyword->fixed_prio<<20))) )\r
007c44c5 1595 {\r
1596 ip->prio=priority_sequence--;\r
4358455e 1597 if(ip->prio<highest_priority+1)\r
1598 {\r
1599 ip->prio=highest_priority+1;\r
1600 }\r
007c44c5 1601 }\r
1602 \r
1603 if(credit_file)\r
1604 {\r
1605 unsigned long long lcredit=0;\r
99127c70 1606 \r
4358455e 1607 if((ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))>ip->traffic)\r
1608 {\r
007c44c5 1609 lcredit=(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))-ip->traffic;\r
4358455e 1610 }\r
007c44c5 1611 fprintf(credit_file,"%s %Lu\n",ip->addr,lcredit);\r
1612 }\r
1613 }\r
6cc38f96 1614 } \r
007c44c5 1615 }\r
1616 }\r
4358455e 1617 if(credit_file)\r
1618 {\r
1619 fclose(credit_file);\r
1620 }\r
007c44c5 1621 }\r
1622\r
1623 if(just_preview)\r
1624 {\r
1625 f=fopen(preview,"w");\r
1626 ptr=preview; \r
1627 }\r
1628 else if(!dry_run && !just_flush)\r
1629 {\r
1630 /*-----------------------------------------------------------------*/\r
be96b71b 1631 printf("Writing daily statistics %s ... ", json);\r
007c44c5 1632 /*-----------------------------------------------------------------*/\r
be96b71b 1633 f=fopen(json, "w");\r
1634 if(f > 0)\r
007c44c5 1635 {\r
be96b71b 1636 int jsoncount=0;\r
1637 fprintf(f, "{\n");\r
1638 for_each(ip, ips)\r
6cc38f96 1639 {\r
be96b71b 1640 if(jsoncount)\r
1641 {\r
1642 fprintf(f, ",\n");\r
1643 }\r
260c2719 1644 if(ip->traffic || ip->direct || ip->proxy || ip->upload)\r
1645 {\r
be96b71b 1646 fprintf(f, "%d:{\"ip\":%s, \"total\":%Lu, \"down\":%Lu, \"proxy\":%Lu, \"up\":%Lu}\n",\r
1647 ip->lmsid, ip->addr, ip->traffic, ip->direct, ip->proxy, ip->upload);\r
260c2719 1648 }\r
be96b71b 1649 jsoncount++;\r
6cc38f96 1650 }\r
be96b71b 1651 fprintf(f, "}\n");\r
007c44c5 1652 fclose(f);\r
be96b71b 1653 puts("done.");\r
add90548 1654 }\r
1655 else\r
1656 {\r
be96b71b 1657 perror(json);\r
007c44c5 1658 }\r
007c44c5 1659 f=fopen(html,"w");\r
1660 ptr=html;\r
1661 }\r
1662\r
1663 if(f)\r
1664 {\r
007c44c5 1665 int count=1;\r
1666 i=0;\r
1667\r
1668 /*-----------------------------------------------------------------*/\r
6cc38f96 1669 printf("Sorting data and generating statistics page %s ...\n", ptr);\r
007c44c5 1670 /*-----------------------------------------------------------------*/\r
1671\r
6cc38f96 1672 if(use_jquery_popups)\r
1673 {\r
1674 fprintf(f,"<script type=\"text/javascript\" src=\"%s\"></script>\n", jquery_url);\r
1675 }\r
3ece6581 1676 fputs("<table class=\"decorated last\">\n\\r
1677<caption>Bandwidth classes</caption>\n\\r
1678<thead><tr>\n\\r
1679<th style=\"text-align: right\">#</th>\n\\r
103d292c 1680<th style=\"text-align: right\">group</th>\n\\r
1681<th style=\"text-align: right\">IPs</th>\n\\r
1682<th style=\"text-align: right\">requested</th>\n",f);\r
6cc38f96 1683 fprintf(f,"<th colspan=\"%d\">data limits</th>\n", keywordcount);\r
9aa195f6 1684 fputs("</tr></thead><tbody>\n",f);\r
208112af 1685\r
9aa195f6 1686 row_odd_even = 0;\r
6cc38f96 1687 for_each(group, groups) \r
007c44c5 1688 { \r
1689#ifdef DEBUG\r
3ece6581 1690 printf("%d kb/s group: %d bandwidth requested: %d kb/s\n",group->min,group->count,group->desired);\r
007c44c5 1691#endif\r
3ece6581 1692 fprintf(f, "%s<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d&nbsp;kb/s</td>",\r
9aa195f6 1693 tr_odd_even(), count, group->min);\r
3ece6581 1694 fprintf(f, "<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d&nbsp;kb/s</td>",\r
9aa195f6 1695 group->count, group->desired);\r
007c44c5 1696\r
c864e623 1697 for_each(keyword, keywords) if(keyword->ip_count)\r
208112af 1698 {\r
c864e623 1699 fprintf(f,"<td style=\"text-align: right\"><span style=\"color:#%s\">%d&nbsp;MB</span></td>",\r
6cc38f96 1700 keyword->html_color, group->min*keyword->data_limit);\r
208112af 1701 } \r
6cc38f96 1702 i += group->desired; \r
1703 total += group->count;\r
007c44c5 1704 count++; \r
1705 }\r
1706#ifdef DEBUG\r
3ece6581 1707 printf("Total groups: %d Total bandwidth requested: %d kb/s\nAGGREGATION: 1/%d\n",\r
6cc38f96 1708 count, i, i/line);\r
007c44c5 1709#endif\r
e64e760d 1710 fprintf(f,"</tr></tbody>\n\\r
1711<thead><tr>\n\\r
1712<th colspan=\"2\" style=\"text-align: left\">Line %Ld kb/s</td>",line);\r
3ece6581 1713 fprintf(f,"<th style=\"text-align: right\">%d</td><th style=\"text-align: right\">%d kb/s</td>",total,i);\r
007c44c5 1714\r
c864e623 1715 for_each(keyword, keywords) if(keyword->ip_count)\r
208112af 1716 {\r
103d292c 1717 fprintf(f,"<th style=\"text-align: right\">%d IPs</th>",keyword->ip_count);\r
208112af 1718 }\r
6cc38f96 1719 fprintf(f,"</tr><tr><th colspan=\"4\">Aggregation 1/%d</th>\n", (int)(0.5+i/line));\r
1720 fprintf(f,"<th colspan=\"%d\">%d traffic classes</th></tr>\n", keywordcount, total);\r
007c44c5 1721\r
e64e760d 1722 fputs("</thead></table>\n",f);\r
007c44c5 1723 }\r
6cc38f96 1724 else if(!dry_run && !just_flush)\r
1725 {\r
007c44c5 1726 perror(html);\r
6cc38f96 1727 }\r
007c44c5 1728\r
6cc38f96 1729 i=0;\r
007c44c5 1730 if(f)\r
1731 {\r
b014f181 1732 unsigned long long total_traffic=0, total_direct=0, total_proxy=0, total_upload=0, tmp_sum=0;\r
007c44c5 1733 int active_classes=0;\r
3ece6581 1734 int colspan=12;\r
007c44c5 1735 struct Sum {unsigned long long l; int i; list(Sum);} *sum,*sums=NULL;\r
78884bad 1736 int limit_count=0, prio_count=0;\r
4a1b62ea 1737 int popup_button=0;\r
007c44c5 1738\r
1739 if(qos_proxy)\r
4358455e 1740 {\r
1741 colspan++;\r
1742 }\r
007c44c5 1743 \r
3ece6581 1744 fprintf(f,"<p><table class=\"decorated last\">\n<caption>%s",title);\r
9aa195f6 1745 fprintf(f," (%s)</caption>\n", d);\r
3ece6581 1746 fputs("<thead><tr>\n<th colspan=\"3\">&nbsp;</th>\n",f);\r
1747 fputs("<th style=\"text-align: right\">credit</th>\n\\r
1748<th style=\"text-align: right\">FUP</th>\n\\r
1749<th style=\"text-align: right\">total</th>\n\\r
1750<th style=\"text-align: right\">down</th>\n",f);\r
007c44c5 1751 if(qos_proxy)\r
4358455e 1752 {\r
103d292c 1753 fputs("<th style=\"text-align: right\">proxy</th>\n",f);\r
4358455e 1754 }\r
3ece6581 1755 fputs("<th style=\"text-align: right\">up</th>\n\\r
1756<th style=\"text-align: right\">min</th>\n\\r
1757<th style=\"text-align: right\">max</th>\n\\r
1758<th style=\"text-align: right\">limit</th>\n\\r
e64e760d 1759<th>&nbsp;</th>\n\\r
1760</tr><tr>\n\\r
3ece6581 1761<th style=\"text-align: right\">#</th>\n\\r
1762<th>hostname [+sharing]</th>\n\\r
1763<th style=\"text-align: right\">LMS</th>\n\\r
1764<th style=\"text-align: right\">MB</th>\n\\r
1765<th style=\"text-align: right\">MB</th>\n\\r
1766<th style=\"text-align: right\">MB</th>\n\\r
1767<th style=\"text-align: right\">MB</th>\n\\r
1768<th style=\"text-align: right\">MB</th>\n\\r
1769<th style=\"text-align: right\">kb/s</th>\n\\r
1770<th style=\"text-align: right\">kb/s</th>\n\\r
1771<th style=\"text-align: right\">kb/s</th>\n\\r
e64e760d 1772<th>prio</th>\n\\r
3ece6581 1773</tr></thead><tbody>\n",f); \r
007c44c5 1774\r
9aa195f6 1775 row_odd_even = 0;\r
6cc38f96 1776 for_each(ip,ips) if(!use_jquery_popups || !ip->sharing)\r
007c44c5 1777 {\r
1778 char *f1="", *f2="";\r
6cc38f96 1779 i++;\r
1780 \r
1781 if(ip->max < ip->desired)\r
007c44c5 1782 {\r
78884bad 1783 f1="<span style=\"color:red\">";\r
1784 f2="</span>";\r
1785 limit_count++;\r
007c44c5 1786 }\r
6cc38f96 1787 else if(ip->prio > highest_priority+1)\r
007c44c5 1788 {\r
78884bad 1789 f1="<span style=\"color:brown\">";\r
1790 f2="</span>";\r
1791 prio_count++;\r
007c44c5 1792 }\r
1793\r
1794#ifdef DEBUG\r
1795 printf("%03d. %-22s %10Lu (%d/%d)\n",i ,ip->name, ip->traffic, ip->min, ip->max); \r
1796#endif\r
4a1b62ea 1797 /* hostnames -------------------------------------- */\r
103d292c 1798 fprintf(f,"%s<td style=\"text-align: right\"><a name=\"%s\"></a>%d</td><td><a class=\"blue\" href=\"%s%s.log\">%s</a>\n", \r
9aa195f6 1799 tr_odd_even(), ip->name, i, log_url, ip->name, ip->name);\r
3ece6581 1800\r
6cc38f96 1801 if(use_jquery_popups)\r
4a1b62ea 1802 {\r
6cc38f96 1803 fprintf(f,"<span id=\"sharing_%d\" style=\"display:none\">",i);\r
1804 popup_button=0;\r
1805 for_each(sharedip, ips) if(eq(ip->name, sharedip->sharing))\r
1806 {\r
103d292c 1807 fprintf(f,"<br /><a class=\"blue\" href=\"%s%s.log\">%s</a>\n", log_url, sharedip->name, sharedip->name);\r
6cc38f96 1808 popup_button++;\r
1809 }\r
1810 fputs("</span>\n",f);\r
1811 if(popup_button)\r
1812 {\r
103d292c 1813 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 1814 i, i, i, popup_button);\r
1815 }\r
4a1b62ea 1816 }\r
1817 fputs("</td>\n",f);\r
1818 /* ----------------------------------------------- */\r
1819\r
4358455e 1820 if(found_lmsid)\r
1821 {\r
103d292c 1822 fputs("<td style=\"text-align: right\">",f);\r
a1d21464 1823 if(ip->lmsid > 0)\r
4358455e 1824 {\r
103d292c 1825 fprintf(f,"<a class=\"blue\" href=\"%s%d\">%04d</a>\n", lms_url, ip->lmsid, ip->lmsid);\r
4358455e 1826 }\r
a1d21464 1827 else if(ip->lmsid == 0)\r
1828 {\r
ad4cb129 1829 fputs("-------",f);\r
a1d21464 1830 }\r
4a1b62ea 1831 fputs("</td>\n",f);\r
4358455e 1832 }\r
3ece6581 1833 fprintf(f,"<td style=\"text-align: right\">%Lu</td>\n", ip->credit);\r
1834 fprintf(f,"<td style=\"text-align: right\"><span style=\"color:#%s\">%Lu</span></td>",\r
4a1b62ea 1835 ip->keyword->html_color,\r
1836 ip->credit+(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20)));\r
3ece6581 1837 fprintf(f,"<td style=\"text-align: right\">%s%Lu%s", f1, ip->traffic, f2);\r
4a1b62ea 1838\r
1839 /* download --------------------------------------- */\r
3ece6581 1840 fprintf(f,"</td><td style=\"text-align: right\">%Lu", ip->direct);\r
6cc38f96 1841 if(use_jquery_popups)\r
4a1b62ea 1842 {\r
6cc38f96 1843 fprintf(f,"<span id=\"download_%d\" style=\"display:none\">",i);\r
1844 for_each(sharedip, ips) if(eq(ip->name, sharedip->sharing))\r
1845 {\r
3ece6581 1846 fprintf(f,"<br />%Lu", sharedip->direct);\r
6cc38f96 1847 }\r
1848 fputs("</span>\n",f);\r
4a1b62ea 1849 }\r
6cc38f96 1850 fputs("</td>\n",f);\r
4a1b62ea 1851 /* ----------------------------------------------- */\r
1852\r
007c44c5 1853 if(qos_proxy)\r
4358455e 1854 {\r
3ece6581 1855 fprintf(f,"<td style=\"text-align: right\">%Lu</td>\n", ip->proxy);\r
4358455e 1856 }\r
4a1b62ea 1857 /* upload ---------------------------------------- */\r
3ece6581 1858 fprintf(f,"<td style=\"text-align: right\">%Lu", ip->upload);\r
6cc38f96 1859 if(use_jquery_popups)\r
4a1b62ea 1860 {\r
6cc38f96 1861 fprintf(f,"<span id=\"upload_%d\" style=\"display:none\">",i);\r
1862 for_each(sharedip,ips) if(eq(ip->name, sharedip->sharing))\r
1863 {\r
3ece6581 1864 fprintf(f,"<br />%Lu", sharedip->upload);\r
add90548 1865 if(!just_preview)\r
1866 {\r
1867 append_log(sharedip);\r
1868 }\r
6cc38f96 1869 }\r
1870 fputs("</span>\n",f);\r
4a1b62ea 1871 }\r
6cc38f96 1872 fputs("</td>\n",f);\r
4a1b62ea 1873 /* ----------------------------------------------- */\r
1874\r
3ece6581 1875 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1876<td style=\"text-align: right\">%d</td>\n\\r
1877<td style=\"text-align: right\">%s%d%s</td>\n\\r
1878<td>%s%d%s</td></tr>\n",\r
1879 ip->min, ip->desired, \r
1880 f1, ip->max, f2, \r
1881 f1, ip->prio, f2);\r
6cc38f96 1882\r
b014f181 1883 total_traffic+=ip->traffic;\r
007c44c5 1884 total_direct+=ip->direct;\r
1885 total_proxy+=ip->proxy;\r
1886 total_upload+=ip->upload;\r
1887 if(ip->traffic>0)\r
1888 {\r
1889 active_classes++;\r
1890 tmp_sum+=ip->traffic;\r
1891 create(sum,Sum);\r
1892 sum->l=tmp_sum;\r
1893 sum->i=active_classes;\r
1894 insert(sum,sums,order_by,i);\r
1895 }\r
6cc38f96 1896\r
007c44c5 1897 if(!just_preview)\r
1898 {\r
add90548 1899 append_log(ip);\r
007c44c5 1900 }\r
007c44c5 1901 }\r
e64e760d 1902 fprintf(f,"</tbody><thead><tr>\n\\r
1903<th colspan=\"%d\" style=\"text-align: left\">%d CLASSES</th>", colspan-7, i);\r
3ece6581 1904 fprintf(f,"<th style=\"text-align: right\">%Lu</th><th style=\"text-align: right\">%Lu</th>\n", total_traffic, total_direct);\r
007c44c5 1905 if(qos_proxy)\r
4358455e 1906 {\r
3ece6581 1907 fprintf(f,"<th style=\"text-align: right\">%Lu</th>\n", total_proxy);\r
4358455e 1908 }\r
3ece6581 1909 fprintf(f,"<th style=\"text-align: right\">%Lu</th>", total_upload);\r
e64e760d 1910 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 1911\r
9aa195f6 1912 row_odd_even = 0;\r
007c44c5 1913 if(active_classes>10)\r
c9012978 1914 {\r
60a8251d 1915 int top20_count=0,top20_perc1=0;\r
1916 long long top20_perc2=0;\r
1917 unsigned long long top20_sum=0l;\r
1918 \r
3ece6581 1919 fputs("<a name=\"erp\"></a><p><table class=\"decorated last\"><caption>Enterprise Resource Planning (ERP)</caption>\n",f);\r
1920 fputs("<thead><tr>\n\\r
1921<th>Analytic category</th>\n\\r
1922<th colspan=\"2\" style=\"text-align: center\">Active Classes</th>\n\\r
1923<th colspan=\"2\" style=\"text-align: center\">Data transfers</th>\n\\r
1924</tr></thead><tbody>\n",f);\r
c9012978 1925\r
b014f181 1926 if_exists(sum,sums,sum->l>=total_traffic/4)\r
c9012978 1927 {\r
9aa195f6 1928 fprintf(f,"%s<td>Top 25%% of traffic</td>\n", tr_odd_even());\r
103d292c 1929 fprintf(f,"<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d %%</td><td style=\"text-align: right\">%Lu M</td><td style=\"text-align: right\">%Ld %%</td></tr>\n",sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
c9012978 1930 }\r
1931 \r
208112af 1932 if_exists(sum,sums,sum->i==10)\r
c9012978 1933 {\r
9aa195f6 1934 fprintf(f,"%s<td>Top 10 downloaders</td>\n", tr_odd_even());\r
3ece6581 1935 fprintf(f,"<td style=\"text-align: right\"><strong>10</strong></td>\n\\r
1936<td style=\"text-align: right\">%d %%</td>\n\\r
1937<td style=\"text-align: right\">%Lu MB</td>\n\\r
1938<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
1939 (100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
c9012978 1940 }\r
1941\r
b014f181 1942 if_exists(sum,sums,sum->l>=total_traffic/2)\r
c9012978 1943 {\r
9aa195f6 1944 fprintf(f,"%s<td>Top 50%% of traffic</td>\n", tr_odd_even());\r
3ece6581 1945 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1946<td style=\"text-align: right\">%d %%</td>\n\\r
1947<td style=\"text-align: right\">%Lu MB</td>\n\\r
1948<td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",\r
1949 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
c9012978 1950 }\r
1951\r
b014f181 1952 if_exists(sum,sums,sum->l>=4*total_traffic/5)\r
c9012978 1953 {\r
9aa195f6 1954 fprintf(f,"%s<td>Top 80%% of traffic</td>\n", tr_odd_even());\r
3ece6581 1955 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1956<td style=\"text-align: right\">%d %%</td>\n\\r
1957<td style=\"text-align: right\">%Lu MB</td>\n\\r
1958<td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",\r
1959 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
c9012978 1960 }\r
1961\r
60a8251d 1962 if_exists(sum,sums,sum->i>=(active_classes+1)/5)\r
c9012978 1963 {\r
9aa195f6 1964 fprintf(f,"%s<td>Top 20%% downloaders</td>\n", tr_odd_even());\r
60a8251d 1965 top20_count=sum->i;\r
1966 top20_perc1=(100*sum->i+50)/active_classes;\r
1967 top20_sum=sum->l;\r
b014f181 1968 top20_perc2=(100*sum->l+50)/total_traffic;\r
3ece6581 1969 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1970<td style=\"text-align: right\"><strong>%d %%</strong></td>\n\\r
1971<td style=\"text-align: right\">%Lu MB</td>\n\\r
1972<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
1973 top20_count,top20_perc1,top20_sum,top20_perc2);\r
c9012978 1974 }\r
1975\r
208112af 1976 if_exists(sum,sums,sum->i>=(active_classes+1)/4)\r
c9012978 1977 {\r
9aa195f6 1978 fprintf(f,"%s<td>Top 25%% downloaders</td>\n", tr_odd_even());\r
3ece6581 1979 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1980<td style=\"text-align: right\">%d %%</td>\n\\r
1981<td style=\"text-align: right\">%Lu MB</td>\n\\r
1982<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
1983 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
c9012978 1984 }\r
1985\r
208112af 1986 if_exists(sum,sums,sum->i>=(active_classes+1)/2)\r
c9012978 1987 {\r
9aa195f6 1988 fprintf(f,"%s<td>Top 50%% downloaders</td>\n", tr_odd_even());\r
3ece6581 1989 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1990<td style=\"text-align: right\"><strong>%d %%</strong></td>\n\\r
1991<td style=\"text-align: right\">%Lu MB</td>\n\\r
1992<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
1993 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
c9012978 1994 }\r
1995\r
208112af 1996 if_exists(sum,sums,sum->i>=4*(active_classes+1)/5)\r
c9012978 1997 {\r
9aa195f6 1998 fprintf(f,"%s<td>Top 80%% downloaders</td>\n", tr_odd_even());\r
3ece6581 1999 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
2000<td style=\"text-align: right\">%d %%</td>\n\\r
2001<td style=\"text-align: right\">%Lu MB</td>\n\\r
2002<td style=\"text-align: right\">%Ld %%</td></tr></tbody>\n",\r
2003 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
c9012978 2004 }\r
2005\r
3ece6581 2006 fprintf(f,"<tr><thead><th><a class=\"blue\" href=\"%sERP.log\">All users, all traffic</a></th>\n", log_url);\r
103d292c 2007 fprintf(f,"<th style=\"text-align: right\">%d</th>\n\\r
2008<th style=\"text-align: right\">100 %%</th>\n\\r
2009<th style=\"text-align: right\">%Lu M</th>\n\\r
2010<th style=\"text-align: right\">100 %%</th></tr>\n",active_classes,total_traffic);\r
3ece6581 2011 fputs("</thead></table>\n", f);\r
60a8251d 2012\r
5da44508 2013 /* write basic ERP data to log directory */\r
60a8251d 2014 if(!just_preview)\r
2015 {\r
add90548 2016 FILE *iplog;\r
60a8251d 2017 sprintf(str,"%s/ERP.log",log_dir);\r
2018 iplog=fopen(str,"a");\r
2019 if(iplog)\r
2020 {\r
78884bad 2021 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 2022 time(NULL), top20_count, top20_perc1, top20_sum, top20_perc2, \r
6cc38f96 2023 active_classes, total_traffic, i, limit_count, prio_count, d); /* d = date*/\r
60a8251d 2024 fclose(iplog);\r
2025 }\r
add90548 2026 else\r
2027 {\r
2028 perror(str);\r
2029 }\r
60a8251d 2030 }\r
c9012978 2031 }\r
60a8251d 2032\r
2d114137 2033 fprintf(f, stats_html_signature, version);\r
007c44c5 2034 fclose(f);\r
2035 }\r
2036\r
2037 if(just_preview)\r
2038 {\r
2039 puts("Statistics preview generated (-p switch) - now exiting ...");\r
2040 exit(0);\r
be96b71b 2041 } \r
007c44c5 2042\r
2043 i=0;\r
260c2719 2044#ifdef DEBUG\r
007c44c5 2045 printf("%-22s %-15s mark\n","name","ip");\r
260c2719 2046#endif\r
208112af 2047\r
be96b71b 2048 printf("Writing %s ... ", classmap); \r
2049 f = fopen(classmap, "w"); \r
2050 if(f < 0)\r
2051 {\r
2052 perror(classmap);\r
2053 }\r
2054\r
2055 /*-----------------------------------------------------------------*/\r
2056 puts("Generating iptables and tc classes ... ");\r
2057 /*-----------------------------------------------------------------*/\r
2058\r
2059 for_each(ip, ips) if(ip->mark > 0)\r
2060 {\r
007c44c5 2061 if(idxs)\r
2062 {\r
2063 char *buf;\r
2064 duplicate(ip->addr,buf);\r
2065 buf=hash_id(ip->addr,32-idxtable_bitmask1); \r
2066 \r
2067 string(chain_forward,6+strlen(buf));\r
2068 strcpy(chain_forward,"forw_");\r
2069 strcat(chain_forward,buf);\r
2070\r
2071 string(chain_postrouting,6+strlen(buf));\r
2072 strcpy(chain_postrouting,"post_");\r
2073 strcat(chain_postrouting,buf);\r
2074 \r
2075 free(buf);\r
2076 }\r
2077 else\r
2078 {\r
2079 chain_forward="FORWARD";\r
2080 chain_postrouting="POSTROUTING";\r
2081 }\r
2082\r
260c2719 2083#ifdef DEBUG\r
007c44c5 2084 printf("%-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
260c2719 2085#endif\r
007c44c5 2086\r
2087 /* -------------------------------------------------------- mark download */\r
2088 \r
be96b71b 2089 sprintf(str, "-A %s -d %s/32 -o %s -j %s%d",\r
2090 chain_postrouting, ip->addr, lan, mark_iptables, ip->mark);\r
007c44c5 2091 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/\r
2092 /* -m limit --limit 1/s */ \r
2093 save_line(str);\r
2094\r
2095 if(qos_proxy)\r
2096 {\r
be96b71b 2097 sprintf(str, "-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",\r
2098 chain_postrouting, proxy_ip, proxy_port, ip->addr, lan, mark_iptables, ip->mark);\r
007c44c5 2099 /*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
2100 save_line(str);\r
2101 }\r
2102\r
be96b71b 2103 sprintf(str, "-A %s -d %s/32 -o %s -j ACCEPT",\r
2104 chain_postrouting, ip->addr, lan);\r
007c44c5 2105 save_line(str);\r
2106\r
2107 /* -------------------------------------------------------- mark upload */\r
be96b71b 2108 sprintf(str, "-A %s -s %s/32 -o %s -j %s%d", \r
2109 chain_forward, ip->addr, wan, mark_iptables, ip->mark);\r
007c44c5 2110 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/\r
2111 save_line(str);\r
2112\r
be96b71b 2113 sprintf(str, "-A %s -s %s/32 -o %s -j ACCEPT",\r
2114 chain_forward, ip->addr, wan);\r
007c44c5 2115 save_line(str);\r
2116\r
2117 if(ip->min)\r
2118 {\r
2119 /* -------------------------------------------------------- download class */\r
260c2719 2120#ifdef DEBUG\r
007c44c5 2121 printf("(down: %dk-%dk ", ip->min, ip->max); \r
260c2719 2122#endif\r
007c44c5 2123\r
be96b71b 2124 sprintf(str, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
2125 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
007c44c5 2126 safe_run(str);\r
2127\r
260c2719 2128 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
dee5592e 2129 {\r
be96b71b 2130 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s", \r
2131 tc, lan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
dee5592e 2132 safe_run(str);\r
be96b71b 2133 }\r
2134\r
260c2719 2135 if(filter_type == 1)\r
dee5592e 2136 {\r
be96b71b 2137 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
2138 tc, lan, ip->mark, ip->mark);\r
dee5592e 2139 safe_run(str);\r
007c44c5 2140 }\r
2141\r
2142 /* -------------------------------------------------------- upload class */\r
260c2719 2143#ifdef DEBUG\r
007c44c5 2144 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
2145 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
260c2719 2146#endif\r
007c44c5 2147\r
2148 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
2149 tc, wan, ip->group, ip->mark,\r
2150 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
2151 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
2152 safe_run(str);\r
2153 \r
260c2719 2154 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
dee5592e 2155 {\r
be96b71b 2156 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s",\r
2157 tc, wan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
dee5592e 2158 safe_run(str);\r
2159 } \r
be96b71b 2160\r
260c2719 2161 if(filter_type == 1)\r
dee5592e 2162 {\r
be96b71b 2163 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
2164 tc, wan, ip->mark, ip->mark);\r
dee5592e 2165 safe_run(str);\r
007c44c5 2166 }\r
be96b71b 2167 \r
2168 if(f)\r
2169 {\r
2170 fprintf(f, "%s %d", ip->addr, ip->mark);\r
2171 }\r
007c44c5 2172 }\r
2173 else\r
260c2719 2174 {\r
2175#ifdef DEBUG\r
007c44c5 2176 printf("(sharing %s)\n", ip->sharing);\r
260c2719 2177#endif\r
2178 }\r
007c44c5 2179 i++;\r
2180 }\r
be96b71b 2181 if(f)\r
2182 {\r
2183 puts("done.");\r
2184 fclose(f);\r
2185 }\r
2186 \r
007c44c5 2187 if(idxs)\r
2188 {\r
dee5592e 2189 chain_forward = "forw_common";\r
2190 chain_postrouting = "post_common";\r
007c44c5 2191 }\r
2192 else\r
2193 {\r
dee5592e 2194 chain_forward = "FORWARD";\r
2195 chain_postrouting = "POSTROUTING";\r
007c44c5 2196 }\r
dee5592e 2197 /* -------------------------------- classify or reject free download */\r
007c44c5 2198 {\r
b6a8d473 2199 char *final_chain = "DROP"; /* REJECT would be better, but it is impossible in mangle */\r
be96b71b 2200 if(free_min)\r
2201 {\r
2202 final_chain = "ACCEPT";\r
2203 }\r
dee5592e 2204 if(qos_proxy)\r
2205 {\r
2206 if(free_min)\r
2207 {\r
be96b71b 2208 sprintf(str,"-A %s -s %s -p tcp --sport %d -o %s -j %s%d",\r
2209 chain_postrouting,proxy_ip,proxy_port,lan,mark_iptables,3);\r
dee5592e 2210 save_line(str);\r
2211 }\r
be96b71b 2212 sprintf(str,"-A %s -s %s -p tcp --sport %d -o %s -j %s",\r
2213 chain_postrouting,proxy_ip,proxy_port,lan,final_chain);\r
dee5592e 2214 save_line(str);\r
2215 }\r
2216 if(free_min)\r
2217 {\r
be96b71b 2218 sprintf(str,"-A %s -o %s -j %s%d", chain_postrouting, lan, mark_iptables, 3);\r
dee5592e 2219 save_line(str);\r
2220 }\r
be96b71b 2221 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
dee5592e 2222 save_line(str);\r
2223 /* ------------------------------- classify or reject free upload */\r
2224 if(free_min)\r
2225 {\r
be96b71b 2226 sprintf(str,"-A %s -o %s -j %s%d", chain_forward, wan, mark_iptables, 3);\r
dee5592e 2227 save_line(str);\r
2228 }\r
be96b71b 2229 sprintf(str,"-A %s -o %s -j %s", chain_forward, wan, final_chain);\r
dee5592e 2230 save_line(str);\r
007c44c5 2231 }\r
abe9b855 2232\r
dee5592e 2233 if(free_min) /* allocate free bandwith if it is not zero... */ \r
2234 {\r
2235 /*-----------------------------------------------------------------*/\r
2236 puts("Generating free bandwith classes ...");\r
2237 /*-----------------------------------------------------------------*/\r
208112af 2238 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
be96b71b 2239 tc, lan, parent, free_min, free_max,burst, lowest_priority);\r
dee5592e 2240 safe_run(str);\r
208112af 2241 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
be96b71b 2242 tc, wan, parent, free_min, free_max, burst, lowest_priority);\r
dee5592e 2243 safe_run(str);\r
2244 /* tc SFQ */\r
260c2719 2245 if(strcmpi(qos_leaf, "none"))\r
dee5592e 2246 {\r
be96b71b 2247 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, lan, qos_leaf);\r
dee5592e 2248 safe_run(str);\r
2249 \r
be96b71b 2250 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, wan, qos_leaf);\r
dee5592e 2251 safe_run(str);\r
2252 } \r
2253 /* tc handle 1 fw flowid */\r
be96b71b 2254 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, lan);\r
dee5592e 2255 safe_run(str);\r
007c44c5 2256\r
be96b71b 2257 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, wan);\r
dee5592e 2258 safe_run(str);\r
007c44c5 2259 }\r
dee5592e 2260 printf("Total IP count: %d\n", i);\r
2261 run_restore(); \r
260c2719 2262 if(log_file)\r
2263 {\r
2264 fclose(log_file);\r
2265 }\r
007c44c5 2266 return 0;\r
007c44c5 2267 /* that's all folks, thank you for reading it all the way up to this point ;-) */\r
2268 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */\r
2269}\r
This page took 4.557963 seconds and 4 git commands to generate.