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