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