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