it is 2013 now
[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-2013 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, 20130107\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-2013 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)\r
236 {\r
237 defaultkeyword=keyword;\r
238 }\r
239 keywordcount++;\r
240 \r
241 kwd=NULL;\r
242 }\r
243 else\r
244 {\r
245 for_each(keyword,keywords)\r
246 {\r
247 int l=strlen(keyword->key);\r
248\r
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
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
268 {\r
269 use_credit=1; \r
270 }\r
271 }\r
272 }\r
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
279 option("iptables-in-filename",iptablesfile); /* new */\r
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
290 option("json-filename",json_traffic);\r
291 option("hall-of-fame-preview",preview);\r
292 option("json-preview",json_preview);\r
293 option("log-filename",cmdlog);\r
294 option("credit-filename",credit);\r
295 option("classmap-filename",classmap);\r
296 ioption("credit-enable",enable_credit);\r
297 option("log-traffic-directory",log_dir);\r
298 option("log-traffic-html-directory",html_log_dir);\r
299 option("log-traffic-url-path",log_url);\r
300 option("jquery-url",jquery_url);\r
301 option("lms-url",lms_url);\r
302 ioption("use-jquery-popups",use_jquery_popups);\r
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
317 ioption("magic-treshold",magic_treshold); \r
318 option("filter-type", cnf); \r
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
329 done; /* ugly macro end */\r
330 printf("\n");\r
331 \r
332 /* leaf discipline for keywords */\r
333 for_each(keyword,keywords)\r
334 {\r
335 if(!strcmpi(keyword->leaf_discipline, ""))\r
336 {\r
337 keyword->leaf_discipline = qos_leaf;\r
338 }\r
339 }\r
340\r
341 if(strcmpi(cnf, "mark"))\r
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
352 }\r
353\r
354 /* are supplied values meaningful ?*/\r
355 if(line<=0 || up<=0)\r
356 {\r
357 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");\r
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
383 for_each(line,lines)\r
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
395 {\r
396 setchainname=1;\r
397 }\r
398 else if(eq(ptr,"pkts")) \r
399 {\r
400 valid=0;\r
401 }\r
402 else\r
403 {\r
404 sscanf(ptr,"%lu",&pkts); \r
405 }\r
406 break;\r
407 case 2: if(setchainname)\r
408 {\r
409 if(!strncmp(ptr,"post_",5) || eq(ptr,"POSTROUTING"))\r
410 {\r
411 downloadflag = 1; \r
412 }\r
413 else \r
414 {\r
415 if(!strncmp(ptr,"forw_",5) || eq(ptr,"FORWARD"))\r
416 {\r
417 downloadflag = 0;\r
418 }\r
419 } \r
420 if(eq(ptr,"post_common") || eq(ptr,"forw_common"))\r
421 {\r
422 commonflag = 1;\r
423 }\r
424 }\r
425 else\r
426 {\r
427 sscanf(ptr,"%Lu",&traffic); \r
428 traffic += (1<<19);\r
429 traffic >>= 20;\r
430 }\r
431 break;\r
432 case 3: if((strncmp(ptr,"post_",5) && strncmp(ptr,"forw_",5)) || commonflag)\r
433 {\r
434 accept=eq(ptr,mark);\r
435 }\r
436 /*if(filter_type==1) accept=eq(ptr,"MARK"); else accept=eq(ptr,"CLASSIFY");*/\r
437 break;\r
438 case 8: if(downloadflag)\r
439 { \r
440 if(strstr(proxy_ip,ptr))\r
441 {\r
442 proxyflag=1; \r
443 }\r
444 }\r
445 else\r
446 {\r
447 ipaddr=ptr; \r
448 }\r
449 break;\r
450 case 9: if(downloadflag)ipaddr=ptr;break;\r
451 }\r
452 \r
453 if(accept && traffic>0 && ipaddr)\r
454 {\r
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
463 printf("IP %s: %Lu MB (%ld pkts)\n", ipaddr, traffic, pkts);\r
464\r
465 if_exists(ip,ips,eq(ip->addr,ipaddr)); \r
466 else \r
467 {\r
468 TheIP();\r
469 ip->addr = ipaddr;\r
470 if(eq(ip->addr,"0.0.0.0/0"))\r
471 {\r
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
479 }\r
480 }\r
481 \r
482 if(downloadflag)\r
483 {\r
484 if(proxyflag)\r
485 {\r
486 ip->proxy=traffic;\r
487 }\r
488 else\r
489 {\r
490 ip->traffic+=traffic;\r
491 }\r
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
500 {\r
501 ip->traffic+=traffic;\r
502 }\r
503 else \r
504 {\r
505 if(traffic>ip->traffic)\r
506 {\r
507 ip->traffic=traffic; \r
508 }\r
509 }\r
510 }\r
511 } \r
512 }\r
513 free(cmd);\r
514}\r
515 \r
516/* ========== This function executes, logs OR ALSO prints command ========== */\r
517\r
518void safe_run(char *cmd)\r
519{\r
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
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
541 char *restor;\r
542 string(restor,STRLEN);\r
543\r
544 /*-----------------------------------------------------------------*/\r
545 printf("Running %s <%s ...\n", iptablesrestore, iptablesfile);\r
546 /*-----------------------------------------------------------------*/\r
547 \r
548 save_line("COMMIT");\r
549 fclose(iptables_file);\r
550 if(dry_run) \r
551 {\r
552 parse(iptablesfile)\r
553 {\r
554 printf("%s\n",_);\r
555 }\r
556 done; /* ugly macro end */\r
557 }\r
558\r
559 sprintf(restor,"%s <%s",iptablesrestore, iptablesfile);\r
560 safe_run(restor);\r
561 \r
562 free(restor);\r
563}\r
564\r
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
576 {\r
577 return NULL;\r
578 }\r
579}\r
580\r
581\r
582/*-----------------------------------------------------------------*/\r
583/* Are you looking for int main(int argc, char **argv) ? :-)) */\r
584/*-----------------------------------------------------------------*/\r
585\r
586program\r
587{\r
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
591 char *substring;\r
592\r
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
601 \r
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
607Version %s - Copyright (C)2005-2012 Michael Polak, Arachne Labs\n\\r
608iptables-restore & burst tunning & classify modification by Ludva\n\\r
609Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version);\r
610\r
611 /*----- Boring... we have to check command line options first: ----*/ \r
612 arguments\r
613 {\r
614 argument("-c") { nextargument(config); }\r
615 argument("-h") { nextargument(althosts);}\r
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
620 argument("-s") { run=TRUE; just_preview=TRUE; start_shaping=TRUE; }\r
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
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
631 \r
632 if(dry_run)\r
633 {\r
634 puts("*** THIS IS JUST DRY RUN ! ***\n");\r
635 }\r
636\r
637 date(d); /* this is typical cll1.h macro - prints current date */\r
638\r
639 /*-----------------------------------------------------------------*/\r
640 printf("Parsing configuration file %s ...\n", config);\r
641 /*-----------------------------------------------------------------*/\r
642 get_config(config);\r
643 \r
644 if(just_logs)\r
645 {\r
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
653 }\r
654\r
655 if(althosts)\r
656 {\r
657 hosts=althosts;\r
658 }\r
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
671 parse_hosts(hosts);\r
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
681 for_each(ip,ips) if(ip->sharing)\r
682 {\r
683 for_each(sharedip,ips) if(eq(sharedip->name,ip->sharing))\r
684 {\r
685 sharedip->traffic+=ip->traffic;\r
686 ip->traffic=0;\r
687 ip->mark=sharedip->mark; \r
688 ip->lmsid=sharedip->lmsid;\r
689 break;\r
690 }\r
691 if(not sharedip)\r
692 {\r
693 printf("Unresolved shared connection: %s %s sharing-%s\n",\r
694 ip->addr, ip->name, ip->sharing);\r
695 }\r
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
708 if_exists(ip,ips,eq(ip->addr,_))\r
709 {\r
710 sscanf(ptr,"%Lu",&(ip->credit));\r
711 }\r
712 }\r
713 }\r
714 done; /* ugly macro end */\r
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
724 if(iptables_file == NULL)\r
725 {\r
726 puts("Cannot open iptablesfile!");\r
727 exit(-1);\r
728 }\r
729 \r
730 log_file=fopen(cmdlog,"w");\r
731 if(log_file == NULL) \r
732 {\r
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
759 sprintf(str,"-A POSTROUTING ! -p tcp -o %s -j post_noproxy", lan);\r
760 save_line(str); \r
761 sprintf(str,"-A POSTROUTING ! -s %s -o %s -j post_noproxy", proxy_ip, lan);\r
762 save_line(str); \r
763 sprintf(str,"-A POSTROUTING -s %s -p tcp ! --sport %d -o %s -j post_noproxy", proxy_ip, proxy_port, lan);\r
764 save_line(str); \r
765\r
766 chain="post_noproxy"; \r
767 }\r
768 else\r
769 {\r
770 chain="POSTROUTING";\r
771 }\r
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
780 char *subnet, *buf;\r
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
788 for_each(ip,ips) if(ip->addr && *(ip->addr) && !eq(ip->addr,"0.0.0.0/0"))\r
789 {\r
790 buf=index_id(ip->addr,bitmask);\r
791 if_exists(idx,idxs,eq(idx->id,buf))\r
792 {\r
793 idx->children++;\r
794 }\r
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
813\r
814 for_each(idx,idxs) if(idx->parent == NULL)\r
815 {\r
816 buf=index_id(idx->addr,bitmask);\r
817 if_exists(metaindex,idxs,eq(metaindex->id,buf))\r
818 {\r
819 metaindex->children++;\r
820 }\r
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
841 for_each(idx,idxs)\r
842 {\r
843 subnet=subnet_id(idx->addr,idx->bitmask);\r
844 printf("%d: %s/%d\n",\r
845 ++i, subnet, idx->bitmask);\r
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
859 {\r
860 buf="POSTROUTING";\r
861 }\r
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
875 {\r
876 buf="FORWARD";\r
877 }\r
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
899 if(log_file)\r
900 { \r
901 fclose(log_file);\r
902 }\r
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
915 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",\r
916 tc,lan,htb_r2q);\r
917 safe_run(str);\r
918\r
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
921 safe_run(str);\r
922\r
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
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
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
932 safe_run(str);\r
933\r
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
936 safe_run(str);\r
937 }\r
938\r
939 /*-----------------------------------------------------------------*/\r
940 puts("Locating heavy downloaders and generating root classes ...");\r
941 /*-----------------------------------------------------------------*/\r
942 sort(ip,ips,desc_order_by,traffic); \r
943\r
944 /*-----------------------------------------------------------------*/\r
945 /* sub-scope - local variables */ \r
946 {\r
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
951 \r
952 if(!just_preview && !dry_run && enable_credit)\r
953 {\r
954 credit_file = fopen(credit,"w");\r
955 }\r
956 \r
957 for_each(group,groups)\r
958 {\r
959 if(!just_preview)\r
960 {\r
961 //download\r
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
964 safe_run(str);\r
965 \r
966 //upload\r
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
969 safe_run(str);\r
970 }\r
971 \r
972 if(group_count++ < max_nesting)\r
973 {\r
974 parent = group->id;\r
975 }\r
976 \r
977 rate -= digital_divide*group->min;\r
978 if(rate < group->min)\r
979 {\r
980 rate = group->min;\r
981 }\r
982 \r
983 /*shaping of aggresive downloaders, with credit file support */\r
984 if(use_credit)\r
985 {\r
986 int group_rate = group->min, priority_sequence = lowest_priority;\r
987 \r
988 for_each(ip, ips) if(ip->min == group->min && ip->max > ip->min)\r
989 {\r
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
994 {\r
995 if(group_rate < ip->max)\r
996 {\r
997 ip->max = group_rate;\r
998 }\r
999 group_rate+=magic_treshold;\r
1000 ip->prio=lowest_priority;\r
1001 if(ip->prio<highest_priority+2)\r
1002 {\r
1003 ip->prio=highest_priority+2;\r
1004 }\r
1005 }\r
1006 else\r
1007 {\r
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
1012 {\r
1013 ip->prio=priority_sequence--;\r
1014 if(ip->prio<highest_priority+1)\r
1015 {\r
1016 ip->prio=highest_priority+1;\r
1017 }\r
1018 }\r
1019 \r
1020 if(credit_file)\r
1021 {\r
1022 unsigned long long lcredit=0;\r
1023 \r
1024 if((ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))>ip->traffic)\r
1025 {\r
1026 lcredit=(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))-ip->traffic;\r
1027 }\r
1028 fprintf(credit_file,"%s %Lu\n",ip->addr,lcredit);\r
1029 }\r
1030 }\r
1031 } \r
1032 }\r
1033 }\r
1034 if(credit_file)\r
1035 {\r
1036 fclose(credit_file);\r
1037 }\r
1038 }\r
1039\r
1040 if(just_preview)\r
1041 {\r
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
1081 html=preview;\r
1082 json_traffic=json_preview;\r
1083 }\r
1084\r
1085 if(!dry_run && !just_flush)\r
1086 {\r
1087 /*-----------------------------------------------------------------*/\r
1088 printf("Writing json traffic overview %s ... ", json_traffic);\r
1089 /*-----------------------------------------------------------------*/\r
1090 write_json_traffic(json_traffic);\r
1091 }\r
1092\r
1093 /*-----------------------------------------------------------------*/\r
1094 printf("Writing statistics into HTML page %s ...\n", html);\r
1095 /*-----------------------------------------------------------------*/\r
1096 write_htmlandlogs(html, d,total, just_preview);\r
1097\r
1098 if(just_preview)\r
1099 {\r
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
1106 exit(0);\r
1107 } \r
1108\r
1109 i=0;\r
1110#ifdef DEBUG\r
1111 printf("%-22s %-15s mark\n","name","ip");\r
1112#endif\r
1113\r
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
1127 if(idxs)\r
1128 {\r
1129 char *buf;\r
1130 duplicate(ip->addr,buf);\r
1131 buf=index_id(ip->addr,32-idxtable_bitmask1); \r
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
1149#ifdef DEBUG\r
1150 printf("%-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
1151#endif\r
1152\r
1153 /* -------------------------------------------------------- mark download */\r
1154 \r
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
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
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
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
1169 sprintf(str, "-A %s -d %s/32 -o %s -j ACCEPT",\r
1170 chain_postrouting, ip->addr, lan);\r
1171 save_line(str);\r
1172\r
1173 /* -------------------------------------------------------- mark upload */\r
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
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
1179 sprintf(str, "-A %s -s %s/32 -o %s -j ACCEPT",\r
1180 chain_forward, ip->addr, wan);\r
1181 save_line(str);\r
1182\r
1183 if(ip->min)\r
1184 {\r
1185 /* -------------------------------------------------------- download class */\r
1186#ifdef DEBUG\r
1187 printf("(down: %dk-%dk ", ip->min, ip->max); \r
1188#endif\r
1189\r
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
1192 safe_run(str);\r
1193\r
1194 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
1195 {\r
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
1198 safe_run(str);\r
1199 }\r
1200\r
1201 if(filter_type == 1)\r
1202 {\r
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
1205 safe_run(str);\r
1206 }\r
1207\r
1208 /* -------------------------------------------------------- upload class */\r
1209#ifdef DEBUG\r
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
1212#endif\r
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
1220 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
1221 {\r
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
1224 safe_run(str);\r
1225 } \r
1226\r
1227 if(filter_type == 1)\r
1228 {\r
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
1231 safe_run(str);\r
1232 }\r
1233 \r
1234 if(f > 0)\r
1235 {\r
1236 fprintf(f, "%s %d\n", ip->addr, ip->mark);\r
1237 }\r
1238 }\r
1239 else\r
1240 {\r
1241#ifdef DEBUG\r
1242 printf("(sharing %s)\n", ip->sharing);\r
1243#endif\r
1244 }\r
1245 i++;\r
1246 }\r
1247 if(f > 0)\r
1248 {\r
1249 puts("done.");\r
1250 fclose(f);\r
1251 }\r
1252 \r
1253 if(idxs)\r
1254 {\r
1255 chain_forward = "forw_common";\r
1256 chain_postrouting = "post_common";\r
1257 }\r
1258 else\r
1259 {\r
1260 chain_forward = "FORWARD";\r
1261 chain_postrouting = "POSTROUTING";\r
1262 }\r
1263 /* -------------------------------- classify or reject free download */\r
1264 {\r
1265 char *final_chain = "DROP"; /* REJECT would be better, but it is impossible in mangle */\r
1266 if(free_min)\r
1267 {\r
1268 final_chain = "ACCEPT";\r
1269 }\r
1270 if(qos_proxy)\r
1271 {\r
1272 if(free_min)\r
1273 {\r
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
1276 save_line(str);\r
1277 }\r
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
1280 save_line(str);\r
1281 }\r
1282 if(free_min)\r
1283 {\r
1284 sprintf(str,"-A %s -o %s -j %s%d", chain_postrouting, lan, mark_iptables, 3);\r
1285 save_line(str);\r
1286 }\r
1287 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
1288 save_line(str);\r
1289 /* ------------------------------- classify or reject free upload */\r
1290 if(free_min)\r
1291 {\r
1292 sprintf(str,"-A %s -o %s -j %s%d", chain_forward, wan, mark_iptables, 3);\r
1293 save_line(str);\r
1294 }\r
1295 sprintf(str,"-A %s -o %s -j %s", chain_forward, wan, final_chain);\r
1296 save_line(str);\r
1297 }\r
1298\r
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
1304 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1305 tc, lan, parent, free_min, free_max,burst, lowest_priority);\r
1306 safe_run(str);\r
1307 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1308 tc, wan, parent, free_min, free_max, burst, lowest_priority);\r
1309 safe_run(str);\r
1310 /* tc SFQ */\r
1311 if(strcmpi(qos_leaf, "none"))\r
1312 {\r
1313 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, lan, qos_leaf);\r
1314 safe_run(str);\r
1315 \r
1316 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, wan, qos_leaf);\r
1317 safe_run(str);\r
1318 } \r
1319 /* tc handle 1 fw flowid */\r
1320 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, lan);\r
1321 safe_run(str);\r
1322\r
1323 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, wan);\r
1324 safe_run(str);\r
1325 }\r
1326 printf("Total IP count: %d\n", i);\r
1327 run_restore(); \r
1328 if(log_file)\r
1329 {\r
1330 fclose(log_file);\r
1331 }\r
1332 return 0;\r
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 0.207443 seconds and 4 git commands to generate.