begining of code cleanup: more modular source code
[svn/Prometheus-QoS/.git] / prometheus.c
CommitLineData
312ac2c1 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
8e29188a 5/* Copyright(C) 2005-2012 Michael Polak, Arachne Labs */\r
312ac2c1 6/* iptables-restore support Copyright(C) 2007-2008 ludva */\r
7/* Credit: CZFree.Net,Martin Devera,Netdave,Aquarius,Gandalf */\r
8/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
9\r
6fb3c58a 10/* Modified by: xChaos, 20120612\r
a031788f 11 ludva, 20080415\r
208112af 12 \r
007c44c5 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
c9012978 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
d1ae4fa7 25 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA \r
26 \r
c9012978 27 GNU General Public License is located in file COPYING */\r
007c44c5 28\r
5692c775 29#define STRLEN 512\r
007c44c5 30#define FIRSTGROUPID 1024\r
43e07280 31#define FIRSTIPCLASS 2048\r
007c44c5 32#undef DEBUG\r
33\r
208112af 34#include "cll1-0.6.2.h"\r
007c44c5 35\r
8e29188a 36const char *version = "0.8.3-f";\r
007c44c5 37\r
208112af 38/* Version numbers: 0.8.3 is development releases ("beta"), 0.8.4 will be "stable" */\r
b1b59b3a 39/* Debian(RPM) package versions/patchlevels: 0.7.9-2, 0.8.0-1, 0.8.0-2, etc. */\r
40/* C source code development versions ("beta"): 0.7.9-a, 0.8.1-b, etc. */\r
41/* C source code release versions: 0.8.0, 0.8.2, 0.8.4, etc. */\r
77e71d6b 42\r
4f4d1820 43const char *stats_html_signature = "<span class=\"small\">Statistics generated by Prometheus QoS version %s<br />GPL+Copyright(C)2005-2012 Michael Polak, <a target=\"_blank\" href=\"http://www.arachne.cz/\">Arachne Labs</a></span>\n";\r
2d114137 44\r
82c702a1 45/* ======= All path names are defined here (for RPM patch) ======= */\r
ae776b10 46\r
be96b71b 47const char *tc = "/sbin/tc"; /* requires tc with HTB support */\r
48const char *iptables = "/sbin/iptables"; /* requires iptables utility */\r
49const char *iptablessave = "/sbin/iptables-save"; /* not yet required */\r
50const char *iptablesrestore = "/sbin/iptables-restore"; /* requires iptables-restore */\r
208112af 51const char *ls = "/bin/ls"; /* this is not user configurable :-) */\r
ae776b10 52\r
2d114137 53char *config = "/etc/prometheus/prometheus.conf"; /* main configuration file */\r
54char *hosts = "/etc/prometheus/hosts"; /* per-IP bandwidth definition file */\r
ae776b10 55\r
2d114137 56char *iptablesfile = "/var/spool/prometheus.iptables"; /* temporary file for iptables-restore*/\r
57char *credit = "/var/lib/misc/prometheus.credit"; /* credit log file */\r
be96b71b 58char *classmap = "/var/lib/misc/prometheus.classes"; /* credit log file */\r
59char *html = "/var/www/traffic.html"; /* hall of fame - html version */\r
6fb3c58a 60char *preview = "/var/www/preview.html"; /* hall of fame preview - html version */\r
a7e55d86 61char *json = "/var/www/logs/traffic.json"; /* hall of fame - json version */\r
6fb3c58a 62char *json_preview = "/var/www/logs/preview.json"; /* hall of fame preview - json version */\r
2d114137 63char *cmdlog = "/var/log/prometheuslog"; /* command log filename */\r
64char *log_dir = "/var/www/logs/"; /* log directory pathname, ended with slash */\r
8bcc3268 65char *log_url = "/logs/"; /* log directory relative URI prefix (partial URL) */\r
2d114137 66char *html_log_dir = "/var/www/logs/html/";\r
ae776b10 67\r
6cc38f96 68char *jquery_url = "http://code.jquery.com/jquery-latest.js";\r
69char *lms_url = "/lms/?m=customerinfo&amp;id=";\r
70int use_jquery_popups = 1;\r
9aa195f6 71int row_odd_even = 0; /*<tr class="odd/even"> */\r
72\r
be96b71b 73\r
5692c775 74void parse_ip_log(int argc, char **argv);\r
75/* implementid in parselog.c */\r
76\r
9aa195f6 77const char *tr_odd_even(void)\r
78{\r
79 row_odd_even = 1 - row_odd_even;\r
80 if(row_odd_even)\r
81 {\r
82 return "<tr class=\"even\">\n";\r
83 }\r
84 else\r
85 {\r
86 return "<tr class=\"odd\">\n";\r
87 }\r
88}\r
6cc38f96 89\r
007c44c5 90/* ======= Help screen is hopefuly self-documenting part of code :-) ======= */\r
91\r
92void help(void)\r
93{\r
94 puts("Command line switches:\n\\r
95\n\\r
8e29188a 96-d Dry run (preview tc and iptables commands on stdout)\n\\r
97-r Run (reset all statistics and start shaping - daily usage)\n\\r
98-p just generate Preview of data transfer statistics and exit (after -r)\n\\r
99-s start Shaping FUP limits (keeps data transfer stat like -p) (after -r)\n\\r
100-n run Now (like -r delay - overrides qos-free-delay keyword, after boot)\n\\r
101-f just Flush iptables and tc classes and exit (stop shaping, no QiS)\n\\r
102-9 emergency iptables flush (like -f, but dumps data transfer statistics)\n\\r
103\n\\r
104-c filename force alternative /etc/prometheus/prometheus.conf filename\n\\r
105-h filename force alternative /etc/hosts filename (overrides hosts keyword)\n\\r
106-l Mmm YYYY generate HTML summary of Logged traffic (Mmm=Jan-Dec) (and exit)\n\\r
107-m generate HTML summary of traffic for yesterday's Month (and exit)\n\\r
108-y generate HTML summary of traffic for yesterday's Year (and exit)\n\\r
109-? --help show this help scree (and exit)\n\\r
110-v --version show Version number of this utility (and exit)\n");\r
007c44c5 111}\r
a1d21464 112\r
007c44c5 113/* === Configuraration file values defaults - stored in global variables ==== */\r
114\r
43cde5c3 115int filter_type = 1; /*1 mark, 2 classify*/\r
116char *mark = "MARK";\r
117char *mark_iptables = "MARK --set-mark ";\r
118int dry_run = 0; /* preview - use puts() instead of system() */\r
119char *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
120FILE *iptables_file = NULL;\r
121int enable_credit = 1; /* enable credit file */\r
122int use_credit = 0; /* use credit file (if enabled)*/\r
123char *title = "Hall of Fame - Greatest Suckers"; /* hall of fame title */\r
124int hall_of_fame = 1; /* enable hall of fame */\r
125char *lan = "eth0"; /* LAN interface */\r
126char *lan_medium = "100Mbit"; /* 10Mbit/100Mbit ethernet */\r
127char *wan = "eth1"; /* WAN/ISP interface */\r
128char *wan_medium = "100Mbit"; /* 10Mbit/100Mbit ethernet */\r
129char *qos_leaf = "sfq perturb 5"; /* leaf discipline */\r
130char *qos_free_zone = NULL; /* QoS free zone */\r
131int qos_proxy = 1; /* include proxy port to QoS */\r
4358455e 132int found_lmsid = 0; /* show links to users in LMS information system */\r
43cde5c3 133int include_upload = 1; /* upload+download=total traffic */\r
134char *proxy_ip = "192.168.1.1/32"; /* our IP with proxy port */\r
135int proxy_port = 3128; /* proxy port number */\r
136long long int line = 1024; /* WAN/ISP download in kbps */\r
137long long int up = 1024; /* WAN/ISP upload in kbps */\r
138int free_min = 32; /* minimum guaranted bandwidth for all undefined hosts */\r
139int free_max = 64; /* maximum allowed bandwidth for all undefined hosts */\r
140int qos_free_delay = 0; /* seconds to sleep before applying new QoS rules */\r
141int digital_divide = 2; /* controls digital divide weirdness ratio, 1...3 */ \r
142int max_nesting = 3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */\r
208112af 143int htb_r2q = 256; /* should work for leaf values 512 kbps to 8 Mbps */\r
43cde5c3 144int burst = 8; /* HTB burst (in kbits) */\r
145int burst_main = 64;\r
146int burst_group = 32;\r
43cde5c3 147int magic_treshold = 8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */\r
148int keywordcount = 0;\r
007c44c5 149/* not yet implemented:\r
43cde5c3 150int fixed_packets = 0; maximum number of pps per IP address (not class!) \r
151int packet_limit = 5; maximum number of pps to htn CEIL, not rate !!! \r
007c44c5 152*/\r
43cde5c3 153FILE *log_file = NULL;\r
154char *kwd = "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */\r
007c44c5 155\r
208112af 156const int highest_priority = 0; /* highest HTB priority (HTB built-in value is 0) */\r
157const int lowest_priority = 7; /* lowest HTB priority (HTB built-in value is 7) */\r
158const int idxtable_treshold1 = 24; /* this is no longer configurable */\r
159const int idxtable_treshold2 = 12; /* this is no longer configurable */\r
160const int idxtable_bitmask1 = 3; /* this is no longer configurable */\r
161const int idxtable_bitmask2 = 3; /* this is no longer configurable */\r
007c44c5 162\r
a1d21464 163/* ==== This is C<<1 stuff - learn C<<1 first! https://dev.arachne.cz/svn/cll1h ==== */\r
007c44c5 164\r
165struct IP\r
166{\r
167 char *addr;\r
168 char *name;\r
169 char *sharing;\r
170 int min;\r
171 int desired;\r
172 int max;\r
173 int mark;\r
174 int prio;\r
175 int fixedprio;\r
176 int group;\r
bb9e11ee 177 int lmsid;\r
007c44c5 178 unsigned long long direct;\r
179 unsigned long long proxy;\r
180 unsigned long long upload;\r
181 unsigned long long traffic;\r
182 unsigned long long credit;\r
183 unsigned long pktsup;\r
184 unsigned long pktsdown;\r
185 struct Keyword *keyword;\r
186 list(IP);\r
187} *ips=NULL, *ip, *sharedip;\r
188\r
189struct Group\r
190{\r
191 int min;\r
192 int count;\r
193 int desired;\r
194 int id;\r
195 list(Group);\r
196} *groups=NULL, *group;\r
197\r
198struct Index\r
199{\r
200 char *addr;\r
201 char *id;\r
202 struct Index *parent;\r
203 int bitmask;\r
204 int children;\r
205 list(Index);\r
206} *idxs=NULL, *idx, *metaindex;\r
207\r
208struct Keyword\r
209{\r
210 char *key;\r
211 \r
212 int asymetry_ratio; /* ratio for ADSL-like upload */\r
213 int asymetry_fixed; /* fixed treshold for ADSL-like upload */\r
214 int data_limit; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */\r
19a47f60 215 int data_prio; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */\r
007c44c5 216 long fixed_limit; /* fixed data limit for setting lower HTB ceil */\r
217 long fixed_prio; /* fixed data lmit for setting lower HTB prio */\r
218 int reserve_min; /* bonus for nominal HTB rate bandwidth (in kbps) */\r
219 int reserve_max; /* malus for nominal HTB ceil (in kbps) */\r
220// int divide_max; /* relative malus: new_ceil=rate+(old_ceil-rate)/divide_max */\r
221// int htb_ceil_bonus_divide; /* relative bonus: new_ceil=old_ceil+old_ceil/htb_ceil_bonus_divide */\r
222 int default_prio; /* default HTB priority for this keyword */\r
223 char *html_color;\r
224 int ip_count;\r
225 char *leaf_discipline;\r
226 \r
227 list(Keyword);\r
228} *keyword,*defaultkeyword=NULL,*keywords=NULL;\r
229\r
230/* Damned, this must be object oriented! This looks almost like constructor ;-) */\r
231\r
232void TheIP(void)\r
233{\r
234 create(ip,IP);\r
19a47f60 235 ip->name = "";\r
236 ip->addr = "";\r
237 ip->sharing = NULL;\r
238 ip->prio = highest_priority+1;\r
a1d21464 239 ip->lmsid = -1;\r
bb9e11ee 240 ip->fixedprio = \\r
19a47f60 241 ip->mark = \\r
242 ip->min = \\r
243 ip->max = \\r
244 ip->desired = \\r
245 ip->credit = \\r
246 ip->upload = \\r
247 ip->proxy = \\r
248 ip->direct = \\r
249 ip->traffic = \\r
250 ip->pktsup = \\r
251 ip->pktsdown = 0;\r
252 ip->keyword = keywords;\r
007c44c5 253 push(ip,ips);\r
254}\r
255\r
5b902402 256/* ====== iptables indexes are used to reduce complexity to log8(N) ===== */\r
007c44c5 257\r
258char *very_ugly_ipv4_code(char *inip,int bitmask,int format_as_chainname)\r
259{\r
260 /* warning: this function was debugged only for bitmask values 20,24,28 !!!*/\r
260c2719 261 int dot=0, n;\r
007c44c5 262 char *ip,*outip,*outptr,*fmt;\r
263\r
264 duplicate(inip,ip);\r
265 /* debug printf("(%s,%d) -> ",ip,bitmask); */\r
266\r
267 if(ip && *ip && bitmask>=0 && bitmask<=32)\r
bb9e11ee 268 {\r
007c44c5 269 string(outip,strlen(ip)+10); /*fuck unicode? assertion: 10>strlen("_%d_%d") */\r
bb9e11ee 270 }\r
007c44c5 271 else \r
bb9e11ee 272 {\r
007c44c5 273 /* should never exit here */\r
274 return "undefined";\r
bb9e11ee 275 }\r
007c44c5 276 outptr=outip;\r
277 while(ip && *ip)\r
278 {\r
279 if(*ip=='.')\r
280 {\r
281 if(dot<(bitmask/8-1)) \r
282 {\r
283 if(format_as_chainname)\r
bb9e11ee 284 {\r
007c44c5 285 *outptr='_';\r
bb9e11ee 286 }\r
007c44c5 287 else\r
bb9e11ee 288 {\r
007c44c5 289 *outptr='.';\r
bb9e11ee 290 }\r
007c44c5 291 outptr++;\r
292 dot++;\r
293 }\r
294 else\r
295 {\r
260c2719 296 char *cutdot=strchr(ip+1,'.'); /*for bitmask<24*/ \r
297 if(cutdot)\r
298 {\r
299 *cutdot = '\0';\r
300 }\r
301 \r
007c44c5 302 if(format_as_chainname)\r
260c2719 303 {\r
304 fmt = "_%d_%d";\r
305 }\r
007c44c5 306 else\r
260c2719 307 {\r
308 fmt = ".%d";\r
309 }\r
310 \r
007c44c5 311 if(bitmask%8)\r
260c2719 312 {\r
313 n = atoi(ip+1)-atoi(ip+1)%(1<<(8-bitmask%8));\r
314 }\r
007c44c5 315 else\r
260c2719 316 {\r
317 n = 0;\r
318 }\r
007c44c5 319\r
320 /*debug printf("%d/%d => [_%d_%d]\n",atoi(ip+1),bitmask,n,bitmask); */\r
321 sprintf(outptr,fmt,n,bitmask);\r
260c2719 322 if(!format_as_chainname)\r
007c44c5 323 {\r
260c2719 324 while(bitmask<24)\r
325 {\r
326 strcat(outip,".0");\r
327 bitmask+=8;\r
328 }\r
007c44c5 329 }\r
330 /* debug printf("[%s]\n",outip); */\r
331 return outip;\r
332 }\r
333 }\r
334 else \r
335 {\r
336 *outptr=*ip;\r
337 outptr++;\r
338 }\r
339 ip++;\r
340 }\r
341 /*should never exit here*/\r
342 *outptr='\0';\r
343 return outip;\r
344}\r
345\r
346char *hash_id(char *ip,int bitmask)\r
a1d21464 347{ \r
348 return very_ugly_ipv4_code(ip,bitmask,1);\r
349}\r
007c44c5 350\r
351char *subnet_id(char *ip,int bitmask)\r
a1d21464 352{\r
353 return very_ugly_ipv4_code(ip,bitmask,0);\r
354}\r
007c44c5 355\r
356/* ================= Let's parse configuration file here =================== */\r
357\r
358void reject_config_and_exit(char *filename)\r
359{\r
360 printf("Configuration file %s rejected - abnormal exit.",filename);\r
361 exit(-1);\r
362}\r
363\r
364void get_config(char *config_filename)\r
365{\r
366 char *cnf="mark";\r
367 \r
368 printf("Configured keywords: ");\r
369 parse(config_filename)\r
370 {\r
371 option("keyword",kwd);\r
372 if(kwd)\r
373 {\r
374 printf("%s ",kwd);\r
375\r
376 create(keyword,Keyword);\r
377 keyword->key=kwd;\r
378 keyword->asymetry_ratio=1; /* ratio for ADSL-like upload */\r
379 keyword->asymetry_fixed=0; /* fixed treshold for ADSL-like upload */\r
380 keyword->data_limit=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */\r
208112af 381 keyword->data_prio=4; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */\r
007c44c5 382 keyword->fixed_limit=0; /* fixed data limit for setting lower HTB ceil */\r
383 keyword->fixed_prio=0; /* fixed data limit for setting lower HTB prio */\r
384 keyword->reserve_min=8; /* bonus for nominal HTB rate bandwidth (in kbps) */\r
385 keyword->reserve_max=0; /* malus for nominal HTB ceil (in kbps) */\r
208112af 386 keyword->default_prio=highest_priority+1;\r
007c44c5 387 keyword->html_color="000000";\r
388 keyword->ip_count=0;\r
389 keyword->leaf_discipline="";\r
390\r
391 push(keyword,keywords);\r
392 if(!defaultkeyword) defaultkeyword=keyword;\r
393 keywordcount++;\r
394 \r
395 kwd=NULL;\r
396 }\r
208112af 397 else\r
007c44c5 398 {\r
208112af 399 for_each(keyword,keywords)\r
400 {\r
401 int l=strlen(keyword->key);\r
007c44c5 402\r
208112af 403 if(!strncmp(keyword->key,_,l) && strlen(_)>l+2)\r
404 {\r
405 char *tmptr=_; /* <---- l+1 ----> */\r
406 _+=l+1; /* via-prometheus-asymetry-ratio, etc. */\r
407 ioption("asymetry-ratio",keyword->asymetry_ratio);\r
408 ioption("asymetry-treshold",keyword->asymetry_fixed);\r
409 ioption("magic-relative-limit",keyword->data_limit);\r
410 ioption("magic-relative-prio",keyword->data_prio);\r
411 loption("magic-fixed-limit",keyword->fixed_limit);\r
412 loption("magic-fixed-prio",keyword->fixed_prio);\r
413 ioption("htb-default-prio",keyword->default_prio);\r
414 ioption("htb-rate-bonus",keyword->reserve_min);\r
415 ioption("htb-ceil-malus",keyword->reserve_max);\r
208112af 416 option("leaf-discipline",keyword->leaf_discipline);\r
417 option("html-color",keyword->html_color);\r
418 _=tmptr;\r
419 \r
420 if(keyword->data_limit || keyword->fixed_limit || \r
421 keyword->data_prio || keyword->fixed_prio)\r
bb9e11ee 422 {\r
423 use_credit=1; \r
424 }\r
208112af 425 }\r
426 }\r
007c44c5 427 }\r
428\r
429 option("tc",tc);\r
430 option("iptables",iptables);\r
431 option("iptables-save",iptablessave); /* new */\r
432 option("iptables-restore",iptablesrestore); /* new */\r
be96b71b 433 option("iptables-in-filename",iptablesfile); /* new */\r
007c44c5 434 option("hosts",hosts);\r
435 option("lan-interface",lan);\r
436 option("wan-interface",wan);\r
437 option("lan-medium",lan_medium);\r
438 option("wan-medium",wan_medium);\r
439 lloption("wan-download",line);\r
440 lloption("wan-upload",up);\r
441 ioption("hall-of-fame-enable",hall_of_fame);\r
442 option("hall-of-fame-title",title);\r
443 option("hall-of-fame-filename",html);\r
be96b71b 444 option("json-filename",json);\r
007c44c5 445 option("hall-of-fame-preview",preview);\r
6fb3c58a 446 option("json-preview",json_preview);\r
007c44c5 447 option("log-filename",cmdlog);\r
448 option("credit-filename",credit);\r
be96b71b 449 option("classmap-filename",classmap);\r
007c44c5 450 ioption("credit-enable",enable_credit);\r
451 option("log-traffic-directory",log_dir);\r
5b902402 452 option("log-traffic-html-directory",html_log_dir);\r
007c44c5 453 option("log-traffic-url-path",log_url);\r
6cc38f96 454 option("jquery-url",jquery_url);\r
455 option("lms-url",lms_url);\r
456 ioption("use-jquery-popups",use_jquery_popups);\r
007c44c5 457 option("qos-free-zone",qos_free_zone);\r
458 ioption("qos-free-delay",qos_free_delay);\r
459 ioption("qos-proxy-enable",qos_proxy);\r
460 option("qos-proxy-ip",proxy_ip);\r
461 option("htb-leaf-discipline",qos_leaf);\r
462 ioption("qos-proxy-port",proxy_port);\r
463 ioption("free-rate",free_min);\r
464 ioption("free-ceil",free_max);\r
465 ioption("htb-burst",burst);\r
466 ioption("htb-burst-main",burst_main);\r
467 ioption("htb-burst-group",burst_group);\r
468 ioption("htb-nesting-limit",max_nesting);\r
469 ioption("htb-r2q",htb_r2q);\r
470 ioption("magic-include-upload",include_upload);\r
5b902402 471 ioption("magic-treshold",magic_treshold); \r
260c2719 472 option("filter-type", cnf); \r
007c44c5 473/* not yet implemented:\r
474 ioption("magic-fixed-packets",fixed_packets);\r
475 ioption("magic-relative-packets",packet_limit);\r
476*/\r
477 }\r
478 fail\r
479 { \r
480 perror(config_filename);\r
481 puts("Warning - using built-in defaults instead ...");\r
482 }\r
8e29188a 483 done; /* ugly macro end */\r
007c44c5 484 printf("\n");\r
485 \r
be96b71b 486 /* leaf discipline for keywords */\r
208112af 487 for_each(keyword,keywords)\r
007c44c5 488 {\r
260c2719 489 if(!strcmpi(keyword->leaf_discipline, ""))\r
208112af 490 {\r
007c44c5 491 keyword->leaf_discipline = qos_leaf;\r
492 }\r
493 }\r
494\r
260c2719 495 if(strcmpi(cnf, "mark"))\r
bb9e11ee 496 {\r
497 filter_type = 2;\r
498 mark = "CLASSIFY";\r
499 mark_iptables = "CLASSIFY --set-class 1:";\r
500 }\r
501 else\r
502 {\r
503 filter_type = 1;\r
504 mark = "MARK";\r
505 mark_iptables = "MARK --set-mark ";\r
007c44c5 506 }\r
507\r
508 /* are supplied values meaningful ?*/\r
509 if(line<=0 || up<=0)\r
510 {\r
b1b59b3a 511 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");\r
007c44c5 512 reject_config_and_exit(config_filename);\r
513 }\r
514}\r
515\r
516/* ===================== traffic analyser - uses iptables ================ */ \r
517\r
518void get_traffic_statistics(void)\r
519{\r
520 char *str,*cmd;\r
521 int downloadflag=0;\r
522\r
523 textfile(Pipe,str) *line,*lines=NULL;\r
524 string(str,STRLEN);\r
525 string(cmd,STRLEN);\r
526\r
527 sprintf(cmd,"%s -L -v -x -n -t mangle",iptables);\r
528 shell(cmd);\r
529 input(str,STRLEN)\r
530 {\r
531 create(line,Pipe);\r
532 line->str=str;\r
533 string(str,STRLEN);\r
534 append(line,lines);\r
535 }\r
536\r
208112af 537 for_each(line,lines)\r
007c44c5 538 {\r
539 int col, accept=0,proxyflag=0,valid=1,setchainname=0,commonflag=0; \r
540 unsigned long long traffic=0;\r
541 unsigned long pkts=0;\r
542 char *ipaddr=NULL,*ptr;\r
543 \r
544 /* debug puts(line->str); */\r
545 valid_columns(ptr,line->str,' ',col) \r
546 if(valid) switch(col)\r
547 { \r
548 case 1: if(eq(ptr,"Chain"))\r
260c2719 549 {\r
007c44c5 550 setchainname=1;\r
260c2719 551 }\r
007c44c5 552 else if(eq(ptr,"pkts")) \r
260c2719 553 {\r
007c44c5 554 valid=0;\r
260c2719 555 }\r
007c44c5 556 else\r
260c2719 557 {\r
007c44c5 558 sscanf(ptr,"%lu",&pkts); \r
260c2719 559 }\r
007c44c5 560 break;\r
561 case 2: if(setchainname)\r
562 {\r
563 if(!strncmp(ptr,"post_",5) || eq(ptr,"POSTROUTING"))\r
260c2719 564 {\r
565 downloadflag = 1; \r
566 }\r
007c44c5 567 else \r
260c2719 568 {\r
569 if(!strncmp(ptr,"forw_",5) || eq(ptr,"FORWARD"))\r
570 {\r
571 downloadflag = 0;\r
572 }\r
573 } \r
007c44c5 574 if(eq(ptr,"post_common") || eq(ptr,"forw_common"))\r
260c2719 575 {\r
576 commonflag = 1;\r
577 }\r
007c44c5 578 }\r
579 else\r
260c2719 580 {\r
581 sscanf(ptr,"%Lu",&traffic); \r
582 traffic += (1<<19);\r
583 traffic >>= 20;\r
584 }\r
007c44c5 585 break;\r
0045483c 586 case 3: if((strncmp(ptr,"post_",5) && strncmp(ptr,"forw_",5)) || commonflag)\r
260c2719 587 {\r
007c44c5 588 accept=eq(ptr,mark);\r
260c2719 589 }\r
590 /*if(filter_type==1) accept=eq(ptr,"MARK"); else accept=eq(ptr,"CLASSIFY");*/\r
007c44c5 591 break;\r
592 case 8: if(downloadflag)\r
593 { \r
260c2719 594 if(strstr(proxy_ip,ptr))\r
595 {\r
596 proxyflag=1; \r
597 }\r
007c44c5 598 }\r
599 else\r
260c2719 600 {\r
007c44c5 601 ipaddr=ptr; \r
260c2719 602 }\r
603 break;\r
007c44c5 604 case 9: if(downloadflag)ipaddr=ptr;break;\r
605 }\r
606 \r
607 if(accept && traffic>0 && ipaddr)\r
608 {\r
a1d21464 609 if(proxyflag)\r
610 {\r
611 printf("(proxy) ");\r
612 }\r
613 else if(!downloadflag)\r
614 {\r
615 printf("(upload) ");\r
616 }\r
457d52f2 617 printf("IP %s: %Lu MB (%ld pkts)\n", ipaddr, traffic, pkts);\r
208112af 618\r
619 if_exists(ip,ips,eq(ip->addr,ipaddr)); \r
007c44c5 620 else \r
621 {\r
622 TheIP();\r
623 ip->addr=ipaddr;\r
624 if(eq(ip->addr,"0.0.0.0/0"))\r
625 {\r
626 ip->name="(unregistered)";\r
627 ip->min=free_min;\r
628 ip->max=ip->desired=free_max;\r
629 }\r
630 }\r
631 \r
632 if(downloadflag)\r
633 {\r
634 if(proxyflag)\r
a1d21464 635 {\r
007c44c5 636 ip->proxy=traffic;\r
a1d21464 637 }\r
007c44c5 638 else\r
a1d21464 639 {\r
007c44c5 640 ip->traffic+=traffic;\r
a1d21464 641 }\r
007c44c5 642 ip->direct=ip->traffic-ip->upload-ip->proxy;\r
643 ip->pktsdown=pkts;\r
644 }\r
645 else\r
646 {\r
647 ip->upload=traffic;\r
648 ip->pktsup=pkts;\r
649 if(include_upload)\r
bb9e11ee 650 {\r
007c44c5 651 ip->traffic+=traffic;\r
bb9e11ee 652 }\r
007c44c5 653 else \r
bb9e11ee 654 {\r
007c44c5 655 if(traffic>ip->traffic)\r
bb9e11ee 656 {\r
007c44c5 657 ip->traffic=traffic; \r
bb9e11ee 658 }\r
659 }\r
007c44c5 660 }\r
661 } \r
662 }\r
1c004f15 663 free(cmd);\r
007c44c5 664}\r
665 \r
666/* ========== This function executes, logs OR ALSO prints command ========== */\r
667\r
668void safe_run(char *cmd)\r
669{\r
a1d21464 670 if(dry_run)\r
671 {\r
672 printf("\n=>%s\n",cmd);\r
673 }\r
674 else\r
675 {\r
676 system(cmd);\r
677 }\r
678 if(log_file)\r
679 {\r
680 fprintf(log_file,"%s\n",cmd);\r
681 }\r
007c44c5 682}\r
683\r
684void save_line(char *line)\r
685{\r
686 fprintf(iptables_file,"%s\n",line);\r
687}\r
688\r
689void run_restore(void)\r
690{\r
5da44508 691 char *restor;\r
007c44c5 692 string(restor,STRLEN);\r
abe9b855 693\r
694 /*-----------------------------------------------------------------*/\r
1c004f15 695 printf("Running %s <%s ...\n", iptablesrestore, iptablesfile);\r
abe9b855 696 /*-----------------------------------------------------------------*/\r
007c44c5 697 \r
698 save_line("COMMIT");\r
699 fclose(iptables_file);\r
ae776b10 700 if(dry_run) \r
701 {\r
a1d21464 702 parse(iptablesfile)\r
703 {\r
704 printf("%s\n",_);\r
705 }\r
8e29188a 706 done; /* ugly macro end */\r
ae776b10 707 }\r
708\r
709 sprintf(restor,"%s <%s",iptablesrestore, iptablesfile);\r
710 safe_run(restor);\r
007c44c5 711 \r
712 free(restor);\r
713}\r
714\r
715/* == This function strips extra characters after IP address and stores it = */\r
716\r
0eb8bc04 717void parse_ip(char *str)\r
007c44c5 718{\r
4358455e 719 char *ptr,*ipaddr=NULL,*ipname=NULL,*lmsid=NULL;\r
720\r
721 ptr=strchr(str,'{');\r
722 if(ptr)\r
723 {\r
724 lmsid=++ptr;\r
725 while(*ptr && *ptr!='}')\r
a1d21464 726 {\r
4358455e 727 ptr++;\r
a1d21464 728 }\r
4358455e 729 *ptr=0;\r
730 }\r
007c44c5 731 \r
4358455e 732 ptr=str;\r
007c44c5 733 while(*ptr && *ptr!=' ' && *ptr!=9)\r
a1d21464 734 {\r
007c44c5 735 ptr++;\r
a1d21464 736 }\r
007c44c5 737 \r
738 *ptr=0;\r
739 ipaddr=str;\r
740 ptr++;\r
741 while(*ptr && (*ptr==' ' || *ptr==9))\r
a1d21464 742 {\r
007c44c5 743 ptr++;\r
a1d21464 744 }\r
007c44c5 745 ipname=ptr; \r
746 while(*ptr && *ptr!=' ' && *ptr!=9)\r
a1d21464 747 {\r
007c44c5 748 ptr++;\r
a1d21464 749 }\r
007c44c5 750 *ptr=0;\r
751\r
208112af 752 if_exists(ip,ips,eq(ip->addr,ipaddr));\r
753 else\r
754 {\r
755 TheIP();\r
756 }\r
007c44c5 757 ip->addr=ipaddr;\r
758 ip->name=ipname;\r
4358455e 759 if(lmsid)\r
760 {\r
761 ip->lmsid=atoi(lmsid);\r
762 found_lmsid=1;\r
763 }\r
007c44c5 764}\r
765\r
766char *parse_datafile_line(char *str)\r
767{\r
768 char *ptr=strchr(str,' ');\r
769\r
770 if(ptr)\r
771 {\r
772 *ptr=0;\r
773 ptr++;\r
774 return ptr;\r
775 } \r
776 else \r
4358455e 777 {\r
007c44c5 778 return NULL;\r
4358455e 779 }\r
007c44c5 780}\r
781\r
c9012978 782\r
b1b59b3a 783\r
add90548 784\r
785void append_log(struct IP *self) /*using global variables*/\r
786{\r
787 char *d, *str;\r
788 FILE *f; \r
789\r
790 date(d); /* this is typical cll1.h macro - prints current date */ \r
791 string(str,STRLEN); \r
792 sprintf(str,"%s/%s.log", log_dir, self->name);\r
793 f=fopen(str,"a");\r
be96b71b 794 if(f > 0)\r
add90548 795 {\r
796 fprintf(f,"%ld\t%s\t%Lu\t%Lu\t%Lu\t%Lu\t%d\t%d\t%d\t%d\t%s",\r
797 time(NULL), self->name, self->traffic, self->direct, self->proxy,\r
798 self->upload, self->min, self->max, self->desired, self->lmsid, d); /* d = date*/\r
799 fclose(f);\r
800 }\r
801 else\r
802 {\r
803 perror(str);\r
804 }\r
c9012978 805}\r
5b902402 806\r
add90548 807\r
007c44c5 808/*-----------------------------------------------------------------*/\r
493e1ccd 809/* Are you looking for int main(int argc, char **argv) ? :-)) */\r
007c44c5 810/*-----------------------------------------------------------------*/\r
811\r
812program\r
813{\r
8e29188a 814 int i=0; /* just plain old Fortran style integer :-) */\r
815 FILE *f=NULL; /* everything is just stream of bytes... */\r
816 char *str, *ptr, *d; /* LET A$=B$ :-) */\r
007c44c5 817 char *substring;\r
818 int class_count=0,ip_count=0;\r
819 int parent=1;\r
8e29188a 820 int just_flush=FALSE; /* deactivates all previous actions */\r
208112af 821 int nodelay=FALSE;\r
8e29188a 822 int just_preview=FALSE; /* preview - generate just stats */\r
823 int start_shaping=FALSE; /* apply FUP - requires classmap file */\r
824 int just_logs=FALSE; /* just parse logs */\r
208112af 825 int run=FALSE;\r
b014f181 826 int total=0;\r
33ec95ab 827 \r
007c44c5 828 char *chain_forward, *chain_postrouting;\r
829 char *althosts=NULL;\r
830 \r
831 printf("\n\\r
832Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\\r
8e29188a 833Version %s - Copyright (C)2005-2012 Michael Polak, Arachne Labs\n\\r
43cde5c3 834iptables-restore & burst tunning & classify modification by Ludva\n\\r
0d5026c6 835Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version);\r
007c44c5 836\r
8e29188a 837 /*----- Boring... we have to check command line options first: ----*/ \r
007c44c5 838 arguments\r
839 {\r
840 argument("-c") { nextargument(config); }\r
841 argument("-h") { nextargument(althosts);}\r
208112af 842 argument("-d") { run=TRUE; dry_run=TRUE; }\r
843 argument("-f") { run=TRUE; just_flush=TRUE; }\r
844 argument("-9") { run=TRUE; just_flush=9; }\r
845 argument("-p") { run=TRUE; just_preview=TRUE; }\r
8e29188a 846 argument("-s") { run=TRUE; just_preview=TRUE; start_shaping=TRUE; }\r
208112af 847 argument("-r") { run=TRUE; }\r
848 argument("-n") { run=TRUE; nodelay=TRUE; }\r
849 argument("-l") { just_logs=TRUE; }\r
850 argument("-m") { just_logs=TRUE; }\r
851 argument("-y") { just_logs=TRUE; }\r
007c44c5 852 argument("-?") { help(); exit(0); }\r
853 argument("--help") { help(); exit(0); }\r
854 argument("-v") { exit(0); } \r
855 argument("--version") { exit(0); } \r
856 }\r
208112af 857 \r
007c44c5 858 if(dry_run)\r
208112af 859 {\r
007c44c5 860 puts("*** THIS IS JUST DRY RUN ! ***\n");\r
208112af 861 }\r
007c44c5 862\r
208112af 863 date(d); /* this is typical cll1.h macro - prints current date */\r
007c44c5 864\r
865 /*-----------------------------------------------------------------*/\r
866 printf("Parsing configuration file %s ...\n", config);\r
867 /*-----------------------------------------------------------------*/\r
868 get_config(config);\r
c9012978 869 \r
33ec95ab 870 if(just_logs)\r
c9012978 871 {\r
208112af 872 parse_ip_log(argc,argv);\r
873 exit(0);\r
874 }\r
875 else if(not run)\r
876 {\r
877 help();\r
878 exit(0);\r
c9012978 879 }\r
007c44c5 880\r
208112af 881 if(althosts)\r
882 {\r
883 hosts=althosts;\r
884 }\r
007c44c5 885\r
886 if(just_flush<9)\r
887 {\r
888 /*-----------------------------------------------------------------*/\r
889 puts("Parsing iptables verbose output ...");\r
890 /*-----------------------------------------------------------------*/\r
891 get_traffic_statistics();\r
892 }\r
893\r
894 /*-----------------------------------------------------------------*/\r
895 printf("Parsing class defintion file %s ...\n", hosts);\r
896 /*-----------------------------------------------------------------*/\r
897 int groupidx = FIRSTGROUPID;\r
898 parse(hosts)\r
899 {\r
900 str=_;\r
901\r
902 if(*str<'0' || *str>'9')\r
4358455e 903 {\r
904 /* any line starting with non-number is comment ...*/\r
007c44c5 905 continue;\r
4358455e 906 }\r
007c44c5 907 \r
908 //Does this IP share QoS class with some other ?\r
909 substring=strstr(str,"sharing-");\r
910 if(substring)\r
911 { \r
912 substring+=8; //"sharing-"\r
0eb8bc04 913 parse_ip(str);\r
007c44c5 914 ip_count++;\r
915 ip->sharing=substring;\r
916 ip->keyword=defaultkeyword; /* settings for default keyword */\r
917 while(*substring && *substring!='\n')\r
4358455e 918 {\r
007c44c5 919 substring++;\r
4358455e 920 }\r
007c44c5 921 *substring=0; \r
922 }\r
923 else\r
924 {\r
925 //Do we have to create new QoS class for this IP ?\r
926\r
208112af 927 if_exists(keyword,keywords,(substring=strstr(str,keyword->key)))\r
007c44c5 928 {\r
0eb8bc04 929 parse_ip(str);\r
007c44c5 930 ip_count++;\r
931 ip->keyword=keyword;\r
932 keyword->ip_count++;\r
933 ip->prio=keyword->default_prio;\r
934 substring+=strlen(keyword->key)+1;\r
935 ptr=substring;\r
936 while(*ptr && *ptr!='-')\r
bb9e11ee 937 {\r
007c44c5 938 ptr++;\r
bb9e11ee 939 }\r
007c44c5 940 if(*ptr=='-')\r
941 {\r
942 *ptr=0;\r
260c2719 943 ip->max = ip->desired=atoi(ptr+1);\r
007c44c5 944 }\r
260c2719 945 ip->min = atoi(substring);\r
946 if(ip->min <= 0)\r
007c44c5 947 {\r
3ece6581 948 printf(" %s: Illegal value of minimum bandwidth 0 kbps, using %d kb/s\n",\r
260c2719 949 str, free_min);\r
950 ip->min = free_min;\r
007c44c5 951 }\r
260c2719 952 if(ip->max <= ip->min)\r
007c44c5 953 {\r
260c2719 954 ip->fixedprio = 1;\r
955 ip->max = ip->min+ip->keyword->reserve_min;\r
007c44c5 956 }\r
957 else \r
958 {\r
260c2719 959 ip->max -= ip->keyword->reserve_max;\r
007c44c5 960 if(ip->max<ip->min)\r
bb9e11ee 961 {\r
007c44c5 962 ip->max=ip->min;\r
bb9e11ee 963 }\r
007c44c5 964 }\r
43e07280 965 ip->mark=FIRSTIPCLASS+1+class_count++;\r
007c44c5 966\r
208112af 967 if_exists(group,groups,group->min==ip->min) \r
007c44c5 968 { \r
969 group->count++; \r
260c2719 970 group->desired += ip->min;\r
007c44c5 971 ip->group = group->id; \r
972 }\r
973 else\r
974 {\r
975 create(group,Group);\r
260c2719 976 group->min = ip->min;\r
007c44c5 977 group->id = groupidx++;\r
978 ip->group = group->id;\r
979\r
980 if(group->min<8) group->min=8;\r
981 /* Warning - this is maybe because of primitive tc namespace, can be fixed */\r
982 /* it is because class IDs are derived from min. bandwidth. - xCh */\r
983 //if(group->min>MAX_GUARANTED_KBPS) group->min=MAX_GUARANTED_KBPS;\r
984 \r
985 group->count=1;\r
986 group->desired=ip->min; \r
987 insert(group,groups,desc_order_by,min);\r
988 }\r
989 }//endif keyword-\r
990 }//endif sharing-\r
991 }\r
992 fail\r
993 {\r
994 perror(hosts);\r
995 exit(-1);\r
996 }\r
8e29188a 997 done; /* ugly macro end */\r
007c44c5 998\r
999 /*-----------------------------------------------------------------*/\r
1000 /* cll1.h - let's allocate brand new character buffer... */\r
1001 /*-----------------------------------------------------------------*/\r
1002 string(str,STRLEN); \r
1003\r
1004 /*-----------------------------------------------------------------*/\r
1005 puts("Resolving shared connections ...");\r
1006 /*-----------------------------------------------------------------*/\r
6cc38f96 1007 for_each(ip,ips) if(ip->sharing)\r
007c44c5 1008 {\r
6cc38f96 1009 for_each(sharedip,ips) if(eq(sharedip->name,ip->sharing))\r
007c44c5 1010 {\r
1011 sharedip->traffic+=ip->traffic;\r
1012 ip->traffic=0;\r
1013 ip->mark=sharedip->mark; \r
b3175d62 1014 ip->lmsid=sharedip->lmsid;\r
007c44c5 1015 break;\r
1016 }\r
1017 if(!sharedip)\r
bb9e11ee 1018 {\r
260c2719 1019 printf("Unresolved shared connection: %s %s sharing-%s\n",\r
1020 ip->addr, ip->name, ip->sharing);\r
bb9e11ee 1021 }\r
007c44c5 1022 }\r
1023\r
1024 if(enable_credit && just_flush<9)\r
1025 {\r
1026 /*-----------------------------------------------------------------*/\r
1027 printf("Parsing credit file %s ...\n", credit);\r
1028 /*-----------------------------------------------------------------*/\r
1029 parse(credit)\r
1030 {\r
1031 ptr=parse_datafile_line(_);\r
1032 if(ptr)\r
1033 {\r
208112af 1034 if_exists(ip,ips,eq(ip->addr,_))\r
1035 {\r
007c44c5 1036 sscanf(ptr,"%Lu",&(ip->credit));\r
208112af 1037 }\r
007c44c5 1038 }\r
1039 }\r
8e29188a 1040 done; /* ugly macro end */\r
007c44c5 1041 }\r
1042\r
1043 if(!just_preview)\r
1044 {\r
1045 /*-----------------------------------------------------------------*/\r
1046 puts("Initializing iptables and tc classes ...");\r
1047 /*-----------------------------------------------------------------*/\r
1048 \r
1049 iptables_file=fopen(iptablesfile,"w");\r
260c2719 1050 if(iptables_file == NULL)\r
bb9e11ee 1051 {\r
007c44c5 1052 puts("Cannot open iptablesfile!");\r
1053 exit(-1);\r
1054 }\r
1055 \r
1056 log_file=fopen(cmdlog,"w");\r
260c2719 1057 if(log_file == NULL) \r
bb9e11ee 1058 {\r
007c44c5 1059 puts("Cannot open logfile!");\r
1060 exit(-1);\r
1061 }\r
1062 \r
1063 save_line(iptablespreamble);\r
1064 run_restore();\r
1065 \r
1066 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,lan);\r
1067 safe_run(str);\r
1068\r
1069 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,wan);\r
1070 safe_run(str);\r
1071 \r
1072 iptables_file=fopen(iptablesfile,"w");\r
1073 save_line(iptablespreamble);\r
1074\r
1075 if(qos_free_zone && *qos_free_zone!='0')\r
1076 {\r
1077 char *chain;\r
1078 \r
1079 sprintf(str,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone, wan);\r
1080 save_line(str);\r
1081 \r
1082 if(qos_proxy)\r
1083 {\r
1084 save_line(":post_noproxy - [0:0]");\r
1085 sprintf(str,"-A POSTROUTING -p ! tcp -o %s -j post_noproxy", lan);\r
1086 save_line(str); \r
1087 sprintf(str,"-A POSTROUTING -s ! %s -o %s -j post_noproxy", proxy_ip, lan);\r
1088 save_line(str); \r
1089 sprintf(str,"-A POSTROUTING -s %s -p tcp --sport ! %d -o %s -j post_noproxy", proxy_ip, proxy_port, lan);\r
1090 save_line(str); \r
1091\r
1092 chain="post_noproxy"; \r
1093 }\r
1094 else\r
bb9e11ee 1095 {\r
007c44c5 1096 chain="POSTROUTING";\r
bb9e11ee 1097 }\r
007c44c5 1098 \r
1099 sprintf(str,"-A %s -s %s -o %s -j ACCEPT", chain, qos_free_zone, lan);\r
1100 save_line(str);\r
1101 }\r
1102 \r
1103 if(ip_count>idxtable_treshold1 && !just_flush)\r
1104 {\r
1105 int idxcount=0, bitmask=32-idxtable_bitmask1; /* default net mask: 255.255.255.240 */\r
e0161edb 1106 char *subnet, *buf;\r
007c44c5 1107 /*-----------------------------------------------------------------*/\r
1108 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count);\r
1109 /*-----------------------------------------------------------------*/\r
1110\r
1111 save_line(":post_common - [0:0]");\r
1112 save_line(":forw_common - [0:0]");\r
1113\r
260c2719 1114 for_each(ip,ips) if(ip->addr && *(ip->addr) && !eq(ip->addr,"0.0.0.0/0"))\r
007c44c5 1115 {\r
1116 buf=hash_id(ip->addr,bitmask);\r
208112af 1117 if_exists(idx,idxs,eq(idx->id,buf))\r
1118 {\r
007c44c5 1119 idx->children++;\r
208112af 1120 }\r
007c44c5 1121 else\r
1122 {\r
1123 create(idx,Index);\r
1124 idx->addr=ip->addr;\r
1125 idx->id=buf;\r
1126 idx->bitmask=bitmask;\r
1127 idx->parent=NULL;\r
1128 idx->children=0;\r
1129 idxcount++;\r
1130 push(idx,idxs);\r
1131 }\r
1132 }\r
1133\r
1134 /* brutal perfomance optimalization */\r
1135 while(idxcount>idxtable_treshold2 && bitmask>2*idxtable_bitmask2)\r
1136 {\r
1137 bitmask-=idxtable_bitmask2;\r
1138 idxcount=0;\r
208112af 1139\r
6cc38f96 1140 for_each(idx,idxs) if(idx->parent == NULL)\r
007c44c5 1141 {\r
1142 buf=hash_id(idx->addr,bitmask);\r
208112af 1143 if_exists(metaindex,idxs,eq(metaindex->id,buf))\r
1144 {\r
1145 metaindex->children++;\r
1146 }\r
007c44c5 1147 else\r
1148 {\r
1149 create(metaindex,Index);\r
1150 metaindex->addr=idx->addr;\r
1151 metaindex->id=buf;\r
1152 metaindex->bitmask=bitmask;\r
1153 metaindex->parent=NULL;\r
1154 metaindex->children=0;\r
1155 idxcount++;\r
1156 push(metaindex,idxs);\r
1157 }\r
1158 idx->parent=metaindex;\r
1159 }\r
1160 }\r
1161\r
1162 /* this should slightly optimize throughout ... */\r
1163 sort(idx,idxs,desc_order_by,children);\r
1164 sort(idx,idxs,order_by,bitmask);\r
1165\r
1166 i=0;\r
208112af 1167 for_each(idx,idxs)\r
007c44c5 1168 {\r
1169 subnet=subnet_id(idx->addr,idx->bitmask);\r
260c2719 1170 printf("%d: %s/%d\n",\r
1171 ++i, subnet, idx->bitmask);\r
007c44c5 1172 \r
1173 sprintf(str,":post_%s - [0:0]", idx->id);\r
1174 save_line(str);\r
1175\r
1176 sprintf(str,":forw_%s - [0:0]", idx->id);\r
1177 save_line(str);\r
1178\r
1179 if(idx->parent)\r
1180 {\r
1181 string(buf,strlen(idx->parent->id)+6);\r
1182 sprintf(buf,"post_%s",idx->parent->id);\r
1183 }\r
1184 else\r
bb9e11ee 1185 {\r
007c44c5 1186 buf="POSTROUTING";\r
bb9e11ee 1187 }\r
007c44c5 1188\r
1189 sprintf(str,"-A %s -d %s/%d -o %s -j post_%s", buf, subnet, idx->bitmask, lan, idx->id);\r
1190 save_line(str);\r
1191\r
1192 sprintf(str,"-A %s -d %s/%d -o %s -j post_common", buf, subnet, idx->bitmask, lan);\r
1193 save_line(str);\r
1194\r
1195 if(idx->parent)\r
1196 {\r
1197 string(buf,strlen(idx->parent->id)+6);\r
1198 sprintf(buf,"forw_%s",idx->parent->id);\r
1199 }\r
1200 else\r
bb9e11ee 1201 {\r
007c44c5 1202 buf="FORWARD";\r
bb9e11ee 1203 }\r
007c44c5 1204\r
1205 sprintf(str,"-A %s -s %s/%d -o %s -j forw_%s", buf, subnet, idx->bitmask, wan, idx->id);\r
1206 save_line(str);\r
1207\r
1208 sprintf(str,"-A %s -s %s/%d -o %s -j forw_common", buf, subnet, idx->bitmask, wan);\r
1209 save_line(str);\r
1210 }\r
1211 printf("Total indexed iptables chains created: %d\n", i);\r
1212\r
1213 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);\r
1214 save_line(str);\r
1215 \r
1216 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);\r
1217 save_line(str);\r
1218 }\r
1219 \r
1220 }\r
1221\r
1222 if(just_flush)\r
1223 {\r
1224 fclose(iptables_file);\r
add90548 1225 if(log_file)\r
1226 { \r
1227 fclose(log_file);\r
1228 }\r
007c44c5 1229 puts("Just flushed iptables and tc classes - now exiting ...");\r
1230 exit(0);\r
1231 }\r
1232\r
1233 if(!just_preview)\r
1234 {\r
1235 if(!dry_run && !nodelay && qos_free_delay)\r
1236 {\r
1237 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay);\r
1238 sleep(qos_free_delay);\r
1239 }\r
1240\r
6cc38f96 1241 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",\r
1242 tc,lan,htb_r2q);\r
007c44c5 1243 safe_run(str);\r
1244\r
208112af 1245 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
1246 tc,lan,lan_medium,lan_medium,burst_main,highest_priority);\r
007c44c5 1247 safe_run(str);\r
1248\r
208112af 1249 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
1250 tc,lan,line,line,burst_main,highest_priority);\r
007c44c5 1251 safe_run(str);\r
1252\r
1253 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc,wan,htb_r2q);\r
1254 safe_run(str);\r
1255\r
208112af 1256 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
1257 tc,wan,wan_medium,wan_medium,burst_main,highest_priority);\r
007c44c5 1258 safe_run(str);\r
1259\r
208112af 1260 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
1261 tc,wan,up,up,burst_main,highest_priority);\r
007c44c5 1262 safe_run(str);\r
1263 }\r
1264\r
1265 /*-----------------------------------------------------------------*/\r
208112af 1266 puts("Locating heavy downloaders and generating root classes ...");\r
007c44c5 1267 /*-----------------------------------------------------------------*/\r
bb9e11ee 1268 sort(ip,ips,desc_order_by,traffic); \r
007c44c5 1269\r
1270 /*-----------------------------------------------------------------*/\r
1271 /* sub-scope - local variables */ \r
1272 {\r
6cc38f96 1273 long long int rate = line;\r
1274 long long int max = line;\r
1275 int group_count = 0;\r
1276 FILE *credit_file = NULL;\r
007c44c5 1277 \r
4358455e 1278 if(!just_preview && !dry_run && enable_credit)\r
1279 {\r
6cc38f96 1280 credit_file = fopen(credit,"w");\r
4358455e 1281 }\r
007c44c5 1282 \r
208112af 1283 for_each(group,groups)\r
007c44c5 1284 {\r
1285 if(!just_preview)\r
1286 {\r
007c44c5 1287 //download\r
208112af 1288 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
1289 tc, lan, parent, group->id, rate, max, burst_group, highest_priority+1, group->desired);\r
007c44c5 1290 safe_run(str);\r
1291 \r
1292 //upload\r
208112af 1293 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
1294 tc, wan, parent, group->id, rate*up/line, max*up/line, burst_group, highest_priority+1, group->desired);\r
007c44c5 1295 safe_run(str);\r
1296 }\r
1297 \r
6cc38f96 1298 if(group_count++ < max_nesting)\r
bb9e11ee 1299 {\r
6cc38f96 1300 parent = group->id;\r
bb9e11ee 1301 }\r
007c44c5 1302 \r
6cc38f96 1303 rate -= digital_divide*group->min;\r
1304 if(rate < group->min)\r
4358455e 1305 {\r
6cc38f96 1306 rate = group->min;\r
4358455e 1307 }\r
007c44c5 1308 \r
1309 /*shaping of aggresive downloaders, with credit file support */\r
1310 if(use_credit)\r
1311 {\r
6cc38f96 1312 int group_rate = group->min, priority_sequence = lowest_priority;\r
007c44c5 1313 \r
6cc38f96 1314 for_each(ip, ips) if(ip->min == group->min && ip->max > ip->min)\r
007c44c5 1315 {\r
6cc38f96 1316 if( ip->keyword->data_limit && !ip->fixedprio \r
1317 && ( ip->traffic>ip->credit\r
1318 + (ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))) )\r
007c44c5 1319 {\r
4358455e 1320 if(group_rate<ip->max)\r
1321 {\r
1322 ip->max=group_rate;\r
1323 }\r
007c44c5 1324 group_rate+=magic_treshold;\r
208112af 1325 ip->prio=lowest_priority;\r
4358455e 1326 if(ip->prio<highest_priority+2)\r
1327 {\r
1328 ip->prio=highest_priority+2;\r
1329 }\r
007c44c5 1330 }\r
1331 else\r
1332 {\r
6cc38f96 1333 if( ip->keyword->data_prio \r
1334 && !ip->fixedprio \r
1335 && ( ip->traffic>ip->credit\r
1336 + (ip->min*ip->keyword->data_prio+(ip->keyword->fixed_prio<<20))) )\r
007c44c5 1337 {\r
1338 ip->prio=priority_sequence--;\r
4358455e 1339 if(ip->prio<highest_priority+1)\r
1340 {\r
1341 ip->prio=highest_priority+1;\r
1342 }\r
007c44c5 1343 }\r
1344 \r
1345 if(credit_file)\r
1346 {\r
1347 unsigned long long lcredit=0;\r
99127c70 1348 \r
4358455e 1349 if((ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))>ip->traffic)\r
1350 {\r
007c44c5 1351 lcredit=(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))-ip->traffic;\r
4358455e 1352 }\r
007c44c5 1353 fprintf(credit_file,"%s %Lu\n",ip->addr,lcredit);\r
1354 }\r
1355 }\r
6cc38f96 1356 } \r
007c44c5 1357 }\r
1358 }\r
4358455e 1359 if(credit_file)\r
1360 {\r
1361 fclose(credit_file);\r
1362 }\r
007c44c5 1363 }\r
1364\r
1365 if(just_preview)\r
1366 {\r
8e29188a 1367 if(start_shaping)\r
1368 {\r
1369 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap);\r
1370 parse(classmap)\r
1371 {\r
1372 ptr=strchr(_,' ');\r
1373 if(ptr)\r
1374 {\r
1375 *ptr=0;\r
1376 ptr++;\r
1377 if_exists(ip,ips,eq(ip->addr,_))\r
1378 {\r
1379 ip->mark=atoi(ptr);\r
1380 if(ip->max < ip->desired) /* apply FUP limit immediately.... */\r
1381 {\r
1382 printf("Applying limit for %-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
1383 printf("(down: %dk-%dk ", ip->min, ip->max); \r
1384 sprintf(str, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
1385 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
1386 safe_run(str);\r
1387 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1388 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
1389 sprintf(str,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1390 tc, wan, ip->group, ip->mark,\r
1391 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1392 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1393 safe_run(str);\r
1394 }\r
1395 }\r
1396 }\r
1397 }\r
1398 fail\r
1399 { \r
1400 perror(classmap);\r
1401 puts("Warning - classmap file not fund, just generating preview ...");\r
1402 start_shaping=FALSE;\r
1403 }\r
1404 done; /* ugly macro end */\r
1405 }\r
6fb3c58a 1406 html=preview;\r
1407 json=json_preview;\r
007c44c5 1408 }\r
6fb3c58a 1409\r
1410 if(!dry_run && !just_flush)\r
007c44c5 1411 {\r
1412 /*-----------------------------------------------------------------*/\r
6fb3c58a 1413 printf("Writing json overview %s ... ", json);\r
007c44c5 1414 /*-----------------------------------------------------------------*/\r
be96b71b 1415 f=fopen(json, "w");\r
1416 if(f > 0)\r
007c44c5 1417 {\r
be96b71b 1418 int jsoncount=0;\r
1419 fprintf(f, "{\n");\r
1420 for_each(ip, ips)\r
6cc38f96 1421 {\r
1f13bb8e 1422 if( ip->lmsid > 0 \r
1423 && (ip->traffic || ip->direct || ip->proxy || ip->upload))\r
260c2719 1424 {\r
a7e55d86 1425 if(jsoncount)\r
1426 {\r
1427 fprintf(f, ",\n");\r
1428 }\r
6fb3c58a 1429 fprintf(f, " \"%s\":{ \"lms\": %d, \"ip\":\"%s\", \"total\":%Lu, \"down\":%Lu, \"proxy\":%Lu, \"up\":%Lu, \"min\":%d, \"max\":%d, \"limit\":%d }",\r
1430 ip->name, ip->lmsid, ip->addr, ip->traffic, ip->direct, ip->proxy, ip->upload, ip->min, ip->desired, ip->max);\r
a7e55d86 1431 jsoncount++;\r
260c2719 1432 }\r
6cc38f96 1433 }\r
be96b71b 1434 fprintf(f, "}\n");\r
007c44c5 1435 fclose(f);\r
be96b71b 1436 puts("done.");\r
add90548 1437 }\r
1438 else\r
1439 {\r
be96b71b 1440 perror(json);\r
007c44c5 1441 }\r
007c44c5 1442 }\r
1443\r
6fb3c58a 1444 f=fopen(html,"w");\r
1445 if(f > 0)\r
007c44c5 1446 {\r
007c44c5 1447 int count=1;\r
1448 i=0;\r
1449\r
1450 /*-----------------------------------------------------------------*/\r
6fb3c58a 1451 printf("Sorting data and generating statistics page %s ...\n", html);\r
007c44c5 1452 /*-----------------------------------------------------------------*/\r
1453\r
6cc38f96 1454 if(use_jquery_popups)\r
1455 {\r
1456 fprintf(f,"<script type=\"text/javascript\" src=\"%s\"></script>\n", jquery_url);\r
1457 }\r
3ece6581 1458 fputs("<table class=\"decorated last\">\n\\r
1459<caption>Bandwidth classes</caption>\n\\r
1460<thead><tr>\n\\r
1461<th style=\"text-align: right\">#</th>\n\\r
103d292c 1462<th style=\"text-align: right\">group</th>\n\\r
1463<th style=\"text-align: right\">IPs</th>\n\\r
1464<th style=\"text-align: right\">requested</th>\n",f);\r
6cc38f96 1465 fprintf(f,"<th colspan=\"%d\">data limits</th>\n", keywordcount);\r
9aa195f6 1466 fputs("</tr></thead><tbody>\n",f);\r
208112af 1467\r
9aa195f6 1468 row_odd_even = 0;\r
6cc38f96 1469 for_each(group, groups) \r
007c44c5 1470 { \r
1471#ifdef DEBUG\r
3ece6581 1472 printf("%d kb/s group: %d bandwidth requested: %d kb/s\n",group->min,group->count,group->desired);\r
007c44c5 1473#endif\r
3ece6581 1474 fprintf(f, "%s<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d&nbsp;kb/s</td>",\r
9aa195f6 1475 tr_odd_even(), count, group->min);\r
3ece6581 1476 fprintf(f, "<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d&nbsp;kb/s</td>",\r
9aa195f6 1477 group->count, group->desired);\r
007c44c5 1478\r
c864e623 1479 for_each(keyword, keywords) if(keyword->ip_count)\r
208112af 1480 {\r
c864e623 1481 fprintf(f,"<td style=\"text-align: right\"><span style=\"color:#%s\">%d&nbsp;MB</span></td>",\r
6cc38f96 1482 keyword->html_color, group->min*keyword->data_limit);\r
208112af 1483 } \r
6cc38f96 1484 i += group->desired; \r
1485 total += group->count;\r
007c44c5 1486 count++; \r
1487 }\r
1488#ifdef DEBUG\r
3ece6581 1489 printf("Total groups: %d Total bandwidth requested: %d kb/s\nAGGREGATION: 1/%d\n",\r
6cc38f96 1490 count, i, i/line);\r
007c44c5 1491#endif\r
e64e760d 1492 fprintf(f,"</tr></tbody>\n\\r
1493<thead><tr>\n\\r
1494<th colspan=\"2\" style=\"text-align: left\">Line %Ld kb/s</td>",line);\r
3ece6581 1495 fprintf(f,"<th style=\"text-align: right\">%d</td><th style=\"text-align: right\">%d kb/s</td>",total,i);\r
007c44c5 1496\r
c864e623 1497 for_each(keyword, keywords) if(keyword->ip_count)\r
208112af 1498 {\r
103d292c 1499 fprintf(f,"<th style=\"text-align: right\">%d IPs</th>",keyword->ip_count);\r
208112af 1500 }\r
6cc38f96 1501 fprintf(f,"</tr><tr><th colspan=\"4\">Aggregation 1/%d</th>\n", (int)(0.5+i/line));\r
1502 fprintf(f,"<th colspan=\"%d\">%d traffic classes</th></tr>\n", keywordcount, total);\r
007c44c5 1503\r
e64e760d 1504 fputs("</thead></table>\n",f);\r
007c44c5 1505 }\r
6cc38f96 1506 else if(!dry_run && !just_flush)\r
1507 {\r
007c44c5 1508 perror(html);\r
6cc38f96 1509 }\r
007c44c5 1510\r
6cc38f96 1511 i=0;\r
6fb3c58a 1512 if(f > 0)\r
007c44c5 1513 {\r
b014f181 1514 unsigned long long total_traffic=0, total_direct=0, total_proxy=0, total_upload=0, tmp_sum=0;\r
007c44c5 1515 int active_classes=0;\r
3ece6581 1516 int colspan=12;\r
007c44c5 1517 struct Sum {unsigned long long l; int i; list(Sum);} *sum,*sums=NULL;\r
78884bad 1518 int limit_count=0, prio_count=0;\r
4a1b62ea 1519 int popup_button=0;\r
007c44c5 1520\r
1521 if(qos_proxy)\r
4358455e 1522 {\r
1523 colspan++;\r
1524 }\r
007c44c5 1525 \r
3ece6581 1526 fprintf(f,"<p><table class=\"decorated last\">\n<caption>%s",title);\r
9aa195f6 1527 fprintf(f," (%s)</caption>\n", d);\r
3ece6581 1528 fputs("<thead><tr>\n<th colspan=\"3\">&nbsp;</th>\n",f);\r
1529 fputs("<th style=\"text-align: right\">credit</th>\n\\r
1530<th style=\"text-align: right\">FUP</th>\n\\r
1531<th style=\"text-align: right\">total</th>\n\\r
1532<th style=\"text-align: right\">down</th>\n",f);\r
007c44c5 1533 if(qos_proxy)\r
4358455e 1534 {\r
103d292c 1535 fputs("<th style=\"text-align: right\">proxy</th>\n",f);\r
4358455e 1536 }\r
3ece6581 1537 fputs("<th style=\"text-align: right\">up</th>\n\\r
1538<th style=\"text-align: right\">min</th>\n\\r
1539<th style=\"text-align: right\">max</th>\n\\r
1540<th style=\"text-align: right\">limit</th>\n\\r
e64e760d 1541<th>&nbsp;</th>\n\\r
1542</tr><tr>\n\\r
3ece6581 1543<th style=\"text-align: right\">#</th>\n\\r
1544<th>hostname [+sharing]</th>\n\\r
1545<th style=\"text-align: right\">LMS</th>\n\\r
1546<th style=\"text-align: right\">MB</th>\n\\r
1547<th style=\"text-align: right\">MB</th>\n\\r
1548<th style=\"text-align: right\">MB</th>\n\\r
1549<th style=\"text-align: right\">MB</th>\n\\r
1550<th style=\"text-align: right\">MB</th>\n\\r
1551<th style=\"text-align: right\">kb/s</th>\n\\r
1552<th style=\"text-align: right\">kb/s</th>\n\\r
1553<th style=\"text-align: right\">kb/s</th>\n\\r
e64e760d 1554<th>prio</th>\n\\r
3ece6581 1555</tr></thead><tbody>\n",f); \r
007c44c5 1556\r
9aa195f6 1557 row_odd_even = 0;\r
6cc38f96 1558 for_each(ip,ips) if(!use_jquery_popups || !ip->sharing)\r
007c44c5 1559 {\r
1560 char *f1="", *f2="";\r
6cc38f96 1561 i++;\r
f1e0e082 1562\r
1563 if(ip->max < ip->desired) \r
1564 { \r
1565 f1="<span style=\"color:red\">"; \r
1566 f2="</span>"; \r
1567 limit_count++; \r
1568 } \r
1569 else if(ip->prio > highest_priority+1) \r
1570 { \r
1571 f1="<span style=\"color:brown\">"; \r
1572 f2="</span>"; \r
1573 prio_count++; \r
1574 } \r
007c44c5 1575\r
1576#ifdef DEBUG\r
1577 printf("%03d. %-22s %10Lu (%d/%d)\n",i ,ip->name, ip->traffic, ip->min, ip->max); \r
1578#endif\r
4a1b62ea 1579 /* hostnames -------------------------------------- */\r
4f4d1820 1580 fprintf(f,"%s<td style=\"text-align: right\"><a name=\"%s\"></a>%d</td><td><a class=\"blue\" target=\"_blank\" href=\"%s%s.log\">%s</a>\n", \r
9aa195f6 1581 tr_odd_even(), ip->name, i, log_url, ip->name, ip->name);\r
3ece6581 1582\r
6cc38f96 1583 if(use_jquery_popups)\r
4a1b62ea 1584 {\r
6cc38f96 1585 fprintf(f,"<span id=\"sharing_%d\" style=\"display:none\">",i);\r
1586 popup_button=0;\r
1587 for_each(sharedip, ips) if(eq(ip->name, sharedip->sharing))\r
1588 {\r
4f4d1820 1589 fprintf(f,"<br /><a class=\"blue\" target=\"_blank\" href=\"%s%s.log\">%s</a>\n", log_url, sharedip->name, sharedip->name);\r
6cc38f96 1590 popup_button++;\r
1591 }\r
1592 fputs("</span>\n",f);\r
1593 if(popup_button)\r
1594 {\r
103d292c 1595 fprintf(f,"<span>[<a class=\"blue\" href=\"#\" onClick=\"$(this).parent().hide();$(\'#sharing_%d\').show();$(\'#download_%d\').show();$(\'#upload_%d\').show();return(false);\" style=\"cursor: pointer;\">+%d</a>]</span>",\r
6cc38f96 1596 i, i, i, popup_button);\r
1597 }\r
4a1b62ea 1598 }\r
1599 fputs("</td>\n",f);\r
1600 /* ----------------------------------------------- */\r
1601\r
4358455e 1602 if(found_lmsid)\r
1603 {\r
103d292c 1604 fputs("<td style=\"text-align: right\">",f);\r
a1d21464 1605 if(ip->lmsid > 0)\r
4358455e 1606 {\r
4f4d1820 1607 fprintf(f,"<a class=\"blue\" target=\"_blank\" href=\"%s%d\">%04d</a>\n", lms_url, ip->lmsid, ip->lmsid);\r
4358455e 1608 }\r
a1d21464 1609 else if(ip->lmsid == 0)\r
1610 {\r
ad4cb129 1611 fputs("-------",f);\r
a1d21464 1612 }\r
4a1b62ea 1613 fputs("</td>\n",f);\r
4358455e 1614 }\r
3ece6581 1615 fprintf(f,"<td style=\"text-align: right\">%Lu</td>\n", ip->credit);\r
1616 fprintf(f,"<td style=\"text-align: right\"><span style=\"color:#%s\">%Lu</span></td>",\r
4a1b62ea 1617 ip->keyword->html_color,\r
1618 ip->credit+(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20)));\r
3ece6581 1619 fprintf(f,"<td style=\"text-align: right\">%s%Lu%s", f1, ip->traffic, f2);\r
4a1b62ea 1620\r
1621 /* download --------------------------------------- */\r
3ece6581 1622 fprintf(f,"</td><td style=\"text-align: right\">%Lu", ip->direct);\r
6cc38f96 1623 if(use_jquery_popups)\r
4a1b62ea 1624 {\r
6cc38f96 1625 fprintf(f,"<span id=\"download_%d\" style=\"display:none\">",i);\r
1626 for_each(sharedip, ips) if(eq(ip->name, sharedip->sharing))\r
1627 {\r
3ece6581 1628 fprintf(f,"<br />%Lu", sharedip->direct);\r
6cc38f96 1629 }\r
1630 fputs("</span>\n",f);\r
4a1b62ea 1631 }\r
6cc38f96 1632 fputs("</td>\n",f);\r
4a1b62ea 1633 /* ----------------------------------------------- */\r
1634\r
007c44c5 1635 if(qos_proxy)\r
4358455e 1636 {\r
3ece6581 1637 fprintf(f,"<td style=\"text-align: right\">%Lu</td>\n", ip->proxy);\r
4358455e 1638 }\r
4a1b62ea 1639 /* upload ---------------------------------------- */\r
3ece6581 1640 fprintf(f,"<td style=\"text-align: right\">%Lu", ip->upload);\r
6cc38f96 1641 if(use_jquery_popups)\r
4a1b62ea 1642 {\r
6cc38f96 1643 fprintf(f,"<span id=\"upload_%d\" style=\"display:none\">",i);\r
1644 for_each(sharedip,ips) if(eq(ip->name, sharedip->sharing))\r
1645 {\r
3ece6581 1646 fprintf(f,"<br />%Lu", sharedip->upload);\r
6cc38f96 1647 }\r
1648 fputs("</span>\n",f);\r
4a1b62ea 1649 }\r
6cc38f96 1650 fputs("</td>\n",f);\r
4a1b62ea 1651 /* ----------------------------------------------- */\r
1652\r
3ece6581 1653 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1654<td style=\"text-align: right\">%d</td>\n\\r
1655<td style=\"text-align: right\">%s%d%s</td>\n\\r
1656<td>%s%d%s</td></tr>\n",\r
1657 ip->min, ip->desired, \r
1658 f1, ip->max, f2, \r
1659 f1, ip->prio, f2);\r
6cc38f96 1660\r
b014f181 1661 total_traffic+=ip->traffic;\r
007c44c5 1662 total_direct+=ip->direct;\r
1663 total_proxy+=ip->proxy;\r
1664 total_upload+=ip->upload;\r
1665 if(ip->traffic>0)\r
1666 {\r
1667 active_classes++;\r
1668 tmp_sum+=ip->traffic;\r
1669 create(sum,Sum);\r
1670 sum->l=tmp_sum;\r
1671 sum->i=active_classes;\r
1672 insert(sum,sums,order_by,i);\r
1673 }\r
6cc38f96 1674\r
007c44c5 1675 if(!just_preview)\r
1676 {\r
add90548 1677 append_log(ip);\r
52e8df5d 1678 for_each(sharedip,ips) if(eq(ip->name, sharedip->sharing))\r
1679 {\r
1680 append_log(sharedip);\r
1681 }\r
007c44c5 1682 }\r
007c44c5 1683 }\r
e64e760d 1684 fprintf(f,"</tbody><thead><tr>\n\\r
1685<th colspan=\"%d\" style=\"text-align: left\">%d CLASSES</th>", colspan-7, i);\r
3ece6581 1686 fprintf(f,"<th style=\"text-align: right\">%Lu</th><th style=\"text-align: right\">%Lu</th>\n", total_traffic, total_direct);\r
007c44c5 1687 if(qos_proxy)\r
4358455e 1688 {\r
3ece6581 1689 fprintf(f,"<th style=\"text-align: right\">%Lu</th>\n", total_proxy);\r
4358455e 1690 }\r
3ece6581 1691 fprintf(f,"<th style=\"text-align: right\">%Lu</th>", total_upload);\r
e64e760d 1692 fprintf(f,"<th colspan=\"4\"><span style=\"color:red\">LIMIT %dx</span> <span style=\"color:brown\">LOW-PRIO %dx</span></th></tr>\n</thead></table>\n",limit_count,prio_count);\r
007c44c5 1693\r
9aa195f6 1694 row_odd_even = 0;\r
007c44c5 1695 if(active_classes>10)\r
c9012978 1696 {\r
60a8251d 1697 int top20_count=0,top20_perc1=0;\r
1698 long long top20_perc2=0;\r
1699 unsigned long long top20_sum=0l;\r
1700 \r
3ece6581 1701 fputs("<a name=\"erp\"></a><p><table class=\"decorated last\"><caption>Enterprise Resource Planning (ERP)</caption>\n",f);\r
1702 fputs("<thead><tr>\n\\r
1703<th>Analytic category</th>\n\\r
1704<th colspan=\"2\" style=\"text-align: center\">Active Classes</th>\n\\r
1705<th colspan=\"2\" style=\"text-align: center\">Data transfers</th>\n\\r
1706</tr></thead><tbody>\n",f);\r
c9012978 1707\r
b014f181 1708 if_exists(sum,sums,sum->l>=total_traffic/4)\r
c9012978 1709 {\r
9aa195f6 1710 fprintf(f,"%s<td>Top 25%% of traffic</td>\n", tr_odd_even());\r
9690db8e 1711 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1712<td style=\"text-align: right\">%d %%</td>\n\\r
1713<td style=\"text-align: right\">%Lu MB</td>\n\\r
1714<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
1715 sum->i, (100*sum->i+50)/active_classes, sum->l, (100*sum->l+50)/total_traffic);\r
c9012978 1716 }\r
1717 \r
208112af 1718 if_exists(sum,sums,sum->i==10)\r
c9012978 1719 {\r
9aa195f6 1720 fprintf(f,"%s<td>Top 10 downloaders</td>\n", tr_odd_even());\r
3ece6581 1721 fprintf(f,"<td style=\"text-align: right\"><strong>10</strong></td>\n\\r
1722<td style=\"text-align: right\">%d %%</td>\n\\r
1723<td style=\"text-align: right\">%Lu MB</td>\n\\r
1724<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
9690db8e 1725 (100*sum->i+50)/active_classes, sum->l, (100*sum->l+50)/total_traffic);\r
c9012978 1726 }\r
1727\r
b014f181 1728 if_exists(sum,sums,sum->l>=total_traffic/2)\r
c9012978 1729 {\r
9aa195f6 1730 fprintf(f,"%s<td>Top 50%% of traffic</td>\n", tr_odd_even());\r
3ece6581 1731 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1732<td style=\"text-align: right\">%d %%</td>\n\\r
1733<td style=\"text-align: right\">%Lu MB</td>\n\\r
1734<td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",\r
1735 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
c9012978 1736 }\r
1737\r
b014f181 1738 if_exists(sum,sums,sum->l>=4*total_traffic/5)\r
c9012978 1739 {\r
9aa195f6 1740 fprintf(f,"%s<td>Top 80%% of traffic</td>\n", tr_odd_even());\r
3ece6581 1741 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1742<td style=\"text-align: right\">%d %%</td>\n\\r
1743<td style=\"text-align: right\">%Lu MB</td>\n\\r
1744<td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",\r
1745 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
c9012978 1746 }\r
1747\r
60a8251d 1748 if_exists(sum,sums,sum->i>=(active_classes+1)/5)\r
c9012978 1749 {\r
9aa195f6 1750 fprintf(f,"%s<td>Top 20%% downloaders</td>\n", tr_odd_even());\r
60a8251d 1751 top20_count=sum->i;\r
1752 top20_perc1=(100*sum->i+50)/active_classes;\r
1753 top20_sum=sum->l;\r
b014f181 1754 top20_perc2=(100*sum->l+50)/total_traffic;\r
3ece6581 1755 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1756<td style=\"text-align: right\"><strong>%d %%</strong></td>\n\\r
1757<td style=\"text-align: right\">%Lu MB</td>\n\\r
1758<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
1759 top20_count,top20_perc1,top20_sum,top20_perc2);\r
c9012978 1760 }\r
1761\r
208112af 1762 if_exists(sum,sums,sum->i>=(active_classes+1)/4)\r
c9012978 1763 {\r
9aa195f6 1764 fprintf(f,"%s<td>Top 25%% downloaders</td>\n", tr_odd_even());\r
3ece6581 1765 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1766<td style=\"text-align: right\">%d %%</td>\n\\r
1767<td style=\"text-align: right\">%Lu MB</td>\n\\r
1768<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
1769 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
c9012978 1770 }\r
1771\r
208112af 1772 if_exists(sum,sums,sum->i>=(active_classes+1)/2)\r
c9012978 1773 {\r
9aa195f6 1774 fprintf(f,"%s<td>Top 50%% downloaders</td>\n", tr_odd_even());\r
3ece6581 1775 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1776<td style=\"text-align: right\"><strong>%d %%</strong></td>\n\\r
1777<td style=\"text-align: right\">%Lu MB</td>\n\\r
1778<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
1779 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
c9012978 1780 }\r
1781\r
208112af 1782 if_exists(sum,sums,sum->i>=4*(active_classes+1)/5)\r
c9012978 1783 {\r
9aa195f6 1784 fprintf(f,"%s<td>Top 80%% downloaders</td>\n", tr_odd_even());\r
3ece6581 1785 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1786<td style=\"text-align: right\">%d %%</td>\n\\r
1787<td style=\"text-align: right\">%Lu MB</td>\n\\r
1788<td style=\"text-align: right\">%Ld %%</td></tr></tbody>\n",\r
1789 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
c9012978 1790 }\r
1791\r
4f4d1820 1792 fprintf(f,"<thead><tr><th><a class=\"blue\" target=\"_blank\" href=\"%sERP.log\">All users, all traffic</a></th>\n", log_url);\r
103d292c 1793 fprintf(f,"<th style=\"text-align: right\">%d</th>\n\\r
1794<th style=\"text-align: right\">100 %%</th>\n\\r
9690db8e 1795<th style=\"text-align: right\">%Lu MB</th>\n\\r
103d292c 1796<th style=\"text-align: right\">100 %%</th></tr>\n",active_classes,total_traffic);\r
3ece6581 1797 fputs("</thead></table>\n", f);\r
60a8251d 1798\r
5da44508 1799 /* write basic ERP data to log directory */\r
60a8251d 1800 if(!just_preview)\r
1801 {\r
add90548 1802 FILE *iplog;\r
60a8251d 1803 sprintf(str,"%s/ERP.log",log_dir);\r
1804 iplog=fopen(str,"a");\r
1805 if(iplog)\r
1806 {\r
78884bad 1807 fprintf(iplog,"%ld\t%d\t%d %%\t%Lu M\t%Ld %%\tACTIVE %d\tTRAFFIC %Lu M\tCLASSES %d\tFUP-LIMIT %d\tLOW-PRIO %d\t%s",\r
4a1b62ea 1808 time(NULL), top20_count, top20_perc1, top20_sum, top20_perc2, \r
6cc38f96 1809 active_classes, total_traffic, i, limit_count, prio_count, d); /* d = date*/\r
60a8251d 1810 fclose(iplog);\r
1811 }\r
add90548 1812 else\r
1813 {\r
1814 perror(str);\r
1815 }\r
60a8251d 1816 }\r
c9012978 1817 }\r
60a8251d 1818\r
2d114137 1819 fprintf(f, stats_html_signature, version);\r
007c44c5 1820 fclose(f);\r
1821 }\r
1822\r
1823 if(just_preview)\r
1824 {\r
8e29188a 1825 char swchar='p';\r
1826 if(start_shaping)\r
1827 {\r
1828 swchar='s';\r
1829 }\r
1830 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar);\r
007c44c5 1831 exit(0);\r
be96b71b 1832 } \r
007c44c5 1833\r
1834 i=0;\r
260c2719 1835#ifdef DEBUG\r
007c44c5 1836 printf("%-22s %-15s mark\n","name","ip");\r
260c2719 1837#endif\r
208112af 1838\r
be96b71b 1839 printf("Writing %s ... ", classmap); \r
1840 f = fopen(classmap, "w"); \r
1841 if(f < 0)\r
1842 {\r
1843 perror(classmap);\r
1844 }\r
1845\r
1846 /*-----------------------------------------------------------------*/\r
1847 puts("Generating iptables and tc classes ... ");\r
1848 /*-----------------------------------------------------------------*/\r
1849\r
1850 for_each(ip, ips) if(ip->mark > 0)\r
1851 {\r
007c44c5 1852 if(idxs)\r
1853 {\r
1854 char *buf;\r
1855 duplicate(ip->addr,buf);\r
1856 buf=hash_id(ip->addr,32-idxtable_bitmask1); \r
1857 \r
1858 string(chain_forward,6+strlen(buf));\r
1859 strcpy(chain_forward,"forw_");\r
1860 strcat(chain_forward,buf);\r
1861\r
1862 string(chain_postrouting,6+strlen(buf));\r
1863 strcpy(chain_postrouting,"post_");\r
1864 strcat(chain_postrouting,buf);\r
1865 \r
1866 free(buf);\r
1867 }\r
1868 else\r
1869 {\r
1870 chain_forward="FORWARD";\r
1871 chain_postrouting="POSTROUTING";\r
1872 }\r
1873\r
260c2719 1874#ifdef DEBUG\r
007c44c5 1875 printf("%-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
260c2719 1876#endif\r
007c44c5 1877\r
1878 /* -------------------------------------------------------- mark download */\r
1879 \r
be96b71b 1880 sprintf(str, "-A %s -d %s/32 -o %s -j %s%d",\r
1881 chain_postrouting, ip->addr, lan, mark_iptables, ip->mark);\r
007c44c5 1882 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/\r
1883 /* -m limit --limit 1/s */ \r
1884 save_line(str);\r
1885\r
1886 if(qos_proxy)\r
1887 {\r
be96b71b 1888 sprintf(str, "-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",\r
1889 chain_postrouting, proxy_ip, proxy_port, ip->addr, lan, mark_iptables, ip->mark);\r
007c44c5 1890 /*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
1891 save_line(str);\r
1892 }\r
1893\r
be96b71b 1894 sprintf(str, "-A %s -d %s/32 -o %s -j ACCEPT",\r
1895 chain_postrouting, ip->addr, lan);\r
007c44c5 1896 save_line(str);\r
1897\r
1898 /* -------------------------------------------------------- mark upload */\r
be96b71b 1899 sprintf(str, "-A %s -s %s/32 -o %s -j %s%d", \r
1900 chain_forward, ip->addr, wan, mark_iptables, ip->mark);\r
007c44c5 1901 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/\r
1902 save_line(str);\r
1903\r
be96b71b 1904 sprintf(str, "-A %s -s %s/32 -o %s -j ACCEPT",\r
1905 chain_forward, ip->addr, wan);\r
007c44c5 1906 save_line(str);\r
1907\r
1908 if(ip->min)\r
1909 {\r
1910 /* -------------------------------------------------------- download class */\r
260c2719 1911#ifdef DEBUG\r
007c44c5 1912 printf("(down: %dk-%dk ", ip->min, ip->max); \r
260c2719 1913#endif\r
007c44c5 1914\r
be96b71b 1915 sprintf(str, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
1916 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
007c44c5 1917 safe_run(str);\r
1918\r
260c2719 1919 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
dee5592e 1920 {\r
be96b71b 1921 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s", \r
1922 tc, lan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
dee5592e 1923 safe_run(str);\r
be96b71b 1924 }\r
1925\r
260c2719 1926 if(filter_type == 1)\r
dee5592e 1927 {\r
be96b71b 1928 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
1929 tc, lan, ip->mark, ip->mark);\r
dee5592e 1930 safe_run(str);\r
007c44c5 1931 }\r
1932\r
1933 /* -------------------------------------------------------- upload class */\r
260c2719 1934#ifdef DEBUG\r
007c44c5 1935 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1936 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
260c2719 1937#endif\r
007c44c5 1938\r
1939 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1940 tc, wan, ip->group, ip->mark,\r
1941 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1942 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1943 safe_run(str);\r
1944 \r
260c2719 1945 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
dee5592e 1946 {\r
be96b71b 1947 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s",\r
1948 tc, wan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
dee5592e 1949 safe_run(str);\r
1950 } \r
be96b71b 1951\r
260c2719 1952 if(filter_type == 1)\r
dee5592e 1953 {\r
be96b71b 1954 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
1955 tc, wan, ip->mark, ip->mark);\r
dee5592e 1956 safe_run(str);\r
007c44c5 1957 }\r
be96b71b 1958 \r
6fb3c58a 1959 if(f > 0)\r
be96b71b 1960 {\r
457d52f2 1961 fprintf(f, "%s %d\n", ip->addr, ip->mark);\r
be96b71b 1962 }\r
007c44c5 1963 }\r
1964 else\r
260c2719 1965 {\r
1966#ifdef DEBUG\r
007c44c5 1967 printf("(sharing %s)\n", ip->sharing);\r
260c2719 1968#endif\r
1969 }\r
007c44c5 1970 i++;\r
1971 }\r
6fb3c58a 1972 if(f > 0)\r
be96b71b 1973 {\r
1974 puts("done.");\r
1975 fclose(f);\r
1976 }\r
1977 \r
007c44c5 1978 if(idxs)\r
1979 {\r
dee5592e 1980 chain_forward = "forw_common";\r
1981 chain_postrouting = "post_common";\r
007c44c5 1982 }\r
1983 else\r
1984 {\r
dee5592e 1985 chain_forward = "FORWARD";\r
1986 chain_postrouting = "POSTROUTING";\r
007c44c5 1987 }\r
dee5592e 1988 /* -------------------------------- classify or reject free download */\r
007c44c5 1989 {\r
b6a8d473 1990 char *final_chain = "DROP"; /* REJECT would be better, but it is impossible in mangle */\r
be96b71b 1991 if(free_min)\r
1992 {\r
1993 final_chain = "ACCEPT";\r
1994 }\r
dee5592e 1995 if(qos_proxy)\r
1996 {\r
1997 if(free_min)\r
1998 {\r
be96b71b 1999 sprintf(str,"-A %s -s %s -p tcp --sport %d -o %s -j %s%d",\r
2000 chain_postrouting,proxy_ip,proxy_port,lan,mark_iptables,3);\r
dee5592e 2001 save_line(str);\r
2002 }\r
be96b71b 2003 sprintf(str,"-A %s -s %s -p tcp --sport %d -o %s -j %s",\r
2004 chain_postrouting,proxy_ip,proxy_port,lan,final_chain);\r
dee5592e 2005 save_line(str);\r
2006 }\r
2007 if(free_min)\r
2008 {\r
be96b71b 2009 sprintf(str,"-A %s -o %s -j %s%d", chain_postrouting, lan, mark_iptables, 3);\r
dee5592e 2010 save_line(str);\r
2011 }\r
be96b71b 2012 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
dee5592e 2013 save_line(str);\r
2014 /* ------------------------------- classify or reject free upload */\r
2015 if(free_min)\r
2016 {\r
be96b71b 2017 sprintf(str,"-A %s -o %s -j %s%d", chain_forward, wan, mark_iptables, 3);\r
dee5592e 2018 save_line(str);\r
2019 }\r
be96b71b 2020 sprintf(str,"-A %s -o %s -j %s", chain_forward, wan, final_chain);\r
dee5592e 2021 save_line(str);\r
007c44c5 2022 }\r
abe9b855 2023\r
dee5592e 2024 if(free_min) /* allocate free bandwith if it is not zero... */ \r
2025 {\r
2026 /*-----------------------------------------------------------------*/\r
2027 puts("Generating free bandwith classes ...");\r
2028 /*-----------------------------------------------------------------*/\r
208112af 2029 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
be96b71b 2030 tc, lan, parent, free_min, free_max,burst, lowest_priority);\r
dee5592e 2031 safe_run(str);\r
208112af 2032 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
be96b71b 2033 tc, wan, parent, free_min, free_max, burst, lowest_priority);\r
dee5592e 2034 safe_run(str);\r
2035 /* tc SFQ */\r
260c2719 2036 if(strcmpi(qos_leaf, "none"))\r
dee5592e 2037 {\r
be96b71b 2038 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, lan, qos_leaf);\r
dee5592e 2039 safe_run(str);\r
2040 \r
be96b71b 2041 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, wan, qos_leaf);\r
dee5592e 2042 safe_run(str);\r
2043 } \r
2044 /* tc handle 1 fw flowid */\r
be96b71b 2045 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, lan);\r
dee5592e 2046 safe_run(str);\r
007c44c5 2047\r
be96b71b 2048 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, wan);\r
dee5592e 2049 safe_run(str);\r
007c44c5 2050 }\r
dee5592e 2051 printf("Total IP count: %d\n", i);\r
2052 run_restore(); \r
260c2719 2053 if(log_file)\r
2054 {\r
2055 fclose(log_file);\r
2056 }\r
007c44c5 2057 return 0;\r
007c44c5 2058 /* that's all folks, thank you for reading it all the way up to this point ;-) */\r
2059 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */\r
2060}\r
This page took 2.357861 seconds and 4 git commands to generate.