prometheus -2, prometheus -4
[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, 20130124
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-i";
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 /* not yet implemented:
122 int fixed_packets = 0; maximum number of pps per IP address (not class!)
123 int packet_limit = 5; maximum number of pps to htn CEIL, not rate !!!
124 */
125 FILE *log_file = NULL;
126 char *kwd = "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */
127
128 const int highest_priority = 0; /* highest HTB priority (HTB built-in value is 0) */
129 const int lowest_priority = 7; /* lowest HTB priority (HTB built-in value is 7) */
130 const int idxtable_treshold1 = 24; /* this is no longer configurable */
131 const int idxtable_treshold2 = 12; /* this is no longer configurable */
132 const int idxtable_bitmask1 = 3; /* this is no longer configurable */
133 const int idxtable_bitmask2 = 3; /* this is no longer configurable */
134
135 struct IP *ips = NULL, *ip, *sharedip;
136 struct Group *groups = NULL, *group;
137 struct Keyword *keyword, *defaultkeyword=NULL, *keywords=NULL;
138
139 void help(void);
140 /* implemented in help.c */
141
142 void get_traffic_statistics(const char *whichiptables, int ipv6);
143 /* implemented in parseiptables.c */
144
145 void parse_ip_log(int argc, char **argv);
146 /* implemented in parselog.c */
147
148 void parse_hosts(char *hosts);
149 /* implemented in parsehosts.c */
150
151 void write_json_traffic(char *json);
152 /* implemented in json.c */
153
154 void write_htmlandlogs(char *html, char *d, int total, int just_preview);
155 /* implemented in htmlandlogs.c */
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;
469
470 int parent = 1;
471 int just_flush = FALSE; /* deactivates all previous actions */
472 int nodelay = FALSE;
473 int just_preview = FALSE; /* preview - generate just stats */
474 int start_shaping = FALSE; /* apply FUP - requires classmap file */
475 int stop_shaping = FALSE; /* lift FUP - requires classmap file */
476 int reduce_ceil = 0; /* allow only rate+(ceil-rate)/2, /4, etc. */
477 int just_logs = FALSE; /* just parse logs */
478 int run = FALSE;
479 int total = 0;
480
481 char *chain_forward, *chain_postrouting;
482 char *althosts=NULL;
483
484 printf("\n\
485 Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\
486 Version %s - Copyright (C)2005-2013 Michael Polak, Arachne Labs\n\
487 iptables-restore & burst tunning & classify modification by Ludva\n\
488 Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version);
489
490 /*----- Boring... we have to check command line options first: ----*/
491 arguments
492 {
493 argument("-c") { nextargument(config); }
494 argument("-h") { nextargument(althosts);}
495 argument("-d") { run=TRUE; dry_run=TRUE; }
496 argument("-f") { run=TRUE; just_flush=TRUE; }
497 argument("-9") { run=TRUE; just_flush=9; }
498 argument("-p") { run=TRUE; just_preview=TRUE; }
499 argument("-q") { run=TRUE; just_preview=TRUE; stop_shaping=TRUE; }
500 argument("-2") { run=TRUE; just_preview=TRUE; reduce_ceil=2; }
501 argument("-4") { run=TRUE; just_preview=TRUE; reduce_ceil=4; }
502 argument("-s") { run=TRUE; just_preview=TRUE; start_shaping=TRUE; }
503 argument("-r") { run=TRUE; }
504 argument("-n") { run=TRUE; nodelay=TRUE; }
505 argument("-l") { just_logs=TRUE; }
506 argument("-m") { just_logs=TRUE; }
507 argument("-y") { just_logs=TRUE; }
508 argument("-?") { help(); exit(0); }
509 argument("--help") { help(); exit(0); }
510 argument("-v") { exit(0); }
511 argument("--version") { exit(0); }
512 }
513
514 if(dry_run)
515 {
516 puts("*** THIS IS JUST DRY RUN ! ***\n");
517 }
518
519 date(d); /* this is typical cll1.h macro - prints current date */
520
521 /*-----------------------------------------------------------------*/
522 printf("Parsing configuration file %s ...\n", config);
523 /*-----------------------------------------------------------------*/
524 get_config(config);
525
526 if(just_logs)
527 {
528 parse_ip_log(argc,argv);
529 exit(0);
530 }
531 else if(not run)
532 {
533 help();
534 exit(0);
535 }
536
537 if(althosts)
538 {
539 hosts=althosts;
540 }
541
542 if(just_flush<9)
543 {
544 /*-----------------------------------------------------------------*/
545 puts("Parsing iptables verbose output ...");
546 /*-----------------------------------------------------------------*/
547 get_traffic_statistics(iptables, FALSE);
548 if(ip6prefix)
549 {
550 /*-----------------------------------------------------------------*/
551 puts("Parsing ip6tables verbose output ...");
552 /*-----------------------------------------------------------------*/
553 get_traffic_statistics(ip6tables, TRUE);
554 }
555 }
556
557 /*-----------------------------------------------------------------*/
558 printf("Parsing class defintion file %s ...\n", hosts);
559 /*-----------------------------------------------------------------*/
560 parse_hosts(hosts);
561
562 /*-----------------------------------------------------------------*/
563 /* cll1.h - let's allocate brand new character buffer... */
564 /*-----------------------------------------------------------------*/
565 string(str,STRLEN);
566
567 /*-----------------------------------------------------------------*/
568 puts("Resolving shared connections ...");
569 /*-----------------------------------------------------------------*/
570 for_each(ip,ips) if(ip->sharing)
571 {
572 for_each(sharedip,ips) if(eq(sharedip->name, ip->sharing))
573 {
574 sharedip->traffic += ip->traffic;
575 ip->traffic = 0;
576 ip->mark = sharedip->mark;
577 ip->lmsid = sharedip->lmsid;
578 break;
579 }
580 if(not sharedip)
581 {
582 printf("Unresolved shared connection: %s %s sharing-%s\n",
583 ip->addr, ip->name, ip->sharing);
584 }
585 }
586
587 if(enable_credit && just_flush<9)
588 {
589 /*-----------------------------------------------------------------*/
590 printf("Parsing credit file %s ...\n", credit);
591 /*-----------------------------------------------------------------*/
592 parse(credit)
593 {
594 ptr=parse_datafile_line(_);
595 if(ptr)
596 {
597 if_exists(ip,ips,eq(ip->addr,_))
598 {
599 sscanf(ptr,"%Lu",&(ip->credit));
600 }
601 }
602 }
603 done; /* ugly macro end */
604 }
605
606 if(!just_preview)
607 {
608 /*-----------------------------------------------------------------*/
609 puts("Initializing iptables and tc classes ...");
610 /*-----------------------------------------------------------------*/
611
612 iptables_file = fopen(iptablesfile, "w");
613 if(iptables_file == NULL)
614 {
615 perror(iptablesfile);
616 exit(-1);
617 }
618 iptables_save_line(iptablespreamble, FALSE);
619
620 if(ip6prefix)
621 {
622 ip6tables_file = fopen(ip6tablesfile, "w");
623 if(ip6tables_file == NULL)
624 {
625 perror(ip6tablesfile);
626 exit(-1);
627 }
628 iptables_save_line(iptablespreamble, TRUE);
629 iptables_save_line(ip6preamble, TRUE);
630 }
631
632 run_iptables_restore();
633
634 log_file = fopen(cmdlog, "w");
635 if(log_file == NULL)
636 {
637 perror(cmdlog);
638 exit(-1);
639 }
640
641 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,lan);
642 safe_run(str);
643
644 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,wan);
645 safe_run(str);
646
647 iptables_file=fopen(iptablesfile,"w");
648 iptables_save_line(iptablespreamble, FALSE);
649 if(ip6prefix)
650 {
651 ip6tables_file=fopen(ip6tablesfile,"w");
652 iptables_save_line(iptablespreamble, TRUE);
653 iptables_save_line(ip6preamble, TRUE);
654 }
655
656 if(qos_free_zone && *qos_free_zone!='0') /* this is currently supported only for IPv4 */
657 {
658 char *chain;
659
660 sprintf(str,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone, wan);
661 iptables_save_line(str, FALSE); /* this is currently supported only for IPv4 */
662
663 if(qos_proxy)
664 {
665 iptables_save_line(":post_noproxy - [0:0]", FALSE);
666 sprintf(str,"-A POSTROUTING ! -p tcp -o %s -j post_noproxy", lan);
667 iptables_save_line(str , FALSE);
668 sprintf(str,"-A POSTROUTING ! -s %s -o %s -j post_noproxy", proxy_ip, lan);
669 iptables_save_line(str, FALSE);
670 sprintf(str,"-A POSTROUTING -s %s -p tcp ! --sport %d -o %s -j post_noproxy", proxy_ip, proxy_port, lan);
671 iptables_save_line(str, FALSE);
672
673 chain="post_noproxy";
674 }
675 else
676 {
677 chain="POSTROUTING";
678 }
679
680 sprintf(str,"-A %s -s %s -o %s -j ACCEPT", chain, qos_free_zone, lan);
681 iptables_save_line(str, FALSE);
682 }
683
684 if(ip_count > idxtable_treshold1 && !just_flush)
685 {
686 int idxcount=0, bitmask=32-idxtable_bitmask1;
687 char *subnet, *buf;
688 /*-----------------------------------------------------------------*/
689 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count);
690 /*-----------------------------------------------------------------*/
691
692 iptables_save_line(":post_common - [0:0]", FALSE);
693 iptables_save_line(":forw_common - [0:0]", FALSE);
694 if(ip6prefix)
695 {
696 iptables_save_line(":post_common - [0:0]", TRUE);
697 iptables_save_line(":forw_common - [0:0]", TRUE);
698 }
699
700 for_each(ip,ips) if(ip->addr && *(ip->addr) && !eq(ip->addr,"0.0.0.0/0"))
701 {
702 if(ip->v6)
703 {
704 buf=index6_id(ip->addr,bitmask+32);
705 }
706 else
707 {
708 buf=index_id(ip->addr, bitmask);
709 }
710
711 if_exists(idx,idxs,eq(idx->id,buf))
712 {
713 idx->children++;
714 }
715 else
716 {
717 create(idx,Index);
718 idx->addr = ip->addr;
719 idx->id = buf;
720 idx->bitmask = bitmask+32*ip->v6;
721 idx->parent = NULL;
722 idx->children = 0;
723 idx->ipv6 = ip->v6;
724 idxcount++;
725 push(idx,idxs);
726 }
727 }
728
729 /* brutal perfomance optimalization */
730 while(idxcount > idxtable_treshold2 && bitmask > 2*idxtable_bitmask2)
731 {
732 bitmask -= idxtable_bitmask2;
733 idxcount = 0;
734
735 for_each(idx,idxs) if(idx->parent == NULL)
736 {
737 if(idx->ipv6)
738 {
739 buf = index6_id(idx->addr, bitmask+32);
740 }
741 else
742 {
743 buf = index_id(idx->addr, bitmask);
744 }
745 if_exists(metaindex,idxs,eq(metaindex->id,buf))
746 {
747 metaindex->children++;
748 }
749 else
750 {
751 create(metaindex,Index);
752 metaindex->addr = idx->addr;
753 metaindex->id = buf;
754 metaindex->bitmask = bitmask+32*idx->ipv6;
755 metaindex->parent = NULL;
756 metaindex->children = 0;
757 metaindex->ipv6 = idx->ipv6;
758 idxcount++;
759 push(metaindex,idxs);
760 }
761 idx->parent=metaindex;
762 }
763 }
764
765 /* this should slightly optimize throughput ... */
766 sort(idx,idxs,desc_order_by,children);
767 sort(idx,idxs,order_by,bitmask);
768
769 i=0;
770 for_each(idx,idxs)
771 {
772 if(idx->ipv6)
773 {
774 subnet=subnet6_id(idx->addr, idx->bitmask);
775 }
776 else
777 {
778 subnet=subnet_id(idx->addr, idx->bitmask);
779 }
780 printf("%d: %s/%d\n", ++i, subnet, idx->bitmask);
781
782 sprintf(str,":post_%s - [0:0]", idx->id);
783 iptables_save_line(str, idx->ipv6);
784
785 sprintf(str,":forw_%s - [0:0]", idx->id);
786 iptables_save_line(str, idx->ipv6);
787
788 if(idx->parent)
789 {
790 string(buf,strlen(idx->parent->id)+6);
791 sprintf(buf,"post_%s", idx->parent->id);
792 }
793 else
794 {
795 buf="POSTROUTING";
796 }
797
798 sprintf(str,"-A %s -d %s/%d -o %s -j post_%s", buf, subnet, idx->bitmask, lan, idx->id);
799 iptables_save_line(str, idx->ipv6);
800
801 sprintf(str,"-A %s -d %s/%d -o %s -j post_common", buf, subnet, idx->bitmask, lan);
802 iptables_save_line(str, idx->ipv6);
803
804 if(idx->parent)
805 {
806 string(buf,strlen(idx->parent->id)+6);
807 sprintf(buf,"forw_%s",idx->parent->id);
808 }
809 else
810 {
811 buf="FORWARD";
812 }
813
814 sprintf(str,"-A %s -s %s/%d -o %s -j forw_%s", buf, subnet, idx->bitmask, wan, idx->id);
815 iptables_save_line(str, idx->ipv6);
816
817 sprintf(str,"-A %s -s %s/%d -o %s -j forw_common", buf, subnet, idx->bitmask, wan);
818 iptables_save_line(str, idx->ipv6);
819 }
820 printf("Total indexed iptables chains created: %d\n", i);
821
822 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);
823 iptables_save_line(str, FALSE);
824
825 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);
826 iptables_save_line(str, FALSE);
827
828 if(ip6prefix)
829 {
830 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);
831 iptables_save_line(str, TRUE);
832
833 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);
834 iptables_save_line(str, TRUE);
835 }
836 }
837 }
838
839 if(just_flush)
840 {
841 fclose(iptables_file);
842 if(log_file)
843 {
844 fclose(log_file);
845 }
846 puts("Just flushed iptables and tc classes - now exiting ...");
847 exit(0);
848 }
849
850 if(!just_preview)
851 {
852 if(!dry_run && !nodelay && qos_free_delay)
853 {
854 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay);
855 sleep(qos_free_delay);
856 }
857
858 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",
859 tc,lan,htb_r2q);
860 safe_run(str);
861
862 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
863 tc,lan,lan_medium,lan_medium,burst_main,highest_priority);
864 safe_run(str);
865
866 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
867 tc,lan,line,line,burst_main,highest_priority);
868 safe_run(str);
869
870 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc,wan,htb_r2q);
871 safe_run(str);
872
873 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
874 tc,wan,wan_medium,wan_medium,burst_main,highest_priority);
875 safe_run(str);
876
877 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
878 tc,wan,up,up,burst_main,highest_priority);
879 safe_run(str);
880 }
881
882 /*-----------------------------------------------------------------*/
883 puts("Locating heavy downloaders and generating root classes ...");
884 /*-----------------------------------------------------------------*/
885 sort(ip,ips,desc_order_by,traffic);
886
887 /*-----------------------------------------------------------------*/
888 /* sub-scope - local variables */
889 {
890 long long int rate = line;
891 long long int max = line;
892 int group_count = 0;
893 FILE *credit_file = NULL;
894
895 if(!just_preview && !dry_run && enable_credit)
896 {
897 credit_file = fopen(credit,"w");
898 }
899
900 for_each(group,groups)
901 {
902 if(!just_preview)
903 {
904 //download
905 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",
906 tc, lan, parent, group->id, rate, max, burst_group, highest_priority+1, group->desired);
907 safe_run(str);
908
909 //upload
910 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",
911 tc, wan, parent, group->id, rate*up/line, max*up/line, burst_group, highest_priority+1, group->desired);
912 safe_run(str);
913 }
914
915 if(group_count++ < max_nesting)
916 {
917 parent = group->id;
918 }
919
920 rate -= digital_divide*group->min;
921 if(rate < group->min)
922 {
923 rate = group->min;
924 }
925
926 /*shaping of aggresive downloaders, with credit file support */
927 if(use_credit)
928 {
929 int group_rate = group->min, priority_sequence = lowest_priority;
930
931 for_each(ip, ips) if(ip->min == group->min && ip->max > ip->min)
932 {
933 ip->realquota=ip->credit+(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20));
934 if( ip->keyword->data_limit
935 and not ip->fixedprio
936 and ip->traffic > ip->realquota )
937 {
938 if(group_rate < ip->max)
939 {
940 ip->max = group_rate;
941 }
942 group_rate+=magic_treshold;
943 ip->prio=lowest_priority;
944 if(ip->prio<highest_priority+2)
945 {
946 ip->prio=highest_priority+2;
947 }
948 }
949 else
950 {
951 if( ip->keyword->data_prio
952 && !ip->fixedprio
953 && ( ip->traffic>ip->credit
954 + (ip->min*ip->keyword->data_prio+(ip->keyword->fixed_prio<<20))) )
955 {
956 ip->prio=priority_sequence--;
957 if(ip->prio<highest_priority+1)
958 {
959 ip->prio=highest_priority+1;
960 }
961 }
962
963 if(credit_file)
964 {
965 unsigned long long lcredit=0;
966
967 if((ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))>ip->traffic)
968 {
969 lcredit=(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))-ip->traffic;
970 }
971 fprintf(credit_file,"%s %Lu\n",ip->addr,lcredit);
972 }
973 }
974 }
975 }
976 }
977 if(credit_file)
978 {
979 fclose(credit_file);
980 }
981 }
982
983 if(just_preview)
984 {
985 if(start_shaping || stop_shaping || reduce_ceil)
986 {
987 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap);
988 parse(classmap)
989 {
990 ptr=strchr(_,' ');
991 if(ptr)
992 {
993 *ptr=0;
994 ptr++;
995 if_exists(ip,ips,eq(ip->addr,_))
996 {
997 ip->mark=atoi(ptr);
998 if(ip->max < ip->desired || stop_shaping || reduce_ceil) /* apply or disable FUP limit immediately.... */
999 {
1000 if(stop_shaping)
1001 {
1002 ip->max = ip->desired;
1003 printf("Removing limit for %-22s %-16s %04d ", ip->name, ip->addr, ip->mark);
1004 }
1005 else
1006 {
1007 printf("Applying limit for %-22s %-16s %04d ", ip->name, ip->addr, ip->mark);
1008 if(reduce_ceil)
1009 {
1010 ip->max = ip->min + (ip->desired-ip->min)/reduce_ceil;
1011 }
1012 }
1013 printf("(down: %dk-%dk ", ip->min, ip->max);
1014 sprintf(str, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1015 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);
1016 safe_run(str);
1017 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),
1018 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));
1019 sprintf(str,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1020 tc, wan, ip->group, ip->mark,
1021 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),
1022 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);
1023 safe_run(str);
1024 }
1025 }
1026 }
1027 }
1028 fail
1029 {
1030 perror(classmap);
1031 puts("Warning - classmap file not fund, just generating preview ...");
1032 start_shaping=FALSE;
1033 stop_shaping=FALSE;
1034 }
1035 done; /* ugly macro end */
1036 }
1037 html=preview;
1038 json_traffic=json_preview;
1039 }
1040
1041 if(!dry_run && !just_flush)
1042 {
1043 /*-----------------------------------------------------------------*/
1044 printf("Writing json traffic overview %s ... ", json_traffic);
1045 /*-----------------------------------------------------------------*/
1046 write_json_traffic(json_traffic);
1047
1048 /*-----------------------------------------------------------------*/
1049 printf("Writing statistics into HTML page %s ...\n", html);
1050 /*-----------------------------------------------------------------*/
1051 write_htmlandlogs(html, d, total, just_preview);
1052 }
1053
1054 if(just_preview)
1055 {
1056 char swchar='p';
1057 if(start_shaping)
1058 {
1059 swchar='s';
1060 }
1061 else if(reduce_ceil)
1062 {
1063 swchar='0'+reduce_ceil; /* -2, -4 */
1064 }
1065 else if(stop_shaping)
1066 {
1067 swchar='q';
1068 }
1069
1070 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar);
1071 exit(0);
1072 }
1073
1074 i=0;
1075 #ifdef DEBUG
1076 printf("%-22s %-15s mark\n","name","ip");
1077 #endif
1078
1079 printf("Writing %s", classmap);
1080 f = fopen(classmap, "w");
1081 if(f < 0)
1082 {
1083 perror(classmap);
1084 }
1085
1086 /*-----------------------------------------------------------------*/
1087 printf(" + generating iptables and tc classes ... ");
1088 /*-----------------------------------------------------------------*/
1089
1090 for_each(ip, ips) if(ip->mark > 0) /* works only for IPv4 so far */
1091 {
1092 if(idxs)
1093 {
1094 char *buf;
1095 duplicate(ip->addr,buf);
1096 if(ip->v6)
1097 {
1098 buf=index6_id(ip->addr,64-idxtable_bitmask1);
1099 }
1100 else
1101 {
1102 buf=index_id(ip->addr,32-idxtable_bitmask1);
1103 }
1104
1105 string(chain_forward,6+strlen(buf));
1106 strcpy(chain_forward,"forw_");
1107 strcat(chain_forward,buf);
1108
1109 string(chain_postrouting,6+strlen(buf));
1110 strcpy(chain_postrouting,"post_");
1111 strcat(chain_postrouting,buf);
1112
1113 free(buf);
1114 }
1115 else
1116 {
1117 chain_forward="FORWARD";
1118 chain_postrouting="POSTROUTING";
1119 }
1120
1121 #ifdef DEBUG
1122 printf("%-22s %-16s %04d ", ip->name, ip->addr, ip->mark);
1123 #endif
1124
1125 /* -------------------------------------------------------- mark download */
1126
1127 sprintf(str, "-A %s -d %s/%d -o %s -j %s%d",
1128 chain_postrouting, ip->addr, 32*(1+ip->v6), lan, mark_iptables, ip->mark);
1129 /* -m limit --limit 1/s */
1130 iptables_save_line(str, ip->v6);
1131
1132 if(qos_proxy)
1133 {
1134 sprintf(str, "-A %s -s %s -p tcp --sport %d -d %s/%d -o %s -j %s%d",
1135 chain_postrouting, proxy_ip, proxy_port, ip->addr, 32*(1+ip->v6), lan, mark_iptables, ip->mark);
1136 iptables_save_line(str, ip->v6);
1137 }
1138
1139 sprintf(str, "-A %s -d %s/%d -o %s -j ACCEPT",
1140 chain_postrouting, ip->addr, 32*(1+ip->v6), lan);
1141 iptables_save_line(str, ip->v6);
1142
1143 /* -------------------------------------------------------- mark upload */
1144 sprintf(str, "-A %s -s %s/%d -o %s -j %s%d",
1145 chain_forward, ip->addr, 32*(1+ip->v6), wan, mark_iptables, ip->mark);
1146 iptables_save_line(str, ip->v6);
1147
1148 sprintf(str, "-A %s -s %s/%d -o %s -j ACCEPT",
1149 chain_forward, ip->addr, 32*(1+ip->v6), wan);
1150 iptables_save_line(str, ip->v6);
1151
1152 if(ip->min)
1153 {
1154 /* -------------------------------------------------------- download class */
1155 #ifdef DEBUG
1156 printf("(down: %dk-%dk ", ip->min, ip->max);
1157 #endif
1158
1159 sprintf(str, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1160 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);
1161 safe_run(str);
1162
1163 if(strcmpi(ip->keyword->leaf_discipline, "none"))
1164 {
1165 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s",
1166 tc, lan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/
1167 safe_run(str);
1168 }
1169
1170 if(filter_type == 1)
1171 {
1172 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1173 tc, lan, ip->mark, ip->mark);
1174 safe_run(str);
1175 }
1176
1177 /* -------------------------------------------------------- upload class */
1178 #ifdef DEBUG
1179 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),
1180 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));
1181 #endif
1182
1183 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1184 tc, wan, ip->group, ip->mark,
1185 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),
1186 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);
1187 safe_run(str);
1188
1189 if(strcmpi(ip->keyword->leaf_discipline, "none"))
1190 {
1191 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s",
1192 tc, wan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/
1193 safe_run(str);
1194 }
1195
1196 if(filter_type == 1)
1197 {
1198 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1199 tc, wan, ip->mark, ip->mark);
1200 safe_run(str);
1201 }
1202
1203 if(f > 0)
1204 {
1205 fprintf(f, "%s %d\n", ip->addr, ip->mark);
1206 }
1207 }
1208 else
1209 {
1210 #ifdef DEBUG
1211 printf("(sharing %s)\n", ip->sharing);
1212 #endif
1213 }
1214 i++;
1215 }
1216 if(f > 0)
1217 {
1218 puts("done.");
1219 fclose(f);
1220 }
1221
1222 if(idxs)
1223 {
1224 chain_forward = "forw_common";
1225 chain_postrouting = "post_common";
1226 }
1227 else
1228 {
1229 chain_forward = "FORWARD";
1230 chain_postrouting = "POSTROUTING";
1231 }
1232
1233 if(free_min)
1234 {
1235 final_chain = "ACCEPT";
1236 }
1237
1238 if(qos_proxy)
1239 {
1240 if(free_min)
1241 {
1242 sprintf(str, "-A %s -s %s -p tcp --sport %d -o %s -j %s%d",
1243 chain_postrouting,proxy_ip,proxy_port,lan,mark_iptables, 3);
1244 iptables_save_line(str, FALSE); /* only for IPv4 */
1245 }
1246 sprintf(str, "-A %s -s %s -p tcp --sport %d -o %s -j %s",
1247 chain_postrouting,proxy_ip,proxy_port,lan,final_chain);
1248 iptables_save_line(str, FALSE); /* only for IPv4 */
1249 }
1250
1251 if(free_min)
1252 {
1253 sprintf(str, "-A %s -o %s -j %s%d",
1254 chain_postrouting, lan, mark_iptables, 3);
1255 iptables_save_line(str, FALSE); /* only for IPv4 */
1256 }
1257
1258 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);
1259 iptables_save_line(str, FALSE);
1260 if(ip6prefix)
1261 {
1262 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);
1263 iptables_save_line(str, TRUE);
1264 }
1265
1266 if(free_min)
1267 {
1268 sprintf(str,"-A %s -o %s -j %s%d", chain_forward, wan, mark_iptables, 3);
1269 iptables_save_line(str, FALSE); /* only for IPv4 */
1270 }
1271
1272 sprintf(str,"-A %s -o %s -j %s", chain_forward, wan, final_chain);
1273 iptables_save_line(str, FALSE);
1274 if(ip6prefix)
1275 {
1276 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);
1277 iptables_save_line(str, TRUE);
1278 }
1279
1280 if(free_min) /* allocate free bandwith if it is not zero... */
1281 {
1282 /*-----------------------------------------------------------------*/
1283 puts("Generating free bandwith classes ...");
1284 /*-----------------------------------------------------------------*/
1285 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1286 tc, lan, parent, free_min, free_max,burst, lowest_priority);
1287 safe_run(str);
1288 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",
1289 tc, wan, parent, free_min, free_max, burst, lowest_priority);
1290 safe_run(str);
1291 /* tc SFQ */
1292 if(strcmpi(qos_leaf, "none"))
1293 {
1294 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, lan, qos_leaf);
1295 safe_run(str);
1296
1297 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, wan, qos_leaf);
1298 safe_run(str);
1299 }
1300 /* tc handle 1 fw flowid */
1301 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, lan);
1302 safe_run(str);
1303
1304 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, wan);
1305 safe_run(str);
1306 }
1307 printf("Total IP count: %d\n", i);
1308 run_iptables_restore();
1309 if(log_file)
1310 {
1311 fclose(log_file);
1312 }
1313 return 0;
1314 /* that's all folks, thank you for reading it all the way up to this point ;-) */
1315 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */
1316 }
This page took 1.697843 seconds and 4 git commands to generate.