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