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