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