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