/4 not /2 :-)
[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
0b9c3c19 10/* Modified by: xChaos, 20130124\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
0b9c3c19 32const char *version = "0.8.3-i";\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
007c44c5 121/* not yet implemented:\r
43cde5c3 122int fixed_packets = 0; maximum number of pps per IP address (not class!) \r
123int packet_limit = 5; maximum number of pps to htn CEIL, not rate !!! \r
007c44c5 124*/\r
43cde5c3 125FILE *log_file = NULL;\r
126char *kwd = "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */\r
007c44c5 127\r
208112af 128const int highest_priority = 0; /* highest HTB priority (HTB built-in value is 0) */\r
129const int lowest_priority = 7; /* lowest HTB priority (HTB built-in value is 7) */\r
130const int idxtable_treshold1 = 24; /* this is no longer configurable */\r
131const int idxtable_treshold2 = 12; /* this is no longer configurable */\r
132const int idxtable_bitmask1 = 3; /* this is no longer configurable */\r
133const int idxtable_bitmask2 = 3; /* this is no longer configurable */\r
007c44c5 134\r
1c9cae56 135struct IP *ips = NULL, *ip, *sharedip;\r
136struct Group *groups = NULL, *group;\r
137struct Keyword *keyword, *defaultkeyword=NULL, *keywords=NULL;\r
007c44c5 138\r
068f0e75 139void help(void);\r
140/* implemented in help.c */
141\r
d7357b63 142void get_traffic_statistics(const char *whichiptables, int ipv6);\r
f19d3cd0 143/* implemented in parseiptables.c */\r
144\r
b6fb849a 145void parse_ip_log(int argc, char **argv);\r
1ab008b9 146/* implemented in parselog.c */\r
b6fb849a 147\r
148void parse_hosts(char *hosts);\r
1ab008b9 149/* implemented in parsehosts.c */\r
150\r
151void write_json_traffic(char *json);\r
152/* implemented in json.c */\r
b6fb849a 153\r
9a56ab25 154void write_htmlandlogs(char *html, char *d, int total, int just_preview);\r
155/* implemented in htmlandlogs.c */\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
260c2719 340 if(!strcmpi(keyword->leaf_discipline, ""))\r
208112af 341 {\r
007c44c5 342 keyword->leaf_discipline = qos_leaf;\r
343 }\r
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
007c44c5 468 char *substring;\r
1c9cae56 469\r
9a56ab25 470 int parent = 1;\r
471 int just_flush = FALSE; /* deactivates all previous actions */\r
472 int nodelay = FALSE;\r
473 int just_preview = FALSE; /* preview - generate just stats */\r
474 int start_shaping = FALSE; /* apply FUP - requires classmap file */\r
62b118c2 475 int stop_shaping = FALSE; /* lift FUP - requires classmap file */\r
476 int reduce_ceil = 0; /* allow only rate+(ceil-rate)/2, /4, etc. */\r
9a56ab25 477 int just_logs = FALSE; /* just parse logs */\r
478 int run = FALSE;\r
479 int total = 0;\r
33ec95ab 480 \r
007c44c5 481 char *chain_forward, *chain_postrouting;\r
482 char *althosts=NULL;\r
483 \r
484 printf("\n\\r
485Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\\r
0b9c3c19 486Version %s - Copyright (C)2005-2013 Michael Polak, Arachne Labs\n\\r
43cde5c3 487iptables-restore & burst tunning & classify modification by Ludva\n\\r
0d5026c6 488Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version);\r
007c44c5 489\r
8e29188a 490 /*----- Boring... we have to check command line options first: ----*/ \r
007c44c5 491 arguments\r
492 {\r
493 argument("-c") { nextargument(config); }\r
494 argument("-h") { nextargument(althosts);}\r
208112af 495 argument("-d") { run=TRUE; dry_run=TRUE; }\r
496 argument("-f") { run=TRUE; just_flush=TRUE; }\r
497 argument("-9") { run=TRUE; just_flush=9; }\r
498 argument("-p") { run=TRUE; just_preview=TRUE; }\r
3f76726a 499 argument("-q") { run=TRUE; just_preview=TRUE; stop_shaping=TRUE; }\r
62b118c2 500 argument("-2") { run=TRUE; just_preview=TRUE; reduce_ceil=2; }\r
501 argument("-4") { run=TRUE; just_preview=TRUE; reduce_ceil=4; }\r
8e29188a 502 argument("-s") { run=TRUE; just_preview=TRUE; start_shaping=TRUE; }\r
208112af 503 argument("-r") { run=TRUE; }\r
504 argument("-n") { run=TRUE; nodelay=TRUE; }\r
505 argument("-l") { just_logs=TRUE; }\r
506 argument("-m") { just_logs=TRUE; }\r
507 argument("-y") { just_logs=TRUE; }\r
007c44c5 508 argument("-?") { help(); exit(0); }\r
509 argument("--help") { help(); exit(0); }\r
510 argument("-v") { exit(0); } \r
511 argument("--version") { exit(0); } \r
512 }\r
208112af 513 \r
007c44c5 514 if(dry_run)\r
208112af 515 {\r
007c44c5 516 puts("*** THIS IS JUST DRY RUN ! ***\n");\r
208112af 517 }\r
007c44c5 518\r
208112af 519 date(d); /* this is typical cll1.h macro - prints current date */\r
007c44c5 520\r
521 /*-----------------------------------------------------------------*/\r
522 printf("Parsing configuration file %s ...\n", config);\r
523 /*-----------------------------------------------------------------*/\r
524 get_config(config);\r
c9012978 525 \r
33ec95ab 526 if(just_logs)\r
c9012978 527 {\r
208112af 528 parse_ip_log(argc,argv);\r
529 exit(0);\r
530 }\r
531 else if(not run)\r
532 {\r
533 help();\r
534 exit(0);\r
c9012978 535 }\r
007c44c5 536\r
208112af 537 if(althosts)\r
538 {\r
539 hosts=althosts;\r
540 }\r
007c44c5 541\r
542 if(just_flush<9)\r
543 {\r
544 /*-----------------------------------------------------------------*/\r
545 puts("Parsing iptables verbose output ...");\r
546 /*-----------------------------------------------------------------*/\r
d7357b63 547 get_traffic_statistics(iptables, FALSE);\r
0b9c3c19 548 if(ip6prefix)\r
549 {\r
550 /*-----------------------------------------------------------------*/\r
551 puts("Parsing ip6tables verbose output ...");\r
552 /*-----------------------------------------------------------------*/ \r
d7357b63 553 get_traffic_statistics(ip6tables, TRUE);\r
0b9c3c19 554 }\r
007c44c5 555 }\r
556\r
557 /*-----------------------------------------------------------------*/\r
558 printf("Parsing class defintion file %s ...\n", hosts);\r
559 /*-----------------------------------------------------------------*/\r
1c9cae56 560 parse_hosts(hosts);\r
007c44c5 561\r
562 /*-----------------------------------------------------------------*/\r
563 /* cll1.h - let's allocate brand new character buffer... */\r
564 /*-----------------------------------------------------------------*/\r
565 string(str,STRLEN); \r
566\r
567 /*-----------------------------------------------------------------*/\r
568 puts("Resolving shared connections ...");\r
569 /*-----------------------------------------------------------------*/\r
6cc38f96 570 for_each(ip,ips) if(ip->sharing)\r
007c44c5 571 {\r
b1a5c883 572 for_each(sharedip,ips) if(eq(sharedip->name, ip->sharing))\r
007c44c5 573 {\r
b1a5c883 574 sharedip->traffic += ip->traffic;\r
575 ip->traffic = 0;\r
576 ip->mark = sharedip->mark; \r
577 ip->lmsid = sharedip->lmsid;\r
007c44c5 578 break;\r
579 }\r
1c9cae56 580 if(not sharedip)\r
bb9e11ee 581 {\r
260c2719 582 printf("Unresolved shared connection: %s %s sharing-%s\n",\r
583 ip->addr, ip->name, ip->sharing);\r
bb9e11ee 584 }\r
007c44c5 585 }\r
586\r
587 if(enable_credit && just_flush<9)\r
588 {\r
589 /*-----------------------------------------------------------------*/\r
590 printf("Parsing credit file %s ...\n", credit);\r
591 /*-----------------------------------------------------------------*/\r
592 parse(credit)\r
593 {\r
594 ptr=parse_datafile_line(_);\r
595 if(ptr)\r
596 {\r
208112af 597 if_exists(ip,ips,eq(ip->addr,_))\r
598 {\r
007c44c5 599 sscanf(ptr,"%Lu",&(ip->credit));\r
208112af 600 }\r
007c44c5 601 }\r
602 }\r
8e29188a 603 done; /* ugly macro end */\r
007c44c5 604 }\r
605\r
606 if(!just_preview)\r
607 {\r
608 /*-----------------------------------------------------------------*/\r
609 puts("Initializing iptables and tc classes ...");\r
610 /*-----------------------------------------------------------------*/\r
611 \r
f64d5431 612 iptables_file = fopen(iptablesfile, "w");\r
260c2719 613 if(iptables_file == NULL)\r
bb9e11ee 614 {\r
f64d5431 615 perror(iptablesfile);\r
007c44c5 616 exit(-1);\r
617 }\r
0b9c3c19 618 iptables_save_line(iptablespreamble, FALSE);\r
619\r
620 if(ip6prefix)\r
621 {\r
622 ip6tables_file = fopen(ip6tablesfile, "w");\r
623 if(ip6tables_file == NULL)\r
624 {\r
625 perror(ip6tablesfile);\r
626 exit(-1);\r
627 }\r
628 iptables_save_line(iptablespreamble, TRUE);\r
e36b49c7 629 iptables_save_line(ip6preamble, TRUE);\r
0b9c3c19 630 }\r
631\r
632 run_iptables_restore();\r
007c44c5 633 \r
f64d5431 634 log_file = fopen(cmdlog, "w");\r
260c2719 635 if(log_file == NULL) \r
bb9e11ee 636 {\r
f64d5431 637 perror(cmdlog);\r
007c44c5 638 exit(-1);\r
ca6f7e80 639 } \r
007c44c5 640 \r
641 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,lan);\r
642 safe_run(str);\r
643\r
644 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,wan);\r
645 safe_run(str);\r
646 \r
647 iptables_file=fopen(iptablesfile,"w");\r
0b9c3c19 648 iptables_save_line(iptablespreamble, FALSE);\r
649 if(ip6prefix)\r
650 {\r
651 ip6tables_file=fopen(ip6tablesfile,"w");\r
652 iptables_save_line(iptablespreamble, TRUE);\r
e36b49c7 653 iptables_save_line(ip6preamble, TRUE);\r
0b9c3c19 654 }\r
007c44c5 655\r
0b9c3c19 656 if(qos_free_zone && *qos_free_zone!='0') /* this is currently supported only for IPv4 */\r
007c44c5 657 {\r
658 char *chain;\r
659 \r
660 sprintf(str,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone, wan);\r
0b9c3c19 661 iptables_save_line(str, FALSE); /* this is currently supported only for IPv4 */\r
007c44c5 662 \r
663 if(qos_proxy)\r
664 {\r
0b9c3c19 665 iptables_save_line(":post_noproxy - [0:0]", FALSE);\r
6b39193d 666 sprintf(str,"-A POSTROUTING ! -p tcp -o %s -j post_noproxy", lan);\r
0b9c3c19 667 iptables_save_line(str , FALSE);\r
6b39193d 668 sprintf(str,"-A POSTROUTING ! -s %s -o %s -j post_noproxy", proxy_ip, lan);\r
0b9c3c19 669 iptables_save_line(str, FALSE);\r
6b39193d 670 sprintf(str,"-A POSTROUTING -s %s -p tcp ! --sport %d -o %s -j post_noproxy", proxy_ip, proxy_port, lan);\r
0b9c3c19 671 iptables_save_line(str, FALSE);\r
007c44c5 672\r
673 chain="post_noproxy"; \r
674 }\r
675 else\r
bb9e11ee 676 {\r
007c44c5 677 chain="POSTROUTING";\r
bb9e11ee 678 }\r
007c44c5 679 \r
680 sprintf(str,"-A %s -s %s -o %s -j ACCEPT", chain, qos_free_zone, lan);\r
0b9c3c19 681 iptables_save_line(str, FALSE);\r
007c44c5 682 }\r
683 \r
f64d5431 684 if(ip_count > idxtable_treshold1 && !just_flush)\r
007c44c5 685 {\r
0b9c3c19 686 int idxcount=0, bitmask=32-idxtable_bitmask1;\r
e0161edb 687 char *subnet, *buf;\r
007c44c5 688 /*-----------------------------------------------------------------*/\r
689 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count);\r
690 /*-----------------------------------------------------------------*/\r
691\r
0b9c3c19 692 iptables_save_line(":post_common - [0:0]", FALSE);\r
693 iptables_save_line(":forw_common - [0:0]", FALSE);\r
694 if(ip6prefix)\r
695 {\r
696 iptables_save_line(":post_common - [0:0]", TRUE);\r
697 iptables_save_line(":forw_common - [0:0]", TRUE);\r
698 }\r
007c44c5 699\r
0b9c3c19 700 for_each(ip,ips) if(ip->addr && *(ip->addr) && !eq(ip->addr,"0.0.0.0/0")) \r
007c44c5 701 {\r
0b9c3c19 702 if(ip->v6)\r
703 {\r
704 buf=index6_id(ip->addr,bitmask+32);\r
705 }\r
706 else\r
707 {\r
708 buf=index_id(ip->addr, bitmask);\r
709 }\r
710 \r
208112af 711 if_exists(idx,idxs,eq(idx->id,buf))\r
712 {\r
007c44c5 713 idx->children++;\r
208112af 714 }\r
007c44c5 715 else\r
716 {\r
717 create(idx,Index);\r
0b9c3c19 718 idx->addr = ip->addr;\r
719 idx->id = buf;\r
720 idx->bitmask = bitmask+32*ip->v6;\r
721 idx->parent = NULL;\r
722 idx->children = 0;\r
723 idx->ipv6 = ip->v6;\r
007c44c5 724 idxcount++;\r
725 push(idx,idxs);\r
726 }\r
727 }\r
728\r
729 /* brutal perfomance optimalization */\r
f64d5431 730 while(idxcount > idxtable_treshold2 && bitmask > 2*idxtable_bitmask2)\r
007c44c5 731 {\r
f64d5431 732 bitmask -= idxtable_bitmask2;\r
733 idxcount = 0;\r
208112af 734\r
6cc38f96 735 for_each(idx,idxs) if(idx->parent == NULL)\r
007c44c5 736 {\r
0b9c3c19 737 if(idx->ipv6)\r
738 {\r
739 buf = index6_id(idx->addr, bitmask+32);\r
740 }\r
741 else\r
742 {\r
743 buf = index_id(idx->addr, bitmask);\r
744 }\r
208112af 745 if_exists(metaindex,idxs,eq(metaindex->id,buf))\r
746 {\r
747 metaindex->children++;\r
748 }\r
007c44c5 749 else\r
750 {\r
751 create(metaindex,Index);\r
0b9c3c19 752 metaindex->addr = idx->addr;\r
753 metaindex->id = buf;\r
754 metaindex->bitmask = bitmask+32*idx->ipv6;\r
755 metaindex->parent = NULL;\r
756 metaindex->children = 0;\r
757 metaindex->ipv6 = idx->ipv6;\r
007c44c5 758 idxcount++;\r
759 push(metaindex,idxs);\r
760 }\r
761 idx->parent=metaindex;\r
762 }\r
763 }\r
764\r
f64d5431 765 /* this should slightly optimize throughput ... */\r
007c44c5 766 sort(idx,idxs,desc_order_by,children);\r
767 sort(idx,idxs,order_by,bitmask);\r
768\r
769 i=0;\r
208112af 770 for_each(idx,idxs)\r
007c44c5 771 {\r
0b9c3c19 772 if(idx->ipv6)\r
773 {\r
774 subnet=subnet6_id(idx->addr, idx->bitmask);\r
775 }\r
776 else\r
777 {\r
778 subnet=subnet_id(idx->addr, idx->bitmask);\r
779 }\r
780 printf("%d: %s/%d\n", ++i, subnet, idx->bitmask);\r
007c44c5 781 \r
782 sprintf(str,":post_%s - [0:0]", idx->id);\r
0b9c3c19 783 iptables_save_line(str, idx->ipv6);\r
007c44c5 784\r
785 sprintf(str,":forw_%s - [0:0]", idx->id);\r
0b9c3c19 786 iptables_save_line(str, idx->ipv6);\r
007c44c5 787\r
788 if(idx->parent)\r
789 {\r
790 string(buf,strlen(idx->parent->id)+6);\r
0b9c3c19 791 sprintf(buf,"post_%s", idx->parent->id);\r
007c44c5 792 }\r
793 else\r
bb9e11ee 794 {\r
007c44c5 795 buf="POSTROUTING";\r
bb9e11ee 796 }\r
007c44c5 797\r
798 sprintf(str,"-A %s -d %s/%d -o %s -j post_%s", buf, subnet, idx->bitmask, lan, idx->id);\r
0b9c3c19 799 iptables_save_line(str, idx->ipv6);\r
007c44c5 800\r
801 sprintf(str,"-A %s -d %s/%d -o %s -j post_common", buf, subnet, idx->bitmask, lan);\r
0b9c3c19 802 iptables_save_line(str, idx->ipv6);\r
007c44c5 803\r
804 if(idx->parent)\r
805 {\r
806 string(buf,strlen(idx->parent->id)+6);\r
807 sprintf(buf,"forw_%s",idx->parent->id);\r
808 }\r
809 else\r
bb9e11ee 810 {\r
007c44c5 811 buf="FORWARD";\r
bb9e11ee 812 }\r
007c44c5 813\r
814 sprintf(str,"-A %s -s %s/%d -o %s -j forw_%s", buf, subnet, idx->bitmask, wan, idx->id);\r
0b9c3c19 815 iptables_save_line(str, idx->ipv6);\r
007c44c5 816\r
817 sprintf(str,"-A %s -s %s/%d -o %s -j forw_common", buf, subnet, idx->bitmask, wan);\r
0b9c3c19 818 iptables_save_line(str, idx->ipv6);\r
007c44c5 819 }\r
820 printf("Total indexed iptables chains created: %d\n", i);\r
821\r
822 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);\r
0b9c3c19 823 iptables_save_line(str, FALSE);\r
007c44c5 824 \r
825 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);\r
0b9c3c19 826 iptables_save_line(str, FALSE);\r
827\r
828 if(ip6prefix)\r
829 {\r
830 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);\r
831 iptables_save_line(str, TRUE);\r
832 \r
833 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);\r
834 iptables_save_line(str, TRUE);\r
835 }\r
007c44c5 836 }\r
007c44c5 837 }\r
838\r
839 if(just_flush)\r
840 {\r
841 fclose(iptables_file);\r
add90548 842 if(log_file)\r
843 { \r
844 fclose(log_file);\r
845 }\r
007c44c5 846 puts("Just flushed iptables and tc classes - now exiting ...");\r
847 exit(0);\r
848 }\r
849\r
850 if(!just_preview)\r
851 {\r
852 if(!dry_run && !nodelay && qos_free_delay)\r
853 {\r
854 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay);\r
855 sleep(qos_free_delay);\r
856 }\r
857\r
6cc38f96 858 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",\r
859 tc,lan,htb_r2q);\r
007c44c5 860 safe_run(str);\r
861\r
208112af 862 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
863 tc,lan,lan_medium,lan_medium,burst_main,highest_priority);\r
007c44c5 864 safe_run(str);\r
865\r
208112af 866 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
867 tc,lan,line,line,burst_main,highest_priority);\r
007c44c5 868 safe_run(str);\r
869\r
870 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc,wan,htb_r2q);\r
871 safe_run(str);\r
872\r
208112af 873 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
874 tc,wan,wan_medium,wan_medium,burst_main,highest_priority);\r
007c44c5 875 safe_run(str);\r
876\r
208112af 877 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
878 tc,wan,up,up,burst_main,highest_priority);\r
007c44c5 879 safe_run(str);\r
880 }\r
881\r
882 /*-----------------------------------------------------------------*/\r
208112af 883 puts("Locating heavy downloaders and generating root classes ...");\r
007c44c5 884 /*-----------------------------------------------------------------*/\r
bb9e11ee 885 sort(ip,ips,desc_order_by,traffic); \r
007c44c5 886\r
887 /*-----------------------------------------------------------------*/\r
888 /* sub-scope - local variables */ \r
889 {\r
6cc38f96 890 long long int rate = line;\r
891 long long int max = line;\r
892 int group_count = 0;\r
893 FILE *credit_file = NULL;\r
007c44c5 894 \r
4358455e 895 if(!just_preview && !dry_run && enable_credit)\r
896 {\r
6cc38f96 897 credit_file = fopen(credit,"w");\r
4358455e 898 }\r
007c44c5 899 \r
208112af 900 for_each(group,groups)\r
007c44c5 901 {\r
902 if(!just_preview)\r
903 {\r
007c44c5 904 //download\r
208112af 905 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d #down desired %d", \r
906 tc, lan, parent, group->id, rate, max, burst_group, highest_priority+1, group->desired);\r
007c44c5 907 safe_run(str);\r
908 \r
909 //upload\r
208112af 910 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
911 tc, wan, parent, group->id, rate*up/line, max*up/line, burst_group, highest_priority+1, group->desired);\r
007c44c5 912 safe_run(str);\r
913 }\r
914 \r
6cc38f96 915 if(group_count++ < max_nesting)\r
bb9e11ee 916 {\r
6cc38f96 917 parent = group->id;\r
bb9e11ee 918 }\r
007c44c5 919 \r
6cc38f96 920 rate -= digital_divide*group->min;\r
921 if(rate < group->min)\r
4358455e 922 {\r
6cc38f96 923 rate = group->min;\r
4358455e 924 }\r
007c44c5 925 \r
926 /*shaping of aggresive downloaders, with credit file support */\r
927 if(use_credit)\r
928 {\r
6cc38f96 929 int group_rate = group->min, priority_sequence = lowest_priority;\r
007c44c5 930 \r
6cc38f96 931 for_each(ip, ips) if(ip->min == group->min && ip->max > ip->min)\r
007c44c5 932 {\r
e48d46c9 933 ip->realquota=ip->credit+(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20));\r
934 if( ip->keyword->data_limit \r
935 and not ip->fixedprio \r
936 and ip->traffic > ip->realquota )\r
007c44c5 937 {\r
e48d46c9 938 if(group_rate < ip->max)\r
4358455e 939 {\r
e48d46c9 940 ip->max = group_rate;\r
4358455e 941 }\r
007c44c5 942 group_rate+=magic_treshold;\r
208112af 943 ip->prio=lowest_priority;\r
4358455e 944 if(ip->prio<highest_priority+2)\r
945 {\r
946 ip->prio=highest_priority+2;\r
947 }\r
007c44c5 948 }\r
949 else\r
950 {\r
6cc38f96 951 if( ip->keyword->data_prio \r
952 && !ip->fixedprio \r
953 && ( ip->traffic>ip->credit\r
954 + (ip->min*ip->keyword->data_prio+(ip->keyword->fixed_prio<<20))) )\r
007c44c5 955 {\r
956 ip->prio=priority_sequence--;\r
4358455e 957 if(ip->prio<highest_priority+1)\r
958 {\r
959 ip->prio=highest_priority+1;\r
960 }\r
007c44c5 961 }\r
962 \r
963 if(credit_file)\r
964 {\r
965 unsigned long long lcredit=0;\r
99127c70 966 \r
4358455e 967 if((ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))>ip->traffic)\r
968 {\r
007c44c5 969 lcredit=(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))-ip->traffic;\r
4358455e 970 }\r
007c44c5 971 fprintf(credit_file,"%s %Lu\n",ip->addr,lcredit);\r
972 }\r
973 }\r
6cc38f96 974 } \r
007c44c5 975 }\r
976 }\r
4358455e 977 if(credit_file)\r
978 {\r
979 fclose(credit_file);\r
980 }\r
007c44c5 981 }\r
982\r
983 if(just_preview)\r
984 {\r
62b118c2 985 if(start_shaping || stop_shaping || reduce_ceil)\r
8e29188a 986 {\r
987 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap);\r
988 parse(classmap)\r
989 {\r
990 ptr=strchr(_,' ');\r
991 if(ptr)\r
992 {\r
993 *ptr=0;\r
994 ptr++;\r
995 if_exists(ip,ips,eq(ip->addr,_))\r
996 {\r
997 ip->mark=atoi(ptr);\r
62b118c2 998 if(ip->max < ip->desired || stop_shaping || reduce_ceil) /* apply or disable FUP limit immediately.... */\r
8e29188a 999 {\r
3f76726a 1000 if(stop_shaping)\r
1001 {\r
1002 ip->max = ip->desired;\r
1003 printf("Removing limit for %-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
1004 }\r
1005 else\r
1006 {\r
62b118c2 1007 printf("Applying limit for %-22s %-16s %04d ", ip->name, ip->addr, ip->mark);\r
1008 if(reduce_ceil)\r
1009 {\r
1010 ip->max = ip->min + (ip->desired-ip->min)/reduce_ceil;\r
1011 }\r
3f76726a 1012 }\r
8e29188a 1013 printf("(down: %dk-%dk ", ip->min, ip->max); \r
1014 sprintf(str, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
1015 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
1016 safe_run(str);\r
1017 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1018 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
1019 sprintf(str,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1020 tc, wan, ip->group, ip->mark,\r
1021 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1022 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1023 safe_run(str);\r
1024 }\r
1025 }\r
1026 }\r
1027 }\r
1028 fail\r
1029 { \r
1030 perror(classmap);\r
1031 puts("Warning - classmap file not fund, just generating preview ...");\r
1032 start_shaping=FALSE;\r
3f76726a 1033 stop_shaping=FALSE;\r
8e29188a 1034 }\r
1035 done; /* ugly macro end */\r
1036 }\r
6fb3c58a 1037 html=preview;\r
1ab008b9 1038 json_traffic=json_preview;\r
007c44c5 1039 }\r
6fb3c58a 1040\r
1041 if(!dry_run && !just_flush)\r
007c44c5 1042 {\r
1043 /*-----------------------------------------------------------------*/\r
1ab008b9 1044 printf("Writing json traffic overview %s ... ", json_traffic);\r
007c44c5 1045 /*-----------------------------------------------------------------*/\r
1ab008b9 1046 write_json_traffic(json_traffic);\r
007c44c5 1047\r
0b9c3c19 1048 /*-----------------------------------------------------------------*/\r
1049 printf("Writing statistics into HTML page %s ...\n", html);\r
1050 /*-----------------------------------------------------------------*/\r
1051 write_htmlandlogs(html, d, total, just_preview);\r
1052 }\r
007c44c5 1053\r
1054 if(just_preview)\r
1055 {\r
8e29188a 1056 char swchar='p';\r
1057 if(start_shaping)\r
1058 {\r
1059 swchar='s';\r
1060 }\r
62b118c2 1061 else if(reduce_ceil)\r
1062 {\r
1063 swchar='0'+reduce_ceil; /* -2, -4 */\r
1064 }\r
3f76726a 1065 else if(stop_shaping)\r
1066 {\r
1067 swchar='q';\r
1068 }\r
1069\r
8e29188a 1070 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar);\r
007c44c5 1071 exit(0);\r
be96b71b 1072 } \r
007c44c5 1073\r
1074 i=0;\r
260c2719 1075#ifdef DEBUG\r
007c44c5 1076 printf("%-22s %-15s mark\n","name","ip");\r
260c2719 1077#endif\r
208112af 1078\r
14e28c6f 1079 printf("Writing %s", classmap); \r
be96b71b 1080 f = fopen(classmap, "w"); \r
1081 if(f < 0)\r
1082 {\r
1083 perror(classmap);\r
1084 }\r
1085\r
1086 /*-----------------------------------------------------------------*/\r
0995c4ad 1087 printf(" + generating iptables and tc classes ... ");\r
be96b71b 1088 /*-----------------------------------------------------------------*/\r
1089\r
0b9c3c19 1090 for_each(ip, ips) if(ip->mark > 0) /* works only for IPv4 so far */\r
be96b71b 1091 {\r
007c44c5 1092 if(idxs)\r
1093 {\r
1094 char *buf;\r
1095 duplicate(ip->addr,buf);\r
0b9c3c19 1096 if(ip->v6)\r
1097 {\r
1098 buf=index6_id(ip->addr,64-idxtable_bitmask1);\r
1099 }\r
1100 else\r
1101 {\r
1102 buf=index_id(ip->addr,32-idxtable_bitmask1);\r
1103 }\r
007c44c5 1104 \r
1105 string(chain_forward,6+strlen(buf));\r
1106 strcpy(chain_forward,"forw_");\r
1107 strcat(chain_forward,buf);\r
1108\r
1109 string(chain_postrouting,6+strlen(buf));\r
1110 strcpy(chain_postrouting,"post_");\r
1111 strcat(chain_postrouting,buf);\r
1112 \r
1113 free(buf);\r
1114 }\r
1115 else\r
1116 {\r
1117 chain_forward="FORWARD";\r
1118 chain_postrouting="POSTROUTING";\r
1119 }\r
1120\r
260c2719 1121#ifdef DEBUG\r
007c44c5 1122 printf("%-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
260c2719 1123#endif\r
007c44c5 1124\r
1125 /* -------------------------------------------------------- mark download */\r
1126 \r
0b9c3c19 1127 sprintf(str, "-A %s -d %s/%d -o %s -j %s%d",\r
1128 chain_postrouting, ip->addr, 32*(1+ip->v6), lan, mark_iptables, ip->mark);\r
007c44c5 1129 /* -m limit --limit 1/s */ \r
0b9c3c19 1130 iptables_save_line(str, ip->v6);\r
007c44c5 1131\r
1132 if(qos_proxy)\r
1133 {\r
0b9c3c19 1134 sprintf(str, "-A %s -s %s -p tcp --sport %d -d %s/%d -o %s -j %s%d",\r
1135 chain_postrouting, proxy_ip, proxy_port, ip->addr, 32*(1+ip->v6), lan, mark_iptables, ip->mark);\r
1136 iptables_save_line(str, ip->v6);\r
007c44c5 1137 }\r
1138\r
0b9c3c19 1139 sprintf(str, "-A %s -d %s/%d -o %s -j ACCEPT",\r
1140 chain_postrouting, ip->addr, 32*(1+ip->v6), lan);\r
1141 iptables_save_line(str, ip->v6);\r
007c44c5 1142\r
1143 /* -------------------------------------------------------- mark upload */\r
0b9c3c19 1144 sprintf(str, "-A %s -s %s/%d -o %s -j %s%d", \r
1145 chain_forward, ip->addr, 32*(1+ip->v6), wan, mark_iptables, ip->mark);\r
1146 iptables_save_line(str, ip->v6);\r
007c44c5 1147\r
0b9c3c19 1148 sprintf(str, "-A %s -s %s/%d -o %s -j ACCEPT",\r
1149 chain_forward, ip->addr, 32*(1+ip->v6), wan);\r
1150 iptables_save_line(str, ip->v6);\r
007c44c5 1151\r
1152 if(ip->min)\r
1153 {\r
1154 /* -------------------------------------------------------- download class */\r
260c2719 1155#ifdef DEBUG\r
007c44c5 1156 printf("(down: %dk-%dk ", ip->min, ip->max); \r
260c2719 1157#endif\r
007c44c5 1158\r
be96b71b 1159 sprintf(str, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
1160 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
007c44c5 1161 safe_run(str);\r
1162\r
260c2719 1163 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
dee5592e 1164 {\r
0b9c3c19 1165 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s", \r
1166 tc, lan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
1167 safe_run(str);\r
be96b71b 1168 }\r
1169\r
260c2719 1170 if(filter_type == 1)\r
dee5592e 1171 {\r
0b9c3c19 1172 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
1173 tc, lan, ip->mark, ip->mark);\r
1174 safe_run(str);\r
007c44c5 1175 }\r
1176\r
1177 /* -------------------------------------------------------- upload class */\r
260c2719 1178#ifdef DEBUG\r
007c44c5 1179 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1180 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
260c2719 1181#endif\r
007c44c5 1182\r
1183 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1184 tc, wan, ip->group, ip->mark,\r
1185 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1186 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1187 safe_run(str);\r
1188 \r
260c2719 1189 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
dee5592e 1190 {\r
0b9c3c19 1191 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s",\r
1192 tc, wan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
1193 safe_run(str);\r
dee5592e 1194 } \r
be96b71b 1195\r
260c2719 1196 if(filter_type == 1)\r
dee5592e 1197 {\r
0b9c3c19 1198 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
1199 tc, wan, ip->mark, ip->mark);\r
1200 safe_run(str);\r
007c44c5 1201 }\r
be96b71b 1202 \r
6fb3c58a 1203 if(f > 0)\r
be96b71b 1204 {\r
0b9c3c19 1205 fprintf(f, "%s %d\n", ip->addr, ip->mark);\r
be96b71b 1206 }\r
007c44c5 1207 }\r
1208 else\r
260c2719 1209 {\r
1210#ifdef DEBUG\r
007c44c5 1211 printf("(sharing %s)\n", ip->sharing);\r
260c2719 1212#endif\r
1213 }\r
007c44c5 1214 i++;\r
1215 }\r
6fb3c58a 1216 if(f > 0)\r
be96b71b 1217 {\r
1218 puts("done.");\r
1219 fclose(f);\r
1220 }\r
1221 \r
007c44c5 1222 if(idxs)\r
1223 {\r
0b9c3c19 1224 chain_forward = "forw_common";\r
1225 chain_postrouting = "post_common";\r
007c44c5 1226 }\r
1227 else\r
1228 {\r
0b9c3c19 1229 chain_forward = "FORWARD";\r
1230 chain_postrouting = "POSTROUTING";\r
007c44c5 1231 }\r
0b9c3c19 1232\r
1233 if(free_min)\r
007c44c5 1234 {\r
0b9c3c19 1235 final_chain = "ACCEPT";\r
1236 }\r
1237\r
1238 if(qos_proxy)\r
1239 {\r
1240 if(free_min) \r
1241 {\r
1242 sprintf(str, "-A %s -s %s -p tcp --sport %d -o %s -j %s%d",\r
1243 chain_postrouting,proxy_ip,proxy_port,lan,mark_iptables, 3);\r
1244 iptables_save_line(str, FALSE); /* only for IPv4 */\r
1245 }\r
1246 sprintf(str, "-A %s -s %s -p tcp --sport %d -o %s -j %s",\r
1247 chain_postrouting,proxy_ip,proxy_port,lan,final_chain);\r
1248 iptables_save_line(str, FALSE); /* only for IPv4 */\r
1249 }\r
1250\r
1251 if(free_min)\r
1252 {\r
1253 sprintf(str, "-A %s -o %s -j %s%d",\r
1254 chain_postrouting, lan, mark_iptables, 3);\r
1255 iptables_save_line(str, FALSE); /* only for IPv4 */\r
1256 }\r
1257\r
1258 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
1259 iptables_save_line(str, FALSE);\r
1260 if(ip6prefix)\r
1261 {\r
1262 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
1263 iptables_save_line(str, TRUE);\r
1264 }\r
1265\r
1266 if(free_min)\r
1267 {\r
1268 sprintf(str,"-A %s -o %s -j %s%d", chain_forward, wan, mark_iptables, 3);\r
1269 iptables_save_line(str, FALSE); /* only for IPv4 */\r
1270 }\r
1271\r
1272 sprintf(str,"-A %s -o %s -j %s", chain_forward, wan, final_chain);\r
1273 iptables_save_line(str, FALSE);\r
1274 if(ip6prefix)\r
1275 {\r
1276 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
1277 iptables_save_line(str, TRUE);\r
007c44c5 1278 }\r
abe9b855 1279\r
dee5592e 1280 if(free_min) /* allocate free bandwith if it is not zero... */ \r
1281 {\r
1282 /*-----------------------------------------------------------------*/\r
1283 puts("Generating free bandwith classes ...");\r
1284 /*-----------------------------------------------------------------*/\r
208112af 1285 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
be96b71b 1286 tc, lan, parent, free_min, free_max,burst, lowest_priority);\r
dee5592e 1287 safe_run(str);\r
208112af 1288 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
be96b71b 1289 tc, wan, parent, free_min, free_max, burst, lowest_priority);\r
dee5592e 1290 safe_run(str);\r
1291 /* tc SFQ */\r
260c2719 1292 if(strcmpi(qos_leaf, "none"))\r
dee5592e 1293 {\r
be96b71b 1294 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, lan, qos_leaf);\r
dee5592e 1295 safe_run(str);\r
1296 \r
be96b71b 1297 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, wan, qos_leaf);\r
dee5592e 1298 safe_run(str);\r
1299 } \r
1300 /* tc handle 1 fw flowid */\r
be96b71b 1301 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, lan);\r
dee5592e 1302 safe_run(str);\r
007c44c5 1303\r
be96b71b 1304 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, wan);\r
dee5592e 1305 safe_run(str);\r
007c44c5 1306 }\r
dee5592e 1307 printf("Total IP count: %d\n", i);\r
0b9c3c19 1308 run_iptables_restore();\r
260c2719 1309 if(log_file)\r
1310 {\r
1311 fclose(log_file);\r
1312 }\r
007c44c5 1313 return 0;\r
007c44c5 1314 /* that's all folks, thank you for reading it all the way up to this point ;-) */\r
1315 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */\r
1316}\r
This page took 1.533331 seconds and 4 git commands to generate.