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