macro definitions...
[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 = 3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */\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 (HTB built-in value is 7) */\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 class defintion file %s ...\n", hosts);\r
586 /*-----------------------------------------------------------------*/\r
587 parse_hosts(hosts);\r
588 if(just_networks)\r
589 {\r
590 analyse_topology("/usr/sbin/traceroute -n -m 10 -w 2 %s.%d");\r
591 exit(-1); \r
592 }\r
593\r
594 /*-----------------------------------------------------------------*/\r
595 puts("Resolving shared connections ...");\r
596 /*-----------------------------------------------------------------*/\r
597 for_each(ip, ips) if(ip->sharing)\r
598 {\r
599 for_each(sharedip, ips) if(eq(sharedip->name, ip->sharing))\r
600 {\r
601 sharedip->traffic += ip->traffic;\r
602 ip->traffic = 0;\r
603 ip->mark = sharedip->mark; \r
604 ip->lmsid = sharedip->lmsid;\r
605 ip->pps_limit = sharedip->pps_limit; /* no other way to do this */\r
606 break;\r
607 }\r
608 if(not sharedip)\r
609 {\r
610 printf("Unresolved shared connection: %s %s sharing-%s\n",\r
611 ip->addr, ip->name, ip->sharing);\r
612 }\r
613 }\r
614\r
615 if(enable_credit && just_flush<9)\r
616 {\r
617 /*-----------------------------------------------------------------*/\r
618 printf("Parsing credit file %s ...\n", credit);\r
619 /*-----------------------------------------------------------------*/\r
620 parse(credit)\r
621 {\r
622 ptr = parse_datafile_line(_);\r
623 if(ptr)\r
624 {\r
625 if_exists(ip,ips,eq(ip->addr,_))\r
626 {\r
627 sscanf(ptr,"%Lu",&(ip->credit));\r
628 }\r
629 }\r
630 }\r
631 done; /* ugly macro end */\r
632 }\r
633\r
634 if(enable_credit && just_flush<9)\r
635 {\r
636 /*-----------------------------------------------------------------*/\r
637 printf("Parsing macro definition file %s ...\n", macrosfile);\r
638 /*-----------------------------------------------------------------*/\r
639 parse(macrosfile)\r
640 {\r
641 ptr = parse_datafile_line(_);\r
642 if(ptr)\r
643 {\r
644 create(macro, Macro);\r
645 macro->rewrite_from = _;\r
646 macro->rewrite_to = ptr;\r
647 push(macro, macros);\r
648 printf("%s -> %s\n", macro->rewrite_from, macro->rewrite_to);\r
649 }\r
650 }\r
651 done; /* ugly macro end */\r
652 }\r
653\r
654 if(!just_preview)\r
655 {\r
656 /*-----------------------------------------------------------------*/\r
657 puts("Initializing iptables and tc classes ...");\r
658 /*-----------------------------------------------------------------*/\r
659 \r
660 iptables_file = fopen(iptablesfile, "w");\r
661 if(iptables_file == NULL)\r
662 {\r
663 perror(iptablesfile);\r
664 exit(-1);\r
665 }\r
666 iptables_save_line(iptablespreamble, FALSE);\r
667\r
668 if(ip6prefix)\r
669 {\r
670 ip6tables_file = fopen(ip6tablesfile, "w");\r
671 if(ip6tables_file == NULL)\r
672 {\r
673 perror(ip6tablesfile);\r
674 exit(-1);\r
675 }\r
676 iptables_save_line(iptablespreamble, TRUE);\r
677 iptables_save_line(ip6preamble, TRUE);\r
678 }\r
679\r
680 run_iptables_restore();\r
681 \r
682 log_file = fopen(cmdlog, "w");\r
683 if(log_file == NULL) \r
684 {\r
685 perror(cmdlog);\r
686 exit(-1);\r
687 } \r
688 \r
689 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,lan);\r
690 safe_run(str);\r
691\r
692 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,wan);\r
693 safe_run(str);\r
694 \r
695 iptables_file=fopen(iptablesfile,"w");\r
696 iptables_save_line(iptablespreamble, FALSE);\r
697 if(ip6prefix)\r
698 {\r
699 ip6tables_file=fopen(ip6tablesfile,"w");\r
700 iptables_save_line(iptablespreamble, TRUE);\r
701 iptables_save_line(ip6preamble, TRUE);\r
702 }\r
703\r
704 if(qos_free_zone && *qos_free_zone!='0') /* this is currently supported only for IPv4 */\r
705 {\r
706 char *chain;\r
707 \r
708 sprintf(str,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone, wan);\r
709 iptables_save_line(str, FALSE); /* this is currently supported only for IPv4 */\r
710 \r
711/*\r
712 if(qos_proxy)\r
713 {\r
714 iptables_save_line(":post_noproxy - [0:0]", FALSE);\r
715 sprintf(str,"-A POSTROUTING ! -p tcp -o %s -j post_noproxy", lan);\r
716 iptables_save_line(str , FALSE);\r
717 sprintf(str,"-A POSTROUTING ! -s %s -o %s -j post_noproxy", proxy_ip, lan);\r
718 iptables_save_line(str, FALSE);\r
719 sprintf(str,"-A POSTROUTING -s %s -p tcp ! --sport %d -o %s -j post_noproxy", proxy_ip, proxy_port, lan);\r
720 iptables_save_line(str, FALSE);\r
721\r
722 chain="post_noproxy"; \r
723 }\r
724\r
725 else\r
726 {\r
727*/\r
728 chain = "POSTROUTING";\r
729// }\r
730 \r
731 sprintf(str,"-A %s -s %s -o %s -j ACCEPT", chain, qos_free_zone, lan);\r
732 iptables_save_line(str, FALSE);\r
733 }\r
734 \r
735 if(ip_count > idxtable_treshold1 && !just_flush)\r
736 {\r
737 int idxcount=0, bitmask=32-idxtable_bitmask1;\r
738 char *subnet, *buf;\r
739 /*-----------------------------------------------------------------*/\r
740 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count);\r
741 /*-----------------------------------------------------------------*/\r
742\r
743 iptables_save_line(":post_common - [0:0]", FALSE);\r
744 iptables_save_line(":forw_common - [0:0]", FALSE);\r
745 if(ip6prefix)\r
746 {\r
747 iptables_save_line(":post_common - [0:0]", TRUE);\r
748 iptables_save_line(":forw_common - [0:0]", TRUE);\r
749 }\r
750\r
751 for_each(ip,ips) if(ip->addr && *(ip->addr) && !eq(ip->addr,"0.0.0.0/0")) \r
752 {\r
753 if(ip->v6)\r
754 {\r
755 buf=index6_id(ip->addr,bitmask+32);\r
756 }\r
757 else\r
758 {\r
759 buf=index_id(ip->addr, bitmask);\r
760 }\r
761 \r
762 if_exists(idx,idxs,eq(idx->id,buf))\r
763 {\r
764 idx->children++;\r
765 }\r
766 else\r
767 {\r
768 create(idx,Index);\r
769 idx->addr = ip->addr;\r
770 idx->id = buf;\r
771 idx->bitmask = bitmask+32*ip->v6;\r
772 idx->parent = NULL;\r
773 idx->children = 0;\r
774 idx->ipv6 = ip->v6;\r
775 idxcount++;\r
776 push(idx,idxs);\r
777 }\r
778 }\r
779\r
780 /* brutal perfomance optimalization */\r
781 while(idxcount > idxtable_treshold2 && bitmask > 2*idxtable_bitmask2)\r
782 {\r
783 bitmask -= idxtable_bitmask2;\r
784 idxcount = 0;\r
785\r
786 for_each(idx,idxs) if(idx->parent == NULL)\r
787 {\r
788 if(idx->ipv6)\r
789 {\r
790 buf = index6_id(idx->addr, bitmask+32);\r
791 }\r
792 else\r
793 {\r
794 buf = index_id(idx->addr, bitmask);\r
795 }\r
796 if_exists(metaindex,idxs,eq(metaindex->id,buf))\r
797 {\r
798 metaindex->children++;\r
799 }\r
800 else\r
801 {\r
802 create(metaindex,Index);\r
803 metaindex->addr = idx->addr;\r
804 metaindex->id = buf;\r
805 metaindex->bitmask = bitmask+32*idx->ipv6;\r
806 metaindex->parent = NULL;\r
807 metaindex->children = 0;\r
808 metaindex->ipv6 = idx->ipv6;\r
809 idxcount++;\r
810 push(metaindex,idxs);\r
811 }\r
812 idx->parent=metaindex;\r
813 }\r
814 }\r
815\r
816 /* this should slightly optimize throughput ... */\r
817 sort(idx,idxs,desc_order_by,children);\r
818 sort(idx,idxs,order_by,bitmask);\r
819\r
820 i=0;\r
821 for_each(idx,idxs)\r
822 {\r
823 if(idx->ipv6)\r
824 {\r
825 subnet=subnet6_id(idx->addr, idx->bitmask);\r
826 }\r
827 else\r
828 {\r
829 subnet=subnet_id(idx->addr, idx->bitmask);\r
830 }\r
831 printf("%d: %s/%d\n", ++i, subnet, idx->bitmask);\r
832 \r
833 sprintf(str,":post_%s - [0:0]", idx->id);\r
834 iptables_save_line(str, idx->ipv6);\r
835\r
836 sprintf(str,":forw_%s - [0:0]", idx->id);\r
837 iptables_save_line(str, idx->ipv6);\r
838\r
839 if(idx->parent)\r
840 {\r
841 string(buf,strlen(idx->parent->id)+6);\r
842 sprintf(buf,"post_%s", idx->parent->id);\r
843 }\r
844 else\r
845 {\r
846 buf="POSTROUTING";\r
847 }\r
848\r
849 sprintf(str,"-A %s -d %s/%d -o %s -j post_%s", buf, subnet, idx->bitmask, lan, idx->id);\r
850 iptables_save_line(str, idx->ipv6);\r
851\r
852 sprintf(str,"-A %s -d %s/%d -o %s -j post_common", buf, subnet, idx->bitmask, lan);\r
853 iptables_save_line(str, idx->ipv6);\r
854\r
855 if(idx->parent)\r
856 {\r
857 string(buf,strlen(idx->parent->id)+6);\r
858 sprintf(buf,"forw_%s",idx->parent->id);\r
859 }\r
860 else\r
861 {\r
862 buf="FORWARD";\r
863 }\r
864\r
865 sprintf(str,"-A %s -s %s/%d -o %s -j forw_%s", buf, subnet, idx->bitmask, wan, idx->id);\r
866 iptables_save_line(str, idx->ipv6);\r
867\r
868 sprintf(str,"-A %s -s %s/%d -o %s -j forw_common", buf, subnet, idx->bitmask, wan);\r
869 iptables_save_line(str, idx->ipv6);\r
870 }\r
871 printf("Total indexed iptables chains created: %d\n", i);\r
872\r
873 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);\r
874 iptables_save_line(str, FALSE);\r
875 \r
876 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);\r
877 iptables_save_line(str, FALSE);\r
878\r
879 if(ip6prefix)\r
880 {\r
881 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);\r
882 iptables_save_line(str, TRUE);\r
883 \r
884 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);\r
885 iptables_save_line(str, TRUE);\r
886 }\r
887 }\r
888 }\r
889\r
890 if(just_flush)\r
891 {\r
892 fclose(iptables_file);\r
893 if(log_file)\r
894 { \r
895 fclose(log_file);\r
896 }\r
897 puts("Just flushed iptables and tc classes - now exiting ...");\r
898 exit(0);\r
899 }\r
900\r
901 if(!just_preview)\r
902 {\r
903 if(!dry_run && !nodelay && qos_free_delay)\r
904 {\r
905 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay);\r
906 sleep(qos_free_delay);\r
907 }\r
908\r
909 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",\r
910 tc,lan,htb_r2q);\r
911 safe_run(str);\r
912\r
913 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
914 tc,lan,lan_medium,lan_medium,burst_main,highest_priority);\r
915 safe_run(str);\r
916\r
917 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
918 tc,lan,line,line,burst_main,highest_priority);\r
919 safe_run(str);\r
920\r
921 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc,wan,htb_r2q);\r
922 safe_run(str);\r
923\r
924 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
925 tc,wan,wan_medium,wan_medium,burst_main,highest_priority);\r
926 safe_run(str);\r
927\r
928 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
929 tc,wan,up,up,burst_main,highest_priority);\r
930 safe_run(str);\r
931 }\r
932\r
933 /*-----------------------------------------------------------------*/\r
934 puts("Locating heavy downloaders and generating root classes ...");\r
935 /*-----------------------------------------------------------------*/\r
936 sort(ip,ips,desc_order_by,traffic); \r
937\r
938 /*-----------------------------------------------------------------*/\r
939 /* sub-scope - local variables */ \r
940 {\r
941 long long int rate = line;\r
942 long long int max = line;\r
943 int group_count = 0;\r
944 FILE *credit_file = NULL;\r
945 \r
946 if(!just_preview && !dry_run && enable_credit)\r
947 {\r
948 credit_file = fopen(credit,"w");\r
949 }\r
950 \r
951 for_each(group,groups)\r
952 {\r
953 if(!just_preview)\r
954 {\r
955 //download\r
956 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
957 tc, lan, parent, group->id, rate, max, burst_group, highest_priority+1, group->desired);\r
958 safe_run(str);\r
959 \r
960 //upload\r
961 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
962 tc, wan, parent, group->id, rate*up/line, max*up/line, burst_group, highest_priority+1, group->desired);\r
963 safe_run(str);\r
964 }\r
965 \r
966 if(group_count++ < max_nesting)\r
967 {\r
968 parent = group->id;\r
969 }\r
970 \r
971 rate -= digital_divide*group->min;\r
972 if(rate < group->min)\r
973 {\r
974 rate = group->min;\r
975 }\r
976 \r
977 /*shaping of aggresive downloaders, with credit file support */\r
978 if(use_credit)\r
979 {\r
980 int group_rate = group->min, priority_sequence = lowest_priority;\r
981 \r
982 for_each(ip, ips) if(ip->min == group->min && ip->max > ip->min)\r
983 {\r
984 ip->realquota=ip->credit+(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20));\r
985 if( ip->keyword->data_limit \r
986 and not ip->fixedprio \r
987 and ip->traffic > ip->realquota )\r
988 {\r
989 if(group_rate < ip->max)\r
990 {\r
991 ip->max = group_rate;\r
992 }\r
993 group_rate+=magic_treshold;\r
994 ip->prio=lowest_priority;\r
995 if(ip->prio<highest_priority+2)\r
996 {\r
997 ip->prio=highest_priority+2;\r
998 }\r
999 }\r
1000 else\r
1001 {\r
1002 if( ip->keyword->data_prio \r
1003 && !ip->fixedprio \r
1004 && ( ip->traffic>ip->credit\r
1005 + (ip->min*ip->keyword->data_prio+(ip->keyword->fixed_prio<<20))) )\r
1006 {\r
1007 ip->prio=priority_sequence--;\r
1008 if(ip->prio<highest_priority+1)\r
1009 {\r
1010 ip->prio=highest_priority+1;\r
1011 }\r
1012 }\r
1013 \r
1014 if(credit_file)\r
1015 {\r
1016 unsigned long long lcredit=0;\r
1017 \r
1018 if((ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))>ip->traffic)\r
1019 {\r
1020 lcredit=(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))-ip->traffic;\r
1021 }\r
1022 fprintf(credit_file,"%s %Lu\n",ip->addr,lcredit);\r
1023 }\r
1024 }\r
1025 } \r
1026 }\r
1027 }\r
1028 if(credit_file)\r
1029 {\r
1030 fclose(credit_file);\r
1031 }\r
1032 }\r
1033\r
1034 if(just_preview)\r
1035 {\r
1036 if(start_shaping || stop_shaping || reduce_ceil)\r
1037 {\r
1038 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap);\r
1039 parse(classmap)\r
1040 {\r
1041 ptr=strchr(_,' ');\r
1042 if(ptr)\r
1043 {\r
1044 *ptr=0;\r
1045 ptr++;\r
1046 if_exists(ip,ips,eq(ip->addr,_))\r
1047 {\r
1048 ip->mark=atoi(ptr);\r
1049 if(ip->max < ip->desired || stop_shaping || reduce_ceil) /* apply or disable FUP limit immediately.... */\r
1050 {\r
1051 if(stop_shaping)\r
1052 {\r
1053 ip->max = ip->desired;\r
1054 printf("Removing limit for %-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
1055 }\r
1056 else\r
1057 {\r
1058 printf("Applying limit for %-22s %-16s %04d ", ip->name, ip->addr, ip->mark);\r
1059 if(reduce_ceil)\r
1060 {\r
1061 ip->max = ip->min + (ip->desired-ip->min)/reduce_ceil;\r
1062 }\r
1063 }\r
1064 printf("(down: %dk-%dk ", ip->min, ip->max); \r
1065 sprintf(str, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
1066 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
1067 safe_run(str);\r
1068 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1069 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
1070 sprintf(str,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1071 tc, wan, ip->group, ip->mark,\r
1072 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1073 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1074 safe_run(str);\r
1075 }\r
1076 }\r
1077 }\r
1078 }\r
1079 fail\r
1080 { \r
1081 perror(classmap);\r
1082 puts("Warning - classmap file not fund, just generating preview ...");\r
1083 start_shaping=FALSE;\r
1084 stop_shaping=FALSE;\r
1085 }\r
1086 done; /* ugly macro end */\r
1087 }\r
1088 html=preview;\r
1089 json_traffic=json_preview;\r
1090 }\r
1091\r
1092 if(!dry_run && !just_flush)\r
1093 {\r
1094 /*-----------------------------------------------------------------*/\r
1095 printf("Writing json traffic overview %s ... ", json_traffic);\r
1096 /*-----------------------------------------------------------------*/\r
1097 write_json_traffic(json_traffic);\r
1098\r
1099 /*-----------------------------------------------------------------*/\r
1100 printf("Writing statistics into HTML page %s ...\n", html);\r
1101 /*-----------------------------------------------------------------*/\r
1102 write_htmlandlogs(html, d, total, just_preview);\r
1103 }\r
1104\r
1105 if(just_preview)\r
1106 {\r
1107 char swchar='p';\r
1108 if(start_shaping)\r
1109 {\r
1110 swchar='s';\r
1111 }\r
1112 else if(reduce_ceil)\r
1113 {\r
1114 swchar='0'+reduce_ceil; /* -2, -4 */\r
1115 }\r
1116 else if(stop_shaping)\r
1117 {\r
1118 swchar='q';\r
1119 }\r
1120\r
1121 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar);\r
1122 exit(0);\r
1123 } \r
1124\r
1125 i=0;\r
1126#ifdef DEBUG\r
1127 printf("%-22s %-15s mark\n","name","ip");\r
1128#endif\r
1129\r
1130 printf("Writing %s", classmap); \r
1131 f = fopen(classmap, "w"); \r
1132 if(f < 0)\r
1133 {\r
1134 perror(classmap);\r
1135 }\r
1136\r
1137 /*-----------------------------------------------------------------*/\r
1138 printf(" + generating iptables and tc classes ... ");\r
1139 /*-----------------------------------------------------------------*/\r
1140\r
1141 for_each(ip, ips) if(ip->mark > 0) /* works only for IPv4 so far */\r
1142 {\r
1143 if(idxs)\r
1144 {\r
1145 char *buf;\r
1146 duplicate(ip->addr,buf);\r
1147 if(ip->v6)\r
1148 {\r
1149 buf=index6_id(ip->addr,64-idxtable_bitmask1);\r
1150 }\r
1151 else\r
1152 {\r
1153 buf=index_id(ip->addr,32-idxtable_bitmask1);\r
1154 }\r
1155 \r
1156 string(chain_forward,6+strlen(buf));\r
1157 strcpy(chain_forward,"forw_");\r
1158 strcat(chain_forward,buf);\r
1159\r
1160 string(chain_postrouting,6+strlen(buf));\r
1161 strcpy(chain_postrouting,"post_");\r
1162 strcat(chain_postrouting,buf);\r
1163 \r
1164 free(buf);\r
1165 }\r
1166 else\r
1167 {\r
1168 chain_forward="FORWARD";\r
1169 chain_postrouting="POSTROUTING";\r
1170 }\r
1171\r
1172 /* packet limits - this will be optional in future */\r
1173 if(ip->pps_limit)\r
1174 {\r
1175 sprintf(limit_pkts, "-m limit --limit %d/s --limit-burst %d ", \r
1176 ip->pps_limit, ip->pps_limit);\r
1177 }\r
1178 else\r
1179 {\r
1180 *limit_pkts = 0;\r
1181 } \r
1182\r
1183#ifdef DEBUG\r
1184 printf("%-22s %-16s %04d %d/s\n", ip->name, ip->addr, ip->mark, ip->pps_limit); \r
1185#endif\r
1186\r
1187 /* -------------------------------------------------------- mark download */ \r
1188 sprintf(str, "-A %s -d %s/%d -o %s -j %s%d",\r
1189 chain_postrouting, ip->addr, 32*(1+ip->v6),\r
1190 lan, mark_iptables, ip->mark);\r
1191 iptables_save_line(str, ip->v6);\r
1192\r
1193/*\r
1194 if(qos_proxy)\r
1195 {\r
1196 sprintf(str, "-A %s -s %s -p tcp --sport %d -d %s/%d -o %s -j %s%d",\r
1197 chain_postrouting, proxy_ip, proxy_port, ip->addr,\r
1198 32*(1+ip->v6), lan, mark_iptables, ip->mark);\r
1199 iptables_save_line(str, ip->v6);\r
1200 }\r
1201*/\r
1202 sprintf(str, "-A %s -d %s/%d -o %s %s-j ACCEPT",\r
1203 chain_postrouting, ip->addr, 32*(1+ip->v6), lan, limit_pkts);\r
1204 iptables_save_line(str, ip->v6);\r
1205\r
1206 /* classify overlimit packets to separate overlimit class */\r
1207 sprintf(str, "-A %s -d %s/%d -o %s -j %s%d",\r
1208 chain_postrouting, ip->addr, 32*(1+ip->v6),\r
1209 lan, mark_iptables, OVERLIMIT_CLASS);\r
1210 iptables_save_line(str, ip->v6);\r
1211\r
1212 sprintf(str, "-A %s -d %s/%d -o %s -j ACCEPT",\r
1213 chain_postrouting, ip->addr, 32*(1+ip->v6), lan);\r
1214 iptables_save_line(str, ip->v6);\r
1215\r
1216 /* -------------------------------------------------------- mark upload */\r
1217 sprintf(str, "-A %s -s %s/%d -o %s -j %s%d", \r
1218 chain_forward, ip->addr, 32*(1+ip->v6), wan, mark_iptables, ip->mark);\r
1219 iptables_save_line(str, ip->v6);\r
1220\r
1221 sprintf(str, "-A %s -s %s/%d -o %s %s-j ACCEPT",\r
1222 chain_forward, ip->addr, 32*(1+ip->v6), wan, limit_pkts);\r
1223 iptables_save_line(str, ip->v6);\r
1224\r
1225 /* classify overlimit packets to separate overlimit class */\r
1226 sprintf(str, "-A %s -s %s/%d -o %s -j %s%d", \r
1227 chain_forward, ip->addr, 32*(1+ip->v6), wan, mark_iptables, OVERLIMIT_CLASS);\r
1228 iptables_save_line(str, ip->v6);\r
1229\r
1230 sprintf(str, "-A %s -s %s/%d -o %s -j ACCEPT",\r
1231 chain_forward, ip->addr, 32*(1+ip->v6), wan);\r
1232 iptables_save_line(str, ip->v6);\r
1233\r
1234 if(ip->min)\r
1235 {\r
1236 /* -------------------------------------------------------- download class */\r
1237#ifdef DEBUG\r
1238 printf("(down: %dk-%dk ", ip->min, ip->max); \r
1239#endif\r
1240\r
1241 sprintf(str, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
1242 tc, lan, ip->group, ip->mark, ip->min, ip->max, burst, ip->prio);\r
1243 safe_run(str);\r
1244\r
1245 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
1246 {\r
1247 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s", \r
1248 tc, lan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
1249 safe_run(str);\r
1250 }\r
1251\r
1252 if(filter_type == 1)\r
1253 {\r
1254 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
1255 tc, lan, ip->mark, ip->mark);\r
1256 safe_run(str);\r
1257 }\r
1258\r
1259 /* -------------------------------------------------------- upload class */\r
1260#ifdef DEBUG\r
1261 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1262 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
1263#endif\r
1264\r
1265 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1266 tc, wan, ip->group, ip->mark,\r
1267 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1268 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1269 safe_run(str);\r
1270 \r
1271 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
1272 {\r
1273 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s",\r
1274 tc, wan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
1275 safe_run(str);\r
1276 } \r
1277\r
1278 if(filter_type == 1)\r
1279 {\r
1280 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
1281 tc, wan, ip->mark, ip->mark);\r
1282 safe_run(str);\r
1283 }\r
1284 \r
1285 if(f > 0)\r
1286 {\r
1287 fprintf(f, "%s %d\n", ip->addr, ip->mark);\r
1288 }\r
1289 }\r
1290 else\r
1291 {\r
1292#ifdef DEBUG\r
1293 printf("(sharing %s)\n", ip->sharing);\r
1294#endif\r
1295 }\r
1296 i++;\r
1297 }\r
1298 if(f > 0)\r
1299 {\r
1300 puts("done.");\r
1301 fclose(f);\r
1302 }\r
1303 \r
1304 if(idxs)\r
1305 {\r
1306 chain_forward = "forw_common";\r
1307 chain_postrouting = "post_common";\r
1308 }\r
1309 else\r
1310 {\r
1311 chain_forward = "FORWARD";\r
1312 chain_postrouting = "POSTROUTING";\r
1313 }\r
1314\r
1315 if(free_min)\r
1316 {\r
1317 final_chain = "ACCEPT";\r
1318 }\r
1319\r
1320/*\r
1321 if(qos_proxy)\r
1322 {\r
1323 if(free_min) \r
1324 {\r
1325 sprintf(str, "-A %s -s %s -p tcp --sport %d -o %s -j %s%d",\r
1326 chain_postrouting,proxy_ip,proxy_port,lan,mark_iptables, 3);\r
1327 iptables_save_line(str, FALSE); // only for IPv4\r
1328 }\r
1329 sprintf(str, "-A %s -s %s -p tcp --sport %d -o %s -j %s",\r
1330 chain_postrouting,proxy_ip,proxy_port,lan,final_chain);\r
1331 iptables_save_line(str, FALSE); // only for IPv4\r
1332 }\r
1333*/\r
1334\r
1335 if(free_min)\r
1336 {\r
1337 sprintf(str, "-A %s -o %s -j %s%d",\r
1338 chain_postrouting, lan, mark_iptables, FREE_CLASS);\r
1339 iptables_save_line(str, FALSE); /* only for IPv4 */\r
1340 }\r
1341\r
1342 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
1343 iptables_save_line(str, FALSE);\r
1344 if(ip6prefix)\r
1345 {\r
1346 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
1347 iptables_save_line(str, TRUE);\r
1348 }\r
1349\r
1350 if(free_min)\r
1351 {\r
1352 sprintf(str,"-A %s -o %s -j %s%d", chain_forward, wan, mark_iptables, FREE_CLASS);\r
1353 iptables_save_line(str, FALSE); /* only for IPv4 */\r
1354 }\r
1355\r
1356 sprintf(str,"-A %s -o %s -j %s", chain_forward, wan, final_chain);\r
1357 iptables_save_line(str, FALSE);\r
1358 if(ip6prefix)\r
1359 {\r
1360 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
1361 iptables_save_line(str, TRUE);\r
1362 }\r
1363\r
1364 if(free_min) /* allocate free bandwith if it is not zero... */ \r
1365 {\r
1366 /*-----------------------------------------------------------------*/\r
1367 puts("Generating free bandwith class ...");\r
1368 /*-----------------------------------------------------------------*/\r
1369 sprintf(str, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1370 tc, lan, parent, FREE_CLASS, free_min, free_max,burst, lowest_priority);\r
1371 safe_run(str);\r
1372 sprintf(str, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1373 tc, wan, parent, FREE_CLASS, free_min, free_max, burst, lowest_priority);\r
1374 safe_run(str);\r
1375 /* tc SFQ */\r
1376 if(strcmpi(qos_leaf, "none"))\r
1377 {\r
1378 sprintf(str,"%s qdisc add dev %s parent 1:%d handle %d %s", tc, lan, FREE_CLASS, FREE_CLASS, qos_leaf);\r
1379 safe_run(str);\r
1380 \r
1381 sprintf(str,"%s qdisc add dev %s parent 1:%d handle %d %s", tc, wan, FREE_CLASS, FREE_CLASS, qos_leaf);\r
1382 safe_run(str);\r
1383 } \r
1384 /* tc handle 1 fw flowid */\r
1385 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
1386 safe_run(str);\r
1387\r
1388 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
1389 safe_run(str);\r
1390\r
1391 /*-----------------------------------------------------------------*/\r
1392 puts("Generating bandwith class for overlimit packets...");\r
1393 /*-----------------------------------------------------------------*/\r
1394 sprintf(str, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1395 tc, lan, parent, OVERLIMIT_CLASS, overlimit_min, overlimit_max, burst, lowest_priority);\r
1396 safe_run(str);\r
1397 sprintf(str, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1398 tc, wan, parent, OVERLIMIT_CLASS, overlimit_min, overlimit_max, burst, lowest_priority);\r
1399 safe_run(str);\r
1400 }\r
1401 printf("Total IP count: %d\n", i);\r
1402 run_iptables_restore();\r
1403 if(log_file)\r
1404 {\r
1405 fclose(log_file);\r
1406 }\r
1407 return 0;\r
1408 /* that's all folks, thank you for reading it all the way up to this point ;-) */\r
1409 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */\r
1410}\r
This page took 0.266743 seconds and 4 git commands to generate.