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