IPv6 iptables exceptions (for OSPF)
[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
633 }\r
634 \r
007c44c5 635 \r
636 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,lan);\r
637 safe_run(str);\r
638\r
639 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,wan);\r
640 safe_run(str);\r
641 \r
642 iptables_file=fopen(iptablesfile,"w");\r
0b9c3c19 643 iptables_save_line(iptablespreamble, FALSE);\r
644 if(ip6prefix)\r
645 {\r
646 ip6tables_file=fopen(ip6tablesfile,"w");\r
647 iptables_save_line(iptablespreamble, TRUE);\r
e36b49c7 648 iptables_save_line(ip6preamble, TRUE);\r
0b9c3c19 649 }\r
007c44c5 650\r
0b9c3c19 651 if(qos_free_zone && *qos_free_zone!='0') /* this is currently supported only for IPv4 */\r
007c44c5 652 {\r
653 char *chain;\r
654 \r
655 sprintf(str,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone, wan);\r
0b9c3c19 656 iptables_save_line(str, FALSE); /* this is currently supported only for IPv4 */\r
007c44c5 657 \r
658 if(qos_proxy)\r
659 {\r
0b9c3c19 660 iptables_save_line(":post_noproxy - [0:0]", FALSE);\r
6b39193d 661 sprintf(str,"-A POSTROUTING ! -p tcp -o %s -j post_noproxy", lan);\r
0b9c3c19 662 iptables_save_line(str , FALSE);\r
6b39193d 663 sprintf(str,"-A POSTROUTING ! -s %s -o %s -j post_noproxy", proxy_ip, lan);\r
0b9c3c19 664 iptables_save_line(str, FALSE);\r
6b39193d 665 sprintf(str,"-A POSTROUTING -s %s -p tcp ! --sport %d -o %s -j post_noproxy", proxy_ip, proxy_port, lan);\r
0b9c3c19 666 iptables_save_line(str, FALSE);\r
007c44c5 667\r
668 chain="post_noproxy"; \r
669 }\r
670 else\r
bb9e11ee 671 {\r
007c44c5 672 chain="POSTROUTING";\r
bb9e11ee 673 }\r
007c44c5 674 \r
675 sprintf(str,"-A %s -s %s -o %s -j ACCEPT", chain, qos_free_zone, lan);\r
0b9c3c19 676 iptables_save_line(str, FALSE);\r
007c44c5 677 }\r
678 \r
f64d5431 679 if(ip_count > idxtable_treshold1 && !just_flush)\r
007c44c5 680 {\r
0b9c3c19 681 int idxcount=0, bitmask=32-idxtable_bitmask1;\r
e0161edb 682 char *subnet, *buf;\r
007c44c5 683 /*-----------------------------------------------------------------*/\r
684 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count);\r
685 /*-----------------------------------------------------------------*/\r
686\r
0b9c3c19 687 iptables_save_line(":post_common - [0:0]", FALSE);\r
688 iptables_save_line(":forw_common - [0:0]", FALSE);\r
689 if(ip6prefix)\r
690 {\r
691 iptables_save_line(":post_common - [0:0]", TRUE);\r
692 iptables_save_line(":forw_common - [0:0]", TRUE);\r
693 }\r
007c44c5 694\r
0b9c3c19 695 for_each(ip,ips) if(ip->addr && *(ip->addr) && !eq(ip->addr,"0.0.0.0/0")) \r
007c44c5 696 {\r
0b9c3c19 697 if(ip->v6)\r
698 {\r
699 buf=index6_id(ip->addr,bitmask+32);\r
700 }\r
701 else\r
702 {\r
703 buf=index_id(ip->addr, bitmask);\r
704 }\r
705 \r
208112af 706 if_exists(idx,idxs,eq(idx->id,buf))\r
707 {\r
007c44c5 708 idx->children++;\r
208112af 709 }\r
007c44c5 710 else\r
711 {\r
712 create(idx,Index);\r
0b9c3c19 713 idx->addr = ip->addr;\r
714 idx->id = buf;\r
715 idx->bitmask = bitmask+32*ip->v6;\r
716 idx->parent = NULL;\r
717 idx->children = 0;\r
718 idx->ipv6 = ip->v6;\r
007c44c5 719 idxcount++;\r
720 push(idx,idxs);\r
721 }\r
722 }\r
723\r
724 /* brutal perfomance optimalization */\r
f64d5431 725 while(idxcount > idxtable_treshold2 && bitmask > 2*idxtable_bitmask2)\r
007c44c5 726 {\r
f64d5431 727 bitmask -= idxtable_bitmask2;\r
728 idxcount = 0;\r
208112af 729\r
6cc38f96 730 for_each(idx,idxs) if(idx->parent == NULL)\r
007c44c5 731 {\r
0b9c3c19 732 if(idx->ipv6)\r
733 {\r
734 buf = index6_id(idx->addr, bitmask+32);\r
735 }\r
736 else\r
737 {\r
738 buf = index_id(idx->addr, bitmask);\r
739 }\r
208112af 740 if_exists(metaindex,idxs,eq(metaindex->id,buf))\r
741 {\r
742 metaindex->children++;\r
743 }\r
007c44c5 744 else\r
745 {\r
746 create(metaindex,Index);\r
0b9c3c19 747 metaindex->addr = idx->addr;\r
748 metaindex->id = buf;\r
749 metaindex->bitmask = bitmask+32*idx->ipv6;\r
750 metaindex->parent = NULL;\r
751 metaindex->children = 0;\r
752 metaindex->ipv6 = idx->ipv6;\r
007c44c5 753 idxcount++;\r
754 push(metaindex,idxs);\r
755 }\r
756 idx->parent=metaindex;\r
757 }\r
758 }\r
759\r
f64d5431 760 /* this should slightly optimize throughput ... */\r
007c44c5 761 sort(idx,idxs,desc_order_by,children);\r
762 sort(idx,idxs,order_by,bitmask);\r
763\r
764 i=0;\r
208112af 765 for_each(idx,idxs)\r
007c44c5 766 {\r
0b9c3c19 767 if(idx->ipv6)\r
768 {\r
769 subnet=subnet6_id(idx->addr, idx->bitmask);\r
770 }\r
771 else\r
772 {\r
773 subnet=subnet_id(idx->addr, idx->bitmask);\r
774 }\r
775 printf("%d: %s/%d\n", ++i, subnet, idx->bitmask);\r
007c44c5 776 \r
777 sprintf(str,":post_%s - [0:0]", idx->id);\r
0b9c3c19 778 iptables_save_line(str, idx->ipv6);\r
007c44c5 779\r
780 sprintf(str,":forw_%s - [0:0]", idx->id);\r
0b9c3c19 781 iptables_save_line(str, idx->ipv6);\r
007c44c5 782\r
783 if(idx->parent)\r
784 {\r
785 string(buf,strlen(idx->parent->id)+6);\r
0b9c3c19 786 sprintf(buf,"post_%s", idx->parent->id);\r
007c44c5 787 }\r
788 else\r
bb9e11ee 789 {\r
007c44c5 790 buf="POSTROUTING";\r
bb9e11ee 791 }\r
007c44c5 792\r
793 sprintf(str,"-A %s -d %s/%d -o %s -j post_%s", buf, subnet, idx->bitmask, lan, idx->id);\r
0b9c3c19 794 iptables_save_line(str, idx->ipv6);\r
007c44c5 795\r
796 sprintf(str,"-A %s -d %s/%d -o %s -j post_common", buf, subnet, idx->bitmask, lan);\r
0b9c3c19 797 iptables_save_line(str, idx->ipv6);\r
007c44c5 798\r
799 if(idx->parent)\r
800 {\r
801 string(buf,strlen(idx->parent->id)+6);\r
802 sprintf(buf,"forw_%s",idx->parent->id);\r
803 }\r
804 else\r
bb9e11ee 805 {\r
007c44c5 806 buf="FORWARD";\r
bb9e11ee 807 }\r
007c44c5 808\r
809 sprintf(str,"-A %s -s %s/%d -o %s -j forw_%s", buf, subnet, idx->bitmask, wan, idx->id);\r
0b9c3c19 810 iptables_save_line(str, idx->ipv6);\r
007c44c5 811\r
812 sprintf(str,"-A %s -s %s/%d -o %s -j forw_common", buf, subnet, idx->bitmask, wan);\r
0b9c3c19 813 iptables_save_line(str, idx->ipv6);\r
007c44c5 814 }\r
815 printf("Total indexed iptables chains created: %d\n", i);\r
816\r
817 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);\r
0b9c3c19 818 iptables_save_line(str, FALSE);\r
007c44c5 819 \r
820 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);\r
0b9c3c19 821 iptables_save_line(str, FALSE);\r
822\r
823 if(ip6prefix)\r
824 {\r
825 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);\r
826 iptables_save_line(str, TRUE);\r
827 \r
828 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);\r
829 iptables_save_line(str, TRUE);\r
830 }\r
007c44c5 831 }\r
007c44c5 832 }\r
833\r
834 if(just_flush)\r
835 {\r
836 fclose(iptables_file);\r
add90548 837 if(log_file)\r
838 { \r
839 fclose(log_file);\r
840 }\r
007c44c5 841 puts("Just flushed iptables and tc classes - now exiting ...");\r
842 exit(0);\r
843 }\r
844\r
845 if(!just_preview)\r
846 {\r
847 if(!dry_run && !nodelay && qos_free_delay)\r
848 {\r
849 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay);\r
850 sleep(qos_free_delay);\r
851 }\r
852\r
6cc38f96 853 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",\r
854 tc,lan,htb_r2q);\r
007c44c5 855 safe_run(str);\r
856\r
208112af 857 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
858 tc,lan,lan_medium,lan_medium,burst_main,highest_priority);\r
007c44c5 859 safe_run(str);\r
860\r
208112af 861 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
862 tc,lan,line,line,burst_main,highest_priority);\r
007c44c5 863 safe_run(str);\r
864\r
865 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc,wan,htb_r2q);\r
866 safe_run(str);\r
867\r
208112af 868 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
869 tc,wan,wan_medium,wan_medium,burst_main,highest_priority);\r
007c44c5 870 safe_run(str);\r
871\r
208112af 872 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
873 tc,wan,up,up,burst_main,highest_priority);\r
007c44c5 874 safe_run(str);\r
875 }\r
876\r
877 /*-----------------------------------------------------------------*/\r
208112af 878 puts("Locating heavy downloaders and generating root classes ...");\r
007c44c5 879 /*-----------------------------------------------------------------*/\r
bb9e11ee 880 sort(ip,ips,desc_order_by,traffic); \r
007c44c5 881\r
882 /*-----------------------------------------------------------------*/\r
883 /* sub-scope - local variables */ \r
884 {\r
6cc38f96 885 long long int rate = line;\r
886 long long int max = line;\r
887 int group_count = 0;\r
888 FILE *credit_file = NULL;\r
007c44c5 889 \r
4358455e 890 if(!just_preview && !dry_run && enable_credit)\r
891 {\r
6cc38f96 892 credit_file = fopen(credit,"w");\r
4358455e 893 }\r
007c44c5 894 \r
208112af 895 for_each(group,groups)\r
007c44c5 896 {\r
897 if(!just_preview)\r
898 {\r
007c44c5 899 //download\r
208112af 900 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
901 tc, lan, parent, group->id, rate, max, burst_group, highest_priority+1, group->desired);\r
007c44c5 902 safe_run(str);\r
903 \r
904 //upload\r
208112af 905 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
906 tc, wan, parent, group->id, rate*up/line, max*up/line, burst_group, highest_priority+1, group->desired);\r
007c44c5 907 safe_run(str);\r
908 }\r
909 \r
6cc38f96 910 if(group_count++ < max_nesting)\r
bb9e11ee 911 {\r
6cc38f96 912 parent = group->id;\r
bb9e11ee 913 }\r
007c44c5 914 \r
6cc38f96 915 rate -= digital_divide*group->min;\r
916 if(rate < group->min)\r
4358455e 917 {\r
6cc38f96 918 rate = group->min;\r
4358455e 919 }\r
007c44c5 920 \r
921 /*shaping of aggresive downloaders, with credit file support */\r
922 if(use_credit)\r
923 {\r
6cc38f96 924 int group_rate = group->min, priority_sequence = lowest_priority;\r
007c44c5 925 \r
6cc38f96 926 for_each(ip, ips) if(ip->min == group->min && ip->max > ip->min)\r
007c44c5 927 {\r
e48d46c9 928 ip->realquota=ip->credit+(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20));\r
929 if( ip->keyword->data_limit \r
930 and not ip->fixedprio \r
931 and ip->traffic > ip->realquota )\r
007c44c5 932 {\r
e48d46c9 933 if(group_rate < ip->max)\r
4358455e 934 {\r
e48d46c9 935 ip->max = group_rate;\r
4358455e 936 }\r
007c44c5 937 group_rate+=magic_treshold;\r
208112af 938 ip->prio=lowest_priority;\r
4358455e 939 if(ip->prio<highest_priority+2)\r
940 {\r
941 ip->prio=highest_priority+2;\r
942 }\r
007c44c5 943 }\r
944 else\r
945 {\r
6cc38f96 946 if( ip->keyword->data_prio \r
947 && !ip->fixedprio \r
948 && ( ip->traffic>ip->credit\r
949 + (ip->min*ip->keyword->data_prio+(ip->keyword->fixed_prio<<20))) )\r
007c44c5 950 {\r
951 ip->prio=priority_sequence--;\r
4358455e 952 if(ip->prio<highest_priority+1)\r
953 {\r
954 ip->prio=highest_priority+1;\r
955 }\r
007c44c5 956 }\r
957 \r
958 if(credit_file)\r
959 {\r
960 unsigned long long lcredit=0;\r
99127c70 961 \r
4358455e 962 if((ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))>ip->traffic)\r
963 {\r
007c44c5 964 lcredit=(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))-ip->traffic;\r
4358455e 965 }\r
007c44c5 966 fprintf(credit_file,"%s %Lu\n",ip->addr,lcredit);\r
967 }\r
968 }\r
6cc38f96 969 } \r
007c44c5 970 }\r
971 }\r
4358455e 972 if(credit_file)\r
973 {\r
974 fclose(credit_file);\r
975 }\r
007c44c5 976 }\r
977\r
978 if(just_preview)\r
979 {\r
8e29188a 980 if(start_shaping)\r
981 {\r
982 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap);\r
983 parse(classmap)\r
984 {\r
985 ptr=strchr(_,' ');\r
986 if(ptr)\r
987 {\r
988 *ptr=0;\r
989 ptr++;\r
990 if_exists(ip,ips,eq(ip->addr,_))\r
991 {\r
992 ip->mark=atoi(ptr);\r
993 if(ip->max < ip->desired) /* apply FUP limit immediately.... */\r
994 {\r
995 printf("Applying limit for %-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
996 printf("(down: %dk-%dk ", ip->min, ip->max); \r
997 sprintf(str, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
998 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
999 safe_run(str);\r
1000 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1001 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
1002 sprintf(str,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1003 tc, wan, ip->group, ip->mark,\r
1004 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1005 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1006 safe_run(str);\r
1007 }\r
1008 }\r
1009 }\r
1010 }\r
1011 fail\r
1012 { \r
1013 perror(classmap);\r
1014 puts("Warning - classmap file not fund, just generating preview ...");\r
1015 start_shaping=FALSE;\r
1016 }\r
1017 done; /* ugly macro end */\r
1018 }\r
6fb3c58a 1019 html=preview;\r
1ab008b9 1020 json_traffic=json_preview;\r
007c44c5 1021 }\r
6fb3c58a 1022\r
1023 if(!dry_run && !just_flush)\r
007c44c5 1024 {\r
1025 /*-----------------------------------------------------------------*/\r
1ab008b9 1026 printf("Writing json traffic overview %s ... ", json_traffic);\r
007c44c5 1027 /*-----------------------------------------------------------------*/\r
1ab008b9 1028 write_json_traffic(json_traffic);\r
007c44c5 1029\r
0b9c3c19 1030 /*-----------------------------------------------------------------*/\r
1031 printf("Writing statistics into HTML page %s ...\n", html);\r
1032 /*-----------------------------------------------------------------*/\r
1033 write_htmlandlogs(html, d, total, just_preview);\r
1034 }\r
007c44c5 1035\r
1036 if(just_preview)\r
1037 {\r
8e29188a 1038 char swchar='p';\r
1039 if(start_shaping)\r
1040 {\r
1041 swchar='s';\r
1042 }\r
1043 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar);\r
007c44c5 1044 exit(0);\r
be96b71b 1045 } \r
007c44c5 1046\r
1047 i=0;\r
260c2719 1048#ifdef DEBUG\r
007c44c5 1049 printf("%-22s %-15s mark\n","name","ip");\r
260c2719 1050#endif\r
208112af 1051\r
0995c4ad 1052 printf("Writing %s ", classmap); \r
be96b71b 1053 f = fopen(classmap, "w"); \r
1054 if(f < 0)\r
1055 {\r
1056 perror(classmap);\r
1057 }\r
1058\r
1059 /*-----------------------------------------------------------------*/\r
0995c4ad 1060 printf(" + generating iptables and tc classes ... ");\r
be96b71b 1061 /*-----------------------------------------------------------------*/\r
1062\r
0b9c3c19 1063 for_each(ip, ips) if(ip->mark > 0) /* works only for IPv4 so far */\r
be96b71b 1064 {\r
007c44c5 1065 if(idxs)\r
1066 {\r
1067 char *buf;\r
1068 duplicate(ip->addr,buf);\r
0b9c3c19 1069 if(ip->v6)\r
1070 {\r
1071 buf=index6_id(ip->addr,64-idxtable_bitmask1);\r
1072 }\r
1073 else\r
1074 {\r
1075 buf=index_id(ip->addr,32-idxtable_bitmask1);\r
1076 }\r
007c44c5 1077 \r
1078 string(chain_forward,6+strlen(buf));\r
1079 strcpy(chain_forward,"forw_");\r
1080 strcat(chain_forward,buf);\r
1081\r
1082 string(chain_postrouting,6+strlen(buf));\r
1083 strcpy(chain_postrouting,"post_");\r
1084 strcat(chain_postrouting,buf);\r
1085 \r
1086 free(buf);\r
1087 }\r
1088 else\r
1089 {\r
1090 chain_forward="FORWARD";\r
1091 chain_postrouting="POSTROUTING";\r
1092 }\r
1093\r
260c2719 1094#ifdef DEBUG\r
007c44c5 1095 printf("%-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
260c2719 1096#endif\r
007c44c5 1097\r
1098 /* -------------------------------------------------------- mark download */\r
1099 \r
0b9c3c19 1100 sprintf(str, "-A %s -d %s/%d -o %s -j %s%d",\r
1101 chain_postrouting, ip->addr, 32*(1+ip->v6), lan, mark_iptables, ip->mark);\r
007c44c5 1102 /* -m limit --limit 1/s */ \r
0b9c3c19 1103 iptables_save_line(str, ip->v6);\r
007c44c5 1104\r
1105 if(qos_proxy)\r
1106 {\r
0b9c3c19 1107 sprintf(str, "-A %s -s %s -p tcp --sport %d -d %s/%d -o %s -j %s%d",\r
1108 chain_postrouting, proxy_ip, proxy_port, ip->addr, 32*(1+ip->v6), lan, mark_iptables, ip->mark);\r
1109 iptables_save_line(str, ip->v6);\r
007c44c5 1110 }\r
1111\r
0b9c3c19 1112 sprintf(str, "-A %s -d %s/%d -o %s -j ACCEPT",\r
1113 chain_postrouting, ip->addr, 32*(1+ip->v6), lan);\r
1114 iptables_save_line(str, ip->v6);\r
007c44c5 1115\r
1116 /* -------------------------------------------------------- mark upload */\r
0b9c3c19 1117 sprintf(str, "-A %s -s %s/%d -o %s -j %s%d", \r
1118 chain_forward, ip->addr, 32*(1+ip->v6), wan, mark_iptables, ip->mark);\r
1119 iptables_save_line(str, ip->v6);\r
007c44c5 1120\r
0b9c3c19 1121 sprintf(str, "-A %s -s %s/%d -o %s -j ACCEPT",\r
1122 chain_forward, ip->addr, 32*(1+ip->v6), wan);\r
1123 iptables_save_line(str, ip->v6);\r
007c44c5 1124\r
1125 if(ip->min)\r
1126 {\r
1127 /* -------------------------------------------------------- download class */\r
260c2719 1128#ifdef DEBUG\r
007c44c5 1129 printf("(down: %dk-%dk ", ip->min, ip->max); \r
260c2719 1130#endif\r
007c44c5 1131\r
be96b71b 1132 sprintf(str, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
1133 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
007c44c5 1134 safe_run(str);\r
1135\r
260c2719 1136 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
dee5592e 1137 {\r
0b9c3c19 1138 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s", \r
1139 tc, lan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
1140 safe_run(str);\r
be96b71b 1141 }\r
1142\r
260c2719 1143 if(filter_type == 1)\r
dee5592e 1144 {\r
0b9c3c19 1145 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
1146 tc, lan, ip->mark, ip->mark);\r
1147 safe_run(str);\r
007c44c5 1148 }\r
1149\r
1150 /* -------------------------------------------------------- upload class */\r
260c2719 1151#ifdef DEBUG\r
007c44c5 1152 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1153 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
260c2719 1154#endif\r
007c44c5 1155\r
1156 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1157 tc, wan, ip->group, ip->mark,\r
1158 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1159 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1160 safe_run(str);\r
1161 \r
260c2719 1162 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
dee5592e 1163 {\r
0b9c3c19 1164 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s",\r
1165 tc, wan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
1166 safe_run(str);\r
dee5592e 1167 } \r
be96b71b 1168\r
260c2719 1169 if(filter_type == 1)\r
dee5592e 1170 {\r
0b9c3c19 1171 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
1172 tc, wan, ip->mark, ip->mark);\r
1173 safe_run(str);\r
007c44c5 1174 }\r
be96b71b 1175 \r
6fb3c58a 1176 if(f > 0)\r
be96b71b 1177 {\r
0b9c3c19 1178 fprintf(f, "%s %d\n", ip->addr, ip->mark);\r
be96b71b 1179 }\r
007c44c5 1180 }\r
1181 else\r
260c2719 1182 {\r
1183#ifdef DEBUG\r
007c44c5 1184 printf("(sharing %s)\n", ip->sharing);\r
260c2719 1185#endif\r
1186 }\r
007c44c5 1187 i++;\r
1188 }\r
6fb3c58a 1189 if(f > 0)\r
be96b71b 1190 {\r
1191 puts("done.");\r
1192 fclose(f);\r
1193 }\r
1194 \r
007c44c5 1195 if(idxs)\r
1196 {\r
0b9c3c19 1197 chain_forward = "forw_common";\r
1198 chain_postrouting = "post_common";\r
007c44c5 1199 }\r
1200 else\r
1201 {\r
0b9c3c19 1202 chain_forward = "FORWARD";\r
1203 chain_postrouting = "POSTROUTING";\r
007c44c5 1204 }\r
0b9c3c19 1205\r
1206 if(free_min)\r
007c44c5 1207 {\r
0b9c3c19 1208 final_chain = "ACCEPT";\r
1209 }\r
1210\r
1211 if(qos_proxy)\r
1212 {\r
1213 if(free_min) \r
1214 {\r
1215 sprintf(str, "-A %s -s %s -p tcp --sport %d -o %s -j %s%d",\r
1216 chain_postrouting,proxy_ip,proxy_port,lan,mark_iptables, 3);\r
1217 iptables_save_line(str, FALSE); /* only for IPv4 */\r
1218 }\r
1219 sprintf(str, "-A %s -s %s -p tcp --sport %d -o %s -j %s",\r
1220 chain_postrouting,proxy_ip,proxy_port,lan,final_chain);\r
1221 iptables_save_line(str, FALSE); /* only for IPv4 */\r
1222 }\r
1223\r
1224 if(free_min)\r
1225 {\r
1226 sprintf(str, "-A %s -o %s -j %s%d",\r
1227 chain_postrouting, lan, mark_iptables, 3);\r
1228 iptables_save_line(str, FALSE); /* only for IPv4 */\r
1229 }\r
1230\r
1231 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
1232 iptables_save_line(str, FALSE);\r
1233 if(ip6prefix)\r
1234 {\r
1235 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
1236 iptables_save_line(str, TRUE);\r
1237 }\r
1238\r
1239 if(free_min)\r
1240 {\r
1241 sprintf(str,"-A %s -o %s -j %s%d", chain_forward, wan, mark_iptables, 3);\r
1242 iptables_save_line(str, FALSE); /* only for IPv4 */\r
1243 }\r
1244\r
1245 sprintf(str,"-A %s -o %s -j %s", chain_forward, wan, final_chain);\r
1246 iptables_save_line(str, FALSE);\r
1247 if(ip6prefix)\r
1248 {\r
1249 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
1250 iptables_save_line(str, TRUE);\r
007c44c5 1251 }\r
abe9b855 1252\r
dee5592e 1253 if(free_min) /* allocate free bandwith if it is not zero... */ \r
1254 {\r
1255 /*-----------------------------------------------------------------*/\r
1256 puts("Generating free bandwith classes ...");\r
1257 /*-----------------------------------------------------------------*/\r
208112af 1258 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
be96b71b 1259 tc, lan, parent, free_min, free_max,burst, lowest_priority);\r
dee5592e 1260 safe_run(str);\r
208112af 1261 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
be96b71b 1262 tc, wan, parent, free_min, free_max, burst, lowest_priority);\r
dee5592e 1263 safe_run(str);\r
1264 /* tc SFQ */\r
260c2719 1265 if(strcmpi(qos_leaf, "none"))\r
dee5592e 1266 {\r
be96b71b 1267 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, lan, qos_leaf);\r
dee5592e 1268 safe_run(str);\r
1269 \r
be96b71b 1270 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, wan, qos_leaf);\r
dee5592e 1271 safe_run(str);\r
1272 } \r
1273 /* tc handle 1 fw flowid */\r
be96b71b 1274 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, lan);\r
dee5592e 1275 safe_run(str);\r
007c44c5 1276\r
be96b71b 1277 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, wan);\r
dee5592e 1278 safe_run(str);\r
007c44c5 1279 }\r
dee5592e 1280 printf("Total IP count: %d\n", i);\r
0b9c3c19 1281 run_iptables_restore();\r
260c2719 1282 if(log_file)\r
1283 {\r
1284 fclose(log_file);\r
1285 }\r
007c44c5 1286 return 0;\r
007c44c5 1287 /* that's all folks, thank you for reading it all the way up to this point ;-) */\r
1288 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */\r
1289}\r
This page took 1.650997 seconds and 4 git commands to generate.