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