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