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