ip protocol usage statistics and more
[svn/Prometheus-QoS/.git] / prometheus.c
CommitLineData
068f0e75 1/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
0b9c3c19 2/* Prometheus QoS - you can "steal fire" from your ISP *//* "fair-per-IP" quality of service (QoS) utility */\r
068f0e75 3/* requires Linux 2.4.x or 2.6.x with HTB support */\r
4/* Copyright(C) 2005-2013 Michael Polak, Arachne Aerospace */\r
5/* iptables-restore support Copyright(C) 2007-2008 ludva */\r
6/* Credit: CZFree.Net,Martin Devera,Netdave,Aquarius,Gandalf */\r
7/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
8\r
0b9c3c19 9/* Modified by: xChaos, 20130124\r
a031788f 10 ludva, 20080415\r
208112af 11 \r
007c44c5 12 Prometheus QoS is free software; you can redistribute it and/or\r
13 modify it under the terms of the GNU General Public License as \r
14 published by the Free Software Foundation; either version 2.1 of \r
15 the License, or (at your option) any later version.\r
16\r
17 Prometheus QoS is distributed in the hope that it will be useful,\r
18 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
20 General Public License for more details.\r
21\r
c9012978 22 You should have received a copy of the GNU General Public License\r
23 along with Prometheus Qos; if not, write to the Free Software\r
d1ae4fa7 24 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA \r
25 \r
c9012978 26 GNU General Public License is located in file COPYING */\r
007c44c5 27\r
208112af 28#include "cll1-0.6.2.h"\r
1c9cae56 29#include "ipstruct.h"\r
007c44c5 30\r
0b9c3c19 31const char *version = "0.8.3-i";\r
007c44c5 32\r
068f0e75 33/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
34/* Versions: 0.8.3 is development release, 0.8.4 will be "stable" */\r
35/* Official Trac URL: https://dev.arachne.cz/svn/prometheus */\r
36/* Official SVN URL: https://dev.arachne.cz/repos/prometheus */\r
37/* BTC donations account: 19rriLx8vR19wGefPaMhakqnCYNYwjLvxq */\r
38/* CZK donations account: 2900242944/2010 (transparent account) */\r
39/* Warning: unofficial Github mirror is not supported by author! */\r
40/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
77e71d6b 41\r
3bf40f9b 42const char *stats_html_signature = "<span class=\"small\">Statistics generated by Prometheus QoS version %s<br />GPL+Copyright(C)2005-2013 Michael Polak, <a target=\"_blank\" href=\"http://www.arachne.cz/\">Arachne Labs</a></span>\n";\r
2d114137 43\r
068f0e75 44#define STRLEN 512\r
45#undef DEBUG\r
46\r
82c702a1 47/* ======= All path names are defined here (for RPM patch) ======= */\r
ae776b10 48\r
f19d3cd0 49const char *tc = "/sbin/tc"; /* requires tc with HTB support */\r
50const char *iptables = "/sbin/iptables"; /* requires iptables utility */\r
51const char *ip6tables = "/sbin/ip6tables"; /* requires iptables utility */\r
52const char *iptablessave = "/sbin/iptables-save"; /* not yet required */\r
53const char *iptablesrestore = "/sbin/iptables-restore"; /* requires iptables-restore */\r
54const char *ip6tablessave = "/sbin/ip6tables-save"; /* not yet required */\r
55const char *ip6tablesrestore = "/sbin/ip6tables-restore"; /* requires iptables-restore */\r
56const char *ls = "/bin/ls"; /* this is not user configurable :-) */\r
ae776b10 57\r
2d114137 58char *config = "/etc/prometheus/prometheus.conf"; /* main configuration file */\r
59char *hosts = "/etc/prometheus/hosts"; /* per-IP bandwidth definition file */\r
2d114137 60char *iptablesfile = "/var/spool/prometheus.iptables"; /* temporary file for iptables-restore*/\r
f64d5431 61char *ip6tablesfile = "/var/spool/prometheus.ip6tables"; /* temporary file for ip6tables-restore*/\r
2d114137 62char *credit = "/var/lib/misc/prometheus.credit"; /* credit log file */\r
be96b71b 63char *classmap = "/var/lib/misc/prometheus.classes"; /* credit log file */\r
64char *html = "/var/www/traffic.html"; /* hall of fame - html version */\r
6fb3c58a 65char *preview = "/var/www/preview.html"; /* hall of fame preview - html version */\r
1ab008b9 66char *json_traffic = "/var/www/logs/traffic.json"; /* hall of fame - json version */\r
6fb3c58a 67char *json_preview = "/var/www/logs/preview.json"; /* hall of fame preview - json version */\r
2d114137 68char *cmdlog = "/var/log/prometheuslog"; /* command log filename */\r
69char *log_dir = "/var/www/logs/"; /* log directory pathname, ended with slash */\r
8bcc3268 70char *log_url = "/logs/"; /* log directory relative URI prefix (partial URL) */\r
2d114137 71char *html_log_dir = "/var/www/logs/html/";\r
ae776b10 72\r
6cc38f96 73char *jquery_url = "http://code.jquery.com/jquery-latest.js";\r
74char *lms_url = "/lms/?m=customerinfo&amp;id=";\r
9a56ab25 75int use_jquery_popups = TRUE;\r
9aa195f6 76int row_odd_even = 0; /*<tr class="odd/even"> */\r
b6fb849a 77 \r
007c44c5 78/* === Configuraration file values defaults - stored in global variables ==== */\r
79\r
43cde5c3 80int filter_type = 1; /*1 mark, 2 classify*/\r
0b9c3c19 81char *final_chain = "DROP"; /* REJECT would be better, but it is impossible in mangle */\r
43cde5c3 82char *mark = "MARK";\r
83char *mark_iptables = "MARK --set-mark ";\r
9a56ab25 84int dry_run = FALSE; /* preview - use puts() instead of system() */\r
43cde5c3 85char *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
0995c4ad 86char *ip6preamble = "-A FORWARD -p ipv6-icmp -j ACCEPT\n-A POSTROUTING -p ipv6-icmp -j ACCEPT\n-A FORWARD -s fe80::/10 -j ACCEPT\n-A FORWARD -d ff00::/8 -j ACCEPT\n-A POSTROUTING -s fe80::/10 -j ACCEPT\n-A POSTROUTING -d ff00::/8 -j ACCEPT";\r
43cde5c3 87FILE *iptables_file = NULL;\r
0b9c3c19 88FILE *ip6tables_file = NULL;\r
9a56ab25 89int enable_credit = TRUE; /* enable credit file */\r
90int use_credit = FALSE; /* use credit file (if enabled)*/\r
43cde5c3 91char *title = "Hall of Fame - Greatest Suckers"; /* hall of fame title */\r
9a56ab25 92int hall_of_fame = TRUE; /* enable hall of fame */\r
43cde5c3 93char *lan = "eth0"; /* LAN interface */\r
94char *lan_medium = "100Mbit"; /* 10Mbit/100Mbit ethernet */\r
95char *wan = "eth1"; /* WAN/ISP interface */\r
f64d5431 96char *ip6prefix = NULL; /* Prefix for global /48 IPv6 subnet */\r
43cde5c3 97char *wan_medium = "100Mbit"; /* 10Mbit/100Mbit ethernet */\r
98char *qos_leaf = "sfq perturb 5"; /* leaf discipline */\r
99char *qos_free_zone = NULL; /* QoS free zone */\r
9a56ab25 100int qos_proxy = TRUE; /* include proxy port to QoS */\r
101int found_lmsid = FALSE; /* show links to users in LMS information system */\r
102int include_upload = TRUE; /* upload+download=total traffic */\r
43cde5c3 103char *proxy_ip = "192.168.1.1/32"; /* our IP with proxy port */\r
104int proxy_port = 3128; /* proxy port number */\r
105long long int line = 1024; /* WAN/ISP download in kbps */\r
106long long int up = 1024; /* WAN/ISP upload in kbps */\r
0b9c3c19 107int free_min = 256; /* minimum guaranted bandwidth for all undefined hosts */\r
108int free_max = 512; /* maximum allowed bandwidth for all undefined hosts */\r
43cde5c3 109int qos_free_delay = 0; /* seconds to sleep before applying new QoS rules */\r
110int digital_divide = 2; /* controls digital divide weirdness ratio, 1...3 */ \r
111int max_nesting = 3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */\r
208112af 112int htb_r2q = 256; /* should work for leaf values 512 kbps to 8 Mbps */\r
43cde5c3 113int burst = 8; /* HTB burst (in kbits) */\r
114int burst_main = 64;\r
115int burst_group = 32;\r
43cde5c3 116int magic_treshold = 8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */\r
117int keywordcount = 0;\r
9a56ab25 118int class_count = 0;\r
119int ip_count = 0;\r
007c44c5 120/* not yet implemented:\r
43cde5c3 121int fixed_packets = 0; maximum number of pps per IP address (not class!) \r
122int packet_limit = 5; maximum number of pps to htn CEIL, not rate !!! \r
007c44c5 123*/\r
43cde5c3 124FILE *log_file = NULL;\r
125char *kwd = "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */\r
007c44c5 126\r
208112af 127const int highest_priority = 0; /* highest HTB priority (HTB built-in value is 0) */\r
128const int lowest_priority = 7; /* lowest HTB priority (HTB built-in value is 7) */\r
129const int idxtable_treshold1 = 24; /* this is no longer configurable */\r
130const int idxtable_treshold2 = 12; /* this is no longer configurable */\r
131const int idxtable_bitmask1 = 3; /* this is no longer configurable */\r
132const int idxtable_bitmask2 = 3; /* this is no longer configurable */\r
007c44c5 133\r
1c9cae56 134struct IP *ips = NULL, *ip, *sharedip;\r
135struct Group *groups = NULL, *group;\r
136struct Keyword *keyword, *defaultkeyword=NULL, *keywords=NULL;\r
007c44c5 137\r
068f0e75 138void help(void);\r
139/* implemented in help.c */
140\r
d7357b63 141void get_traffic_statistics(const char *whichiptables, int ipv6);\r
f19d3cd0 142/* implemented in parseiptables.c */\r
143\r
b6fb849a 144void parse_ip_log(int argc, char **argv);\r
1ab008b9 145/* implemented in parselog.c */\r
b6fb849a 146\r
147void parse_hosts(char *hosts);\r
1ab008b9 148/* implemented in parsehosts.c */\r
149\r
150void write_json_traffic(char *json);\r
151/* implemented in json.c */\r
b6fb849a 152\r
9a56ab25 153void write_htmlandlogs(char *html, char *d, int total, int just_preview);\r
154/* implemented in htmlandlogs.c */\r
155\r
b6fb849a 156const char *tr_odd_even(void)\r
157{\r
158 row_odd_even = 1 - row_odd_even;\r
159 if(row_odd_even)\r
160 {\r
161 return "<tr class=\"even\">\n";\r
162 }\r
163 else\r
164 {\r
165 return "<tr class=\"odd\">\n";\r
166 }\r
167}\r
168\r
1c9cae56 169/* ==== This is C<<1 stuff - learn C<<1 first! https://dev.arachne.cz/svn/cll1h ==== */\r
068f0e75 170/* (except that this code uses obsolete, archaic version of this header file...) */\r
007c44c5 171\r
172struct Index\r
173{\r
174 char *addr;\r
175 char *id;\r
176 struct Index *parent;\r
177 int bitmask;\r
178 int children;\r
0b9c3c19 179 int ipv6;\r
007c44c5 180 list(Index);\r
181} *idxs=NULL, *idx, *metaindex;\r
182\r
007c44c5 183\r
5b902402 184/* ====== iptables indexes are used to reduce complexity to log8(N) ===== */\r
007c44c5 185\r
59c3032e 186char *index_id(char *ip, int bitmask);\r
187/* function implemented in ipv4subnets.c */\r
007c44c5 188\r
59c3032e 189char *subnet_id(char *ip, int bitmask);\r
190/* function implemented in ipv4subnets.c */\r
007c44c5 191\r
0b9c3c19 192char *index6_id(char *ip, int bitmask);\r
193/* function implemented in ipv6subnets.c */\r
194\r
195char *subnet6_id(char *ip, int bitmask);\r
196/* function implemented in ipv6subnets.c */\r
197\r
59c3032e 198/* ================= Let's parse configuration file here ================ */\r
007c44c5 199\r
200void reject_config_and_exit(char *filename)\r
201{\r
202 printf("Configuration file %s rejected - abnormal exit.",filename);\r
203 exit(-1);\r
204}\r
205\r
206void get_config(char *config_filename)\r
207{\r
208 char *cnf="mark";\r
209 \r
210 printf("Configured keywords: ");\r
211 parse(config_filename)\r
212 {\r
213 option("keyword",kwd);\r
214 if(kwd)\r
215 {\r
216 printf("%s ",kwd);\r
217\r
218 create(keyword,Keyword);\r
219 keyword->key=kwd;\r
220 keyword->asymetry_ratio=1; /* ratio for ADSL-like upload */\r
221 keyword->asymetry_fixed=0; /* fixed treshold for ADSL-like upload */\r
222 keyword->data_limit=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */\r
208112af 223 keyword->data_prio=4; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */\r
007c44c5 224 keyword->fixed_limit=0; /* fixed data limit for setting lower HTB ceil */\r
225 keyword->fixed_prio=0; /* fixed data limit for setting lower HTB prio */\r
226 keyword->reserve_min=8; /* bonus for nominal HTB rate bandwidth (in kbps) */\r
227 keyword->reserve_max=0; /* malus for nominal HTB ceil (in kbps) */\r
208112af 228 keyword->default_prio=highest_priority+1;\r
007c44c5 229 keyword->html_color="000000";\r
230 keyword->ip_count=0;\r
231 keyword->leaf_discipline="";\r
232\r
233 push(keyword,keywords);\r
4d41c1e4 234 if(!defaultkeyword)\r
235 {\r
236 defaultkeyword=keyword;\r
237 }\r
007c44c5 238 keywordcount++;\r
239 \r
240 kwd=NULL;\r
241 }\r
208112af 242 else\r
007c44c5 243 {\r
208112af 244 for_each(keyword,keywords)\r
245 {\r
246 int l=strlen(keyword->key);\r
007c44c5 247\r
208112af 248 if(!strncmp(keyword->key,_,l) && strlen(_)>l+2)\r
249 {\r
250 char *tmptr=_; /* <---- l+1 ----> */\r
251 _+=l+1; /* via-prometheus-asymetry-ratio, etc. */\r
252 ioption("asymetry-ratio",keyword->asymetry_ratio);\r
253 ioption("asymetry-treshold",keyword->asymetry_fixed);\r
254 ioption("magic-relative-limit",keyword->data_limit);\r
255 ioption("magic-relative-prio",keyword->data_prio);\r
256 loption("magic-fixed-limit",keyword->fixed_limit);\r
257 loption("magic-fixed-prio",keyword->fixed_prio);\r
258 ioption("htb-default-prio",keyword->default_prio);\r
259 ioption("htb-rate-bonus",keyword->reserve_min);\r
260 ioption("htb-ceil-malus",keyword->reserve_max);\r
208112af 261 option("leaf-discipline",keyword->leaf_discipline);\r
262 option("html-color",keyword->html_color);\r
263 _=tmptr;\r
264 \r
265 if(keyword->data_limit || keyword->fixed_limit || \r
266 keyword->data_prio || keyword->fixed_prio)\r
bb9e11ee 267 {\r
268 use_credit=1; \r
269 }\r
208112af 270 }\r
271 }\r
007c44c5 272 }\r
273\r
274 option("tc",tc);\r
275 option("iptables",iptables);\r
f64d5431 276 option("iptables-save",iptablessave);\r
277 option("iptables-restore",iptablesrestore);\r
f19d3cd0 278 option("ip6tables",ip6tables);\r
f64d5431 279 option("ip6tables-save",ip6tablessave);\r
280 option("ip6tables-restore",ip6tablesrestore);\r
281 option("iptables-in-filename",iptablesfile);\r
282 option("ip6tables-in-filename",ip6tablesfile);\r
007c44c5 283 option("hosts",hosts);\r
284 option("lan-interface",lan);\r
285 option("wan-interface",wan);\r
f64d5431 286 option("ip6-prefix",ip6prefix);\r
007c44c5 287 option("lan-medium",lan_medium);\r
288 option("wan-medium",wan_medium);\r
289 lloption("wan-download",line);\r
290 lloption("wan-upload",up);\r
291 ioption("hall-of-fame-enable",hall_of_fame);\r
292 option("hall-of-fame-title",title);\r
293 option("hall-of-fame-filename",html);\r
1ab008b9 294 option("json-filename",json_traffic);\r
007c44c5 295 option("hall-of-fame-preview",preview);\r
6fb3c58a 296 option("json-preview",json_preview);\r
007c44c5 297 option("log-filename",cmdlog);\r
298 option("credit-filename",credit);\r
be96b71b 299 option("classmap-filename",classmap);\r
007c44c5 300 ioption("credit-enable",enable_credit);\r
301 option("log-traffic-directory",log_dir);\r
5b902402 302 option("log-traffic-html-directory",html_log_dir);\r
007c44c5 303 option("log-traffic-url-path",log_url);\r
6cc38f96 304 option("jquery-url",jquery_url);\r
305 option("lms-url",lms_url);\r
306 ioption("use-jquery-popups",use_jquery_popups);\r
007c44c5 307 option("qos-free-zone",qos_free_zone);\r
308 ioption("qos-free-delay",qos_free_delay);\r
309 ioption("qos-proxy-enable",qos_proxy);\r
310 option("qos-proxy-ip",proxy_ip);\r
311 option("htb-leaf-discipline",qos_leaf);\r
312 ioption("qos-proxy-port",proxy_port);\r
313 ioption("free-rate",free_min);\r
314 ioption("free-ceil",free_max);\r
315 ioption("htb-burst",burst);\r
316 ioption("htb-burst-main",burst_main);\r
317 ioption("htb-burst-group",burst_group);\r
318 ioption("htb-nesting-limit",max_nesting);\r
319 ioption("htb-r2q",htb_r2q);\r
320 ioption("magic-include-upload",include_upload);\r
5b902402 321 ioption("magic-treshold",magic_treshold); \r
260c2719 322 option("filter-type", cnf); \r
007c44c5 323/* not yet implemented:\r
324 ioption("magic-fixed-packets",fixed_packets);\r
325 ioption("magic-relative-packets",packet_limit);\r
326*/\r
327 }\r
328 fail\r
329 { \r
330 perror(config_filename);\r
331 puts("Warning - using built-in defaults instead ...");\r
332 }\r
8e29188a 333 done; /* ugly macro end */\r
007c44c5 334 printf("\n");\r
335 \r
be96b71b 336 /* leaf discipline for keywords */\r
208112af 337 for_each(keyword,keywords)\r
007c44c5 338 {\r
260c2719 339 if(!strcmpi(keyword->leaf_discipline, ""))\r
208112af 340 {\r
007c44c5 341 keyword->leaf_discipline = qos_leaf;\r
342 }\r
343 }\r
344\r
260c2719 345 if(strcmpi(cnf, "mark"))\r
bb9e11ee 346 {\r
347 filter_type = 2;\r
348 mark = "CLASSIFY";\r
349 mark_iptables = "CLASSIFY --set-class 1:";\r
350 }\r
351 else\r
352 {\r
353 filter_type = 1;\r
354 mark = "MARK";\r
355 mark_iptables = "MARK --set-mark ";\r
007c44c5 356 }\r
357\r
358 /* are supplied values meaningful ?*/\r
359 if(line<=0 || up<=0)\r
360 {\r
b1b59b3a 361 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");\r
007c44c5 362 reject_config_and_exit(config_filename);\r
363 }\r
364}\r
365\r
007c44c5 366 \r
367/* ========== This function executes, logs OR ALSO prints command ========== */\r
368\r
369void safe_run(char *cmd)\r
370{\r
a1d21464 371 if(dry_run)\r
372 {\r
373 printf("\n=>%s\n",cmd);\r
374 }\r
375 else\r
376 {\r
377 system(cmd);\r
378 }\r
379 if(log_file)\r
380 {\r
381 fprintf(log_file,"%s\n",cmd);\r
382 }\r
007c44c5 383}\r
384\r
0b9c3c19 385void iptables_save_line(char *line, int ipv6)\r
007c44c5 386{\r
0b9c3c19 387 if(ipv6)\r
388 {\r
389 fprintf(ip6tables_file,"%s\n",line);\r
390 }\r
391 else\r
392 {\r
393 fprintf(iptables_file,"%s\n",line);\r
394 }\r
007c44c5 395}\r
396\r
0b9c3c19 397void run_iptables_restore(void)\r
007c44c5 398{\r
5da44508 399 char *restor;\r
007c44c5 400 string(restor,STRLEN);\r
abe9b855 401\r
402 /*-----------------------------------------------------------------*/\r
1c004f15 403 printf("Running %s <%s ...\n", iptablesrestore, iptablesfile);\r
abe9b855 404 /*-----------------------------------------------------------------*/\r
0b9c3c19 405\r
406 iptables_save_line("COMMIT", FALSE);\r
007c44c5 407 fclose(iptables_file);\r
ae776b10 408 if(dry_run) \r
409 {\r
a1d21464 410 parse(iptablesfile)\r
411 {\r
412 printf("%s\n",_);\r
413 }\r
8e29188a 414 done; /* ugly macro end */\r
ae776b10 415 }\r
416\r
417 sprintf(restor,"%s <%s",iptablesrestore, iptablesfile);\r
418 safe_run(restor);\r
0b9c3c19 419\r
420 if(ip6prefix)\r
421 {\r
422 /*-----------------------------------------------------------------*/\r
423 printf("Running %s <%s ...\n", ip6tablesrestore, ip6tablesfile);\r
424 /*-----------------------------------------------------------------*/\r
425 iptables_save_line("COMMIT", TRUE);\r
426 fclose(ip6tables_file);\r
427 if(dry_run) \r
428 {\r
429 parse(ip6tablesfile)\r
430 {\r
431 printf("%s\n",_);\r
432 }\r
433 done; /* ugly macro end */\r
434 }\r
435 sprintf(restor,"%s <%s",ip6tablesrestore, ip6tablesfile);\r
436 safe_run(restor);\r
437 }\r
007c44c5 438 free(restor);\r
439}\r
440\r
007c44c5 441char *parse_datafile_line(char *str)\r
442{\r
443 char *ptr=strchr(str,' ');\r
444\r
445 if(ptr)\r
446 {\r
447 *ptr=0;\r
448 ptr++;\r
449 return ptr;\r
450 } \r
451 else \r
4358455e 452 {\r
007c44c5 453 return NULL;\r
4358455e 454 }\r
007c44c5 455}\r
456\r
5b902402 457\r
007c44c5 458/*-----------------------------------------------------------------*/\r
493e1ccd 459/* Are you looking for int main(int argc, char **argv) ? :-)) */\r
007c44c5 460/*-----------------------------------------------------------------*/\r
461\r
462program\r
463{\r
8e29188a 464 int i=0; /* just plain old Fortran style integer :-) */\r
465 FILE *f=NULL; /* everything is just stream of bytes... */\r
466 char *str, *ptr, *d; /* LET A$=B$ :-) */\r
007c44c5 467 char *substring;\r
1c9cae56 468\r
9a56ab25 469 int parent = 1;\r
470 int just_flush = FALSE; /* deactivates all previous actions */\r
471 int nodelay = FALSE;\r
472 int just_preview = FALSE; /* preview - generate just stats */\r
473 int start_shaping = FALSE; /* apply FUP - requires classmap file */\r
474 int just_logs = FALSE; /* just parse logs */\r
475 int run = FALSE;\r
476 int total = 0;\r
33ec95ab 477 \r
007c44c5 478 char *chain_forward, *chain_postrouting;\r
479 char *althosts=NULL;\r
480 \r
481 printf("\n\\r
482Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\\r
0b9c3c19 483Version %s - Copyright (C)2005-2013 Michael Polak, Arachne Labs\n\\r
43cde5c3 484iptables-restore & burst tunning & classify modification by Ludva\n\\r
0d5026c6 485Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version);\r
007c44c5 486\r
8e29188a 487 /*----- Boring... we have to check command line options first: ----*/ \r
007c44c5 488 arguments\r
489 {\r
490 argument("-c") { nextargument(config); }\r
491 argument("-h") { nextargument(althosts);}\r
208112af 492 argument("-d") { run=TRUE; dry_run=TRUE; }\r
493 argument("-f") { run=TRUE; just_flush=TRUE; }\r
494 argument("-9") { run=TRUE; just_flush=9; }\r
495 argument("-p") { run=TRUE; just_preview=TRUE; }\r
8e29188a 496 argument("-s") { run=TRUE; just_preview=TRUE; start_shaping=TRUE; }\r
208112af 497 argument("-r") { run=TRUE; }\r
498 argument("-n") { run=TRUE; nodelay=TRUE; }\r
499 argument("-l") { just_logs=TRUE; }\r
500 argument("-m") { just_logs=TRUE; }\r
501 argument("-y") { just_logs=TRUE; }\r
007c44c5 502 argument("-?") { help(); exit(0); }\r
503 argument("--help") { help(); exit(0); }\r
504 argument("-v") { exit(0); } \r
505 argument("--version") { exit(0); } \r
506 }\r
208112af 507 \r
007c44c5 508 if(dry_run)\r
208112af 509 {\r
007c44c5 510 puts("*** THIS IS JUST DRY RUN ! ***\n");\r
208112af 511 }\r
007c44c5 512\r
208112af 513 date(d); /* this is typical cll1.h macro - prints current date */\r
007c44c5 514\r
515 /*-----------------------------------------------------------------*/\r
516 printf("Parsing configuration file %s ...\n", config);\r
517 /*-----------------------------------------------------------------*/\r
518 get_config(config);\r
c9012978 519 \r
33ec95ab 520 if(just_logs)\r
c9012978 521 {\r
208112af 522 parse_ip_log(argc,argv);\r
523 exit(0);\r
524 }\r
525 else if(not run)\r
526 {\r
527 help();\r
528 exit(0);\r
c9012978 529 }\r
007c44c5 530\r
208112af 531 if(althosts)\r
532 {\r
533 hosts=althosts;\r
534 }\r
007c44c5 535\r
536 if(just_flush<9)\r
537 {\r
538 /*-----------------------------------------------------------------*/\r
539 puts("Parsing iptables verbose output ...");\r
540 /*-----------------------------------------------------------------*/\r
d7357b63 541 get_traffic_statistics(iptables, FALSE);\r
0b9c3c19 542 if(ip6prefix)\r
543 {\r
544 /*-----------------------------------------------------------------*/\r
545 puts("Parsing ip6tables verbose output ...");\r
546 /*-----------------------------------------------------------------*/ \r
d7357b63 547 get_traffic_statistics(ip6tables, TRUE);\r
0b9c3c19 548 }\r
007c44c5 549 }\r
550\r
551 /*-----------------------------------------------------------------*/\r
552 printf("Parsing class defintion file %s ...\n", hosts);\r
553 /*-----------------------------------------------------------------*/\r
1c9cae56 554 parse_hosts(hosts);\r
007c44c5 555\r
556 /*-----------------------------------------------------------------*/\r
557 /* cll1.h - let's allocate brand new character buffer... */\r
558 /*-----------------------------------------------------------------*/\r
559 string(str,STRLEN); \r
560\r
561 /*-----------------------------------------------------------------*/\r
562 puts("Resolving shared connections ...");\r
563 /*-----------------------------------------------------------------*/\r
6cc38f96 564 for_each(ip,ips) if(ip->sharing)\r
007c44c5 565 {\r
6cc38f96 566 for_each(sharedip,ips) if(eq(sharedip->name,ip->sharing))\r
007c44c5 567 {\r
568 sharedip->traffic+=ip->traffic;\r
569 ip->traffic=0;\r
570 ip->mark=sharedip->mark; \r
b3175d62 571 ip->lmsid=sharedip->lmsid;\r
007c44c5 572 break;\r
573 }\r
1c9cae56 574 if(not sharedip)\r
bb9e11ee 575 {\r
260c2719 576 printf("Unresolved shared connection: %s %s sharing-%s\n",\r
577 ip->addr, ip->name, ip->sharing);\r
bb9e11ee 578 }\r
007c44c5 579 }\r
580\r
581 if(enable_credit && just_flush<9)\r
582 {\r
583 /*-----------------------------------------------------------------*/\r
584 printf("Parsing credit file %s ...\n", credit);\r
585 /*-----------------------------------------------------------------*/\r
586 parse(credit)\r
587 {\r
588 ptr=parse_datafile_line(_);\r
589 if(ptr)\r
590 {\r
208112af 591 if_exists(ip,ips,eq(ip->addr,_))\r
592 {\r
007c44c5 593 sscanf(ptr,"%Lu",&(ip->credit));\r
208112af 594 }\r
007c44c5 595 }\r
596 }\r
8e29188a 597 done; /* ugly macro end */\r
007c44c5 598 }\r
599\r
600 if(!just_preview)\r
601 {\r
602 /*-----------------------------------------------------------------*/\r
603 puts("Initializing iptables and tc classes ...");\r
604 /*-----------------------------------------------------------------*/\r
605 \r
f64d5431 606 iptables_file = fopen(iptablesfile, "w");\r
260c2719 607 if(iptables_file == NULL)\r
bb9e11ee 608 {\r
f64d5431 609 perror(iptablesfile);\r
007c44c5 610 exit(-1);\r
611 }\r
0b9c3c19 612 iptables_save_line(iptablespreamble, FALSE);\r
613\r
614 if(ip6prefix)\r
615 {\r
616 ip6tables_file = fopen(ip6tablesfile, "w");\r
617 if(ip6tables_file == NULL)\r
618 {\r
619 perror(ip6tablesfile);\r
620 exit(-1);\r
621 }\r
622 iptables_save_line(iptablespreamble, TRUE);\r
e36b49c7 623 iptables_save_line(ip6preamble, TRUE);\r
0b9c3c19 624 }\r
625\r
626 run_iptables_restore();\r
007c44c5 627 \r
f64d5431 628 log_file = fopen(cmdlog, "w");\r
260c2719 629 if(log_file == NULL) \r
bb9e11ee 630 {\r
f64d5431 631 perror(cmdlog);\r
007c44c5 632 exit(-1);\r
ca6f7e80 633 } \r
007c44c5 634 \r
635 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,lan);\r
636 safe_run(str);\r
637\r
638 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,wan);\r
639 safe_run(str);\r
640 \r
641 iptables_file=fopen(iptablesfile,"w");\r
0b9c3c19 642 iptables_save_line(iptablespreamble, FALSE);\r
643 if(ip6prefix)\r
644 {\r
645 ip6tables_file=fopen(ip6tablesfile,"w");\r
646 iptables_save_line(iptablespreamble, TRUE);\r
e36b49c7 647 iptables_save_line(ip6preamble, TRUE);\r
0b9c3c19 648 }\r
007c44c5 649\r
0b9c3c19 650 if(qos_free_zone && *qos_free_zone!='0') /* this is currently supported only for IPv4 */\r
007c44c5 651 {\r
652 char *chain;\r
653 \r
654 sprintf(str,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone, wan);\r
0b9c3c19 655 iptables_save_line(str, FALSE); /* this is currently supported only for IPv4 */\r
007c44c5 656 \r
657 if(qos_proxy)\r
658 {\r
0b9c3c19 659 iptables_save_line(":post_noproxy - [0:0]", FALSE);\r
6b39193d 660 sprintf(str,"-A POSTROUTING ! -p tcp -o %s -j post_noproxy", lan);\r
0b9c3c19 661 iptables_save_line(str , FALSE);\r
6b39193d 662 sprintf(str,"-A POSTROUTING ! -s %s -o %s -j post_noproxy", proxy_ip, lan);\r
0b9c3c19 663 iptables_save_line(str, FALSE);\r
6b39193d 664 sprintf(str,"-A POSTROUTING -s %s -p tcp ! --sport %d -o %s -j post_noproxy", proxy_ip, proxy_port, lan);\r
0b9c3c19 665 iptables_save_line(str, FALSE);\r
007c44c5 666\r
667 chain="post_noproxy"; \r
668 }\r
669 else\r
bb9e11ee 670 {\r
007c44c5 671 chain="POSTROUTING";\r
bb9e11ee 672 }\r
007c44c5 673 \r
674 sprintf(str,"-A %s -s %s -o %s -j ACCEPT", chain, qos_free_zone, lan);\r
0b9c3c19 675 iptables_save_line(str, FALSE);\r
007c44c5 676 }\r
677 \r
f64d5431 678 if(ip_count > idxtable_treshold1 && !just_flush)\r
007c44c5 679 {\r
0b9c3c19 680 int idxcount=0, bitmask=32-idxtable_bitmask1;\r
e0161edb 681 char *subnet, *buf;\r
007c44c5 682 /*-----------------------------------------------------------------*/\r
683 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count);\r
684 /*-----------------------------------------------------------------*/\r
685\r
0b9c3c19 686 iptables_save_line(":post_common - [0:0]", FALSE);\r
687 iptables_save_line(":forw_common - [0:0]", FALSE);\r
688 if(ip6prefix)\r
689 {\r
690 iptables_save_line(":post_common - [0:0]", TRUE);\r
691 iptables_save_line(":forw_common - [0:0]", TRUE);\r
692 }\r
007c44c5 693\r
0b9c3c19 694 for_each(ip,ips) if(ip->addr && *(ip->addr) && !eq(ip->addr,"0.0.0.0/0")) \r
007c44c5 695 {\r
0b9c3c19 696 if(ip->v6)\r
697 {\r
698 buf=index6_id(ip->addr,bitmask+32);\r
699 }\r
700 else\r
701 {\r
702 buf=index_id(ip->addr, bitmask);\r
703 }\r
704 \r
208112af 705 if_exists(idx,idxs,eq(idx->id,buf))\r
706 {\r
007c44c5 707 idx->children++;\r
208112af 708 }\r
007c44c5 709 else\r
710 {\r
711 create(idx,Index);\r
0b9c3c19 712 idx->addr = ip->addr;\r
713 idx->id = buf;\r
714 idx->bitmask = bitmask+32*ip->v6;\r
715 idx->parent = NULL;\r
716 idx->children = 0;\r
717 idx->ipv6 = ip->v6;\r
007c44c5 718 idxcount++;\r
719 push(idx,idxs);\r
720 }\r
721 }\r
722\r
723 /* brutal perfomance optimalization */\r
f64d5431 724 while(idxcount > idxtable_treshold2 && bitmask > 2*idxtable_bitmask2)\r
007c44c5 725 {\r
f64d5431 726 bitmask -= idxtable_bitmask2;\r
727 idxcount = 0;\r
208112af 728\r
6cc38f96 729 for_each(idx,idxs) if(idx->parent == NULL)\r
007c44c5 730 {\r
0b9c3c19 731 if(idx->ipv6)\r
732 {\r
733 buf = index6_id(idx->addr, bitmask+32);\r
734 }\r
735 else\r
736 {\r
737 buf = index_id(idx->addr, bitmask);\r
738 }\r
208112af 739 if_exists(metaindex,idxs,eq(metaindex->id,buf))\r
740 {\r
741 metaindex->children++;\r
742 }\r
007c44c5 743 else\r
744 {\r
745 create(metaindex,Index);\r
0b9c3c19 746 metaindex->addr = idx->addr;\r
747 metaindex->id = buf;\r
748 metaindex->bitmask = bitmask+32*idx->ipv6;\r
749 metaindex->parent = NULL;\r
750 metaindex->children = 0;\r
751 metaindex->ipv6 = idx->ipv6;\r
007c44c5 752 idxcount++;\r
753 push(metaindex,idxs);\r
754 }\r
755 idx->parent=metaindex;\r
756 }\r
757 }\r
758\r
f64d5431 759 /* this should slightly optimize throughput ... */\r
007c44c5 760 sort(idx,idxs,desc_order_by,children);\r
761 sort(idx,idxs,order_by,bitmask);\r
762\r
763 i=0;\r
208112af 764 for_each(idx,idxs)\r
007c44c5 765 {\r
0b9c3c19 766 if(idx->ipv6)\r
767 {\r
768 subnet=subnet6_id(idx->addr, idx->bitmask);\r
769 }\r
770 else\r
771 {\r
772 subnet=subnet_id(idx->addr, idx->bitmask);\r
773 }\r
774 printf("%d: %s/%d\n", ++i, subnet, idx->bitmask);\r
007c44c5 775 \r
776 sprintf(str,":post_%s - [0:0]", idx->id);\r
0b9c3c19 777 iptables_save_line(str, idx->ipv6);\r
007c44c5 778\r
779 sprintf(str,":forw_%s - [0:0]", idx->id);\r
0b9c3c19 780 iptables_save_line(str, idx->ipv6);\r
007c44c5 781\r
782 if(idx->parent)\r
783 {\r
784 string(buf,strlen(idx->parent->id)+6);\r
0b9c3c19 785 sprintf(buf,"post_%s", idx->parent->id);\r
007c44c5 786 }\r
787 else\r
bb9e11ee 788 {\r
007c44c5 789 buf="POSTROUTING";\r
bb9e11ee 790 }\r
007c44c5 791\r
792 sprintf(str,"-A %s -d %s/%d -o %s -j post_%s", buf, subnet, idx->bitmask, lan, idx->id);\r
0b9c3c19 793 iptables_save_line(str, idx->ipv6);\r
007c44c5 794\r
795 sprintf(str,"-A %s -d %s/%d -o %s -j post_common", buf, subnet, idx->bitmask, lan);\r
0b9c3c19 796 iptables_save_line(str, idx->ipv6);\r
007c44c5 797\r
798 if(idx->parent)\r
799 {\r
800 string(buf,strlen(idx->parent->id)+6);\r
801 sprintf(buf,"forw_%s",idx->parent->id);\r
802 }\r
803 else\r
bb9e11ee 804 {\r
007c44c5 805 buf="FORWARD";\r
bb9e11ee 806 }\r
007c44c5 807\r
808 sprintf(str,"-A %s -s %s/%d -o %s -j forw_%s", buf, subnet, idx->bitmask, wan, idx->id);\r
0b9c3c19 809 iptables_save_line(str, idx->ipv6);\r
007c44c5 810\r
811 sprintf(str,"-A %s -s %s/%d -o %s -j forw_common", buf, subnet, idx->bitmask, wan);\r
0b9c3c19 812 iptables_save_line(str, idx->ipv6);\r
007c44c5 813 }\r
814 printf("Total indexed iptables chains created: %d\n", i);\r
815\r
816 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);\r
0b9c3c19 817 iptables_save_line(str, FALSE);\r
007c44c5 818 \r
819 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);\r
0b9c3c19 820 iptables_save_line(str, FALSE);\r
821\r
822 if(ip6prefix)\r
823 {\r
824 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);\r
825 iptables_save_line(str, TRUE);\r
826 \r
827 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);\r
828 iptables_save_line(str, TRUE);\r
829 }\r
007c44c5 830 }\r
007c44c5 831 }\r
832\r
833 if(just_flush)\r
834 {\r
835 fclose(iptables_file);\r
add90548 836 if(log_file)\r
837 { \r
838 fclose(log_file);\r
839 }\r
007c44c5 840 puts("Just flushed iptables and tc classes - now exiting ...");\r
841 exit(0);\r
842 }\r
843\r
844 if(!just_preview)\r
845 {\r
846 if(!dry_run && !nodelay && qos_free_delay)\r
847 {\r
848 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay);\r
849 sleep(qos_free_delay);\r
850 }\r
851\r
6cc38f96 852 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",\r
853 tc,lan,htb_r2q);\r
007c44c5 854 safe_run(str);\r
855\r
208112af 856 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
857 tc,lan,lan_medium,lan_medium,burst_main,highest_priority);\r
007c44c5 858 safe_run(str);\r
859\r
208112af 860 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
861 tc,lan,line,line,burst_main,highest_priority);\r
007c44c5 862 safe_run(str);\r
863\r
864 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc,wan,htb_r2q);\r
865 safe_run(str);\r
866\r
208112af 867 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
868 tc,wan,wan_medium,wan_medium,burst_main,highest_priority);\r
007c44c5 869 safe_run(str);\r
870\r
208112af 871 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
872 tc,wan,up,up,burst_main,highest_priority);\r
007c44c5 873 safe_run(str);\r
874 }\r
875\r
876 /*-----------------------------------------------------------------*/\r
208112af 877 puts("Locating heavy downloaders and generating root classes ...");\r
007c44c5 878 /*-----------------------------------------------------------------*/\r
bb9e11ee 879 sort(ip,ips,desc_order_by,traffic); \r
007c44c5 880\r
881 /*-----------------------------------------------------------------*/\r
882 /* sub-scope - local variables */ \r
883 {\r
6cc38f96 884 long long int rate = line;\r
885 long long int max = line;\r
886 int group_count = 0;\r
887 FILE *credit_file = NULL;\r
007c44c5 888 \r
4358455e 889 if(!just_preview && !dry_run && enable_credit)\r
890 {\r
6cc38f96 891 credit_file = fopen(credit,"w");\r
4358455e 892 }\r
007c44c5 893 \r
208112af 894 for_each(group,groups)\r
007c44c5 895 {\r
896 if(!just_preview)\r
897 {\r
007c44c5 898 //download\r
208112af 899 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
900 tc, lan, parent, group->id, rate, max, burst_group, highest_priority+1, group->desired);\r
007c44c5 901 safe_run(str);\r
902 \r
903 //upload\r
208112af 904 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
905 tc, wan, parent, group->id, rate*up/line, max*up/line, burst_group, highest_priority+1, group->desired);\r
007c44c5 906 safe_run(str);\r
907 }\r
908 \r
6cc38f96 909 if(group_count++ < max_nesting)\r
bb9e11ee 910 {\r
6cc38f96 911 parent = group->id;\r
bb9e11ee 912 }\r
007c44c5 913 \r
6cc38f96 914 rate -= digital_divide*group->min;\r
915 if(rate < group->min)\r
4358455e 916 {\r
6cc38f96 917 rate = group->min;\r
4358455e 918 }\r
007c44c5 919 \r
920 /*shaping of aggresive downloaders, with credit file support */\r
921 if(use_credit)\r
922 {\r
6cc38f96 923 int group_rate = group->min, priority_sequence = lowest_priority;\r
007c44c5 924 \r
6cc38f96 925 for_each(ip, ips) if(ip->min == group->min && ip->max > ip->min)\r
007c44c5 926 {\r
e48d46c9 927 ip->realquota=ip->credit+(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20));\r
928 if( ip->keyword->data_limit \r
929 and not ip->fixedprio \r
930 and ip->traffic > ip->realquota )\r
007c44c5 931 {\r
e48d46c9 932 if(group_rate < ip->max)\r
4358455e 933 {\r
e48d46c9 934 ip->max = group_rate;\r
4358455e 935 }\r
007c44c5 936 group_rate+=magic_treshold;\r
208112af 937 ip->prio=lowest_priority;\r
4358455e 938 if(ip->prio<highest_priority+2)\r
939 {\r
940 ip->prio=highest_priority+2;\r
941 }\r
007c44c5 942 }\r
943 else\r
944 {\r
6cc38f96 945 if( ip->keyword->data_prio \r
946 && !ip->fixedprio \r
947 && ( ip->traffic>ip->credit\r
948 + (ip->min*ip->keyword->data_prio+(ip->keyword->fixed_prio<<20))) )\r
007c44c5 949 {\r
950 ip->prio=priority_sequence--;\r
4358455e 951 if(ip->prio<highest_priority+1)\r
952 {\r
953 ip->prio=highest_priority+1;\r
954 }\r
007c44c5 955 }\r
956 \r
957 if(credit_file)\r
958 {\r
959 unsigned long long lcredit=0;\r
99127c70 960 \r
4358455e 961 if((ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))>ip->traffic)\r
962 {\r
007c44c5 963 lcredit=(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))-ip->traffic;\r
4358455e 964 }\r
007c44c5 965 fprintf(credit_file,"%s %Lu\n",ip->addr,lcredit);\r
966 }\r
967 }\r
6cc38f96 968 } \r
007c44c5 969 }\r
970 }\r
4358455e 971 if(credit_file)\r
972 {\r
973 fclose(credit_file);\r
974 }\r
007c44c5 975 }\r
976\r
977 if(just_preview)\r
978 {\r
8e29188a 979 if(start_shaping)\r
980 {\r
981 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap);\r
982 parse(classmap)\r
983 {\r
984 ptr=strchr(_,' ');\r
985 if(ptr)\r
986 {\r
987 *ptr=0;\r
988 ptr++;\r
989 if_exists(ip,ips,eq(ip->addr,_))\r
990 {\r
991 ip->mark=atoi(ptr);\r
992 if(ip->max < ip->desired) /* apply FUP limit immediately.... */\r
993 {\r
994 printf("Applying limit for %-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
995 printf("(down: %dk-%dk ", ip->min, ip->max); \r
996 sprintf(str, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
997 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
998 safe_run(str);\r
999 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1000 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
1001 sprintf(str,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1002 tc, wan, ip->group, ip->mark,\r
1003 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1004 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1005 safe_run(str);\r
1006 }\r
1007 }\r
1008 }\r
1009 }\r
1010 fail\r
1011 { \r
1012 perror(classmap);\r
1013 puts("Warning - classmap file not fund, just generating preview ...");\r
1014 start_shaping=FALSE;\r
1015 }\r
1016 done; /* ugly macro end */\r
1017 }\r
6fb3c58a 1018 html=preview;\r
1ab008b9 1019 json_traffic=json_preview;\r
007c44c5 1020 }\r
6fb3c58a 1021\r
1022 if(!dry_run && !just_flush)\r
007c44c5 1023 {\r
1024 /*-----------------------------------------------------------------*/\r
1ab008b9 1025 printf("Writing json traffic overview %s ... ", json_traffic);\r
007c44c5 1026 /*-----------------------------------------------------------------*/\r
1ab008b9 1027 write_json_traffic(json_traffic);\r
007c44c5 1028\r
0b9c3c19 1029 /*-----------------------------------------------------------------*/\r
1030 printf("Writing statistics into HTML page %s ...\n", html);\r
1031 /*-----------------------------------------------------------------*/\r
1032 write_htmlandlogs(html, d, total, just_preview);\r
1033 }\r
007c44c5 1034\r
1035 if(just_preview)\r
1036 {\r
8e29188a 1037 char swchar='p';\r
1038 if(start_shaping)\r
1039 {\r
1040 swchar='s';\r
1041 }\r
1042 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar);\r
007c44c5 1043 exit(0);\r
be96b71b 1044 } \r
007c44c5 1045\r
1046 i=0;\r
260c2719 1047#ifdef DEBUG\r
007c44c5 1048 printf("%-22s %-15s mark\n","name","ip");\r
260c2719 1049#endif\r
208112af 1050\r
14e28c6f 1051 printf("Writing %s", classmap); \r
be96b71b 1052 f = fopen(classmap, "w"); \r
1053 if(f < 0)\r
1054 {\r
1055 perror(classmap);\r
1056 }\r
1057\r
1058 /*-----------------------------------------------------------------*/\r
0995c4ad 1059 printf(" + generating iptables and tc classes ... ");\r
be96b71b 1060 /*-----------------------------------------------------------------*/\r
1061\r
0b9c3c19 1062 for_each(ip, ips) if(ip->mark > 0) /* works only for IPv4 so far */\r
be96b71b 1063 {\r
007c44c5 1064 if(idxs)\r
1065 {\r
1066 char *buf;\r
1067 duplicate(ip->addr,buf);\r
0b9c3c19 1068 if(ip->v6)\r
1069 {\r
1070 buf=index6_id(ip->addr,64-idxtable_bitmask1);\r
1071 }\r
1072 else\r
1073 {\r
1074 buf=index_id(ip->addr,32-idxtable_bitmask1);\r
1075 }\r
007c44c5 1076 \r
1077 string(chain_forward,6+strlen(buf));\r
1078 strcpy(chain_forward,"forw_");\r
1079 strcat(chain_forward,buf);\r
1080\r
1081 string(chain_postrouting,6+strlen(buf));\r
1082 strcpy(chain_postrouting,"post_");\r
1083 strcat(chain_postrouting,buf);\r
1084 \r
1085 free(buf);\r
1086 }\r
1087 else\r
1088 {\r
1089 chain_forward="FORWARD";\r
1090 chain_postrouting="POSTROUTING";\r
1091 }\r
1092\r
260c2719 1093#ifdef DEBUG\r
007c44c5 1094 printf("%-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
260c2719 1095#endif\r
007c44c5 1096\r
1097 /* -------------------------------------------------------- mark download */\r
1098 \r
0b9c3c19 1099 sprintf(str, "-A %s -d %s/%d -o %s -j %s%d",\r
1100 chain_postrouting, ip->addr, 32*(1+ip->v6), lan, mark_iptables, ip->mark);\r
007c44c5 1101 /* -m limit --limit 1/s */ \r
0b9c3c19 1102 iptables_save_line(str, ip->v6);\r
007c44c5 1103\r
1104 if(qos_proxy)\r
1105 {\r
0b9c3c19 1106 sprintf(str, "-A %s -s %s -p tcp --sport %d -d %s/%d -o %s -j %s%d",\r
1107 chain_postrouting, proxy_ip, proxy_port, ip->addr, 32*(1+ip->v6), lan, mark_iptables, ip->mark);\r
1108 iptables_save_line(str, ip->v6);\r
007c44c5 1109 }\r
1110\r
0b9c3c19 1111 sprintf(str, "-A %s -d %s/%d -o %s -j ACCEPT",\r
1112 chain_postrouting, ip->addr, 32*(1+ip->v6), lan);\r
1113 iptables_save_line(str, ip->v6);\r
007c44c5 1114\r
1115 /* -------------------------------------------------------- mark upload */\r
0b9c3c19 1116 sprintf(str, "-A %s -s %s/%d -o %s -j %s%d", \r
1117 chain_forward, ip->addr, 32*(1+ip->v6), wan, mark_iptables, ip->mark);\r
1118 iptables_save_line(str, ip->v6);\r
007c44c5 1119\r
0b9c3c19 1120 sprintf(str, "-A %s -s %s/%d -o %s -j ACCEPT",\r
1121 chain_forward, ip->addr, 32*(1+ip->v6), wan);\r
1122 iptables_save_line(str, ip->v6);\r
007c44c5 1123\r
1124 if(ip->min)\r
1125 {\r
1126 /* -------------------------------------------------------- download class */\r
260c2719 1127#ifdef DEBUG\r
007c44c5 1128 printf("(down: %dk-%dk ", ip->min, ip->max); \r
260c2719 1129#endif\r
007c44c5 1130\r
be96b71b 1131 sprintf(str, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
1132 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
007c44c5 1133 safe_run(str);\r
1134\r
260c2719 1135 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
dee5592e 1136 {\r
0b9c3c19 1137 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s", \r
1138 tc, lan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
1139 safe_run(str);\r
be96b71b 1140 }\r
1141\r
260c2719 1142 if(filter_type == 1)\r
dee5592e 1143 {\r
0b9c3c19 1144 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
1145 tc, lan, ip->mark, ip->mark);\r
1146 safe_run(str);\r
007c44c5 1147 }\r
1148\r
1149 /* -------------------------------------------------------- upload class */\r
260c2719 1150#ifdef DEBUG\r
007c44c5 1151 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1152 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
260c2719 1153#endif\r
007c44c5 1154\r
1155 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1156 tc, wan, ip->group, ip->mark,\r
1157 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1158 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1159 safe_run(str);\r
1160 \r
260c2719 1161 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
dee5592e 1162 {\r
0b9c3c19 1163 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s",\r
1164 tc, wan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
1165 safe_run(str);\r
dee5592e 1166 } \r
be96b71b 1167\r
260c2719 1168 if(filter_type == 1)\r
dee5592e 1169 {\r
0b9c3c19 1170 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
1171 tc, wan, ip->mark, ip->mark);\r
1172 safe_run(str);\r
007c44c5 1173 }\r
be96b71b 1174 \r
6fb3c58a 1175 if(f > 0)\r
be96b71b 1176 {\r
0b9c3c19 1177 fprintf(f, "%s %d\n", ip->addr, ip->mark);\r
be96b71b 1178 }\r
007c44c5 1179 }\r
1180 else\r
260c2719 1181 {\r
1182#ifdef DEBUG\r
007c44c5 1183 printf("(sharing %s)\n", ip->sharing);\r
260c2719 1184#endif\r
1185 }\r
007c44c5 1186 i++;\r
1187 }\r
6fb3c58a 1188 if(f > 0)\r
be96b71b 1189 {\r
1190 puts("done.");\r
1191 fclose(f);\r
1192 }\r
1193 \r
007c44c5 1194 if(idxs)\r
1195 {\r
0b9c3c19 1196 chain_forward = "forw_common";\r
1197 chain_postrouting = "post_common";\r
007c44c5 1198 }\r
1199 else\r
1200 {\r
0b9c3c19 1201 chain_forward = "FORWARD";\r
1202 chain_postrouting = "POSTROUTING";\r
007c44c5 1203 }\r
0b9c3c19 1204\r
1205 if(free_min)\r
007c44c5 1206 {\r
0b9c3c19 1207 final_chain = "ACCEPT";\r
1208 }\r
1209\r
1210 if(qos_proxy)\r
1211 {\r
1212 if(free_min) \r
1213 {\r
1214 sprintf(str, "-A %s -s %s -p tcp --sport %d -o %s -j %s%d",\r
1215 chain_postrouting,proxy_ip,proxy_port,lan,mark_iptables, 3);\r
1216 iptables_save_line(str, FALSE); /* only for IPv4 */\r
1217 }\r
1218 sprintf(str, "-A %s -s %s -p tcp --sport %d -o %s -j %s",\r
1219 chain_postrouting,proxy_ip,proxy_port,lan,final_chain);\r
1220 iptables_save_line(str, FALSE); /* only for IPv4 */\r
1221 }\r
1222\r
1223 if(free_min)\r
1224 {\r
1225 sprintf(str, "-A %s -o %s -j %s%d",\r
1226 chain_postrouting, lan, mark_iptables, 3);\r
1227 iptables_save_line(str, FALSE); /* only for IPv4 */\r
1228 }\r
1229\r
1230 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
1231 iptables_save_line(str, FALSE);\r
1232 if(ip6prefix)\r
1233 {\r
1234 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
1235 iptables_save_line(str, TRUE);\r
1236 }\r
1237\r
1238 if(free_min)\r
1239 {\r
1240 sprintf(str,"-A %s -o %s -j %s%d", chain_forward, wan, mark_iptables, 3);\r
1241 iptables_save_line(str, FALSE); /* only for IPv4 */\r
1242 }\r
1243\r
1244 sprintf(str,"-A %s -o %s -j %s", chain_forward, wan, final_chain);\r
1245 iptables_save_line(str, FALSE);\r
1246 if(ip6prefix)\r
1247 {\r
1248 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
1249 iptables_save_line(str, TRUE);\r
007c44c5 1250 }\r
abe9b855 1251\r
dee5592e 1252 if(free_min) /* allocate free bandwith if it is not zero... */ \r
1253 {\r
1254 /*-----------------------------------------------------------------*/\r
1255 puts("Generating free bandwith classes ...");\r
1256 /*-----------------------------------------------------------------*/\r
208112af 1257 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
be96b71b 1258 tc, lan, parent, free_min, free_max,burst, lowest_priority);\r
dee5592e 1259 safe_run(str);\r
208112af 1260 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
be96b71b 1261 tc, wan, parent, free_min, free_max, burst, lowest_priority);\r
dee5592e 1262 safe_run(str);\r
1263 /* tc SFQ */\r
260c2719 1264 if(strcmpi(qos_leaf, "none"))\r
dee5592e 1265 {\r
be96b71b 1266 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, lan, qos_leaf);\r
dee5592e 1267 safe_run(str);\r
1268 \r
be96b71b 1269 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, wan, qos_leaf);\r
dee5592e 1270 safe_run(str);\r
1271 } \r
1272 /* tc handle 1 fw flowid */\r
be96b71b 1273 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, lan);\r
dee5592e 1274 safe_run(str);\r
007c44c5 1275\r
be96b71b 1276 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, wan);\r
dee5592e 1277 safe_run(str);\r
007c44c5 1278 }\r
dee5592e 1279 printf("Total IP count: %d\n", i);\r
0b9c3c19 1280 run_iptables_restore();\r
260c2719 1281 if(log_file)\r
1282 {\r
1283 fclose(log_file);\r
1284 }\r
007c44c5 1285 return 0;\r
007c44c5 1286 /* that's all folks, thank you for reading it all the way up to this point ;-) */\r
1287 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */\r
1288}\r
This page took 2.429182 seconds and 4 git commands to generate.