it is 2013 now
[svn/Prometheus-QoS/.git] / prometheus.c
CommitLineData
312ac2c1 1 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2 /* Prometheus QoS - you can "steal fire" from your ISP */\r
3/* "fair-per-IP" quality of service (QoS) utility */\r
4/* requires Linux 2.4.x or 2.6.x with HTB support */\r
4d41c1e4 5/* Copyright(C) 2005-2013 Michael Polak, Arachne Labs */\r
312ac2c1 6/* iptables-restore support Copyright(C) 2007-2008 ludva */\r
7/* Credit: CZFree.Net,Martin Devera,Netdave,Aquarius,Gandalf */\r
8/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
9\r
4d41c1e4 10/* Modified by: xChaos, 20130107\r
a031788f 11 ludva, 20080415\r
208112af 12 \r
007c44c5 13 Prometheus QoS is free software; you can redistribute it and/or\r
14 modify it under the terms of the GNU General Public License as \r
15 published by the Free Software Foundation; either version 2.1 of \r
16 the License, or (at your option) any later version.\r
17\r
18 Prometheus QoS is distributed in the hope that it will be useful,\r
19 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
21 General Public License for more details.\r
22\r
c9012978 23 You should have received a copy of the GNU General Public License\r
24 along with Prometheus Qos; if not, write to the Free Software\r
d1ae4fa7 25 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA \r
26 \r
c9012978 27 GNU General Public License is located in file COPYING */\r
007c44c5 28\r
5692c775 29#define STRLEN 512\r
007c44c5 30#undef DEBUG\r
31\r
208112af 32#include "cll1-0.6.2.h"\r
1c9cae56 33#include "ipstruct.h"\r
007c44c5 34\r
1c9cae56 35const char *version = "0.8.3-g";\r
007c44c5 36\r
208112af 37/* Version numbers: 0.8.3 is development releases ("beta"), 0.8.4 will be "stable" */\r
b1b59b3a 38/* Debian(RPM) package versions/patchlevels: 0.7.9-2, 0.8.0-1, 0.8.0-2, etc. */\r
39/* C source code development versions ("beta"): 0.7.9-a, 0.8.1-b, etc. */\r
40/* C source code release versions: 0.8.0, 0.8.2, 0.8.4, etc. */\r
77e71d6b 41\r
3bf40f9b 42const char *stats_html_signature = "<span class=\"small\">Statistics generated by Prometheus QoS version %s<br />GPL+Copyright(C)2005-2013 Michael Polak, <a target=\"_blank\" href=\"http://www.arachne.cz/\">Arachne Labs</a></span>\n";\r
2d114137 43\r
b6fb849a 44/* ======= Help screen is hopefuly self-documenting part of code :-) ======= */\r
45\r
46void help(void)\r
47{\r
48 puts("Command line switches:\n\\r
49\n\\r
50-d Dry run (preview tc and iptables commands on stdout)\n\\r
51-r Run (reset all statistics and start shaping - daily usage)\n\\r
52-p just generate Preview of data transfer statistics and exit (after -r)\n\\r
53-s start Shaping FUP limits (keeps data transfer stat like -p) (after -r)\n\\r
54-n run Now (like -r delay - overrides qos-free-delay keyword, after boot)\n\\r
55-f just Flush iptables and tc classes and exit (stop shaping, no QiS)\n\\r
56-9 emergency iptables flush (like -f, but dumps data transfer statistics)\n\\r
57\n\\r
58-c filename force alternative /etc/prometheus/prometheus.conf filename\n\\r
59-h filename force alternative /etc/hosts filename (overrides hosts keyword)\n\\r
60-l Mmm YYYY generate HTML summary of Logged traffic (Mmm=Jan-Dec) (and exit)\n\\r
61-m generate HTML summary of traffic for yesterday's Month (and exit)\n\\r
62-y generate HTML summary of traffic for yesterday's Year (and exit)\n\\r
63-? --help show this help scree (and exit)\n\\r
64-v --version show Version number of this utility (and exit)\n");\r
65}\r
66\r
82c702a1 67/* ======= All path names are defined here (for RPM patch) ======= */\r
ae776b10 68\r
be96b71b 69const char *tc = "/sbin/tc"; /* requires tc with HTB support */\r
70const char *iptables = "/sbin/iptables"; /* requires iptables utility */\r
71const char *iptablessave = "/sbin/iptables-save"; /* not yet required */\r
72const char *iptablesrestore = "/sbin/iptables-restore"; /* requires iptables-restore */\r
208112af 73const char *ls = "/bin/ls"; /* this is not user configurable :-) */\r
ae776b10 74\r
2d114137 75char *config = "/etc/prometheus/prometheus.conf"; /* main configuration file */\r
76char *hosts = "/etc/prometheus/hosts"; /* per-IP bandwidth definition file */\r
ae776b10 77\r
2d114137 78char *iptablesfile = "/var/spool/prometheus.iptables"; /* temporary file for iptables-restore*/\r
79char *credit = "/var/lib/misc/prometheus.credit"; /* credit log file */\r
be96b71b 80char *classmap = "/var/lib/misc/prometheus.classes"; /* credit log file */\r
81char *html = "/var/www/traffic.html"; /* hall of fame - html version */\r
6fb3c58a 82char *preview = "/var/www/preview.html"; /* hall of fame preview - html version */\r
1ab008b9 83char *json_traffic = "/var/www/logs/traffic.json"; /* hall of fame - json version */\r
6fb3c58a 84char *json_preview = "/var/www/logs/preview.json"; /* hall of fame preview - json version */\r
2d114137 85char *cmdlog = "/var/log/prometheuslog"; /* command log filename */\r
86char *log_dir = "/var/www/logs/"; /* log directory pathname, ended with slash */\r
8bcc3268 87char *log_url = "/logs/"; /* log directory relative URI prefix (partial URL) */\r
2d114137 88char *html_log_dir = "/var/www/logs/html/";\r
ae776b10 89\r
6cc38f96 90char *jquery_url = "http://code.jquery.com/jquery-latest.js";\r
91char *lms_url = "/lms/?m=customerinfo&amp;id=";\r
9a56ab25 92int use_jquery_popups = TRUE;\r
9aa195f6 93int row_odd_even = 0; /*<tr class="odd/even"> */\r
b6fb849a 94 \r
007c44c5 95/* === Configuraration file values defaults - stored in global variables ==== */\r
96\r
43cde5c3 97int filter_type = 1; /*1 mark, 2 classify*/\r
98char *mark = "MARK";\r
99char *mark_iptables = "MARK --set-mark ";\r
9a56ab25 100int dry_run = FALSE; /* preview - use puts() instead of system() */\r
43cde5c3 101char *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
102FILE *iptables_file = NULL;\r
9a56ab25 103int enable_credit = TRUE; /* enable credit file */\r
104int use_credit = FALSE; /* use credit file (if enabled)*/\r
43cde5c3 105char *title = "Hall of Fame - Greatest Suckers"; /* hall of fame title */\r
9a56ab25 106int hall_of_fame = TRUE; /* enable hall of fame */\r
43cde5c3 107char *lan = "eth0"; /* LAN interface */\r
108char *lan_medium = "100Mbit"; /* 10Mbit/100Mbit ethernet */\r
109char *wan = "eth1"; /* WAN/ISP interface */\r
110char *wan_medium = "100Mbit"; /* 10Mbit/100Mbit ethernet */\r
111char *qos_leaf = "sfq perturb 5"; /* leaf discipline */\r
112char *qos_free_zone = NULL; /* QoS free zone */\r
9a56ab25 113int qos_proxy = TRUE; /* include proxy port to QoS */\r
114int found_lmsid = FALSE; /* show links to users in LMS information system */\r
115int include_upload = TRUE; /* upload+download=total traffic */\r
43cde5c3 116char *proxy_ip = "192.168.1.1/32"; /* our IP with proxy port */\r
117int proxy_port = 3128; /* proxy port number */\r
118long long int line = 1024; /* WAN/ISP download in kbps */\r
119long long int up = 1024; /* WAN/ISP upload in kbps */\r
120int free_min = 32; /* minimum guaranted bandwidth for all undefined hosts */\r
121int free_max = 64; /* maximum allowed bandwidth for all undefined hosts */\r
122int qos_free_delay = 0; /* seconds to sleep before applying new QoS rules */\r
123int digital_divide = 2; /* controls digital divide weirdness ratio, 1...3 */ \r
124int max_nesting = 3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */\r
208112af 125int htb_r2q = 256; /* should work for leaf values 512 kbps to 8 Mbps */\r
43cde5c3 126int burst = 8; /* HTB burst (in kbits) */\r
127int burst_main = 64;\r
128int burst_group = 32;\r
43cde5c3 129int magic_treshold = 8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */\r
130int keywordcount = 0;\r
9a56ab25 131int class_count = 0;\r
132int ip_count = 0;\r
007c44c5 133/* not yet implemented:\r
43cde5c3 134int fixed_packets = 0; maximum number of pps per IP address (not class!) \r
135int packet_limit = 5; maximum number of pps to htn CEIL, not rate !!! \r
007c44c5 136*/\r
43cde5c3 137FILE *log_file = NULL;\r
138char *kwd = "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */\r
007c44c5 139\r
208112af 140const int highest_priority = 0; /* highest HTB priority (HTB built-in value is 0) */\r
141const int lowest_priority = 7; /* lowest HTB priority (HTB built-in value is 7) */\r
142const int idxtable_treshold1 = 24; /* this is no longer configurable */\r
143const int idxtable_treshold2 = 12; /* this is no longer configurable */\r
144const int idxtable_bitmask1 = 3; /* this is no longer configurable */\r
145const int idxtable_bitmask2 = 3; /* this is no longer configurable */\r
007c44c5 146\r
1c9cae56 147struct IP *ips = NULL, *ip, *sharedip;\r
148struct Group *groups = NULL, *group;\r
149struct Keyword *keyword, *defaultkeyword=NULL, *keywords=NULL;\r
007c44c5 150\r
b6fb849a 151void parse_ip_log(int argc, char **argv);\r
1ab008b9 152/* implemented in parselog.c */\r
b6fb849a 153\r
154void parse_hosts(char *hosts);\r
1ab008b9 155/* implemented in parsehosts.c */\r
156\r
157void write_json_traffic(char *json);\r
158/* implemented in json.c */\r
b6fb849a 159\r
9a56ab25 160void write_htmlandlogs(char *html, char *d, int total, int just_preview);\r
161/* implemented in htmlandlogs.c */\r
162\r
b6fb849a 163const char *tr_odd_even(void)\r
164{\r
165 row_odd_even = 1 - row_odd_even;\r
166 if(row_odd_even)\r
167 {\r
168 return "<tr class=\"even\">\n";\r
169 }\r
170 else\r
171 {\r
172 return "<tr class=\"odd\">\n";\r
173 }\r
174}\r
175\r
1c9cae56 176/* ==== This is C<<1 stuff - learn C<<1 first! https://dev.arachne.cz/svn/cll1h ==== */\r
007c44c5 177\r
178struct Index\r
179{\r
180 char *addr;\r
181 char *id;\r
182 struct Index *parent;\r
183 int bitmask;\r
184 int children;\r
185 list(Index);\r
186} *idxs=NULL, *idx, *metaindex;\r
187\r
a1204fc9 188void TheIP(void);\r
189/* function implemented in parsehosts.c */\r
007c44c5 190\r
5b902402 191/* ====== iptables indexes are used to reduce complexity to log8(N) ===== */\r
007c44c5 192\r
59c3032e 193char *index_id(char *ip, int bitmask);\r
194/* function implemented in ipv4subnets.c */\r
007c44c5 195\r
59c3032e 196char *subnet_id(char *ip, int bitmask);\r
197/* function implemented in ipv4subnets.c */\r
007c44c5 198\r
59c3032e 199/* ================= Let's parse configuration file here ================ */\r
007c44c5 200\r
201void reject_config_and_exit(char *filename)\r
202{\r
203 printf("Configuration file %s rejected - abnormal exit.",filename);\r
204 exit(-1);\r
205}\r
206\r
207void get_config(char *config_filename)\r
208{\r
209 char *cnf="mark";\r
210 \r
211 printf("Configured keywords: ");\r
212 parse(config_filename)\r
213 {\r
214 option("keyword",kwd);\r
215 if(kwd)\r
216 {\r
217 printf("%s ",kwd);\r
218\r
219 create(keyword,Keyword);\r
220 keyword->key=kwd;\r
221 keyword->asymetry_ratio=1; /* ratio for ADSL-like upload */\r
222 keyword->asymetry_fixed=0; /* fixed treshold for ADSL-like upload */\r
223 keyword->data_limit=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */\r
208112af 224 keyword->data_prio=4; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */\r
007c44c5 225 keyword->fixed_limit=0; /* fixed data limit for setting lower HTB ceil */\r
226 keyword->fixed_prio=0; /* fixed data limit for setting lower HTB prio */\r
227 keyword->reserve_min=8; /* bonus for nominal HTB rate bandwidth (in kbps) */\r
228 keyword->reserve_max=0; /* malus for nominal HTB ceil (in kbps) */\r
208112af 229 keyword->default_prio=highest_priority+1;\r
007c44c5 230 keyword->html_color="000000";\r
231 keyword->ip_count=0;\r
232 keyword->leaf_discipline="";\r
233\r
234 push(keyword,keywords);\r
4d41c1e4 235 if(!defaultkeyword)\r
236 {\r
237 defaultkeyword=keyword;\r
238 }\r
007c44c5 239 keywordcount++;\r
240 \r
241 kwd=NULL;\r
242 }\r
208112af 243 else\r
007c44c5 244 {\r
208112af 245 for_each(keyword,keywords)\r
246 {\r
247 int l=strlen(keyword->key);\r
007c44c5 248\r
208112af 249 if(!strncmp(keyword->key,_,l) && strlen(_)>l+2)\r
250 {\r
251 char *tmptr=_; /* <---- l+1 ----> */\r
252 _+=l+1; /* via-prometheus-asymetry-ratio, etc. */\r
253 ioption("asymetry-ratio",keyword->asymetry_ratio);\r
254 ioption("asymetry-treshold",keyword->asymetry_fixed);\r
255 ioption("magic-relative-limit",keyword->data_limit);\r
256 ioption("magic-relative-prio",keyword->data_prio);\r
257 loption("magic-fixed-limit",keyword->fixed_limit);\r
258 loption("magic-fixed-prio",keyword->fixed_prio);\r
259 ioption("htb-default-prio",keyword->default_prio);\r
260 ioption("htb-rate-bonus",keyword->reserve_min);\r
261 ioption("htb-ceil-malus",keyword->reserve_max);\r
208112af 262 option("leaf-discipline",keyword->leaf_discipline);\r
263 option("html-color",keyword->html_color);\r
264 _=tmptr;\r
265 \r
266 if(keyword->data_limit || keyword->fixed_limit || \r
267 keyword->data_prio || keyword->fixed_prio)\r
bb9e11ee 268 {\r
269 use_credit=1; \r
270 }\r
208112af 271 }\r
272 }\r
007c44c5 273 }\r
274\r
275 option("tc",tc);\r
276 option("iptables",iptables);\r
277 option("iptables-save",iptablessave); /* new */\r
278 option("iptables-restore",iptablesrestore); /* new */\r
be96b71b 279 option("iptables-in-filename",iptablesfile); /* new */\r
007c44c5 280 option("hosts",hosts);\r
281 option("lan-interface",lan);\r
282 option("wan-interface",wan);\r
283 option("lan-medium",lan_medium);\r
284 option("wan-medium",wan_medium);\r
285 lloption("wan-download",line);\r
286 lloption("wan-upload",up);\r
287 ioption("hall-of-fame-enable",hall_of_fame);\r
288 option("hall-of-fame-title",title);\r
289 option("hall-of-fame-filename",html);\r
1ab008b9 290 option("json-filename",json_traffic);\r
007c44c5 291 option("hall-of-fame-preview",preview);\r
6fb3c58a 292 option("json-preview",json_preview);\r
007c44c5 293 option("log-filename",cmdlog);\r
294 option("credit-filename",credit);\r
be96b71b 295 option("classmap-filename",classmap);\r
007c44c5 296 ioption("credit-enable",enable_credit);\r
297 option("log-traffic-directory",log_dir);\r
5b902402 298 option("log-traffic-html-directory",html_log_dir);\r
007c44c5 299 option("log-traffic-url-path",log_url);\r
6cc38f96 300 option("jquery-url",jquery_url);\r
301 option("lms-url",lms_url);\r
302 ioption("use-jquery-popups",use_jquery_popups);\r
007c44c5 303 option("qos-free-zone",qos_free_zone);\r
304 ioption("qos-free-delay",qos_free_delay);\r
305 ioption("qos-proxy-enable",qos_proxy);\r
306 option("qos-proxy-ip",proxy_ip);\r
307 option("htb-leaf-discipline",qos_leaf);\r
308 ioption("qos-proxy-port",proxy_port);\r
309 ioption("free-rate",free_min);\r
310 ioption("free-ceil",free_max);\r
311 ioption("htb-burst",burst);\r
312 ioption("htb-burst-main",burst_main);\r
313 ioption("htb-burst-group",burst_group);\r
314 ioption("htb-nesting-limit",max_nesting);\r
315 ioption("htb-r2q",htb_r2q);\r
316 ioption("magic-include-upload",include_upload);\r
5b902402 317 ioption("magic-treshold",magic_treshold); \r
260c2719 318 option("filter-type", cnf); \r
007c44c5 319/* not yet implemented:\r
320 ioption("magic-fixed-packets",fixed_packets);\r
321 ioption("magic-relative-packets",packet_limit);\r
322*/\r
323 }\r
324 fail\r
325 { \r
326 perror(config_filename);\r
327 puts("Warning - using built-in defaults instead ...");\r
328 }\r
8e29188a 329 done; /* ugly macro end */\r
007c44c5 330 printf("\n");\r
331 \r
be96b71b 332 /* leaf discipline for keywords */\r
208112af 333 for_each(keyword,keywords)\r
007c44c5 334 {\r
260c2719 335 if(!strcmpi(keyword->leaf_discipline, ""))\r
208112af 336 {\r
007c44c5 337 keyword->leaf_discipline = qos_leaf;\r
338 }\r
339 }\r
340\r
260c2719 341 if(strcmpi(cnf, "mark"))\r
bb9e11ee 342 {\r
343 filter_type = 2;\r
344 mark = "CLASSIFY";\r
345 mark_iptables = "CLASSIFY --set-class 1:";\r
346 }\r
347 else\r
348 {\r
349 filter_type = 1;\r
350 mark = "MARK";\r
351 mark_iptables = "MARK --set-mark ";\r
007c44c5 352 }\r
353\r
354 /* are supplied values meaningful ?*/\r
355 if(line<=0 || up<=0)\r
356 {\r
b1b59b3a 357 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");\r
007c44c5 358 reject_config_and_exit(config_filename);\r
359 }\r
360}\r
361\r
362/* ===================== traffic analyser - uses iptables ================ */ \r
363\r
364void get_traffic_statistics(void)\r
365{\r
366 char *str,*cmd;\r
367 int downloadflag=0;\r
368\r
369 textfile(Pipe,str) *line,*lines=NULL;\r
370 string(str,STRLEN);\r
371 string(cmd,STRLEN);\r
372\r
373 sprintf(cmd,"%s -L -v -x -n -t mangle",iptables);\r
374 shell(cmd);\r
375 input(str,STRLEN)\r
376 {\r
377 create(line,Pipe);\r
378 line->str=str;\r
379 string(str,STRLEN);\r
380 append(line,lines);\r
381 }\r
382\r
208112af 383 for_each(line,lines)\r
007c44c5 384 {\r
385 int col, accept=0,proxyflag=0,valid=1,setchainname=0,commonflag=0; \r
386 unsigned long long traffic=0;\r
387 unsigned long pkts=0;\r
388 char *ipaddr=NULL,*ptr;\r
389 \r
390 /* debug puts(line->str); */\r
391 valid_columns(ptr,line->str,' ',col) \r
392 if(valid) switch(col)\r
393 { \r
394 case 1: if(eq(ptr,"Chain"))\r
260c2719 395 {\r
007c44c5 396 setchainname=1;\r
260c2719 397 }\r
007c44c5 398 else if(eq(ptr,"pkts")) \r
260c2719 399 {\r
007c44c5 400 valid=0;\r
260c2719 401 }\r
007c44c5 402 else\r
260c2719 403 {\r
007c44c5 404 sscanf(ptr,"%lu",&pkts); \r
260c2719 405 }\r
007c44c5 406 break;\r
407 case 2: if(setchainname)\r
408 {\r
409 if(!strncmp(ptr,"post_",5) || eq(ptr,"POSTROUTING"))\r
260c2719 410 {\r
411 downloadflag = 1; \r
412 }\r
007c44c5 413 else \r
260c2719 414 {\r
415 if(!strncmp(ptr,"forw_",5) || eq(ptr,"FORWARD"))\r
416 {\r
417 downloadflag = 0;\r
418 }\r
419 } \r
007c44c5 420 if(eq(ptr,"post_common") || eq(ptr,"forw_common"))\r
260c2719 421 {\r
422 commonflag = 1;\r
423 }\r
007c44c5 424 }\r
425 else\r
260c2719 426 {\r
427 sscanf(ptr,"%Lu",&traffic); \r
428 traffic += (1<<19);\r
429 traffic >>= 20;\r
430 }\r
007c44c5 431 break;\r
0045483c 432 case 3: if((strncmp(ptr,"post_",5) && strncmp(ptr,"forw_",5)) || commonflag)\r
260c2719 433 {\r
007c44c5 434 accept=eq(ptr,mark);\r
260c2719 435 }\r
436 /*if(filter_type==1) accept=eq(ptr,"MARK"); else accept=eq(ptr,"CLASSIFY");*/\r
007c44c5 437 break;\r
438 case 8: if(downloadflag)\r
439 { \r
260c2719 440 if(strstr(proxy_ip,ptr))\r
441 {\r
442 proxyflag=1; \r
443 }\r
007c44c5 444 }\r
445 else\r
260c2719 446 {\r
007c44c5 447 ipaddr=ptr; \r
260c2719 448 }\r
449 break;\r
007c44c5 450 case 9: if(downloadflag)ipaddr=ptr;break;\r
451 }\r
452 \r
453 if(accept && traffic>0 && ipaddr)\r
454 {\r
a1d21464 455 if(proxyflag)\r
456 {\r
457 printf("(proxy) ");\r
458 }\r
459 else if(!downloadflag)\r
460 {\r
461 printf("(upload) ");\r
462 }\r
457d52f2 463 printf("IP %s: %Lu MB (%ld pkts)\n", ipaddr, traffic, pkts);\r
208112af 464\r
465 if_exists(ip,ips,eq(ip->addr,ipaddr)); \r
007c44c5 466 else \r
467 {\r
468 TheIP();\r
4d41c1e4 469 ip->addr = ipaddr;\r
007c44c5 470 if(eq(ip->addr,"0.0.0.0/0"))\r
471 {\r
4d41c1e4 472 ip->name = "(unregistered)";\r
473 ip->min = free_min;\r
474 ip->max = ip->desired=free_max;\r
475 }\r
476 else\r
477 {\r
478 ip->name = ipaddr;\r
007c44c5 479 }\r
480 }\r
481 \r
482 if(downloadflag)\r
483 {\r
484 if(proxyflag)\r
a1d21464 485 {\r
007c44c5 486 ip->proxy=traffic;\r
a1d21464 487 }\r
007c44c5 488 else\r
a1d21464 489 {\r
007c44c5 490 ip->traffic+=traffic;\r
a1d21464 491 }\r
007c44c5 492 ip->direct=ip->traffic-ip->upload-ip->proxy;\r
493 ip->pktsdown=pkts;\r
494 }\r
495 else\r
496 {\r
497 ip->upload=traffic;\r
498 ip->pktsup=pkts;\r
499 if(include_upload)\r
bb9e11ee 500 {\r
007c44c5 501 ip->traffic+=traffic;\r
bb9e11ee 502 }\r
007c44c5 503 else \r
bb9e11ee 504 {\r
007c44c5 505 if(traffic>ip->traffic)\r
bb9e11ee 506 {\r
007c44c5 507 ip->traffic=traffic; \r
bb9e11ee 508 }\r
509 }\r
007c44c5 510 }\r
511 } \r
512 }\r
1c004f15 513 free(cmd);\r
007c44c5 514}\r
515 \r
516/* ========== This function executes, logs OR ALSO prints command ========== */\r
517\r
518void safe_run(char *cmd)\r
519{\r
a1d21464 520 if(dry_run)\r
521 {\r
522 printf("\n=>%s\n",cmd);\r
523 }\r
524 else\r
525 {\r
526 system(cmd);\r
527 }\r
528 if(log_file)\r
529 {\r
530 fprintf(log_file,"%s\n",cmd);\r
531 }\r
007c44c5 532}\r
533\r
534void save_line(char *line)\r
535{\r
536 fprintf(iptables_file,"%s\n",line);\r
537}\r
538\r
539void run_restore(void)\r
540{\r
5da44508 541 char *restor;\r
007c44c5 542 string(restor,STRLEN);\r
abe9b855 543\r
544 /*-----------------------------------------------------------------*/\r
1c004f15 545 printf("Running %s <%s ...\n", iptablesrestore, iptablesfile);\r
abe9b855 546 /*-----------------------------------------------------------------*/\r
007c44c5 547 \r
548 save_line("COMMIT");\r
549 fclose(iptables_file);\r
ae776b10 550 if(dry_run) \r
551 {\r
a1d21464 552 parse(iptablesfile)\r
553 {\r
554 printf("%s\n",_);\r
555 }\r
8e29188a 556 done; /* ugly macro end */\r
ae776b10 557 }\r
558\r
559 sprintf(restor,"%s <%s",iptablesrestore, iptablesfile);\r
560 safe_run(restor);\r
007c44c5 561 \r
562 free(restor);\r
563}\r
564\r
007c44c5 565char *parse_datafile_line(char *str)\r
566{\r
567 char *ptr=strchr(str,' ');\r
568\r
569 if(ptr)\r
570 {\r
571 *ptr=0;\r
572 ptr++;\r
573 return ptr;\r
574 } \r
575 else \r
4358455e 576 {\r
007c44c5 577 return NULL;\r
4358455e 578 }\r
007c44c5 579}\r
580\r
5b902402 581\r
007c44c5 582/*-----------------------------------------------------------------*/\r
493e1ccd 583/* Are you looking for int main(int argc, char **argv) ? :-)) */\r
007c44c5 584/*-----------------------------------------------------------------*/\r
585\r
586program\r
587{\r
8e29188a 588 int i=0; /* just plain old Fortran style integer :-) */\r
589 FILE *f=NULL; /* everything is just stream of bytes... */\r
590 char *str, *ptr, *d; /* LET A$=B$ :-) */\r
007c44c5 591 char *substring;\r
1c9cae56 592\r
9a56ab25 593 int parent = 1;\r
594 int just_flush = FALSE; /* deactivates all previous actions */\r
595 int nodelay = FALSE;\r
596 int just_preview = FALSE; /* preview - generate just stats */\r
597 int start_shaping = FALSE; /* apply FUP - requires classmap file */\r
598 int just_logs = FALSE; /* just parse logs */\r
599 int run = FALSE;\r
600 int total = 0;\r
33ec95ab 601 \r
007c44c5 602 char *chain_forward, *chain_postrouting;\r
603 char *althosts=NULL;\r
604 \r
605 printf("\n\\r
606Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\\r
8e29188a 607Version %s - Copyright (C)2005-2012 Michael Polak, Arachne Labs\n\\r
43cde5c3 608iptables-restore & burst tunning & classify modification by Ludva\n\\r
0d5026c6 609Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version);\r
007c44c5 610\r
8e29188a 611 /*----- Boring... we have to check command line options first: ----*/ \r
007c44c5 612 arguments\r
613 {\r
614 argument("-c") { nextargument(config); }\r
615 argument("-h") { nextargument(althosts);}\r
208112af 616 argument("-d") { run=TRUE; dry_run=TRUE; }\r
617 argument("-f") { run=TRUE; just_flush=TRUE; }\r
618 argument("-9") { run=TRUE; just_flush=9; }\r
619 argument("-p") { run=TRUE; just_preview=TRUE; }\r
8e29188a 620 argument("-s") { run=TRUE; just_preview=TRUE; start_shaping=TRUE; }\r
208112af 621 argument("-r") { run=TRUE; }\r
622 argument("-n") { run=TRUE; nodelay=TRUE; }\r
623 argument("-l") { just_logs=TRUE; }\r
624 argument("-m") { just_logs=TRUE; }\r
625 argument("-y") { just_logs=TRUE; }\r
007c44c5 626 argument("-?") { help(); exit(0); }\r
627 argument("--help") { help(); exit(0); }\r
628 argument("-v") { exit(0); } \r
629 argument("--version") { exit(0); } \r
630 }\r
208112af 631 \r
007c44c5 632 if(dry_run)\r
208112af 633 {\r
007c44c5 634 puts("*** THIS IS JUST DRY RUN ! ***\n");\r
208112af 635 }\r
007c44c5 636\r
208112af 637 date(d); /* this is typical cll1.h macro - prints current date */\r
007c44c5 638\r
639 /*-----------------------------------------------------------------*/\r
640 printf("Parsing configuration file %s ...\n", config);\r
641 /*-----------------------------------------------------------------*/\r
642 get_config(config);\r
c9012978 643 \r
33ec95ab 644 if(just_logs)\r
c9012978 645 {\r
208112af 646 parse_ip_log(argc,argv);\r
647 exit(0);\r
648 }\r
649 else if(not run)\r
650 {\r
651 help();\r
652 exit(0);\r
c9012978 653 }\r
007c44c5 654\r
208112af 655 if(althosts)\r
656 {\r
657 hosts=althosts;\r
658 }\r
007c44c5 659\r
660 if(just_flush<9)\r
661 {\r
662 /*-----------------------------------------------------------------*/\r
663 puts("Parsing iptables verbose output ...");\r
664 /*-----------------------------------------------------------------*/\r
665 get_traffic_statistics();\r
666 }\r
667\r
668 /*-----------------------------------------------------------------*/\r
669 printf("Parsing class defintion file %s ...\n", hosts);\r
670 /*-----------------------------------------------------------------*/\r
1c9cae56 671 parse_hosts(hosts);\r
007c44c5 672\r
673 /*-----------------------------------------------------------------*/\r
674 /* cll1.h - let's allocate brand new character buffer... */\r
675 /*-----------------------------------------------------------------*/\r
676 string(str,STRLEN); \r
677\r
678 /*-----------------------------------------------------------------*/\r
679 puts("Resolving shared connections ...");\r
680 /*-----------------------------------------------------------------*/\r
6cc38f96 681 for_each(ip,ips) if(ip->sharing)\r
007c44c5 682 {\r
6cc38f96 683 for_each(sharedip,ips) if(eq(sharedip->name,ip->sharing))\r
007c44c5 684 {\r
685 sharedip->traffic+=ip->traffic;\r
686 ip->traffic=0;\r
687 ip->mark=sharedip->mark; \r
b3175d62 688 ip->lmsid=sharedip->lmsid;\r
007c44c5 689 break;\r
690 }\r
1c9cae56 691 if(not sharedip)\r
bb9e11ee 692 {\r
260c2719 693 printf("Unresolved shared connection: %s %s sharing-%s\n",\r
694 ip->addr, ip->name, ip->sharing);\r
bb9e11ee 695 }\r
007c44c5 696 }\r
697\r
698 if(enable_credit && just_flush<9)\r
699 {\r
700 /*-----------------------------------------------------------------*/\r
701 printf("Parsing credit file %s ...\n", credit);\r
702 /*-----------------------------------------------------------------*/\r
703 parse(credit)\r
704 {\r
705 ptr=parse_datafile_line(_);\r
706 if(ptr)\r
707 {\r
208112af 708 if_exists(ip,ips,eq(ip->addr,_))\r
709 {\r
007c44c5 710 sscanf(ptr,"%Lu",&(ip->credit));\r
208112af 711 }\r
007c44c5 712 }\r
713 }\r
8e29188a 714 done; /* ugly macro end */\r
007c44c5 715 }\r
716\r
717 if(!just_preview)\r
718 {\r
719 /*-----------------------------------------------------------------*/\r
720 puts("Initializing iptables and tc classes ...");\r
721 /*-----------------------------------------------------------------*/\r
722 \r
723 iptables_file=fopen(iptablesfile,"w");\r
260c2719 724 if(iptables_file == NULL)\r
bb9e11ee 725 {\r
007c44c5 726 puts("Cannot open iptablesfile!");\r
727 exit(-1);\r
728 }\r
729 \r
730 log_file=fopen(cmdlog,"w");\r
260c2719 731 if(log_file == NULL) \r
bb9e11ee 732 {\r
007c44c5 733 puts("Cannot open logfile!");\r
734 exit(-1);\r
735 }\r
736 \r
737 save_line(iptablespreamble);\r
738 run_restore();\r
739 \r
740 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,lan);\r
741 safe_run(str);\r
742\r
743 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,wan);\r
744 safe_run(str);\r
745 \r
746 iptables_file=fopen(iptablesfile,"w");\r
747 save_line(iptablespreamble);\r
748\r
749 if(qos_free_zone && *qos_free_zone!='0')\r
750 {\r
751 char *chain;\r
752 \r
753 sprintf(str,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone, wan);\r
754 save_line(str);\r
755 \r
756 if(qos_proxy)\r
757 {\r
758 save_line(":post_noproxy - [0:0]");\r
6b39193d 759 sprintf(str,"-A POSTROUTING ! -p tcp -o %s -j post_noproxy", lan);\r
007c44c5 760 save_line(str); \r
6b39193d 761 sprintf(str,"-A POSTROUTING ! -s %s -o %s -j post_noproxy", proxy_ip, lan);\r
007c44c5 762 save_line(str); \r
6b39193d 763 sprintf(str,"-A POSTROUTING -s %s -p tcp ! --sport %d -o %s -j post_noproxy", proxy_ip, proxy_port, lan);\r
007c44c5 764 save_line(str); \r
765\r
766 chain="post_noproxy"; \r
767 }\r
768 else\r
bb9e11ee 769 {\r
007c44c5 770 chain="POSTROUTING";\r
bb9e11ee 771 }\r
007c44c5 772 \r
773 sprintf(str,"-A %s -s %s -o %s -j ACCEPT", chain, qos_free_zone, lan);\r
774 save_line(str);\r
775 }\r
776 \r
777 if(ip_count>idxtable_treshold1 && !just_flush)\r
778 {\r
779 int idxcount=0, bitmask=32-idxtable_bitmask1; /* default net mask: 255.255.255.240 */\r
e0161edb 780 char *subnet, *buf;\r
007c44c5 781 /*-----------------------------------------------------------------*/\r
782 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count);\r
783 /*-----------------------------------------------------------------*/\r
784\r
785 save_line(":post_common - [0:0]");\r
786 save_line(":forw_common - [0:0]");\r
787\r
260c2719 788 for_each(ip,ips) if(ip->addr && *(ip->addr) && !eq(ip->addr,"0.0.0.0/0"))\r
007c44c5 789 {\r
b6fb849a 790 buf=index_id(ip->addr,bitmask);\r
208112af 791 if_exists(idx,idxs,eq(idx->id,buf))\r
792 {\r
007c44c5 793 idx->children++;\r
208112af 794 }\r
007c44c5 795 else\r
796 {\r
797 create(idx,Index);\r
798 idx->addr=ip->addr;\r
799 idx->id=buf;\r
800 idx->bitmask=bitmask;\r
801 idx->parent=NULL;\r
802 idx->children=0;\r
803 idxcount++;\r
804 push(idx,idxs);\r
805 }\r
806 }\r
807\r
808 /* brutal perfomance optimalization */\r
809 while(idxcount>idxtable_treshold2 && bitmask>2*idxtable_bitmask2)\r
810 {\r
811 bitmask-=idxtable_bitmask2;\r
812 idxcount=0;\r
208112af 813\r
6cc38f96 814 for_each(idx,idxs) if(idx->parent == NULL)\r
007c44c5 815 {\r
b6fb849a 816 buf=index_id(idx->addr,bitmask);\r
208112af 817 if_exists(metaindex,idxs,eq(metaindex->id,buf))\r
818 {\r
819 metaindex->children++;\r
820 }\r
007c44c5 821 else\r
822 {\r
823 create(metaindex,Index);\r
824 metaindex->addr=idx->addr;\r
825 metaindex->id=buf;\r
826 metaindex->bitmask=bitmask;\r
827 metaindex->parent=NULL;\r
828 metaindex->children=0;\r
829 idxcount++;\r
830 push(metaindex,idxs);\r
831 }\r
832 idx->parent=metaindex;\r
833 }\r
834 }\r
835\r
836 /* this should slightly optimize throughout ... */\r
837 sort(idx,idxs,desc_order_by,children);\r
838 sort(idx,idxs,order_by,bitmask);\r
839\r
840 i=0;\r
208112af 841 for_each(idx,idxs)\r
007c44c5 842 {\r
843 subnet=subnet_id(idx->addr,idx->bitmask);\r
260c2719 844 printf("%d: %s/%d\n",\r
845 ++i, subnet, idx->bitmask);\r
007c44c5 846 \r
847 sprintf(str,":post_%s - [0:0]", idx->id);\r
848 save_line(str);\r
849\r
850 sprintf(str,":forw_%s - [0:0]", idx->id);\r
851 save_line(str);\r
852\r
853 if(idx->parent)\r
854 {\r
855 string(buf,strlen(idx->parent->id)+6);\r
856 sprintf(buf,"post_%s",idx->parent->id);\r
857 }\r
858 else\r
bb9e11ee 859 {\r
007c44c5 860 buf="POSTROUTING";\r
bb9e11ee 861 }\r
007c44c5 862\r
863 sprintf(str,"-A %s -d %s/%d -o %s -j post_%s", buf, subnet, idx->bitmask, lan, idx->id);\r
864 save_line(str);\r
865\r
866 sprintf(str,"-A %s -d %s/%d -o %s -j post_common", buf, subnet, idx->bitmask, lan);\r
867 save_line(str);\r
868\r
869 if(idx->parent)\r
870 {\r
871 string(buf,strlen(idx->parent->id)+6);\r
872 sprintf(buf,"forw_%s",idx->parent->id);\r
873 }\r
874 else\r
bb9e11ee 875 {\r
007c44c5 876 buf="FORWARD";\r
bb9e11ee 877 }\r
007c44c5 878\r
879 sprintf(str,"-A %s -s %s/%d -o %s -j forw_%s", buf, subnet, idx->bitmask, wan, idx->id);\r
880 save_line(str);\r
881\r
882 sprintf(str,"-A %s -s %s/%d -o %s -j forw_common", buf, subnet, idx->bitmask, wan);\r
883 save_line(str);\r
884 }\r
885 printf("Total indexed iptables chains created: %d\n", i);\r
886\r
887 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);\r
888 save_line(str);\r
889 \r
890 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);\r
891 save_line(str);\r
892 }\r
893 \r
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
1010 && ( ip->traffic>ip->credit\r
1011 + (ip->min*ip->keyword->data_prio+(ip->keyword->fixed_prio<<20))) )\r
007c44c5 1012 {\r
1013 ip->prio=priority_sequence--;\r
4358455e 1014 if(ip->prio<highest_priority+1)\r
1015 {\r
1016 ip->prio=highest_priority+1;\r
1017 }\r
007c44c5 1018 }\r
1019 \r
1020 if(credit_file)\r
1021 {\r
1022 unsigned long long lcredit=0;\r
99127c70 1023 \r
4358455e 1024 if((ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))>ip->traffic)\r
1025 {\r
007c44c5 1026 lcredit=(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))-ip->traffic;\r
4358455e 1027 }\r
007c44c5 1028 fprintf(credit_file,"%s %Lu\n",ip->addr,lcredit);\r
1029 }\r
1030 }\r
6cc38f96 1031 } \r
007c44c5 1032 }\r
1033 }\r
4358455e 1034 if(credit_file)\r
1035 {\r
1036 fclose(credit_file);\r
1037 }\r
007c44c5 1038 }\r
1039\r
1040 if(just_preview)\r
1041 {\r
8e29188a 1042 if(start_shaping)\r
1043 {\r
1044 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap);\r
1045 parse(classmap)\r
1046 {\r
1047 ptr=strchr(_,' ');\r
1048 if(ptr)\r
1049 {\r
1050 *ptr=0;\r
1051 ptr++;\r
1052 if_exists(ip,ips,eq(ip->addr,_))\r
1053 {\r
1054 ip->mark=atoi(ptr);\r
1055 if(ip->max < ip->desired) /* apply FUP limit immediately.... */\r
1056 {\r
1057 printf("Applying limit for %-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
1058 printf("(down: %dk-%dk ", ip->min, ip->max); \r
1059 sprintf(str, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
1060 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
1061 safe_run(str);\r
1062 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1063 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
1064 sprintf(str,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1065 tc, wan, ip->group, ip->mark,\r
1066 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1067 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1068 safe_run(str);\r
1069 }\r
1070 }\r
1071 }\r
1072 }\r
1073 fail\r
1074 { \r
1075 perror(classmap);\r
1076 puts("Warning - classmap file not fund, just generating preview ...");\r
1077 start_shaping=FALSE;\r
1078 }\r
1079 done; /* ugly macro end */\r
1080 }\r
6fb3c58a 1081 html=preview;\r
1ab008b9 1082 json_traffic=json_preview;\r
007c44c5 1083 }\r
6fb3c58a 1084\r
1085 if(!dry_run && !just_flush)\r
007c44c5 1086 {\r
1087 /*-----------------------------------------------------------------*/\r
1ab008b9 1088 printf("Writing json traffic overview %s ... ", json_traffic);\r
007c44c5 1089 /*-----------------------------------------------------------------*/\r
1ab008b9 1090 write_json_traffic(json_traffic);\r
007c44c5 1091 }\r
1092\r
9a56ab25 1093 /*-----------------------------------------------------------------*/\r
1094 printf("Writing statistics into HTML page %s ...\n", html);\r
1095 /*-----------------------------------------------------------------*/\r
0db8e993 1096 write_htmlandlogs(html, d,total, just_preview);\r
007c44c5 1097\r
1098 if(just_preview)\r
1099 {\r
8e29188a 1100 char swchar='p';\r
1101 if(start_shaping)\r
1102 {\r
1103 swchar='s';\r
1104 }\r
1105 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar);\r
007c44c5 1106 exit(0);\r
be96b71b 1107 } \r
007c44c5 1108\r
1109 i=0;\r
260c2719 1110#ifdef DEBUG\r
007c44c5 1111 printf("%-22s %-15s mark\n","name","ip");\r
260c2719 1112#endif\r
208112af 1113\r
be96b71b 1114 printf("Writing %s ... ", classmap); \r
1115 f = fopen(classmap, "w"); \r
1116 if(f < 0)\r
1117 {\r
1118 perror(classmap);\r
1119 }\r
1120\r
1121 /*-----------------------------------------------------------------*/\r
1122 puts("Generating iptables and tc classes ... ");\r
1123 /*-----------------------------------------------------------------*/\r
1124\r
1125 for_each(ip, ips) if(ip->mark > 0)\r
1126 {\r
007c44c5 1127 if(idxs)\r
1128 {\r
1129 char *buf;\r
1130 duplicate(ip->addr,buf);\r
b6fb849a 1131 buf=index_id(ip->addr,32-idxtable_bitmask1); \r
007c44c5 1132 \r
1133 string(chain_forward,6+strlen(buf));\r
1134 strcpy(chain_forward,"forw_");\r
1135 strcat(chain_forward,buf);\r
1136\r
1137 string(chain_postrouting,6+strlen(buf));\r
1138 strcpy(chain_postrouting,"post_");\r
1139 strcat(chain_postrouting,buf);\r
1140 \r
1141 free(buf);\r
1142 }\r
1143 else\r
1144 {\r
1145 chain_forward="FORWARD";\r
1146 chain_postrouting="POSTROUTING";\r
1147 }\r
1148\r
260c2719 1149#ifdef DEBUG\r
007c44c5 1150 printf("%-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
260c2719 1151#endif\r
007c44c5 1152\r
1153 /* -------------------------------------------------------- mark download */\r
1154 \r
be96b71b 1155 sprintf(str, "-A %s -d %s/32 -o %s -j %s%d",\r
1156 chain_postrouting, ip->addr, lan, mark_iptables, ip->mark);\r
007c44c5 1157 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/\r
1158 /* -m limit --limit 1/s */ \r
1159 save_line(str);\r
1160\r
1161 if(qos_proxy)\r
1162 {\r
be96b71b 1163 sprintf(str, "-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",\r
1164 chain_postrouting, proxy_ip, proxy_port, ip->addr, lan, mark_iptables, ip->mark);\r
007c44c5 1165 /*sprintf(str,"-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,proxy_ip,proxy_port,ip->addr,lan,ip->mark);*/\r
1166 save_line(str);\r
1167 }\r
1168\r
be96b71b 1169 sprintf(str, "-A %s -d %s/32 -o %s -j ACCEPT",\r
1170 chain_postrouting, ip->addr, lan);\r
007c44c5 1171 save_line(str);\r
1172\r
1173 /* -------------------------------------------------------- mark upload */\r
be96b71b 1174 sprintf(str, "-A %s -s %s/32 -o %s -j %s%d", \r
1175 chain_forward, ip->addr, wan, mark_iptables, ip->mark);\r
007c44c5 1176 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/\r
1177 save_line(str);\r
1178\r
be96b71b 1179 sprintf(str, "-A %s -s %s/32 -o %s -j ACCEPT",\r
1180 chain_forward, ip->addr, wan);\r
007c44c5 1181 save_line(str);\r
1182\r
1183 if(ip->min)\r
1184 {\r
1185 /* -------------------------------------------------------- download class */\r
260c2719 1186#ifdef DEBUG\r
007c44c5 1187 printf("(down: %dk-%dk ", ip->min, ip->max); \r
260c2719 1188#endif\r
007c44c5 1189\r
be96b71b 1190 sprintf(str, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
1191 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
007c44c5 1192 safe_run(str);\r
1193\r
260c2719 1194 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
dee5592e 1195 {\r
be96b71b 1196 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s", \r
1197 tc, lan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
dee5592e 1198 safe_run(str);\r
be96b71b 1199 }\r
1200\r
260c2719 1201 if(filter_type == 1)\r
dee5592e 1202 {\r
be96b71b 1203 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
1204 tc, lan, ip->mark, ip->mark);\r
dee5592e 1205 safe_run(str);\r
007c44c5 1206 }\r
1207\r
1208 /* -------------------------------------------------------- upload class */\r
260c2719 1209#ifdef DEBUG\r
007c44c5 1210 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1211 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
260c2719 1212#endif\r
007c44c5 1213\r
1214 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1215 tc, wan, ip->group, ip->mark,\r
1216 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1217 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1218 safe_run(str);\r
1219 \r
260c2719 1220 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
dee5592e 1221 {\r
be96b71b 1222 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s",\r
1223 tc, wan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
dee5592e 1224 safe_run(str);\r
1225 } \r
be96b71b 1226\r
260c2719 1227 if(filter_type == 1)\r
dee5592e 1228 {\r
be96b71b 1229 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
1230 tc, wan, ip->mark, ip->mark);\r
dee5592e 1231 safe_run(str);\r
007c44c5 1232 }\r
be96b71b 1233 \r
6fb3c58a 1234 if(f > 0)\r
be96b71b 1235 {\r
457d52f2 1236 fprintf(f, "%s %d\n", ip->addr, ip->mark);\r
be96b71b 1237 }\r
007c44c5 1238 }\r
1239 else\r
260c2719 1240 {\r
1241#ifdef DEBUG\r
007c44c5 1242 printf("(sharing %s)\n", ip->sharing);\r
260c2719 1243#endif\r
1244 }\r
007c44c5 1245 i++;\r
1246 }\r
6fb3c58a 1247 if(f > 0)\r
be96b71b 1248 {\r
1249 puts("done.");\r
1250 fclose(f);\r
1251 }\r
1252 \r
007c44c5 1253 if(idxs)\r
1254 {\r
dee5592e 1255 chain_forward = "forw_common";\r
1256 chain_postrouting = "post_common";\r
007c44c5 1257 }\r
1258 else\r
1259 {\r
dee5592e 1260 chain_forward = "FORWARD";\r
1261 chain_postrouting = "POSTROUTING";\r
007c44c5 1262 }\r
dee5592e 1263 /* -------------------------------- classify or reject free download */\r
007c44c5 1264 {\r
b6a8d473 1265 char *final_chain = "DROP"; /* REJECT would be better, but it is impossible in mangle */\r
be96b71b 1266 if(free_min)\r
1267 {\r
1268 final_chain = "ACCEPT";\r
1269 }\r
dee5592e 1270 if(qos_proxy)\r
1271 {\r
1272 if(free_min)\r
1273 {\r
be96b71b 1274 sprintf(str,"-A %s -s %s -p tcp --sport %d -o %s -j %s%d",\r
1275 chain_postrouting,proxy_ip,proxy_port,lan,mark_iptables,3);\r
dee5592e 1276 save_line(str);\r
1277 }\r
be96b71b 1278 sprintf(str,"-A %s -s %s -p tcp --sport %d -o %s -j %s",\r
1279 chain_postrouting,proxy_ip,proxy_port,lan,final_chain);\r
dee5592e 1280 save_line(str);\r
1281 }\r
1282 if(free_min)\r
1283 {\r
be96b71b 1284 sprintf(str,"-A %s -o %s -j %s%d", chain_postrouting, lan, mark_iptables, 3);\r
dee5592e 1285 save_line(str);\r
1286 }\r
be96b71b 1287 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
dee5592e 1288 save_line(str);\r
1289 /* ------------------------------- classify or reject free upload */\r
1290 if(free_min)\r
1291 {\r
be96b71b 1292 sprintf(str,"-A %s -o %s -j %s%d", chain_forward, wan, mark_iptables, 3);\r
dee5592e 1293 save_line(str);\r
1294 }\r
be96b71b 1295 sprintf(str,"-A %s -o %s -j %s", chain_forward, wan, final_chain);\r
dee5592e 1296 save_line(str);\r
007c44c5 1297 }\r
abe9b855 1298\r
dee5592e 1299 if(free_min) /* allocate free bandwith if it is not zero... */ \r
1300 {\r
1301 /*-----------------------------------------------------------------*/\r
1302 puts("Generating free bandwith classes ...");\r
1303 /*-----------------------------------------------------------------*/\r
208112af 1304 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
be96b71b 1305 tc, lan, parent, free_min, free_max,burst, lowest_priority);\r
dee5592e 1306 safe_run(str);\r
208112af 1307 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
be96b71b 1308 tc, wan, parent, free_min, free_max, burst, lowest_priority);\r
dee5592e 1309 safe_run(str);\r
1310 /* tc SFQ */\r
260c2719 1311 if(strcmpi(qos_leaf, "none"))\r
dee5592e 1312 {\r
be96b71b 1313 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, lan, qos_leaf);\r
dee5592e 1314 safe_run(str);\r
1315 \r
be96b71b 1316 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, wan, qos_leaf);\r
dee5592e 1317 safe_run(str);\r
1318 } \r
1319 /* tc handle 1 fw flowid */\r
be96b71b 1320 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, lan);\r
dee5592e 1321 safe_run(str);\r
007c44c5 1322\r
be96b71b 1323 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, wan);\r
dee5592e 1324 safe_run(str);\r
007c44c5 1325 }\r
dee5592e 1326 printf("Total IP count: %d\n", i);\r
1327 run_restore(); \r
260c2719 1328 if(log_file)\r
1329 {\r
1330 fclose(log_file);\r
1331 }\r
007c44c5 1332 return 0;\r
007c44c5 1333 /* that's all folks, thank you for reading it all the way up to this point ;-) */\r
1334 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */\r
1335}\r
This page took 1.843849 seconds and 4 git commands to generate.