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