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