serious bug fixed
[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
9a56ab25 92int use_jquery_popups = TRUE;\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
9a56ab25 100int dry_run = FALSE; /* preview - use puts() instead of system() */\r
43cde5c3 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
9a56ab25 103int enable_credit = TRUE; /* enable credit file */\r
104int use_credit = FALSE; /* use credit file (if enabled)*/\r
43cde5c3 105char *title = "Hall of Fame - Greatest Suckers"; /* hall of fame title */\r
9a56ab25 106int hall_of_fame = TRUE; /* enable hall of fame */\r
43cde5c3 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
9a56ab25 113int qos_proxy = TRUE; /* include proxy port to QoS */\r
114int found_lmsid = FALSE; /* show links to users in LMS information system */\r
115int include_upload = TRUE; /* upload+download=total traffic */\r
43cde5c3 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
9a56ab25 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
9a56ab25 160void write_htmlandlogs(char *html, char *d, int total, int just_preview);\r
161/* implemented in htmlandlogs.c */\r
162\r
b6fb849a 163const char *tr_odd_even(void)\r
164{\r
165 row_odd_even = 1 - row_odd_even;\r
166 if(row_odd_even)\r
167 {\r
168 return "<tr class=\"even\">\n";\r
169 }\r
170 else\r
171 {\r
172 return "<tr class=\"odd\">\n";\r
173 }\r
174}\r
175\r
1c9cae56 176/* ==== This is C<<1 stuff - learn C<<1 first! https://dev.arachne.cz/svn/cll1h ==== */\r
007c44c5 177\r
178struct Index\r
179{\r
180 char *addr;\r
181 char *id;\r
182 struct Index *parent;\r
183 int bitmask;\r
184 int children;\r
185 list(Index);\r
186} *idxs=NULL, *idx, *metaindex;\r
187\r
a1204fc9 188void TheIP(void);\r
189/* function implemented in parsehosts.c */\r
007c44c5 190\r
5b902402 191/* ====== iptables indexes are used to reduce complexity to log8(N) ===== */\r
007c44c5 192\r
59c3032e 193char *index_id(char *ip, int bitmask);\r
194/* function implemented in ipv4subnets.c */\r
007c44c5 195\r
59c3032e 196char *subnet_id(char *ip, int bitmask);\r
197/* function implemented in ipv4subnets.c */\r
007c44c5 198\r
59c3032e 199/* ================= Let's parse configuration file here ================ */\r
007c44c5 200\r
201void reject_config_and_exit(char *filename)\r
202{\r
203 printf("Configuration file %s rejected - abnormal exit.",filename);\r
204 exit(-1);\r
205}\r
206\r
207void get_config(char *config_filename)\r
208{\r
209 char *cnf="mark";\r
210 \r
211 printf("Configured keywords: ");\r
212 parse(config_filename)\r
213 {\r
214 option("keyword",kwd);\r
215 if(kwd)\r
216 {\r
217 printf("%s ",kwd);\r
218\r
219 create(keyword,Keyword);\r
220 keyword->key=kwd;\r
221 keyword->asymetry_ratio=1; /* ratio for ADSL-like upload */\r
222 keyword->asymetry_fixed=0; /* fixed treshold for ADSL-like upload */\r
223 keyword->data_limit=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */\r
208112af 224 keyword->data_prio=4; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */\r
007c44c5 225 keyword->fixed_limit=0; /* fixed data limit for setting lower HTB ceil */\r
226 keyword->fixed_prio=0; /* fixed data limit for setting lower HTB prio */\r
227 keyword->reserve_min=8; /* bonus for nominal HTB rate bandwidth (in kbps) */\r
228 keyword->reserve_max=0; /* malus for nominal HTB ceil (in kbps) */\r
208112af 229 keyword->default_prio=highest_priority+1;\r
007c44c5 230 keyword->html_color="000000";\r
231 keyword->ip_count=0;\r
232 keyword->leaf_discipline="";\r
233\r
234 push(keyword,keywords);\r
235 if(!defaultkeyword) defaultkeyword=keyword;\r
236 keywordcount++;\r
237 \r
238 kwd=NULL;\r
239 }\r
208112af 240 else\r
007c44c5 241 {\r
208112af 242 for_each(keyword,keywords)\r
243 {\r
244 int l=strlen(keyword->key);\r
007c44c5 245\r
208112af 246 if(!strncmp(keyword->key,_,l) && strlen(_)>l+2)\r
247 {\r
248 char *tmptr=_; /* <---- l+1 ----> */\r
249 _+=l+1; /* via-prometheus-asymetry-ratio, etc. */\r
250 ioption("asymetry-ratio",keyword->asymetry_ratio);\r
251 ioption("asymetry-treshold",keyword->asymetry_fixed);\r
252 ioption("magic-relative-limit",keyword->data_limit);\r
253 ioption("magic-relative-prio",keyword->data_prio);\r
254 loption("magic-fixed-limit",keyword->fixed_limit);\r
255 loption("magic-fixed-prio",keyword->fixed_prio);\r
256 ioption("htb-default-prio",keyword->default_prio);\r
257 ioption("htb-rate-bonus",keyword->reserve_min);\r
258 ioption("htb-ceil-malus",keyword->reserve_max);\r
208112af 259 option("leaf-discipline",keyword->leaf_discipline);\r
260 option("html-color",keyword->html_color);\r
261 _=tmptr;\r
262 \r
263 if(keyword->data_limit || keyword->fixed_limit || \r
264 keyword->data_prio || keyword->fixed_prio)\r
bb9e11ee 265 {\r
266 use_credit=1; \r
267 }\r
208112af 268 }\r
269 }\r
007c44c5 270 }\r
271\r
272 option("tc",tc);\r
273 option("iptables",iptables);\r
274 option("iptables-save",iptablessave); /* new */\r
275 option("iptables-restore",iptablesrestore); /* new */\r
be96b71b 276 option("iptables-in-filename",iptablesfile); /* new */\r
007c44c5 277 option("hosts",hosts);\r
278 option("lan-interface",lan);\r
279 option("wan-interface",wan);\r
280 option("lan-medium",lan_medium);\r
281 option("wan-medium",wan_medium);\r
282 lloption("wan-download",line);\r
283 lloption("wan-upload",up);\r
284 ioption("hall-of-fame-enable",hall_of_fame);\r
285 option("hall-of-fame-title",title);\r
286 option("hall-of-fame-filename",html);\r
1ab008b9 287 option("json-filename",json_traffic);\r
007c44c5 288 option("hall-of-fame-preview",preview);\r
6fb3c58a 289 option("json-preview",json_preview);\r
007c44c5 290 option("log-filename",cmdlog);\r
291 option("credit-filename",credit);\r
be96b71b 292 option("classmap-filename",classmap);\r
007c44c5 293 ioption("credit-enable",enable_credit);\r
294 option("log-traffic-directory",log_dir);\r
5b902402 295 option("log-traffic-html-directory",html_log_dir);\r
007c44c5 296 option("log-traffic-url-path",log_url);\r
6cc38f96 297 option("jquery-url",jquery_url);\r
298 option("lms-url",lms_url);\r
299 ioption("use-jquery-popups",use_jquery_popups);\r
007c44c5 300 option("qos-free-zone",qos_free_zone);\r
301 ioption("qos-free-delay",qos_free_delay);\r
302 ioption("qos-proxy-enable",qos_proxy);\r
303 option("qos-proxy-ip",proxy_ip);\r
304 option("htb-leaf-discipline",qos_leaf);\r
305 ioption("qos-proxy-port",proxy_port);\r
306 ioption("free-rate",free_min);\r
307 ioption("free-ceil",free_max);\r
308 ioption("htb-burst",burst);\r
309 ioption("htb-burst-main",burst_main);\r
310 ioption("htb-burst-group",burst_group);\r
311 ioption("htb-nesting-limit",max_nesting);\r
312 ioption("htb-r2q",htb_r2q);\r
313 ioption("magic-include-upload",include_upload);\r
5b902402 314 ioption("magic-treshold",magic_treshold); \r
260c2719 315 option("filter-type", cnf); \r
007c44c5 316/* not yet implemented:\r
317 ioption("magic-fixed-packets",fixed_packets);\r
318 ioption("magic-relative-packets",packet_limit);\r
319*/\r
320 }\r
321 fail\r
322 { \r
323 perror(config_filename);\r
324 puts("Warning - using built-in defaults instead ...");\r
325 }\r
8e29188a 326 done; /* ugly macro end */\r
007c44c5 327 printf("\n");\r
328 \r
be96b71b 329 /* leaf discipline for keywords */\r
208112af 330 for_each(keyword,keywords)\r
007c44c5 331 {\r
260c2719 332 if(!strcmpi(keyword->leaf_discipline, ""))\r
208112af 333 {\r
007c44c5 334 keyword->leaf_discipline = qos_leaf;\r
335 }\r
336 }\r
337\r
260c2719 338 if(strcmpi(cnf, "mark"))\r
bb9e11ee 339 {\r
340 filter_type = 2;\r
341 mark = "CLASSIFY";\r
342 mark_iptables = "CLASSIFY --set-class 1:";\r
343 }\r
344 else\r
345 {\r
346 filter_type = 1;\r
347 mark = "MARK";\r
348 mark_iptables = "MARK --set-mark ";\r
007c44c5 349 }\r
350\r
351 /* are supplied values meaningful ?*/\r
352 if(line<=0 || up<=0)\r
353 {\r
b1b59b3a 354 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");\r
007c44c5 355 reject_config_and_exit(config_filename);\r
356 }\r
357}\r
358\r
359/* ===================== traffic analyser - uses iptables ================ */ \r
360\r
361void get_traffic_statistics(void)\r
362{\r
363 char *str,*cmd;\r
364 int downloadflag=0;\r
365\r
366 textfile(Pipe,str) *line,*lines=NULL;\r
367 string(str,STRLEN);\r
368 string(cmd,STRLEN);\r
369\r
370 sprintf(cmd,"%s -L -v -x -n -t mangle",iptables);\r
371 shell(cmd);\r
372 input(str,STRLEN)\r
373 {\r
374 create(line,Pipe);\r
375 line->str=str;\r
376 string(str,STRLEN);\r
377 append(line,lines);\r
378 }\r
379\r
208112af 380 for_each(line,lines)\r
007c44c5 381 {\r
382 int col, accept=0,proxyflag=0,valid=1,setchainname=0,commonflag=0; \r
383 unsigned long long traffic=0;\r
384 unsigned long pkts=0;\r
385 char *ipaddr=NULL,*ptr;\r
386 \r
387 /* debug puts(line->str); */\r
388 valid_columns(ptr,line->str,' ',col) \r
389 if(valid) switch(col)\r
390 { \r
391 case 1: if(eq(ptr,"Chain"))\r
260c2719 392 {\r
007c44c5 393 setchainname=1;\r
260c2719 394 }\r
007c44c5 395 else if(eq(ptr,"pkts")) \r
260c2719 396 {\r
007c44c5 397 valid=0;\r
260c2719 398 }\r
007c44c5 399 else\r
260c2719 400 {\r
007c44c5 401 sscanf(ptr,"%lu",&pkts); \r
260c2719 402 }\r
007c44c5 403 break;\r
404 case 2: if(setchainname)\r
405 {\r
406 if(!strncmp(ptr,"post_",5) || eq(ptr,"POSTROUTING"))\r
260c2719 407 {\r
408 downloadflag = 1; \r
409 }\r
007c44c5 410 else \r
260c2719 411 {\r
412 if(!strncmp(ptr,"forw_",5) || eq(ptr,"FORWARD"))\r
413 {\r
414 downloadflag = 0;\r
415 }\r
416 } \r
007c44c5 417 if(eq(ptr,"post_common") || eq(ptr,"forw_common"))\r
260c2719 418 {\r
419 commonflag = 1;\r
420 }\r
007c44c5 421 }\r
422 else\r
260c2719 423 {\r
424 sscanf(ptr,"%Lu",&traffic); \r
425 traffic += (1<<19);\r
426 traffic >>= 20;\r
427 }\r
007c44c5 428 break;\r
0045483c 429 case 3: if((strncmp(ptr,"post_",5) && strncmp(ptr,"forw_",5)) || commonflag)\r
260c2719 430 {\r
007c44c5 431 accept=eq(ptr,mark);\r
260c2719 432 }\r
433 /*if(filter_type==1) accept=eq(ptr,"MARK"); else accept=eq(ptr,"CLASSIFY");*/\r
007c44c5 434 break;\r
435 case 8: if(downloadflag)\r
436 { \r
260c2719 437 if(strstr(proxy_ip,ptr))\r
438 {\r
439 proxyflag=1; \r
440 }\r
007c44c5 441 }\r
442 else\r
260c2719 443 {\r
007c44c5 444 ipaddr=ptr; \r
260c2719 445 }\r
446 break;\r
007c44c5 447 case 9: if(downloadflag)ipaddr=ptr;break;\r
448 }\r
449 \r
450 if(accept && traffic>0 && ipaddr)\r
451 {\r
a1d21464 452 if(proxyflag)\r
453 {\r
454 printf("(proxy) ");\r
455 }\r
456 else if(!downloadflag)\r
457 {\r
458 printf("(upload) ");\r
459 }\r
457d52f2 460 printf("IP %s: %Lu MB (%ld pkts)\n", ipaddr, traffic, pkts);\r
208112af 461\r
462 if_exists(ip,ips,eq(ip->addr,ipaddr)); \r
007c44c5 463 else \r
464 {\r
465 TheIP();\r
466 ip->addr=ipaddr;\r
467 if(eq(ip->addr,"0.0.0.0/0"))\r
468 {\r
469 ip->name="(unregistered)";\r
470 ip->min=free_min;\r
471 ip->max=ip->desired=free_max;\r
472 }\r
473 }\r
474 \r
475 if(downloadflag)\r
476 {\r
477 if(proxyflag)\r
a1d21464 478 {\r
007c44c5 479 ip->proxy=traffic;\r
a1d21464 480 }\r
007c44c5 481 else\r
a1d21464 482 {\r
007c44c5 483 ip->traffic+=traffic;\r
a1d21464 484 }\r
007c44c5 485 ip->direct=ip->traffic-ip->upload-ip->proxy;\r
486 ip->pktsdown=pkts;\r
487 }\r
488 else\r
489 {\r
490 ip->upload=traffic;\r
491 ip->pktsup=pkts;\r
492 if(include_upload)\r
bb9e11ee 493 {\r
007c44c5 494 ip->traffic+=traffic;\r
bb9e11ee 495 }\r
007c44c5 496 else \r
bb9e11ee 497 {\r
007c44c5 498 if(traffic>ip->traffic)\r
bb9e11ee 499 {\r
007c44c5 500 ip->traffic=traffic; \r
bb9e11ee 501 }\r
502 }\r
007c44c5 503 }\r
504 } \r
505 }\r
1c004f15 506 free(cmd);\r
007c44c5 507}\r
508 \r
509/* ========== This function executes, logs OR ALSO prints command ========== */\r
510\r
511void safe_run(char *cmd)\r
512{\r
a1d21464 513 if(dry_run)\r
514 {\r
515 printf("\n=>%s\n",cmd);\r
516 }\r
517 else\r
518 {\r
519 system(cmd);\r
520 }\r
521 if(log_file)\r
522 {\r
523 fprintf(log_file,"%s\n",cmd);\r
524 }\r
007c44c5 525}\r
526\r
527void save_line(char *line)\r
528{\r
529 fprintf(iptables_file,"%s\n",line);\r
530}\r
531\r
532void run_restore(void)\r
533{\r
5da44508 534 char *restor;\r
007c44c5 535 string(restor,STRLEN);\r
abe9b855 536\r
537 /*-----------------------------------------------------------------*/\r
1c004f15 538 printf("Running %s <%s ...\n", iptablesrestore, iptablesfile);\r
abe9b855 539 /*-----------------------------------------------------------------*/\r
007c44c5 540 \r
541 save_line("COMMIT");\r
542 fclose(iptables_file);\r
ae776b10 543 if(dry_run) \r
544 {\r
a1d21464 545 parse(iptablesfile)\r
546 {\r
547 printf("%s\n",_);\r
548 }\r
8e29188a 549 done; /* ugly macro end */\r
ae776b10 550 }\r
551\r
552 sprintf(restor,"%s <%s",iptablesrestore, iptablesfile);\r
553 safe_run(restor);\r
007c44c5 554 \r
555 free(restor);\r
556}\r
557\r
007c44c5 558char *parse_datafile_line(char *str)\r
559{\r
560 char *ptr=strchr(str,' ');\r
561\r
562 if(ptr)\r
563 {\r
564 *ptr=0;\r
565 ptr++;\r
566 return ptr;\r
567 } \r
568 else \r
4358455e 569 {\r
007c44c5 570 return NULL;\r
4358455e 571 }\r
007c44c5 572}\r
573\r
5b902402 574\r
007c44c5 575/*-----------------------------------------------------------------*/\r
493e1ccd 576/* Are you looking for int main(int argc, char **argv) ? :-)) */\r
007c44c5 577/*-----------------------------------------------------------------*/\r
578\r
579program\r
580{\r
8e29188a 581 int i=0; /* just plain old Fortran style integer :-) */\r
582 FILE *f=NULL; /* everything is just stream of bytes... */\r
583 char *str, *ptr, *d; /* LET A$=B$ :-) */\r
007c44c5 584 char *substring;\r
1c9cae56 585\r
9a56ab25 586 int parent = 1;\r
587 int just_flush = FALSE; /* deactivates all previous actions */\r
588 int nodelay = FALSE;\r
589 int just_preview = FALSE; /* preview - generate just stats */\r
590 int start_shaping = FALSE; /* apply FUP - requires classmap file */\r
591 int just_logs = FALSE; /* just parse logs */\r
592 int run = FALSE;\r
593 int total = 0;\r
33ec95ab 594 \r
007c44c5 595 char *chain_forward, *chain_postrouting;\r
596 char *althosts=NULL;\r
597 \r
598 printf("\n\\r
599Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\\r
8e29188a 600Version %s - Copyright (C)2005-2012 Michael Polak, Arachne Labs\n\\r
43cde5c3 601iptables-restore & burst tunning & classify modification by Ludva\n\\r
0d5026c6 602Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version);\r
007c44c5 603\r
8e29188a 604 /*----- Boring... we have to check command line options first: ----*/ \r
007c44c5 605 arguments\r
606 {\r
607 argument("-c") { nextargument(config); }\r
608 argument("-h") { nextargument(althosts);}\r
208112af 609 argument("-d") { run=TRUE; dry_run=TRUE; }\r
610 argument("-f") { run=TRUE; just_flush=TRUE; }\r
611 argument("-9") { run=TRUE; just_flush=9; }\r
612 argument("-p") { run=TRUE; just_preview=TRUE; }\r
8e29188a 613 argument("-s") { run=TRUE; just_preview=TRUE; start_shaping=TRUE; }\r
208112af 614 argument("-r") { run=TRUE; }\r
615 argument("-n") { run=TRUE; nodelay=TRUE; }\r
616 argument("-l") { just_logs=TRUE; }\r
617 argument("-m") { just_logs=TRUE; }\r
618 argument("-y") { just_logs=TRUE; }\r
007c44c5 619 argument("-?") { help(); exit(0); }\r
620 argument("--help") { help(); exit(0); }\r
621 argument("-v") { exit(0); } \r
622 argument("--version") { exit(0); } \r
623 }\r
208112af 624 \r
007c44c5 625 if(dry_run)\r
208112af 626 {\r
007c44c5 627 puts("*** THIS IS JUST DRY RUN ! ***\n");\r
208112af 628 }\r
007c44c5 629\r
208112af 630 date(d); /* this is typical cll1.h macro - prints current date */\r
007c44c5 631\r
632 /*-----------------------------------------------------------------*/\r
633 printf("Parsing configuration file %s ...\n", config);\r
634 /*-----------------------------------------------------------------*/\r
635 get_config(config);\r
c9012978 636 \r
33ec95ab 637 if(just_logs)\r
c9012978 638 {\r
208112af 639 parse_ip_log(argc,argv);\r
640 exit(0);\r
641 }\r
642 else if(not run)\r
643 {\r
644 help();\r
645 exit(0);\r
c9012978 646 }\r
007c44c5 647\r
208112af 648 if(althosts)\r
649 {\r
650 hosts=althosts;\r
651 }\r
007c44c5 652\r
653 if(just_flush<9)\r
654 {\r
655 /*-----------------------------------------------------------------*/\r
656 puts("Parsing iptables verbose output ...");\r
657 /*-----------------------------------------------------------------*/\r
658 get_traffic_statistics();\r
659 }\r
660\r
661 /*-----------------------------------------------------------------*/\r
662 printf("Parsing class defintion file %s ...\n", hosts);\r
663 /*-----------------------------------------------------------------*/\r
1c9cae56 664 parse_hosts(hosts);\r
007c44c5 665\r
666 /*-----------------------------------------------------------------*/\r
667 /* cll1.h - let's allocate brand new character buffer... */\r
668 /*-----------------------------------------------------------------*/\r
669 string(str,STRLEN); \r
670\r
671 /*-----------------------------------------------------------------*/\r
672 puts("Resolving shared connections ...");\r
673 /*-----------------------------------------------------------------*/\r
6cc38f96 674 for_each(ip,ips) if(ip->sharing)\r
007c44c5 675 {\r
6cc38f96 676 for_each(sharedip,ips) if(eq(sharedip->name,ip->sharing))\r
007c44c5 677 {\r
678 sharedip->traffic+=ip->traffic;\r
679 ip->traffic=0;\r
680 ip->mark=sharedip->mark; \r
b3175d62 681 ip->lmsid=sharedip->lmsid;\r
007c44c5 682 break;\r
683 }\r
1c9cae56 684 if(not sharedip)\r
bb9e11ee 685 {\r
260c2719 686 printf("Unresolved shared connection: %s %s sharing-%s\n",\r
687 ip->addr, ip->name, ip->sharing);\r
bb9e11ee 688 }\r
007c44c5 689 }\r
690\r
691 if(enable_credit && just_flush<9)\r
692 {\r
693 /*-----------------------------------------------------------------*/\r
694 printf("Parsing credit file %s ...\n", credit);\r
695 /*-----------------------------------------------------------------*/\r
696 parse(credit)\r
697 {\r
698 ptr=parse_datafile_line(_);\r
699 if(ptr)\r
700 {\r
208112af 701 if_exists(ip,ips,eq(ip->addr,_))\r
702 {\r
007c44c5 703 sscanf(ptr,"%Lu",&(ip->credit));\r
208112af 704 }\r
007c44c5 705 }\r
706 }\r
8e29188a 707 done; /* ugly macro end */\r
007c44c5 708 }\r
709\r
710 if(!just_preview)\r
711 {\r
712 /*-----------------------------------------------------------------*/\r
713 puts("Initializing iptables and tc classes ...");\r
714 /*-----------------------------------------------------------------*/\r
715 \r
716 iptables_file=fopen(iptablesfile,"w");\r
260c2719 717 if(iptables_file == NULL)\r
bb9e11ee 718 {\r
007c44c5 719 puts("Cannot open iptablesfile!");\r
720 exit(-1);\r
721 }\r
722 \r
723 log_file=fopen(cmdlog,"w");\r
260c2719 724 if(log_file == NULL) \r
bb9e11ee 725 {\r
007c44c5 726 puts("Cannot open logfile!");\r
727 exit(-1);\r
728 }\r
729 \r
730 save_line(iptablespreamble);\r
731 run_restore();\r
732 \r
733 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,lan);\r
734 safe_run(str);\r
735\r
736 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,wan);\r
737 safe_run(str);\r
738 \r
739 iptables_file=fopen(iptablesfile,"w");\r
740 save_line(iptablespreamble);\r
741\r
742 if(qos_free_zone && *qos_free_zone!='0')\r
743 {\r
744 char *chain;\r
745 \r
746 sprintf(str,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone, wan);\r
747 save_line(str);\r
748 \r
749 if(qos_proxy)\r
750 {\r
751 save_line(":post_noproxy - [0:0]");\r
6b39193d 752 sprintf(str,"-A POSTROUTING ! -p tcp -o %s -j post_noproxy", lan);\r
007c44c5 753 save_line(str); \r
6b39193d 754 sprintf(str,"-A POSTROUTING ! -s %s -o %s -j post_noproxy", proxy_ip, lan);\r
007c44c5 755 save_line(str); \r
6b39193d 756 sprintf(str,"-A POSTROUTING -s %s -p tcp ! --sport %d -o %s -j post_noproxy", proxy_ip, proxy_port, lan);\r
007c44c5 757 save_line(str); \r
758\r
759 chain="post_noproxy"; \r
760 }\r
761 else\r
bb9e11ee 762 {\r
007c44c5 763 chain="POSTROUTING";\r
bb9e11ee 764 }\r
007c44c5 765 \r
766 sprintf(str,"-A %s -s %s -o %s -j ACCEPT", chain, qos_free_zone, lan);\r
767 save_line(str);\r
768 }\r
769 \r
770 if(ip_count>idxtable_treshold1 && !just_flush)\r
771 {\r
772 int idxcount=0, bitmask=32-idxtable_bitmask1; /* default net mask: 255.255.255.240 */\r
e0161edb 773 char *subnet, *buf;\r
007c44c5 774 /*-----------------------------------------------------------------*/\r
775 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count);\r
776 /*-----------------------------------------------------------------*/\r
777\r
778 save_line(":post_common - [0:0]");\r
779 save_line(":forw_common - [0:0]");\r
780\r
260c2719 781 for_each(ip,ips) if(ip->addr && *(ip->addr) && !eq(ip->addr,"0.0.0.0/0"))\r
007c44c5 782 {\r
b6fb849a 783 buf=index_id(ip->addr,bitmask);\r
208112af 784 if_exists(idx,idxs,eq(idx->id,buf))\r
785 {\r
007c44c5 786 idx->children++;\r
208112af 787 }\r
007c44c5 788 else\r
789 {\r
790 create(idx,Index);\r
791 idx->addr=ip->addr;\r
792 idx->id=buf;\r
793 idx->bitmask=bitmask;\r
794 idx->parent=NULL;\r
795 idx->children=0;\r
796 idxcount++;\r
797 push(idx,idxs);\r
798 }\r
799 }\r
800\r
801 /* brutal perfomance optimalization */\r
802 while(idxcount>idxtable_treshold2 && bitmask>2*idxtable_bitmask2)\r
803 {\r
804 bitmask-=idxtable_bitmask2;\r
805 idxcount=0;\r
208112af 806\r
6cc38f96 807 for_each(idx,idxs) if(idx->parent == NULL)\r
007c44c5 808 {\r
b6fb849a 809 buf=index_id(idx->addr,bitmask);\r
208112af 810 if_exists(metaindex,idxs,eq(metaindex->id,buf))\r
811 {\r
812 metaindex->children++;\r
813 }\r
007c44c5 814 else\r
815 {\r
816 create(metaindex,Index);\r
817 metaindex->addr=idx->addr;\r
818 metaindex->id=buf;\r
819 metaindex->bitmask=bitmask;\r
820 metaindex->parent=NULL;\r
821 metaindex->children=0;\r
822 idxcount++;\r
823 push(metaindex,idxs);\r
824 }\r
825 idx->parent=metaindex;\r
826 }\r
827 }\r
828\r
829 /* this should slightly optimize throughout ... */\r
830 sort(idx,idxs,desc_order_by,children);\r
831 sort(idx,idxs,order_by,bitmask);\r
832\r
833 i=0;\r
208112af 834 for_each(idx,idxs)\r
007c44c5 835 {\r
836 subnet=subnet_id(idx->addr,idx->bitmask);\r
260c2719 837 printf("%d: %s/%d\n",\r
838 ++i, subnet, idx->bitmask);\r
007c44c5 839 \r
840 sprintf(str,":post_%s - [0:0]", idx->id);\r
841 save_line(str);\r
842\r
843 sprintf(str,":forw_%s - [0:0]", idx->id);\r
844 save_line(str);\r
845\r
846 if(idx->parent)\r
847 {\r
848 string(buf,strlen(idx->parent->id)+6);\r
849 sprintf(buf,"post_%s",idx->parent->id);\r
850 }\r
851 else\r
bb9e11ee 852 {\r
007c44c5 853 buf="POSTROUTING";\r
bb9e11ee 854 }\r
007c44c5 855\r
856 sprintf(str,"-A %s -d %s/%d -o %s -j post_%s", buf, subnet, idx->bitmask, lan, idx->id);\r
857 save_line(str);\r
858\r
859 sprintf(str,"-A %s -d %s/%d -o %s -j post_common", buf, subnet, idx->bitmask, lan);\r
860 save_line(str);\r
861\r
862 if(idx->parent)\r
863 {\r
864 string(buf,strlen(idx->parent->id)+6);\r
865 sprintf(buf,"forw_%s",idx->parent->id);\r
866 }\r
867 else\r
bb9e11ee 868 {\r
007c44c5 869 buf="FORWARD";\r
bb9e11ee 870 }\r
007c44c5 871\r
872 sprintf(str,"-A %s -s %s/%d -o %s -j forw_%s", buf, subnet, idx->bitmask, wan, idx->id);\r
873 save_line(str);\r
874\r
875 sprintf(str,"-A %s -s %s/%d -o %s -j forw_common", buf, subnet, idx->bitmask, wan);\r
876 save_line(str);\r
877 }\r
878 printf("Total indexed iptables chains created: %d\n", i);\r
879\r
880 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);\r
881 save_line(str);\r
882 \r
883 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);\r
884 save_line(str);\r
885 }\r
886 \r
887 }\r
888\r
889 if(just_flush)\r
890 {\r
891 fclose(iptables_file);\r
add90548 892 if(log_file)\r
893 { \r
894 fclose(log_file);\r
895 }\r
007c44c5 896 puts("Just flushed iptables and tc classes - now exiting ...");\r
897 exit(0);\r
898 }\r
899\r
900 if(!just_preview)\r
901 {\r
902 if(!dry_run && !nodelay && qos_free_delay)\r
903 {\r
904 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay);\r
905 sleep(qos_free_delay);\r
906 }\r
907\r
6cc38f96 908 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",\r
909 tc,lan,htb_r2q);\r
007c44c5 910 safe_run(str);\r
911\r
208112af 912 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
913 tc,lan,lan_medium,lan_medium,burst_main,highest_priority);\r
007c44c5 914 safe_run(str);\r
915\r
208112af 916 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
917 tc,lan,line,line,burst_main,highest_priority);\r
007c44c5 918 safe_run(str);\r
919\r
920 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc,wan,htb_r2q);\r
921 safe_run(str);\r
922\r
208112af 923 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
924 tc,wan,wan_medium,wan_medium,burst_main,highest_priority);\r
007c44c5 925 safe_run(str);\r
926\r
208112af 927 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
928 tc,wan,up,up,burst_main,highest_priority);\r
007c44c5 929 safe_run(str);\r
930 }\r
931\r
932 /*-----------------------------------------------------------------*/\r
208112af 933 puts("Locating heavy downloaders and generating root classes ...");\r
007c44c5 934 /*-----------------------------------------------------------------*/\r
bb9e11ee 935 sort(ip,ips,desc_order_by,traffic); \r
007c44c5 936\r
937 /*-----------------------------------------------------------------*/\r
938 /* sub-scope - local variables */ \r
939 {\r
6cc38f96 940 long long int rate = line;\r
941 long long int max = line;\r
942 int group_count = 0;\r
943 FILE *credit_file = NULL;\r
007c44c5 944 \r
4358455e 945 if(!just_preview && !dry_run && enable_credit)\r
946 {\r
6cc38f96 947 credit_file = fopen(credit,"w");\r
4358455e 948 }\r
007c44c5 949 \r
208112af 950 for_each(group,groups)\r
007c44c5 951 {\r
952 if(!just_preview)\r
953 {\r
007c44c5 954 //download\r
208112af 955 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
956 tc, lan, parent, group->id, rate, max, burst_group, highest_priority+1, group->desired);\r
007c44c5 957 safe_run(str);\r
958 \r
959 //upload\r
208112af 960 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
961 tc, wan, parent, group->id, rate*up/line, max*up/line, burst_group, highest_priority+1, group->desired);\r
007c44c5 962 safe_run(str);\r
963 }\r
964 \r
6cc38f96 965 if(group_count++ < max_nesting)\r
bb9e11ee 966 {\r
6cc38f96 967 parent = group->id;\r
bb9e11ee 968 }\r
007c44c5 969 \r
6cc38f96 970 rate -= digital_divide*group->min;\r
971 if(rate < group->min)\r
4358455e 972 {\r
6cc38f96 973 rate = group->min;\r
4358455e 974 }\r
007c44c5 975 \r
976 /*shaping of aggresive downloaders, with credit file support */\r
977 if(use_credit)\r
978 {\r
6cc38f96 979 int group_rate = group->min, priority_sequence = lowest_priority;\r
007c44c5 980 \r
6cc38f96 981 for_each(ip, ips) if(ip->min == group->min && ip->max > ip->min)\r
007c44c5 982 {\r
e48d46c9 983 ip->realquota=ip->credit+(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20));\r
984 if( ip->keyword->data_limit \r
985 and not ip->fixedprio \r
986 and ip->traffic > ip->realquota )\r
007c44c5 987 {\r
e48d46c9 988 if(group_rate < ip->max)\r
4358455e 989 {\r
e48d46c9 990 ip->max = group_rate;\r
4358455e 991 }\r
007c44c5 992 group_rate+=magic_treshold;\r
208112af 993 ip->prio=lowest_priority;\r
4358455e 994 if(ip->prio<highest_priority+2)\r
995 {\r
996 ip->prio=highest_priority+2;\r
997 }\r
007c44c5 998 }\r
999 else\r
1000 {\r
6cc38f96 1001 if( ip->keyword->data_prio \r
1002 && !ip->fixedprio \r
1003 && ( ip->traffic>ip->credit\r
1004 + (ip->min*ip->keyword->data_prio+(ip->keyword->fixed_prio<<20))) )\r
007c44c5 1005 {\r
1006 ip->prio=priority_sequence--;\r
4358455e 1007 if(ip->prio<highest_priority+1)\r
1008 {\r
1009 ip->prio=highest_priority+1;\r
1010 }\r
007c44c5 1011 }\r
1012 \r
1013 if(credit_file)\r
1014 {\r
1015 unsigned long long lcredit=0;\r
99127c70 1016 \r
4358455e 1017 if((ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))>ip->traffic)\r
1018 {\r
007c44c5 1019 lcredit=(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))-ip->traffic;\r
4358455e 1020 }\r
007c44c5 1021 fprintf(credit_file,"%s %Lu\n",ip->addr,lcredit);\r
1022 }\r
1023 }\r
6cc38f96 1024 } \r
007c44c5 1025 }\r
1026 }\r
4358455e 1027 if(credit_file)\r
1028 {\r
1029 fclose(credit_file);\r
1030 }\r
007c44c5 1031 }\r
1032\r
1033 if(just_preview)\r
1034 {\r
8e29188a 1035 if(start_shaping)\r
1036 {\r
1037 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap);\r
1038 parse(classmap)\r
1039 {\r
1040 ptr=strchr(_,' ');\r
1041 if(ptr)\r
1042 {\r
1043 *ptr=0;\r
1044 ptr++;\r
1045 if_exists(ip,ips,eq(ip->addr,_))\r
1046 {\r
1047 ip->mark=atoi(ptr);\r
1048 if(ip->max < ip->desired) /* apply FUP limit immediately.... */\r
1049 {\r
1050 printf("Applying limit for %-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
1051 printf("(down: %dk-%dk ", ip->min, ip->max); \r
1052 sprintf(str, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
1053 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
1054 safe_run(str);\r
1055 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1056 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
1057 sprintf(str,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1058 tc, wan, ip->group, ip->mark,\r
1059 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1060 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1061 safe_run(str);\r
1062 }\r
1063 }\r
1064 }\r
1065 }\r
1066 fail\r
1067 { \r
1068 perror(classmap);\r
1069 puts("Warning - classmap file not fund, just generating preview ...");\r
1070 start_shaping=FALSE;\r
1071 }\r
1072 done; /* ugly macro end */\r
1073 }\r
6fb3c58a 1074 html=preview;\r
1ab008b9 1075 json_traffic=json_preview;\r
007c44c5 1076 }\r
6fb3c58a 1077\r
1078 if(!dry_run && !just_flush)\r
007c44c5 1079 {\r
1080 /*-----------------------------------------------------------------*/\r
1ab008b9 1081 printf("Writing json traffic overview %s ... ", json_traffic);\r
007c44c5 1082 /*-----------------------------------------------------------------*/\r
1ab008b9 1083 write_json_traffic(json_traffic);\r
007c44c5 1084 }\r
1085\r
9a56ab25 1086 /*-----------------------------------------------------------------*/\r
1087 printf("Writing statistics into HTML page %s ...\n", html);\r
1088 /*-----------------------------------------------------------------*/\r
0db8e993 1089 write_htmlandlogs(html, d,total, just_preview);\r
007c44c5 1090\r
1091 if(just_preview)\r
1092 {\r
8e29188a 1093 char swchar='p';\r
1094 if(start_shaping)\r
1095 {\r
1096 swchar='s';\r
1097 }\r
1098 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar);\r
007c44c5 1099 exit(0);\r
be96b71b 1100 } \r
007c44c5 1101\r
1102 i=0;\r
260c2719 1103#ifdef DEBUG\r
007c44c5 1104 printf("%-22s %-15s mark\n","name","ip");\r
260c2719 1105#endif\r
208112af 1106\r
be96b71b 1107 printf("Writing %s ... ", classmap); \r
1108 f = fopen(classmap, "w"); \r
1109 if(f < 0)\r
1110 {\r
1111 perror(classmap);\r
1112 }\r
1113\r
1114 /*-----------------------------------------------------------------*/\r
1115 puts("Generating iptables and tc classes ... ");\r
1116 /*-----------------------------------------------------------------*/\r
1117\r
1118 for_each(ip, ips) if(ip->mark > 0)\r
1119 {\r
007c44c5 1120 if(idxs)\r
1121 {\r
1122 char *buf;\r
1123 duplicate(ip->addr,buf);\r
b6fb849a 1124 buf=index_id(ip->addr,32-idxtable_bitmask1); \r
007c44c5 1125 \r
1126 string(chain_forward,6+strlen(buf));\r
1127 strcpy(chain_forward,"forw_");\r
1128 strcat(chain_forward,buf);\r
1129\r
1130 string(chain_postrouting,6+strlen(buf));\r
1131 strcpy(chain_postrouting,"post_");\r
1132 strcat(chain_postrouting,buf);\r
1133 \r
1134 free(buf);\r
1135 }\r
1136 else\r
1137 {\r
1138 chain_forward="FORWARD";\r
1139 chain_postrouting="POSTROUTING";\r
1140 }\r
1141\r
260c2719 1142#ifdef DEBUG\r
007c44c5 1143 printf("%-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
260c2719 1144#endif\r
007c44c5 1145\r
1146 /* -------------------------------------------------------- mark download */\r
1147 \r
be96b71b 1148 sprintf(str, "-A %s -d %s/32 -o %s -j %s%d",\r
1149 chain_postrouting, ip->addr, lan, mark_iptables, ip->mark);\r
007c44c5 1150 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/\r
1151 /* -m limit --limit 1/s */ \r
1152 save_line(str);\r
1153\r
1154 if(qos_proxy)\r
1155 {\r
be96b71b 1156 sprintf(str, "-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",\r
1157 chain_postrouting, proxy_ip, proxy_port, ip->addr, lan, mark_iptables, ip->mark);\r
007c44c5 1158 /*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
1159 save_line(str);\r
1160 }\r
1161\r
be96b71b 1162 sprintf(str, "-A %s -d %s/32 -o %s -j ACCEPT",\r
1163 chain_postrouting, ip->addr, lan);\r
007c44c5 1164 save_line(str);\r
1165\r
1166 /* -------------------------------------------------------- mark upload */\r
be96b71b 1167 sprintf(str, "-A %s -s %s/32 -o %s -j %s%d", \r
1168 chain_forward, ip->addr, wan, mark_iptables, ip->mark);\r
007c44c5 1169 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/\r
1170 save_line(str);\r
1171\r
be96b71b 1172 sprintf(str, "-A %s -s %s/32 -o %s -j ACCEPT",\r
1173 chain_forward, ip->addr, wan);\r
007c44c5 1174 save_line(str);\r
1175\r
1176 if(ip->min)\r
1177 {\r
1178 /* -------------------------------------------------------- download class */\r
260c2719 1179#ifdef DEBUG\r
007c44c5 1180 printf("(down: %dk-%dk ", ip->min, ip->max); \r
260c2719 1181#endif\r
007c44c5 1182\r
be96b71b 1183 sprintf(str, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
1184 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
007c44c5 1185 safe_run(str);\r
1186\r
260c2719 1187 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
dee5592e 1188 {\r
be96b71b 1189 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s", \r
1190 tc, lan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
dee5592e 1191 safe_run(str);\r
be96b71b 1192 }\r
1193\r
260c2719 1194 if(filter_type == 1)\r
dee5592e 1195 {\r
be96b71b 1196 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
1197 tc, lan, ip->mark, ip->mark);\r
dee5592e 1198 safe_run(str);\r
007c44c5 1199 }\r
1200\r
1201 /* -------------------------------------------------------- upload class */\r
260c2719 1202#ifdef DEBUG\r
007c44c5 1203 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1204 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
260c2719 1205#endif\r
007c44c5 1206\r
1207 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1208 tc, wan, ip->group, ip->mark,\r
1209 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1210 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1211 safe_run(str);\r
1212 \r
260c2719 1213 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
dee5592e 1214 {\r
be96b71b 1215 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s",\r
1216 tc, wan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
dee5592e 1217 safe_run(str);\r
1218 } \r
be96b71b 1219\r
260c2719 1220 if(filter_type == 1)\r
dee5592e 1221 {\r
be96b71b 1222 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
1223 tc, wan, ip->mark, ip->mark);\r
dee5592e 1224 safe_run(str);\r
007c44c5 1225 }\r
be96b71b 1226 \r
6fb3c58a 1227 if(f > 0)\r
be96b71b 1228 {\r
457d52f2 1229 fprintf(f, "%s %d\n", ip->addr, ip->mark);\r
be96b71b 1230 }\r
007c44c5 1231 }\r
1232 else\r
260c2719 1233 {\r
1234#ifdef DEBUG\r
007c44c5 1235 printf("(sharing %s)\n", ip->sharing);\r
260c2719 1236#endif\r
1237 }\r
007c44c5 1238 i++;\r
1239 }\r
6fb3c58a 1240 if(f > 0)\r
be96b71b 1241 {\r
1242 puts("done.");\r
1243 fclose(f);\r
1244 }\r
1245 \r
007c44c5 1246 if(idxs)\r
1247 {\r
dee5592e 1248 chain_forward = "forw_common";\r
1249 chain_postrouting = "post_common";\r
007c44c5 1250 }\r
1251 else\r
1252 {\r
dee5592e 1253 chain_forward = "FORWARD";\r
1254 chain_postrouting = "POSTROUTING";\r
007c44c5 1255 }\r
dee5592e 1256 /* -------------------------------- classify or reject free download */\r
007c44c5 1257 {\r
b6a8d473 1258 char *final_chain = "DROP"; /* REJECT would be better, but it is impossible in mangle */\r
be96b71b 1259 if(free_min)\r
1260 {\r
1261 final_chain = "ACCEPT";\r
1262 }\r
dee5592e 1263 if(qos_proxy)\r
1264 {\r
1265 if(free_min)\r
1266 {\r
be96b71b 1267 sprintf(str,"-A %s -s %s -p tcp --sport %d -o %s -j %s%d",\r
1268 chain_postrouting,proxy_ip,proxy_port,lan,mark_iptables,3);\r
dee5592e 1269 save_line(str);\r
1270 }\r
be96b71b 1271 sprintf(str,"-A %s -s %s -p tcp --sport %d -o %s -j %s",\r
1272 chain_postrouting,proxy_ip,proxy_port,lan,final_chain);\r
dee5592e 1273 save_line(str);\r
1274 }\r
1275 if(free_min)\r
1276 {\r
be96b71b 1277 sprintf(str,"-A %s -o %s -j %s%d", chain_postrouting, lan, mark_iptables, 3);\r
dee5592e 1278 save_line(str);\r
1279 }\r
be96b71b 1280 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
dee5592e 1281 save_line(str);\r
1282 /* ------------------------------- classify or reject free upload */\r
1283 if(free_min)\r
1284 {\r
be96b71b 1285 sprintf(str,"-A %s -o %s -j %s%d", chain_forward, wan, mark_iptables, 3);\r
dee5592e 1286 save_line(str);\r
1287 }\r
be96b71b 1288 sprintf(str,"-A %s -o %s -j %s", chain_forward, wan, final_chain);\r
dee5592e 1289 save_line(str);\r
007c44c5 1290 }\r
abe9b855 1291\r
dee5592e 1292 if(free_min) /* allocate free bandwith if it is not zero... */ \r
1293 {\r
1294 /*-----------------------------------------------------------------*/\r
1295 puts("Generating free bandwith classes ...");\r
1296 /*-----------------------------------------------------------------*/\r
208112af 1297 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
be96b71b 1298 tc, lan, parent, free_min, free_max,burst, lowest_priority);\r
dee5592e 1299 safe_run(str);\r
208112af 1300 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
be96b71b 1301 tc, wan, parent, free_min, free_max, burst, lowest_priority);\r
dee5592e 1302 safe_run(str);\r
1303 /* tc SFQ */\r
260c2719 1304 if(strcmpi(qos_leaf, "none"))\r
dee5592e 1305 {\r
be96b71b 1306 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, lan, qos_leaf);\r
dee5592e 1307 safe_run(str);\r
1308 \r
be96b71b 1309 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, wan, qos_leaf);\r
dee5592e 1310 safe_run(str);\r
1311 } \r
1312 /* tc handle 1 fw flowid */\r
be96b71b 1313 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, lan);\r
dee5592e 1314 safe_run(str);\r
007c44c5 1315\r
be96b71b 1316 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, wan);\r
dee5592e 1317 safe_run(str);\r
007c44c5 1318 }\r
dee5592e 1319 printf("Total IP count: %d\n", i);\r
1320 run_restore(); \r
260c2719 1321 if(log_file)\r
1322 {\r
1323 fclose(log_file);\r
1324 }\r
007c44c5 1325 return 0;\r
007c44c5 1326 /* that's all folks, thank you for reading it all the way up to this point ;-) */\r
1327 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */\r
1328}\r
This page took 1.435204 seconds and 4 git commands to generate.