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