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