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