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