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