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