1b510293460791b215ac569c658910a9fc85840e
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-2019 Michael Polak, Arachne Aerospace */
6 /* iptables-restore support Copyright(C) 2007-2008 ludva */
7 /* Credit: CZFree.Net,Martin Devera,Netdave,Aquarius,Gandalf */
8 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
10 /* Modified by: xChaos, 20190127
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.
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.
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
27 GNU General Public License is located in file COPYING */
29 #include "cll1-0.6.2.h"
32 const char *version
= "0.9.1";
34 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
35 /* Versions: 0.9.0 is development release, 1.0 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 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
43 const char *stats_html_signature
= "<span class=\"small\">Statistics generated by Prometheus QoS version %s<br />GPL+Copyright(C)2005-2017 Michael Polak, <a target=\"_blank\" href=\"http://www.arachne.cz/\">Arachne Labs</a></span>\n";
48 /* ======= All path names are defined here (for RPM patch) ======= */
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 :-) */
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 *upstreamfile
= "/etc/prometheus/upstream.interfaces"; /* list of interfaces to manage */
63 char *downstreamfile
= "/etc/prometheus/downstream.interfaces"; /* list of interfaces to manage */
64 char *qosfreefile
= "/etc/prometheus/qosfree.interfaces"; /* list of interfaces to manage */
65 char *iptablesfile
= "/var/spool/prometheus.iptables"; /* temporary file for iptables-restore*/
66 char *ip6tablesfile
= "/var/spool/prometheus.ip6tables"; /* temporary file for ip6tables-restore*/
67 char *credit
= "/var/lib/misc/prometheus.credit"; /* credit log file */
68 char *classmap
= "/var/lib/misc/prometheus.classes"; /* credit log file */
69 char *html
= "/var/www/traffic.html"; /* hall of fame - html version */
70 char *preview
= "/var/www/preview.html"; /* hall of fame preview - html version */
71 char *json_traffic
= "/var/www/logs/traffic.json"; /* hall of fame - json version */
72 char *json_preview
= "/var/www/logs/preview.json"; /* hall of fame preview - json version */
73 char *cmdlog
= "/var/log/prometheuslog"; /* command log filename */
74 char *log_dir
= "/var/www/logs/"; /* log directory pathname, ended with slash */
75 char *log_url
= "/logs/"; /* log directory relative URI prefix (partial URL) */
76 char *html_log_dir
= "/var/www/logs/html/";
78 char *jquery_url
= "http://code.jquery.com/jquery-latest.js";
79 char *lms_url
= "/lms/?m=customerinfo&id=";
80 int use_jquery_popups
= TRUE
;
81 int row_odd_even
= 0; /*<tr class="odd/even"> */
83 /* === Configuraration file values defaults - stored in global variables ==== */
85 int filter_type
= 1; /*1 mark, 2 classify*/
86 char *final_chain
= "DROP"; /* REJECT would be better, but it is impossible in mangle */
88 char *mark_iptables
= "MARK --set-mark ";
89 int dry_run
= FALSE
; /* preview - use puts() instead of system() */
90 int mix_new_hosts
= FALSE
; /* execute only commands not already in log of iptables */
91 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]";
92 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";
93 FILE *iptables_file
= NULL
;
94 FILE *ip6tables_file
= NULL
;
95 int enable_credit
= TRUE
; /* enable credit file */
96 int use_credit
= FALSE
; /* use credit file (if enabled)*/
97 char *title
= "Hall of Fame - Greatest Suckers"; /* hall of fame title */
98 int hall_of_fame
= TRUE
; /* enable hall of fame */
99 char *medium
= "1000Mbit"; /* 10Mbit/100Mbit ethernet */
100 //obsolete: char *lan = "eth0"; /* LAN interface */
101 //obsolete: char *lan_medium = "1000Mbit"; /* 10Mbit/100Mbit ethernet */
102 char *ip6prefix
= NULL
; /* Prefix for global /48 IPv6 subnet */
103 char *qos_leaf
= "sfq perturb 5"; /* leaf discipline */
104 char *qos_free_zone
= NULL
; /* QoS free zone */
105 /* int qos_proxy = TRUE; include proxy port to QoS */
106 int found_lmsid
= FALSE
; /* show links to users in LMS information system */
107 int include_upload
= TRUE
; /* upload+download=total traffic */
108 /* char *proxy_ip = "192.168.1.1/32"; our IP with proxy port */
109 /* int proxy_port = 3128; proxy port number */
110 //obsolete: long long int line = 1024; /* WAN/ISP download in kbps */
111 //obsolete: long long int up = 1024; /* WAN/ISP upload in kbps */
112 int free_min
= 256; /* minimum guaranted bandwidth for all undefined hosts */
113 int free_max
= 512; /* maximum allowed bandwidth for all undefined hosts */
114 int overlimit_min
= 256; /* minimum guaranted bandwidth for all undefined hosts */
115 int overlimit_max
= 512; /* maximum allowed bandwidth for all undefined hosts */
116 int qos_free_delay
= 0; /* seconds to sleep before applying new QoS rules */
117 int digital_divide
= 2; /* controls digital divide weirdness ratio, 1...3 */
118 int max_nesting
= 5; /* /include/uapi/linux/pkt_sched.h: #define TC_HTB_MAXDEPTH 8 [... - 3 parent classes] */
119 int htb_r2q
= 256; /* should work for leaf values 512 kbps to 8 Mbps */
120 int burst
= 8; /* HTB burst (in kbits) */
122 int burst_group
= 32;
123 int magic_treshold
= 8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */
124 int keywordcount
= 0;
127 FILE *log_file
= NULL
;
128 char *kwd
= "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */
130 const int highest_priority
= 0; /* highest HTB priority (HTB built-in value is 0) */
131 const int lowest_priority
= 7; /* lowest HTB priority /include/uapi/linux/pkt_sched.h: #define TC_HTB_NUMPRIO 8 */
132 const int idxtable_treshold1
= 24; /* this is no longer configurable */
133 const int idxtable_treshold2
= 12; /* this is no longer configurable */
134 const int idxtable_bitmask1
= 3; /* this is no longer configurable */
135 const int idxtable_bitmask2
= 3; /* this is no longer configurable */
137 struct IP
*ips
= NULL
, *networks
= NULL
, *ip
, *sharedip
;
138 struct Group
*groups
= NULL
, *group
;
139 struct Keyword
*keyword
, *defaultkeyword
=NULL
, *keywords
= NULL
;
140 struct Macro
*macro
, *macros
= NULL
;
141 struct Index
*idxs
= NULL
, *idx
, *metaindex
;
142 struct Interface
*interfaces
= NULL
, *interface
;
143 struct QosFreeInterface
*qosfreeinterfaces
= NULL
, *qosfreeinterface
;
144 struct Textfile
*previous_commands
= NULL
, *previous_iptables
= NULL
, *previous_ip6tables
= NULL
, *textline
;
147 #define OVERLIMIT_CLASS 4
150 /* implemented in help.c */
152 void get_traffic_statistics(const char *whichiptables
, int ipv6
);
153 /* implemented in parseiptables.c */
155 void parse_ip_log(int argc
, char **argv
);
156 /* implemented in parselog.c */
158 void parse_hosts(char *hosts
);
159 /* implemented in parsehosts.c */
161 void write_json_traffic(char *json
);
162 /* implemented in json.c */
164 void write_htmlandlogs(char *html
, char *d
, int total
, int just_preview
);
165 /* implemented in htmlandlogs.c */
167 void analyse_topology(char *traceroute
);
168 /* implemented in networks.c */
170 char *parse_datafile_line(char *str
);
171 /* implemented in utils.c */
173 time_t get_mtime(const char *path
);
174 /* implemented in utils.c */
176 const char *tr_odd_even(void)
178 row_odd_even
= 1 - row_odd_even
;
181 return "<tr class=\"even\">\n";
185 return "<tr class=\"odd\">\n";
189 /* ====== iptables indexes are used to reduce complexity to log8(N) ===== */
191 char *index_id(char *ip
, int bitmask
);
192 /* function implemented in ipv4subnets.c */
194 char *subnet_id(char *ip
, int bitmask
);
195 /* function implemented in ipv4subnets.c */
197 char *index6_id(char *ip
, int bitmask
);
198 /* function implemented in ipv6subnets.c */
200 char *subnet6_id(char *ip
, int bitmask
);
201 /* function implemented in ipv6subnets.c */
203 /* ================= Let's parse configuration file here ================ */
205 void reject_config_and_exit(char *filename
)
207 printf("Configuration file %s rejected - abnormal exit.",filename
);
211 void get_config(char *config_filename
)
215 printf("Configured keywords: ");
216 parse(config_filename
)
218 option("keyword",kwd
);
223 create(keyword
,Keyword
);
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
->download_aggregation
= keyword
->upload_aggregation
= 0; /* disable by default */
235 keyword
->html_color
= "000000";
236 keyword
->ip_count
= 0;
237 keyword
->leaf_discipline
= "";
238 keyword
->allowed_avgmtu
= 0;
240 push(keyword
, keywords
);
243 defaultkeyword
= keyword
;
251 for_each(keyword
,keywords
)
253 int l
=strlen(keyword
->key
);
255 if(!strncmp(keyword
->key
,_
,l
) && strlen(_
)>l
+2)
257 char *tmptr
=_
; /* <---- l+1 ----> */
258 _
+=l
+1; /* via-prometheus-asymetry-ratio, etc. */
259 foption("asymetry-ratio", keyword
->asymetry_ratio
);
260 ioption("asymetry-treshold", keyword
->asymetry_fixed
);
261 ioption("magic-relative-limit", keyword
->data_limit
);
262 ioption("magic-relative-prio", keyword
->data_prio
);
263 loption("magic-fixed-limit", keyword
->fixed_limit
);
264 loption("magic-fixed-prio", keyword
->fixed_prio
);
265 ioption("htb-default-prio", keyword
->default_prio
);
266 ioption("htb-rate-bonus", keyword
->reserve_min
);
267 ioption("htb-ceil-malus", keyword
->reserve_max
);
268 ioption("download-aggregation", keyword
->download_aggregation
);
269 ioption("upload-aggregation", keyword
->upload_aggregation
);
270 option("leaf-discipline", keyword
->leaf_discipline
);
271 option("html-color", keyword
->html_color
);
272 ioption("allowed-avgmtu" ,keyword
->allowed_avgmtu
);
275 if(keyword
->data_limit
|| keyword
->fixed_limit
||
276 keyword
->data_prio
|| keyword
->fixed_prio
)
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("downstream-interfaces-list-filename",downstreamfile
);
295 option("upstream-interfaces-list-filename",upstreamfile
);
296 option("qos-free-interfaces-list-filename",qosfreefile
);
297 option("macros-filename",macrosfile
);
298 option("ip6-prefix",ip6prefix
);
299 option("medium",medium
);
300 ioption("hall-of-fame-enable",hall_of_fame
);
301 ioption("digital-divide-weirdness-ratio",digital_divide
);
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);
342 perror(config_filename
);
343 puts("Warning - using built-in defaults instead ...");
345 done
; /* ugly macro end */
348 /* leaf discipline for keywords */
349 for_each(keyword
,keywords
)
351 if(!strcmpi(keyword
->leaf_discipline
, ""))
353 keyword
->leaf_discipline
= qos_leaf
;
357 if(strcmpi(cnf
, "mark"))
361 mark_iptables
= "CLASSIFY --set-class 1:";
367 mark_iptables
= "MARK --set-mark ";
372 /* ========== This function executes, logs OR ALSO prints command ========== */
374 void safe_run(char *cmd
)
378 printf("\n=>%s\n",cmd
);
382 int skip_cmd
= FALSE
;
384 for_each(textline
, previous_commands
)
385 if(eq(textline
->str
, cmd
))
395 printf("Executing command: %s\n", cmd
);
402 fprintf(log_file
,"%s\n",cmd
);
406 void iptables_save_line(char *line
, int ipv6
)
411 for_each(textline
, previous_ip6tables
)
412 if(eq(textline
->str
, line
))
415 fprintf(ip6tables_file
,"%s\n",line
);
420 for_each(textline
, previous_iptables
)
421 if(eq(textline
->str
, line
))
424 fprintf(iptables_file
,"%s\n",line
);
428 printf("Adding iptables/ip6tables rule: %s\n", line
);
436 void run_iptables_restore(void)
439 string(restor
, STRLEN
);
441 /*-----------------------------------------------------------------*/
442 printf("Running %s <%s ...\n", iptablesrestore
, iptablesfile
);
443 /*-----------------------------------------------------------------*/
445 iptables_save_line("COMMIT", IPv4
);
446 fclose(iptables_file
);
453 done
; /* ugly macro end */
456 sprintf(restor
,"%s <%s",iptablesrestore
, iptablesfile
);
461 /*-----------------------------------------------------------------*/
462 printf("Running %s <%s ...\n", ip6tablesrestore
, ip6tablesfile
);
463 /*-----------------------------------------------------------------*/
464 iptables_save_line("COMMIT", IPv6
);
465 fclose(ip6tables_file
);
472 done
; /* ugly macro end */
474 sprintf(restor
,"%s <%s",ip6tablesrestore
, ip6tablesfile
);
482 char *parse_datafile_line(char *str
);
483 time_t get_mtime(const char *path
);
485 /*-----------------------------------------------------------------*/
486 /* Are you looking for int main(int argc, char **argv) ? :-)) */
487 /*-----------------------------------------------------------------*/
491 int i
=0; /* just plain old Fortran style integer :-) */
492 FILE *f
=NULL
; /* everything is just stream of bytes... */
493 char *str
, *ptr
, *d
; /* LET A$=B$ :-) */
494 char *substring
, *limit_pkts
;
497 int just_networks
= FALSE
;
498 int just_flush
= FALSE
; /* deactivates all previous actions */
500 int just_preview
= FALSE
; /* preview - generate just stats */
501 int start_shaping
= FALSE
; /* apply FUP - requires classmap file */
502 int stop_shaping
= FALSE
; /* lift FUP - requires classmap file */
503 int reduce_ceil
= 0; /* allow only rate+(ceil-rate)/2, /4, etc. */
504 int just_logs
= FALSE
; /* just parse logs */
511 Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\
512 Version %s - Copyright (C)2005-2019 Michael Polak, Arachne Labs\n\
513 iptables-restore & burst tunning & classify modification by Ludva\n\
514 Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version
);
516 /*----- Boring... we have to check command line options first: ----*/
519 argument("-c") { nextargument(config
); }
520 argument("-h") { nextargument(althosts
);}
521 argument("-d") { run
= TRUE
; dry_run
= TRUE
; }
522 argument("-f") { run
= TRUE
; just_flush
= TRUE
; }
523 argument("-9") { run
= TRUE
; just_flush
= 9; }
524 argument("-p") { run
= TRUE
; just_preview
= TRUE
; }
525 argument("-q") { run
= TRUE
; just_preview
= TRUE
; stop_shaping
= TRUE
; }
526 argument("-2") { run
= TRUE
; just_preview
= TRUE
; reduce_ceil
= 2; }
527 argument("-4") { run
= TRUE
; just_preview
= TRUE
; reduce_ceil
= 4; }
528 argument("-s") { run
= TRUE
; just_preview
= TRUE
; start_shaping
= TRUE
; }
529 argument("-x") { run
= TRUE
; just_preview
= TRUE
; mix_new_hosts
= TRUE
; }
530 argument("-r") { run
= TRUE
; }
531 argument("-n") { run
= TRUE
; nodelay
= TRUE
; }
532 argument("-a") { run
= TRUE
; just_networks
= TRUE
; }
533 argument("-l") { just_logs
= TRUE
; }
534 argument("-m") { just_logs
= TRUE
; }
535 argument("-y") { just_logs
= TRUE
; }
536 argument("-?") { help(); exit(0); }
537 argument("--help") { help(); exit(0); }
538 argument("-v") { exit(0); }
539 argument("--version") { exit(0); }
544 puts("*** THIS IS JUST DRY RUN ! ***\n");
547 date(d
); /* this is typical cll1.h macro - prints current date */
549 /*-----------------------------------------------------------------*/
550 printf("Parsing configuration file %s ...\n", config
);
551 /*-----------------------------------------------------------------*/
553 /*-----------------------------------------------------------------*/
554 printf("Parsing upstream interfaces list %s ...\n", upstreamfile
);
555 /*-----------------------------------------------------------------*/
558 ptr
= parse_datafile_line(_
);
561 create(interface
, Interface
);
563 interface
->speed
= (long long)atol(ptr
);
564 /* is supplied value meaningful ?*/
565 if(interface
->speed
<= 0)
567 printf("Illegal value of %s interface bandwidth.\n", interface
->name
);
568 reject_config_and_exit(upstreamfile
);
570 interface
->is_upstream
= TRUE
;
571 interface
->chain
= "FORWARD";
572 interface
->idxprefix
= "forw";
573 push(interface
, interfaces
);
574 printf("Upstream interface %s: medium %s capacity %ld kbps\n", interface
->name
, medium
, interface
->speed
);
577 done
; /* ugly macro end */
579 /*-----------------------------------------------------------------*/
580 printf("Parsing downstream interfaces list %s ...\n", downstreamfile
);
581 /*-----------------------------------------------------------------*/
582 parse(downstreamfile
)
584 ptr
= parse_datafile_line(_
);
587 create(interface
, Interface
);
589 interface
->speed
= (long long)atol(ptr
);
590 /* is supplied value meaningful ?*/
591 if(interface
->speed
<= 0)
593 printf("Illegal value of %s interface bandwidth.\n", interface
->name
);
594 reject_config_and_exit(downstreamfile
);
596 interface
->is_upstream
= FALSE
;
597 interface
->chain
= "POSTROUTING";
598 interface
->idxprefix
= "post";
599 push(interface
, interfaces
);
600 printf("Downstream interface %s: medium %s capacity %ld kbps\n", interface
->name
, medium
, interface
->speed
);
603 done
; /* ugly macro end */
607 parse_ip_log(argc
,argv
);
621 if(!mix_new_hosts
&& just_flush
<9)
623 /*-----------------------------------------------------------------*/
624 puts("Parsing iptables verbose output ...");
625 /*-----------------------------------------------------------------*/
626 get_traffic_statistics(iptables
, FALSE
);
629 /*-----------------------------------------------------------------*/
630 puts("Parsing ip6tables verbose output ...");
631 /*-----------------------------------------------------------------*/
632 get_traffic_statistics(ip6tables
, TRUE
);
636 /*-----------------------------------------------------------------*/
637 /* cll1.h - let's allocate brand new character buffer... */
638 /*-----------------------------------------------------------------*/
640 string(limit_pkts
, STRLEN
);
642 /*-----------------------------------------------------------------*/
643 printf("Parsing qos free interfaces file %s ...\n", qosfreefile
);
644 /*-----------------------------------------------------------------*/
645 load(qosfreeinterface
, qosfreeinterfaces
,
646 qosfreefile
, QosFreeInterface
, name
);
648 /*-----------------------------------------------------------------*/
649 printf("Parsing macro definition file %s ...\n", macrosfile
);
650 /*-----------------------------------------------------------------*/
653 ptr
= parse_datafile_line(_
);
656 create(macro
, Macro
);
657 macro
->rewrite_from
= _
;
658 macro
->rewrite_to
= ptr
;
660 printf("%s -> %s\n", macro
->rewrite_from
, macro
->rewrite_to
);
663 done
; /* ugly macro end */
665 /*-----------------------------------------------------------------*/
666 printf("Parsing class defintion file %s ...\n", hosts
);
667 /*-----------------------------------------------------------------*/
670 //this was pretty dumb idea anyway...
673 analyse_topology("/usr/sbin/traceroute -n -m 10 -w 2 %s.%d");
681 /*-----------------------------------------------------------------*/
682 printf("Loading log of previously executed commands %s ...\n", cmdlog
);
683 /*-----------------------------------------------------------------*/
684 load(textline
, previous_commands
, cmdlog
, Textfile
, str
);
685 /*-----------------------------------------------------------------*/
686 printf("Loading log of iptables-restore commands %s ...\n", iptablesfile
);
687 /*-----------------------------------------------------------------*/
688 load(textline
, previous_iptables
, iptablesfile
, Textfile
, str
);
689 /*-----------------------------------------------------------------*/
690 printf("Loading log of ip6tables-restore commands %s ...\n", ip6tablesfile
);
691 /*-----------------------------------------------------------------*/
692 load(textline
, previous_ip6tables
, ip6tablesfile
, Textfile
, str
);
694 string(new_filename
, strlen(iptablesfile
)+2);
695 strcpy(new_filename
, iptablesfile
);
696 strcat(new_filename
, "-x");
697 iptablesfile
= new_filename
;
699 string(new_filename
, strlen(ip6tablesfile
)+2);
700 strcpy(new_filename
, ip6tablesfile
);
701 strcat(new_filename
, "-x");
702 ip6tablesfile
= new_filename
;
705 /*-----------------------------------------------------------------*/
706 puts("Resolving shared connections ...");
707 /*-----------------------------------------------------------------*/
708 for_each(ip
, ips
) if(ip
->sharing
)
710 for_each(sharedip
, ips
) if(eq(sharedip
->name
, ip
->sharing
))
712 sharedip
->traffic
+= ip
->traffic
;
713 sharedip
->traffic_down
+= ip
->direct
;
714 sharedip
->traffic_up
+= ip
->upload
;
716 ip
->mark
= sharedip
->mark
;
717 ip
->lmsid
= sharedip
->lmsid
;
718 ip
->pps_limit
= sharedip
->pps_limit
; /* no other way to do this */
720 /* Ugly hack: append IPv4 addresses of sharedip to IPv6 uplinks */
721 ptr
= strchr(ip
->addr
, '+');
722 if(ptr
&& ptr
-ip
->addr
> 1 && !sharedip
->v6
)
725 concatenate(ip
->addr
, sharedip
->addr
, ptr
);
726 ip
->name
= ip
->addr
= ptr
;
727 ptr
= strchr(ip
->addr
, '.');
731 ptr
= strchr(ptr
, '.');
740 printf("Unresolved shared connection: %s %s sharing-%s\n",
741 ip
->addr
, ip
->name
, ip
->sharing
);
745 if(!mix_new_hosts
&& enable_credit
&& just_flush
<9)
747 /*-----------------------------------------------------------------*/
748 printf("Parsing credit file %s ...\n", credit
);
749 /*-----------------------------------------------------------------*/
752 ptr
= parse_datafile_line(_
);
755 if_exists(ip
,ips
,eq(ip
->addr
,_
))
757 sscanf(ptr
,"%Lu",&(ip
->credit
));
761 done
; /* ugly macro end */
765 if(!mix_new_hosts
&& !just_preview
)
767 /*-----------------------------------------------------------------*/
768 puts("Initializing iptables and tc classes ...");
769 /*-----------------------------------------------------------------*/
771 iptables_file
= fopen(iptablesfile
, "w");
772 if(iptables_file
== NULL
)
774 perror(iptablesfile
);
777 iptables_save_line(iptablespreamble
, IPv4
);
781 ip6tables_file
= fopen(ip6tablesfile
, "w");
782 if(ip6tables_file
== NULL
)
784 perror(ip6tablesfile
);
787 iptables_save_line(iptablespreamble
, IPv6
);
788 iptables_save_line(ip6preamble
, IPv6
);
791 run_iptables_restore();
793 log_file
= fopen(cmdlog
, "w");
800 for_each(interface
, interfaces
)
802 sprintf(str
,"%s qdisc del dev %s root 2>/dev/null", tc
, interface
->name
);
806 iptables_file
=fopen(iptablesfile
,"w");
807 iptables_save_line(iptablespreamble
, IPv4
);
810 ip6tables_file
=fopen(ip6tablesfile
,"w");
811 iptables_save_line(iptablespreamble
, IPv6
);
812 iptables_save_line(ip6preamble
, IPv6
);
815 if(qos_free_zone
&& *qos_free_zone
!='0') /* this is currently supported only for IPv4 */
817 for_each(interface
, interfaces
)
819 sprintf(str
,"-A %s -%c %s -o %s -j ACCEPT", interface
->chain
, (interface
->is_upstream
?'d':'s'), qos_free_zone
, interface
->name
);
820 iptables_save_line(str
, IPv4
);
824 for_each(qosfreeinterface
, qosfreeinterfaces
)
826 sprintf(str
,"-A FORWARD -i %s -j ACCEPT", qosfreeinterface
->name
);
827 iptables_save_line(str
, IPv4
);
828 iptables_save_line(str
, IPv6
);
829 sprintf(str
,"-A POSTROUTING -o %s -j ACCEPT", qosfreeinterface
->name
);
830 iptables_save_line(str
, IPv4
);
831 iptables_save_line(str
, IPv6
);
834 if(ip_count
> idxtable_treshold1
&& !just_flush
)
836 int idxcount
=0, bitmask
=32-idxtable_bitmask1
;
838 /*-----------------------------------------------------------------*/
839 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count
);
840 /*-----------------------------------------------------------------*/
842 iptables_save_line(":post_common - [0:0]", IPv4
);
843 iptables_save_line(":forw_common - [0:0]", IPv4
);
846 iptables_save_line(":post_common - [0:0]", IPv6
);
847 iptables_save_line(":forw_common - [0:0]", IPv6
);
850 for_each(ip
,ips
) if(ip
->addr
&& *(ip
->addr
) && !eq(ip
->addr
,"0.0.0.0/0"))
854 buf
=index6_id(ip
->addr
,bitmask
+32);
858 buf
=index_id(ip
->addr
, bitmask
);
861 if_exists(idx
,idxs
,eq(idx
->id
,buf
))
868 idx
->addr
= ip
->addr
;
870 idx
->bitmask
= bitmask
+32*ip
->v6
;
879 /* brutal perfomance optimalization */
880 while(idxcount
> idxtable_treshold2
&& bitmask
> 2*idxtable_bitmask2
)
882 bitmask
-= idxtable_bitmask2
;
885 for_each(idx
,idxs
) if(idx
->parent
== NULL
)
889 buf
= index6_id(idx
->addr
, bitmask
+32);
893 buf
= index_id(idx
->addr
, bitmask
);
895 if_exists(metaindex
,idxs
,eq(metaindex
->id
,buf
))
897 metaindex
->children
++;
901 create(metaindex
,Index
);
902 metaindex
->addr
= idx
->addr
;
904 metaindex
->bitmask
= bitmask
+32*idx
->ipv6
;
905 metaindex
->parent
= NULL
;
906 metaindex
->children
= 0;
907 metaindex
->ipv6
= idx
->ipv6
;
909 push(metaindex
,idxs
);
911 idx
->parent
=metaindex
;
915 /* this should slightly optimize throughput ... */
916 sort(idx
,idxs
,desc_order_by
,children
);
917 sort(idx
,idxs
,order_by
,bitmask
);
924 subnet
=subnet6_id(idx
->addr
, idx
->bitmask
);
928 subnet
=subnet_id(idx
->addr
, idx
->bitmask
);
930 printf("%d: %s/%d\n", ++i
, subnet
, idx
->bitmask
);
932 sprintf(str
,":post_%s - [0:0]", idx
->id
);
933 iptables_save_line(str
, idx
->ipv6
);
935 sprintf(str
,":forw_%s - [0:0]", idx
->id
);
936 iptables_save_line(str
, idx
->ipv6
);
938 for_each(interface
, interfaces
)
942 string(buf
, strlen(idx
->parent
->id
)+6);
943 sprintf(buf
, "%s_%s", interface
->idxprefix
, idx
->parent
->id
);
947 buf
= interface
->chain
;
950 sprintf(str
, "-A %s -%c %s/%d -o %s -j %s_%s",
951 buf
, (interface
->is_upstream
?'s':'d'), subnet
, idx
->bitmask
, interface
->name
, interface
->idxprefix
, idx
->id
);
952 iptables_save_line(str
, idx
->ipv6
);
954 sprintf(str
, "-A %s -%c %s/%d -o %s -j %s_common",
955 buf
, (interface
->is_upstream
?'s':'d'), subnet
, idx
->bitmask
, interface
->name
, interface
->idxprefix
);
956 iptables_save_line(str
, idx
->ipv6
);
959 printf("Total indexed iptables chains created: %d\n", i
);
961 for_each(interface
, interfaces
)
963 sprintf(str
,"-A %s -o %s -j %s_common", interface
->chain
, interface
->name
, interface
->idxprefix
);
964 iptables_save_line(str
, IPv4
);
967 sprintf(str
,"-A %s -o %s -j %s_common", interface
->chain
, interface
->name
, interface
->idxprefix
);
968 iptables_save_line(str
, IPv6
);
976 fclose(iptables_file
);
981 puts("Just flushed iptables and tc classes - now exiting ...");
985 if(!mix_new_hosts
&& !just_preview
)
987 if(!dry_run
&& !nodelay
&& qos_free_delay
)
989 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n", qos_free_delay
);
990 sleep(qos_free_delay
);
993 for_each(interface
, interfaces
)
995 sprintf(str
, "%s qdisc add dev %s root handle 1: htb r2q %d default 1",
996 tc
, interface
->name
, htb_r2q
);
999 sprintf(str
, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",
1000 tc
, interface
->name
, medium
, medium
, burst_main
, highest_priority
);
1003 sprintf(str
, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",
1004 tc
, interface
->name
, interface
->speed
, interface
->speed
, burst_main
, highest_priority
);
1011 /*-----------------------------------------------------------------*/
1012 puts("Locating heavy downloaders and generating root classes ...");
1013 /*-----------------------------------------------------------------*/
1014 sort(ip
,ips
,desc_order_by
,traffic
);
1017 /*-----------------------------------------------------------------*/
1018 for_each(interface
, interfaces
)
1020 long long int rate
= interface
->speed
;
1021 long long int max
= interface
->speed
;
1022 int group_count
= 0;
1023 //obsolete: FILE *credit_file = NULL;
1025 //obsolete: if(!just_preview && !dry_run && enable_credit)
1027 //obsolete: credit_file = fopen(credit,"w");
1030 for_each(group
,groups
)
1034 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",
1035 tc
, interface
->name
, parent
, group
->id
, rate
, max
, burst_group
, highest_priority
+1, group
->desired
);
1039 if(group_count
++ < max_nesting
)
1044 rate
-= digital_divide
*group
->min
;
1045 if(rate
< group
->min
)
1050 /*shaping of aggresive downloaders, with credit file support */
1054 int group_rate = group->min, priority_sequence = lowest_priority;
1056 for_each(ip, ips) if(ip->min == group->min && ip->max > ip->min)
1058 ip->realquota=ip->credit+(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20));
1059 if( ip->keyword->data_limit
1060 and not ip->fixedprio
1061 and ip->traffic > ip->realquota )
1063 if(group_rate < ip->max)
1065 ip->max = group_rate;
1067 group_rate+=magic_treshold;
1068 ip->prio=lowest_priority;
1069 if(ip->prio<highest_priority+2)
1071 ip->prio=highest_priority+2;
1076 if( ip->keyword->data_prio
1078 && ( ip->traffic > ip->credit + (ip->min*ip->keyword->data_prio+(ip->keyword->fixed_prio<<20))) )
1080 ip->prio=priority_sequence--;
1081 if(ip->prio<highest_priority+1)
1083 ip->prio=highest_priority+1;
1089 unsigned long long lcredit=0;
1091 if((ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))>ip->traffic)
1093 lcredit=(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))-ip->traffic;
1095 fprintf(credit_file,"%s %Lu\n",ip->addr,lcredit);
1104 fclose(credit_file);
1110 if(start_shaping
|| stop_shaping
|| reduce_ceil
)
1112 time_t how_much_seconds
= time(NULL
) - get_mtime(classmap
); /* sice start of daily aggregation session */
1113 printf("Reading %s (%ld seconds old) and applying Fair Use Policy and Aggregation rules... \n", classmap
, how_much_seconds
);
1122 if_exists(ip
,ips
,eq(ip
->addr
,_
))
1124 int unshape_this_ip
= 0;
1125 long avg_mbps_down
= ip
->traffic_down
* 8 / how_much_seconds
;
1126 long avg_mbps_up
= ip
->traffic_up
* 8 / how_much_seconds
;
1127 int agreg
= 1, print_stats
= 1;
1129 if(ip
->keyword
->download_aggregation
)
1131 int min_mbps
= (ip
->min
/ip
->keyword
->download_aggregation
)>>10;
1137 if(min_mbps
<= avg_mbps_down
)
1139 unshape_this_ip
= 0;
1140 agreg
= (int)((float)(avg_mbps_down
+1)/min_mbps
+.5);
1142 ip
->pps_limit
/= agreg
;
1143 printf("Download aggregation 1:%d for %s (min: %lu Mbps avg: %ld Mbps)\n", agreg
, ip
->name
, min_mbps
, avg_mbps_down
);
1147 unshape_this_ip
= 1;
1150 else if(ip
->keyword
->upload_aggregation
)
1152 int min_mbps
= (ip
->min
/ip
->keyword
->upload_aggregation
)>>10;
1158 if(min_mbps
<= avg_mbps_up
)
1160 unshape_this_ip
= 0;
1161 agreg
= (int)((float)(avg_mbps_up
+1)/min_mbps
+.5);
1163 printf("Upload aggregation 1:%d for %s: (min: %lu Mbps avg: %ld Mbps)\n", agreg
, ip
->name
, min_mbps
, avg_mbps_up
);
1167 unshape_this_ip
= 1;
1172 unshape_this_ip
= 1;
1174 ip
->aggregated
= agreg
;
1175 ip
->mark
= atoi(ptr
);
1176 if(ip
->max
< ip
->desired
|| unshape_this_ip
|| reduce_ceil
) /* apply or disable FUP limit immediately.... */
1180 ip
->max
= ip
->desired
;
1181 if(stop_shaping
) /* all limits removed, but not printed with -s (start_shaping) switch */
1183 printf("Removing limit for %s (%s) ", ip
->name
, ip
->addr
);
1192 printf("Updating %s (%s) ", ip
->name
, ip
->addr
);
1195 ip
->max
= ip
->min
+ (ip
->desired
-ip
->min
)/reduce_ceil
;
1197 else if(ip
->max
< ip
->min
)
1202 for_each(interface
, interfaces
)
1204 if(!interface
->is_upstream
)
1208 printf("[down %s: %dk-%dk wants %d]", interface
->name
, ip
->min
, ip
->max
, ip
->desired
);
1210 sprintf(str
, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1211 tc
, interface
->name
, ip
->group
, ip
->mark
, ip
->min
, ip
->max
, burst
, ip
->prio
);
1218 printf("[up %s: %dk-%dk wants %dk]", interface
->name
, (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1219 (int)((ip
->desired
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1220 (int)((ip
->desired
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
));
1222 sprintf(str
,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1223 tc
, interface
->name
, ip
->group
, ip
->mark
,
1224 (int)((ip
->min
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
),
1225 (int)((ip
->max
/ip
->keyword
->asymetry_ratio
)-ip
->keyword
->asymetry_fixed
), burst
, ip
->prio
);
1240 puts("Warning - classmap file not fund, just generating preview ...");
1241 start_shaping
=FALSE
;
1244 done
; /* ugly macro end */
1247 json_traffic
=json_preview
;
1250 if(!mix_new_hosts
&& !dry_run
&& !just_flush
)
1252 /*-----------------------------------------------------------------*/
1253 printf("Writing json traffic overview %s ... ", json_traffic
);
1254 /*-----------------------------------------------------------------*/
1255 write_json_traffic(json_traffic
);
1257 /*-----------------------------------------------------------------*/
1258 printf("Writing statistics into HTML page %s ...\n", html
);
1259 /*-----------------------------------------------------------------*/
1260 write_htmlandlogs(html
, d
, total
, just_preview
);
1270 else if(reduce_ceil
)
1272 swchar
='0'+reduce_ceil
; /* -2, -4 */
1274 else if(stop_shaping
)
1279 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar
);
1285 printf("%-22s %-15s mark\n","name","ip");
1288 printf("Writing %s", classmap
);
1289 f
= fopen(classmap
, "w");
1295 /*-----------------------------------------------------------------*/
1296 printf(" + generating iptables and tc classes ... ");
1297 /*-----------------------------------------------------------------*/
1299 for_each(ip
, ips
) if(ip
->mark
> 0)
1301 for_each(interface
, interfaces
)
1307 duplicate(ip
->addr
,buf
);
1310 buf
=index6_id(ip
->addr
,64-idxtable_bitmask1
);
1314 buf
=index_id(ip
->addr
,32-idxtable_bitmask1
);
1317 string(chain
, 6+strlen(buf
));
1318 sprintf(chain
, "%s_", interface
->idxprefix
);
1325 chain
= interface
->chain
;
1328 /* packet limits - this will be optional in future */
1331 sprintf(limit_pkts
, "-m limit --limit %d/s --limit-burst %d ",
1332 ip
->pps_limit
, ip
->pps_limit
);
1340 printf("%-22s %-16s %04d %d/s\n", ip
->name
, ip
->addr
, ip
->mark
, ip
->pps_limit
);
1343 /* ------------------------------------------------ iptables classify */
1344 sprintf(str
, "-A %s -%c %s/%d -o %s -j %s%d",
1345 chain
, (interface
->is_upstream
?'s':'d'), ip
->addr
, ip
->mask
,
1346 interface
->name
, mark_iptables
, ip
->mark
);
1347 iptables_save_line(str
, ip
->v6
);
1349 sprintf(str
, "-A %s -%c %s/%d -o %s %s-j ACCEPT",
1350 chain
, (interface
->is_upstream
?'s':'d'),ip
->addr
, ip
->mask
,
1351 interface
->name
, limit_pkts
);
1352 iptables_save_line(str
, ip
->v6
);
1354 if(*limit_pkts
) /* non-empty string?*/
1356 /* classify overlimit packets to separate overlimit class */
1357 sprintf(str
, "-A %s -%c %s/%d -o %s -j %s%d",
1358 chain
, (interface
->is_upstream
?'s':'d'), ip
->addr
, ip
->mask
,
1359 interface
->name
, mark_iptables
, OVERLIMIT_CLASS
);
1360 iptables_save_line(str
, ip
->v6
);
1362 sprintf(str
, "-A %s -%c %s/%d -o %s -j ACCEPT",
1363 chain
, (interface
->is_upstream
?'s':'d'), ip
->addr
, ip
->mask
,
1365 iptables_save_line(str
, ip
->v6
);
1370 //TODO - min and max should not exceed interface->speed
1372 /* -------------------------------------------------------- tc class */
1374 printf("[down: %dk-%dk]", ip
->min
, ip
->max
);
1377 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1378 tc
, interface
->name
, ip
->group
, ip
->mark
, ip
->min
, ip
->max
, burst
, ip
->prio
);
1381 if(strcmpi(ip
->keyword
->leaf_discipline
, "none"))
1383 sprintf(str
, "%s qdisc add dev %s parent 1:%d handle %d %s",
1384 tc
, interface
->name
, ip
->mark
, ip
->mark
, ip
->keyword
->leaf_discipline
); /*qos_leaf*/
1388 if(filter_type
== 1)
1390 sprintf(str
, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",
1391 tc
, interface
->name
, ip
->mark
, ip
->mark
);
1398 printf("(sharing %s)\n", ip
->sharing
);
1403 if(ip
->min
&& f
> 0)
1405 fprintf(f
, "%s %d\n", ip
->addr
, ip
->mark
);
1414 for_each(interface
, interfaces
)
1419 string(chain
, STRLEN
);
1420 sprintf(chain
, "%s_common", interface
->idxprefix
);
1424 chain
= interface
->chain
;
1429 final_chain
= "ACCEPT";
1431 sprintf(str
, "-A %s -o %s -j %s%d",
1432 chain
, interface
->name
, mark_iptables
, FREE_CLASS
);
1433 iptables_save_line(str
, IPv4
); /* only for IPv4 */
1436 sprintf(str
,"-A %s -o %s -j %s", chain
, interface
->name
, final_chain
);
1437 iptables_save_line(str
, IPv4
);
1440 sprintf(str
,"-A %s -o %s -j %s", chain
, interface
->name
, final_chain
);
1441 iptables_save_line(str
, IPv6
);
1444 if(free_min
) /* allocate free bandwith if it is not zero... */
1446 /*-----------------------------------------------------------------*/
1447 puts("Generating free bandwith class ...");
1448 /*-----------------------------------------------------------------*/
1449 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1450 tc
, interface
->name
, parent
, FREE_CLASS
, free_min
, free_max
,burst
, lowest_priority
);
1453 if(strcmpi(qos_leaf
, "none"))
1455 sprintf(str
,"%s qdisc add dev %s parent 1:%d handle %d %s", tc
, interface
->name
, FREE_CLASS
, FREE_CLASS
, qos_leaf
);
1458 /* tc handle 1 fw flowid */
1459 sprintf(str
,"%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d", tc
, interface
->name
, FREE_CLASS
, FREE_CLASS
);
1462 /*-----------------------------------------------------------------*/
1463 puts("Generating bandwith class for overlimit packets...");
1464 /*-----------------------------------------------------------------*/
1465 sprintf(str
, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1466 tc
, interface
->name
, parent
, OVERLIMIT_CLASS
, overlimit_min
, overlimit_max
, burst
, lowest_priority
);
1469 printf("Total IP count: %d\n", i
);
1470 run_iptables_restore();
1476 /* that's all folks, thank you for reading it all the way up to this point ;-) */
1477 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */
This page took 1.144382 seconds and 4 git commands to generate.