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