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