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