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