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