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