Presunuti sekce "releases" do Downloads
[svn/Prometheus-QoS/.git] / prometheus.c
1
2 /* ============================================================= */
3 /* === Prometheus QoS - you can "steal fire" from your ISP === */
4 /* === "fair-per-IP" quality of service (QoS) utility === */
5 /* === requires Linux 2.4.x or 2.6.x with HTB support === */
6 /* === Copyright(C) 2005-2007 Michael Polak (xChaos) === */
7 /* === Credits: CZFree.Net, Martin Devera, Netdave, Aquarius === */
8 /* ============================================================= */
9
10 /* Modified: xChaos, 20070502
11 ludva, 20071227
12
13 Prometheus QoS is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2.1 of
16 the License, or (at your option) any later version.
17
18 Prometheus QoS is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with the Linux kernel source code; if not, write to
25 Michael Polak, Svojsikova 7, 169 00 Praha 6 Czech Republic */
26
27 #define STRLEN 256
28 #define FIRSTGROUPID 1024
29 #define MAX_GUARANTED_KBPS 2048
30 #undef DEBUG
31
32 #include "cll1.h"
33
34 const char *version="0.7.7"; /*0.7.9 will be last development, 0.8.0 first stable */
35
36 /* ======= Help screen is hopefuly self-documenting part of code :-) ======= */
37
38 void help(void)
39 {
40 puts("Command line switches:\n\
41 \n\
42 -?, --help this help screen\n\
43 -v, --version show version number of this utility and exit\n\
44 -c filename force alternative /etc/prometheus.conf filename\n\
45 -h filename force alternative /etc/hosts filename (overrides hosts keyword)\n\
46 -f just flush iptables and tc classes and exit (stop shaping)\n\
47 -9 emergency iptables flush (do not read data transfer statistics)\n\
48 -p just generate preview of data transfer statistics and exit\n\
49 -n no delay (overrides qos-free-delay keyword)\n\
50 -d dry run (preview tc and iptables commands on stdout)\n\
51 ");
52 }
53
54 /* === Configuraration file values defaults - stored in global variables ==== */
55
56 int filter_type=1; /*1 mark, 2 classify*/
57 char *mark="MARK";
58 char *mark_iptables="MARK --set-mark ";
59 int dry_run=0; /* preview - use puts() instead of system() */
60 char *config="/etc/prometheus.conf"; /* main configuration file */
61 char *hosts="/etc/hosts"; /* line bandwidth definition file */
62 char *tc="/sbin/tc"; /* requires tc with HTB support */
63 char *iptables="/usr/sbin/iptables"; /* requires iptables utility */
64 char *iptablessave="/usr/sbin/iptables-save"; /* new */
65 char *iptablesrestore="/usr/sbin/iptables-restore"; /* new */
66 char *iptablesfile="/var/spool/prometheus.iptables"; /* new; file for iptables-restore*/
67 char *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]";
68 FILE *iptables_file=NULL;
69 char *html="/var/www/traffic.html"; /* hall of fame filename */
70 char *preview="/var/www/preview.html"; /* hall of fame preview */
71 char *cmdlog="/var/log/prometheus"; /* command log filename */
72 char *credit="/var/run/prometheus.credit"; /* credit log file */
73 int enable_credit=1; /* enable credit file */
74 int use_credit=0; /* use credit file (if enabled)*/
75 char *log_dir="/var/www/html/logs/"; /* log directory pathname */
76 char *log_url="logs/"; /* log directory URL prefix */
77 char *title="Hall of Fame - Greatest Suckers"; /* hall of fame title */
78 int hall_of_fame=1; /* enable hall of fame */
79 char *lan="eth0"; /* LAN interface */
80 char *lan_medium="100Mbit"; /* 10Mbit/100Mbit ethernet */
81 char *wan="eth1"; /* WAN/ISP interface */
82 char *wan_medium="100Mbit"; /* 10Mbit/100Mbit ethernet */
83 char *qos_leaf="sfq perturb 5"; /* leaf discipline */
84 char *qos_free_zone=NULL; /* QoS free zone */
85 int qos_proxy=1; /* include proxy port to QoS */
86 int include_upload=1; /* upload+download=total traffic */
87 char *proxy_ip="192.168.1.1/32"; /* our IP with proxy port */
88 int proxy_port=3128; /* proxy port number */
89 long long int line=1024; /* WAN/ISP download in kbps */
90 long long int up=1024; /* WAN/ISP upload in kbps */
91 int free_min=32; /* minimum guaranted bandwidth for all undefined hosts */
92 int free_max=64; /* maximum allowed bandwidth for all undefined hosts */
93 int qos_free_delay=0; /* seconds to sleep before applying new QoS rules */
94 int digital_divide=2; /* controls digital divide weirdness ratio, 1...3 */
95 int max_nesting=3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */
96 int htb_r2q=1;
97 int burst=8; /* HTB burst (in kbits) */
98 int burst_main=64;
99 int burst_group=32;
100 int magic_priorities=8; /* number of priority levels (soft shaping) */
101 int magic_treshold=8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */
102 int keywordcount=0;
103
104 /* not yet implemented:
105 int fixed_packets=0; maximum number of pps per IP address (not class!)
106 int packet_limit=5; maximum number of pps to htn CEIL, not rate !!!
107 */
108 FILE *log_file=NULL;
109
110 char *kwd="via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */
111
112 const int idxtable_treshold1=24; /* this is no longer configurable */
113 const int idxtable_treshold2=12; /* this is no longer configurable */
114 const int idxtable_bitmask1=3; /* this is no longer configurable */
115 const int idxtable_bitmask2=3; /* this is no longer configurable */
116
117
118 /* not yet implemented:
119 -s start shaping! (keep data transfer statistics - but apply shaping)\n\
120 -r just reload configuration (...and keep data transfer statistics)\n\
121 */
122
123 /* ==== This is C<<1 stuff - learn C<<1 first! http://cll1.arachne.cz ==== */
124
125 struct IP
126 {
127 char *addr;
128 char *name;
129 char *sharing;
130 int min;
131 int desired;
132 int max;
133 int mark;
134 int prio;
135 int fixedprio;
136 int group;
137 unsigned long long direct;
138 unsigned long long proxy;
139 unsigned long long upload;
140 unsigned long long traffic;
141 unsigned long long credit;
142 unsigned long pktsup;
143 unsigned long pktsdown;
144 struct Keyword *keyword;
145 list(IP);
146 } *ips=NULL, *ip, *sharedip;
147
148 struct Group
149 {
150 int min;
151 int count;
152 int desired;
153 int id;
154 list(Group);
155 } *groups=NULL, *group;
156
157 struct Index
158 {
159 char *addr;
160 char *id;
161 struct Index *parent;
162 int bitmask;
163 int children;
164 list(Index);
165 } *idxs=NULL, *idx, *metaindex;
166
167 struct Keyword
168 {
169 char *key;
170
171 int asymetry_ratio; /* ratio for ADSL-like upload */
172 int asymetry_fixed; /* fixed treshold for ADSL-like upload */
173 int data_limit; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */
174 int prio_limit; /* soft shaping (qos): reduce HTB prio if max*prio_limit MB exceeded */
175 long fixed_limit; /* fixed data limit for setting lower HTB ceil */
176 long fixed_prio; /* fixed data lmit for setting lower HTB prio */
177 int reserve_min; /* bonus for nominal HTB rate bandwidth (in kbps) */
178 int reserve_max; /* malus for nominal HTB ceil (in kbps) */
179 // int divide_max; /* relative malus: new_ceil=rate+(old_ceil-rate)/divide_max */
180 // int htb_ceil_bonus_divide; /* relative bonus: new_ceil=old_ceil+old_ceil/htb_ceil_bonus_divide */
181 int default_prio; /* default HTB priority for this keyword */
182 char *html_color;
183 int ip_count;
184 char *leaf_discipline;
185
186 list(Keyword);
187 } *keyword,*defaultkeyword=NULL,*keywords=NULL;
188
189 /* Damned, this must be object oriented! This looks almost like constructor ;-) */
190
191 void TheIP(void)
192 {
193 create(ip,IP);
194 ip->name="";
195 ip->addr="";
196 ip->sharing=NULL;
197 ip->prio=1;
198 ip->fixedprio=0;
199 ip->mark=ip->min=ip->max=ip->desired=ip->credit=0;
200 ip->upload=ip->proxy=ip->direct=ip->traffic=0;
201 ip->pktsup=ip->pktsdown=0;
202 ip->keyword=keywords;
203 push(ip,ips);
204 }
205
206 /* ====== Iptables indexes are used to reduce complexity to log8(N) ===== */
207
208 char *very_ugly_ipv4_code(char *inip,int bitmask,int format_as_chainname)
209 {
210 /* warning: this function was debugged only for bitmask values 20,24,28 !!!*/
211 int dot=0,n;
212 char *ip,*outip,*outptr,*fmt;
213
214 duplicate(inip,ip);
215 /* debug printf("(%s,%d) -> ",ip,bitmask); */
216
217 if(ip && *ip && bitmask>=0 && bitmask<=32)
218 string(outip,strlen(ip)+10); /*fuck unicode? assertion: 10>strlen("_%d_%d") */
219 else
220 /* should never exit here */
221 return "undefined";
222 outptr=outip;
223 while(ip && *ip)
224 {
225 if(*ip=='.')
226 {
227 if(dot<(bitmask/8-1))
228 {
229 if(format_as_chainname)
230 *outptr='_';
231 else
232 *outptr='.';
233 outptr++;
234 dot++;
235 }
236 else
237 {
238 char *cutdot=strchr(ip+1,'.'); /*for bitmask<24*/
239 if(cutdot)*cutdot='\0';
240 if(format_as_chainname)
241 fmt="_%d_%d";
242 else
243 fmt=".%d";
244 if(bitmask%8)
245 n=atoi(ip+1)-atoi(ip+1)%(1<<(8-bitmask%8));
246 else
247 n=0;
248
249 /*debug printf("%d/%d => [_%d_%d]\n",atoi(ip+1),bitmask,n,bitmask); */
250 sprintf(outptr,fmt,n,bitmask);
251 if(!format_as_chainname) while(bitmask<24)
252 {
253 strcat(outip,".0");
254 bitmask+=8;
255 }
256 /* debug printf("[%s]\n",outip); */
257 return outip;
258 }
259 }
260 else
261 {
262 *outptr=*ip;
263 outptr++;
264 }
265 ip++;
266 }
267 /*should never exit here*/
268 *outptr='\0';
269 return outip;
270 }
271
272 char *hash_id(char *ip,int bitmask)
273 { return very_ugly_ipv4_code(ip,bitmask,1); }
274
275 char *subnet_id(char *ip,int bitmask)
276 { return very_ugly_ipv4_code(ip,bitmask,0); }
277
278 /* ================= Let's parse configuration file here =================== */
279
280 void reject_config_and_exit(char *filename)
281 {
282 printf("Configuration file %s rejected - abnormal exit.",filename);
283 exit(-1);
284 }
285
286 void get_config(char *config_filename)
287 {
288 char *cnf="mark";
289
290 printf("Configured keywords: ");
291 parse(config_filename)
292 {
293 option("keyword",kwd);
294 if(kwd)
295 {
296 printf("%s ",kwd);
297
298 create(keyword,Keyword);
299 keyword->key=kwd;
300 keyword->asymetry_ratio=1; /* ratio for ADSL-like upload */
301 keyword->asymetry_fixed=0; /* fixed treshold for ADSL-like upload */
302 keyword->data_limit=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */
303 keyword->prio_limit=4; /* soft shaping (qos): reduce HTB prio if max*prio_limit MB exceeded */
304 keyword->fixed_limit=0; /* fixed data limit for setting lower HTB ceil */
305 keyword->fixed_prio=0; /* fixed data limit for setting lower HTB prio */
306 keyword->reserve_min=8; /* bonus for nominal HTB rate bandwidth (in kbps) */
307 keyword->reserve_max=0; /* malus for nominal HTB ceil (in kbps) */
308 /* obsolete:
309 keyword->divide_max=0; relative malus: new_ceil=rate+(old_ceil-rate)/divide_max
310 keyword->htb_ceil_bonus_divide=0; relative bonus: new_ceil=old_ceil+old_ceil/htb_ceil_bonus_divide
311 */
312 keyword->default_prio=1;
313 keyword->html_color="000000";
314 keyword->ip_count=0;
315 keyword->leaf_discipline="";
316
317 push(keyword,keywords);
318 if(!defaultkeyword) defaultkeyword=keyword;
319 keywordcount++;
320
321 kwd=NULL;
322 }
323 else every(keyword,keywords)
324 {
325 int l=strlen(keyword->key);
326
327
328 if(!strncmp(keyword->key,_,l) && strlen(_)>l+2)
329 {
330 char *tmptr=_; /* <---- l+1 ----> */
331 _+=l+1; /* via-prometheus-asymetry-ratio, etc. */
332 ioption("asymetry-ratio",keyword->asymetry_ratio);
333 ioption("asymetry-treshold",keyword->asymetry_fixed);
334 ioption("magic-relative-limit",keyword->data_limit);
335 ioption("magic-relative-prio",keyword->prio_limit);
336 loption("magic-fixed-limit",keyword->fixed_limit);
337 loption("magic-fixed-prio",keyword->fixed_prio);
338 ioption("htb-default-prio",keyword->default_prio);
339 ioption("htb-rate-bonus",keyword->reserve_min);
340 ioption("htb-ceil-malus",keyword->reserve_max);
341 /* obsolete:
342 ioption("htb-ceil-divide",keyword->divide_max);
343 ioption("htb-ceil-bonus-divide",keyword->htb_ceil_bonus_divide);
344 */
345 option("leaf-discipline",keyword->leaf_discipline);
346 option("html-color",keyword->html_color);
347 _=tmptr;
348
349 if(keyword->data_limit || keyword->fixed_limit ||
350 keyword->prio_limit || keyword->fixed_prio)
351 use_credit=1;
352
353
354 }
355 }
356
357 option("tc",tc);
358 option("iptables",iptables);
359 option("iptables-save",iptablessave); /* new */
360 option("iptables-restore",iptablesrestore); /* new */
361 option("iptables-file",iptablesfile); /* new */
362 option("hosts",hosts);
363 option("lan-interface",lan);
364 option("wan-interface",wan);
365 option("lan-medium",lan_medium);
366 option("wan-medium",wan_medium);
367 lloption("wan-download",line);
368 lloption("wan-upload",up);
369 ioption("hall-of-fame-enable",hall_of_fame);
370 option("hall-of-fame-title",title);
371 option("hall-of-fame-filename",html);
372 option("hall-of-fame-preview",preview);
373 option("log-filename",cmdlog);
374 option("credit-filename",credit);
375 ioption("credit-enable",enable_credit);
376 option("log-traffic-directory",log_dir);
377 option("log-traffic-url-path",log_url);
378 option("qos-free-zone",qos_free_zone);
379 ioption("qos-free-delay",qos_free_delay);
380 ioption("qos-proxy-enable",qos_proxy);
381 option("qos-proxy-ip",proxy_ip);
382 option("htb-leaf-discipline",qos_leaf);
383 ioption("qos-proxy-port",proxy_port);
384 ioption("free-rate",free_min);
385 ioption("free-ceil",free_max);
386 ioption("htb-burst",burst);
387 ioption("htb-burst-main",burst_main);
388 ioption("htb-burst-group",burst_group);
389 ioption("htb-nesting-limit",max_nesting);
390 ioption("htb-r2q",htb_r2q);
391 ioption("magic-include-upload",include_upload);
392 ioption("magic-priorities",magic_priorities);
393 ioption("magic-treshold",magic_treshold);
394
395 option("filter-type", cnf);
396
397 /* not yet implemented:
398 ioption("magic-fixed-packets",fixed_packets);
399 ioption("magic-relative-packets",packet_limit);
400 */
401 }
402 fail
403 {
404 perror(config_filename);
405 puts("Warning - using built-in defaults instead ...");
406 }
407 done;
408 printf("\n");
409
410 /*leaf discipline for keywords*/
411 every(keyword,keywords)
412 {
413 if (!strcmpi(keyword->leaf_discipline, "")){
414 keyword->leaf_discipline = qos_leaf;
415 }
416 }
417
418 if (strcmpi(cnf, "mark")){
419 filter_type = 2;
420 mark = "CLASSIFY";
421 mark_iptables = "CLASSIFY --set-class 1:";
422 }else{
423 filter_type = 1;
424 mark = "MARK";
425 mark_iptables = "MARK --set-mark ";
426 }
427
428 /* are supplied values meaningful ?*/
429 if(line<=0 || up<=0)
430 {
431 puts("Illegal value of wan bandwidth: 0 kbps.");
432 reject_config_and_exit(config_filename);
433 }
434 }
435
436 /* ===================== traffic analyser - uses iptables ================ */
437
438 void get_traffic_statistics(void)
439 {
440 char *str,*cmd;
441 int downloadflag=0;
442
443 textfile(Pipe,str) *line,*lines=NULL;
444 string(str,STRLEN);
445 string(cmd,STRLEN);
446
447 sprintf(cmd,"%s -L -v -x -n -t mangle",iptables);
448 shell(cmd);
449 input(str,STRLEN)
450 {
451 create(line,Pipe);
452 line->str=str;
453 string(str,STRLEN);
454 append(line,lines);
455 }
456
457 every(line,lines)
458 {
459 int col, accept=0,proxyflag=0,valid=1,setchainname=0,commonflag=0;
460 unsigned long long traffic=0;
461 unsigned long pkts=0;
462 char *ipaddr=NULL,*ptr;
463
464 /* debug puts(line->str); */
465 valid_columns(ptr,line->str,' ',col)
466 if(valid) switch(col)
467 {
468 case 1: if(eq(ptr,"Chain"))
469 setchainname=1;
470 else if(eq(ptr,"pkts"))
471 valid=0;
472 else
473 sscanf(ptr,"%lu",&pkts);
474 break;
475 case 2: if(setchainname)
476 {
477 if(!strncmp(ptr,"post_",5) || eq(ptr,"POSTROUTING"))
478 downloadflag=1;
479 else
480 if(!strncmp(ptr,"forw_",5) || eq(ptr,"FORWARD"))
481 downloadflag=0;
482
483 if(eq(ptr,"post_common") || eq(ptr,"forw_common"))
484 commonflag=1;
485 }
486 else
487 sscanf(ptr,"%Lu",&traffic); traffic+=(1<<19); traffic>>=20;
488 break;
489 case 3: if((strncmp(ptr,"post_",5) && strncmp(ptr,"forw_",5)) || commonflag)
490 accept=eq(ptr,mark);
491 /*if (filter_type==1) accept=eq(ptr,"MARK"); else accept=eq(ptr,"CLASSIFY");*/
492 break;
493 case 8: if(downloadflag)
494 {
495 if(strstr(proxy_ip,ptr))proxyflag=1;
496 }
497 else
498 ipaddr=ptr;
499 break;
500 case 9: if(downloadflag)ipaddr=ptr;break;
501 }
502
503 if(accept && traffic>0 && ipaddr)
504 {
505 if(proxyflag)printf("(proxy) ");
506 else if(!downloadflag) printf("(upload) ");
507 printf("IP %s: %Lu M (%ld pkts)\n", ipaddr, traffic, pkts);
508 find(ip,ips,eq(ip->addr,ipaddr));
509 else
510 {
511 TheIP();
512 ip->addr=ipaddr;
513 if(eq(ip->addr,"0.0.0.0/0"))
514 {
515 ip->name="(unregistered)";
516 ip->min=free_min;
517 ip->max=ip->desired=free_max;
518 }
519 }
520
521 if(downloadflag)
522 {
523 if(proxyflag)
524 ip->proxy=traffic;
525 else
526 ip->traffic+=traffic;
527 ip->direct=ip->traffic-ip->upload-ip->proxy;
528 ip->pktsdown=pkts;
529 }
530 else
531 {
532 ip->upload=traffic;
533 ip->pktsup=pkts;
534 if(include_upload)
535 ip->traffic+=traffic;
536 else
537 if(traffic>ip->traffic)
538 ip->traffic=traffic;
539 }
540 }
541 }
542
543
544 free(cmd);
545 }
546
547 /* ========== This function executes, logs OR ALSO prints command ========== */
548
549 void safe_run(char *cmd)
550 {
551 if(dry_run) printf("\n=>%s\n",cmd); else system(cmd);
552 if(log_file) fprintf(log_file,"%s\n",cmd);
553 }
554
555 void save_line(char *line)
556 {
557 fprintf(iptables_file,"%s\n",line);
558 }
559
560 void run_restore(void)
561 {
562 char *restor, *str;
563 string(restor,STRLEN);
564
565 save_line("COMMIT");
566 fclose(iptables_file);
567 if(dry_run) {
568 parse(iptablesfile)
569 {
570 str=_;
571 printf("%s\n", str);
572 }done;
573 }else{
574 //sprintf(restor,"cat %s",iptablesfile); else
575 sprintf(restor,"%s <%s",iptablesrestore, iptablesfile);
576 system(restor);
577 };
578
579 free(restor);
580 }
581
582 /* == This function strips extra characters after IP address and stores it = */
583
584 void parse_ip(char *str)
585 {
586 char *ptr=str,*ipaddr=NULL,*ipname=NULL;;
587
588 while(*ptr && *ptr!=' ' && *ptr!=9)
589 ptr++;
590
591 *ptr=0;
592 ipaddr=str;
593 ptr++;
594 while(*ptr && (*ptr==' ' || *ptr==9))
595 ptr++;
596 ipname=ptr;
597 while(*ptr && *ptr!=' ' && *ptr!=9)
598 ptr++;
599 *ptr=0;
600
601 find(ip,ips,eq(ip->addr,ipaddr)); else TheIP();
602 ip->addr=ipaddr;
603 ip->name=ipname;
604 }
605
606 char *parse_datafile_line(char *str)
607 {
608 char *ptr=strchr(str,' ');
609
610 if(ptr)
611 {
612 *ptr=0;
613 ptr++;
614 return ptr;
615 }
616 else
617 return NULL;
618 }
619
620 /*-----------------------------------------------------------------*/
621 /* Are you looking for int main (int argc, char **argv) ? :-)) */
622 /*-----------------------------------------------------------------*/
623
624 program
625 {
626 int i=0;
627 FILE *f=NULL;
628 char *str, *ptr, *d;
629 char *substring;
630 int class_count=0,ip_count=0;
631 int parent=1;
632 int just_flush=0;
633 int nodelay=0;
634 int just_preview=0; /* preview - generate just stats */
635 char *chain_forward, *chain_postrouting;
636 char *althosts=NULL;
637
638 printf("\n\
639 Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\
640 Version %s - Copyright (C)2005-2007 Michael Polak (xChaos)\n\
641 iptables-restore & burst tunning & classify modification 0.7d by Ludva\n\
642 Credits: CZFree.Net, Martin Devera, Netdave, Aquarius\n\n",version);
643
644 /*----- Boring... we have to check command line options first: ----*/
645
646 arguments
647 {
648 argument("-c") { nextargument(config); }
649 argument("-h") { nextargument(althosts);}
650 argument("-d") { dry_run=1; }
651 argument("-f") { just_flush=1; }
652 argument("-9") { just_flush=9; }
653 argument("-p") { just_preview=1; }
654 argument("-n") { nodelay=1; }
655 argument("-?") { help(); exit(0); }
656 argument("--help") { help(); exit(0); }
657 argument("-v") { exit(0); }
658 argument("--version") { exit(0); }
659 }
660
661 if(dry_run)
662 puts("*** THIS IS JUST DRY RUN ! ***\n");
663
664 date(d); /* this is typical cll1.h macro */
665
666 /*-----------------------------------------------------------------*/
667 printf("Parsing configuration file %s ...\n", config);
668 /*-----------------------------------------------------------------*/
669 get_config(config);
670
671 if(althosts) hosts=althosts;
672
673 if(just_flush<9)
674 {
675 /*-----------------------------------------------------------------*/
676 puts("Parsing iptables verbose output ...");
677 /*-----------------------------------------------------------------*/
678 get_traffic_statistics();
679 }
680
681 /*-----------------------------------------------------------------*/
682 printf("Parsing class defintion file %s ...\n", hosts);
683 /*-----------------------------------------------------------------*/
684 int groupidx = FIRSTGROUPID;
685 parse(hosts)
686 {
687 str=_;
688
689 if(*str<'0' || *str>'9')
690 continue;
691
692 //Does this IP share QoS class with some other ?
693 substring=strstr(str,"sharing-");
694 if(substring)
695 {
696 substring+=8; //"sharing-"
697 parse_ip(str);
698 ip_count++;
699 ip->sharing=substring;
700 ip->keyword=defaultkeyword; /* settings for default keyword */
701 while(*substring && *substring!='\n')
702 substring++;
703 *substring=0;
704 }
705 else
706 {
707 //Do we have to create new QoS class for this IP ?
708
709 find(keyword,keywords,(substring=strstr(str,keyword->key)))
710 {
711 parse_ip(str);
712 ip_count++;
713 ip->keyword=keyword;
714 keyword->ip_count++;
715 ip->prio=keyword->default_prio;
716 substring+=strlen(keyword->key)+1;
717 ptr=substring;
718 while(*ptr && *ptr!='-')
719 ptr++;
720 if(*ptr=='-')
721 {
722 *ptr=0;
723 ip->max=ip->desired=atoi(ptr+1);
724 }
725 ip->min=atoi(substring);
726 if(ip->min<=0)
727 {
728 puts("Illegal value of minimum bandwidth: 0 kbps.");
729 reject_config_and_exit(hosts);
730 }
731 if(ip->max<=ip->min)
732 {
733 ip->fixedprio=1;
734 ip->max=ip->min+ip->keyword->reserve_min;
735 }
736 else
737 {
738 ip->max-=ip->keyword->reserve_max;
739
740 /*
741 if(ip->keyword->divide_max>1)
742 ip->max=ip->min+(ip->max-ip->min)/ip->keyword->divide_max;
743 if(ip->keyword->htb_ceil_bonus_divide>0)
744 ip->max+=ip->max/ip->keyword->htb_ceil_bonus_divide;
745 */
746 if(ip->max<ip->min)
747 ip->max=ip->min;
748 }
749 ip->mark=MAX_GUARANTED_KBPS+1+class_count++;
750
751 find(group,groups,group->min==ip->min)
752 {
753 group->count++;
754 group->desired+=ip->min;
755 ip->group = group->id;
756 }
757 else
758 {
759 create(group,Group);
760 group->min=ip->min;
761 group->id = groupidx++;
762 ip->group = group->id;
763
764 if(group->min<8) group->min=8;
765 /* Warning - this is maybe because of primitive tc namespace, can be fixed */
766 /* it is because class IDs are derived from min. bandwidth. - xCh */
767 //if(group->min>MAX_GUARANTED_KBPS) group->min=MAX_GUARANTED_KBPS;
768
769 group->count=1;
770 group->desired=ip->min;
771 insert(group,groups,desc_order_by,min);
772 }
773 }//endif keyword-
774 }//endif sharing-
775 }
776 fail
777 {
778 perror(hosts);
779 exit(-1);
780 }
781 done;
782
783 /*-----------------------------------------------------------------*/
784 /* cll1.h - let's allocate brand new character buffer... */
785 /*-----------------------------------------------------------------*/
786 string(str,STRLEN);
787
788 /*-----------------------------------------------------------------*/
789 puts("Resolving shared connections ...");
790 /*-----------------------------------------------------------------*/
791 search(ip,ips,ip->sharing)
792 {
793 search(sharedip,ips,eq(sharedip->name,ip->sharing))
794 {
795 sharedip->traffic+=ip->traffic;
796 ip->traffic=0;
797 ip->mark=sharedip->mark;
798 break;
799 }
800 if(!sharedip)
801 printf("Unresolved shared connection: %s %s sharing-%s\n",ip->addr,ip->name,ip->sharing);
802 }
803
804 if(enable_credit && just_flush<9)
805 {
806 /*-----------------------------------------------------------------*/
807 printf("Parsing credit file %s ...\n", credit);
808 /*-----------------------------------------------------------------*/
809 parse(credit)
810 {
811 ptr=parse_datafile_line(_);
812 if(ptr)
813 {
814 find(ip,ips,eq(ip->addr,_))
815 sscanf(ptr,"%Lu",&(ip->credit));
816 }
817 }
818 done;
819 }
820
821 if(!just_preview)
822 {
823 /*-----------------------------------------------------------------*/
824 puts("Initializing iptables and tc classes ...");
825 /*-----------------------------------------------------------------*/
826
827 iptables_file=fopen(iptablesfile,"w");
828 if (iptables_file == NULL) {
829 puts("Cannot open iptablesfile!");
830 exit(-1);
831 }
832
833 log_file=fopen(cmdlog,"w");
834 if (log_file == NULL) {
835 puts("Cannot open logfile!");
836 exit(-1);
837 }
838
839 save_line(iptablespreamble);
840 run_restore();
841
842 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,lan);
843 safe_run(str);
844
845 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,wan);
846 safe_run(str);
847
848 iptables_file=fopen(iptablesfile,"w");
849 save_line(iptablespreamble);
850
851 if(qos_free_zone && *qos_free_zone!='0')
852 {
853 char *chain;
854
855 sprintf(str,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone, wan);
856 save_line(str);
857
858 if(qos_proxy)
859 {
860 save_line(":post_noproxy - [0:0]");
861 sprintf(str,"-A POSTROUTING -p ! tcp -o %s -j post_noproxy", lan);
862 save_line(str);
863 sprintf(str,"-A POSTROUTING -s ! %s -o %s -j post_noproxy", proxy_ip, lan);
864 save_line(str);
865 sprintf(str,"-A POSTROUTING -s %s -p tcp --sport ! %d -o %s -j post_noproxy", proxy_ip, proxy_port, lan);
866 save_line(str);
867
868 chain="post_noproxy";
869 }
870 else
871 chain="POSTROUTING";
872
873 sprintf(str,"-A %s -s %s -o %s -j ACCEPT", chain, qos_free_zone, lan);
874 save_line(str);
875 }
876
877 if(ip_count>idxtable_treshold1 && !just_flush)
878 {
879 int idxcount=0, bitmask=32-idxtable_bitmask1; /* default net mask: 255.255.255.240 */
880 char *subnet, *buf;
881 /*-----------------------------------------------------------------*/
882 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count);
883 /*-----------------------------------------------------------------*/
884
885 save_line(":post_common - [0:0]");
886 save_line(":forw_common - [0:0]");
887
888 search(ip,ips,ip->addr && *(ip->addr) && !eq(ip->addr,"0.0.0.0/0"))
889 {
890 buf=hash_id(ip->addr,bitmask);
891 find(idx,idxs,eq(idx->id,buf))
892 idx->children++;
893 else
894 {
895 create(idx,Index);
896 idx->addr=ip->addr;
897 idx->id=buf;
898 idx->bitmask=bitmask;
899 idx->parent=NULL;
900 idx->children=0;
901 idxcount++;
902 push(idx,idxs);
903 }
904 }
905
906 /* brutal perfomance optimalization */
907 while(idxcount>idxtable_treshold2 && bitmask>2*idxtable_bitmask2)
908 {
909 bitmask-=idxtable_bitmask2;
910 idxcount=0;
911 search(idx,idxs,idx->parent==NULL)
912 {
913 buf=hash_id(idx->addr,bitmask);
914 find(metaindex,idxs,eq(metaindex->id,buf))
915 metaindex->children++;
916 else
917 {
918 create(metaindex,Index);
919 metaindex->addr=idx->addr;
920 metaindex->id=buf;
921 metaindex->bitmask=bitmask;
922 metaindex->parent=NULL;
923 metaindex->children=0;
924 idxcount++;
925 push(metaindex,idxs);
926 }
927 idx->parent=metaindex;
928 }
929 }
930
931 /* this should slightly optimize throughout ... */
932 sort(idx,idxs,desc_order_by,children);
933 sort(idx,idxs,order_by,bitmask);
934
935 i=0;
936 every(idx,idxs)
937 {
938 subnet=subnet_id(idx->addr,idx->bitmask);
939 printf("%d: %s/%d\n",++i,subnet,idx->bitmask);
940
941 sprintf(str,":post_%s - [0:0]", idx->id);
942 save_line(str);
943
944 sprintf(str,":forw_%s - [0:0]", idx->id);
945 save_line(str);
946
947 if(idx->parent)
948 {
949 string(buf,strlen(idx->parent->id)+6);
950 sprintf(buf,"post_%s",idx->parent->id);
951 }
952 else
953 buf="POSTROUTING";
954
955 sprintf(str,"-A %s -d %s/%d -o %s -j post_%s", buf, subnet, idx->bitmask, lan, idx->id);
956 save_line(str);
957
958 sprintf(str,"-A %s -d %s/%d -o %s -j post_common", buf, subnet, idx->bitmask, lan);
959 save_line(str);
960
961 if(idx->parent)
962 {
963 string(buf,strlen(idx->parent->id)+6);
964 sprintf(buf,"forw_%s",idx->parent->id);
965 }
966 else
967 buf="FORWARD";
968
969 sprintf(str,"-A %s -s %s/%d -o %s -j forw_%s", buf, subnet, idx->bitmask, wan, idx->id);
970 save_line(str);
971
972 sprintf(str,"-A %s -s %s/%d -o %s -j forw_common", buf, subnet, idx->bitmask, wan);
973 save_line(str);
974 }
975 printf("Total indexed iptables chains created: %d\n", i);
976
977 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);
978 save_line(str);
979
980 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);
981 save_line(str);
982 }
983
984 }
985
986 if(just_flush)
987 {
988 fclose(iptables_file);
989 if (log_file) fclose(log_file);
990 puts("Just flushed iptables and tc classes - now exiting ...");
991 exit(0);
992 }
993
994 if(!just_preview)
995 {
996 if(!dry_run && !nodelay && qos_free_delay)
997 {
998 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay);
999 sleep(qos_free_delay);
1000 }
1001
1002 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc,lan,htb_r2q);
1003 safe_run(str);
1004
1005 sprintf(str,"%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio 0",tc,lan,lan_medium,lan_medium,burst_main);
1006 safe_run(str);
1007
1008 sprintf(str,"%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio 0",tc,lan,line,line,burst_main);
1009 safe_run(str);
1010
1011 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc,wan,htb_r2q);
1012 safe_run(str);
1013
1014 sprintf(str,"%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio 0",tc,wan,wan_medium,wan_medium,burst_main);
1015 safe_run(str);
1016
1017 sprintf(str,"%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio 0",tc,wan,up,up,burst_main);
1018 safe_run(str);
1019 }
1020
1021 /*-----------------------------------------------------------------*/
1022 puts("Locating suckers and generating root classes ...");
1023 /*-----------------------------------------------------------------*/
1024 sort(ip,ips,desc_order_by,traffic);
1025
1026
1027 /*-----------------------------------------------------------------*/
1028 /* sub-scope - local variables */
1029 {
1030 long long int rate=line;
1031 long long int max=line;
1032 int group_count=0;
1033 FILE *credit_file=NULL;
1034
1035 if(!just_preview && !dry_run && enable_credit) credit_file=fopen(credit,"w");
1036
1037 every(group,groups)
1038 {
1039 if(!just_preview)
1040 {
1041
1042 //download
1043 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %Ldkbit ceil %Ldkbit burst %dk prio 1 #down desired %d",
1044 tc, lan, parent, group->id, rate, max, burst_group, group->desired);
1045 safe_run(str);
1046
1047 //upload
1048 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %Ldkbit ceil %Ldkbit burst %dk prio 1 #up desired %d",
1049 tc, wan, parent, group->id, rate*up/line, max*up/line, burst_group, group->desired);
1050 safe_run(str);
1051 }
1052
1053 if(group_count++<max_nesting) parent=group->id;
1054
1055 rate-=digital_divide*group->min;
1056 if(rate<group->min)rate=group->min;
1057
1058 /*shaping of aggresive downloaders, with credit file support */
1059 if(use_credit)
1060 {
1061 int group_rate=group->min, priority_sequence=magic_priorities+1;
1062
1063 search(ip, ips, ip->min==group->min && ip->max>ip->min)
1064 {
1065 if(ip->keyword->data_limit>0 &&
1066 ip->traffic>ip->credit+
1067 (ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))
1068 && !ip->fixedprio)
1069 {
1070 if(group_rate<ip->max) ip->max=group_rate;
1071 group_rate+=magic_treshold;
1072 ip->prio=magic_priorities+2;
1073 if(ip->prio<3) ip->prio=3;
1074 }
1075 else
1076 {
1077 if(ip->traffic>ip->credit+
1078 (ip->min*ip->keyword->prio_limit+(ip->keyword->fixed_prio<<20)) &&
1079 !ip->fixedprio)
1080 {
1081 ip->prio=priority_sequence--;
1082 if(ip->prio<2) ip->prio=2;
1083 }
1084
1085 if(credit_file)
1086 {
1087 unsigned long long lcredit=0;
1088 if((ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))>ip->traffic)
1089 lcredit=(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))-ip->traffic;
1090 fprintf(credit_file,"%s %Lu\n",ip->addr,lcredit);
1091 }
1092 }
1093 }
1094
1095 }
1096 }
1097 if(credit_file)fclose(credit_file);
1098 }
1099
1100 if(just_preview)
1101 {
1102 f=fopen(preview,"w");
1103 ptr=preview;
1104 }
1105 else if(!dry_run && !just_flush)
1106 {
1107 /*-----------------------------------------------------------------*/
1108 printf("Writing data transfer database ...\n");
1109 /*-----------------------------------------------------------------*/
1110 f=fopen("/var/run/prometheus.previous","w");
1111 if(f)
1112 {
1113 search(ip,ips,ip->traffic || ip->direct || ip->proxy ||ip->upload)
1114 fprintf(f,"%s %Lu %Lu %Lu %Lu\n",ip->addr,ip->traffic,ip->direct,ip->proxy,ip->upload);
1115 fclose(f);
1116 }
1117
1118 f=fopen(html,"w");
1119 ptr=html;
1120 }
1121
1122 if(f)
1123 {
1124 int total=0;
1125 int count=1;
1126 i=0;
1127
1128 /*-----------------------------------------------------------------*/
1129 printf("Sorting data and generating statistics page %s ...\n",ptr);
1130 /*-----------------------------------------------------------------*/
1131
1132 fputs("<table border>\n<tr><th align=\"right\">#</th><th align=\"right\">group</th><th align=\"right\">IPs</th><th align=\"right\">requested</th>\n",f);
1133 fprintf(f,"<th colspan=\"%d\">data limits</th>\n",keywordcount);
1134 fputs("</tr>\n",f);
1135 every(group,groups)
1136 {
1137 #ifdef DEBUG
1138 printf("%d k group: %d bandwidth requested: %d k\n",group->min,group->count,group->desired);
1139 #endif
1140 fprintf(f,"<tr><td align=\"right\">%d</td><td align=\"right\">%d k</td>",count,group->min);
1141 fprintf(f,"<td align=\"right\">%d</td><td align=\"right\">%d k</td>",group->count,group->desired);
1142
1143 every(keyword,keywords)
1144 fprintf(f,"<td align=\"right\"><font color=\"#%s\">%d M</font></td>",keyword->html_color,group->min*keyword->data_limit);
1145
1146 i+=group->desired;
1147 total+=group->count;
1148 count++;
1149 }
1150 #ifdef DEBUG
1151 printf("Total groups: %d Total bandwidth requested: %d k\nAGGREGATION: 1/%d\n",count,i,i/line);
1152 #endif
1153 fprintf(f,"<tr><th colspan=\"2\" align=\"left\">Line %Ld k</td>",line);
1154 fprintf(f,"<th align=\"right\">%d</td><th align=\"right\">%d k</td>",total,i);
1155
1156 every(keyword,keywords)
1157 fprintf(f,"<th align=\"right\">%d IPs</th>",keyword->ip_count);
1158
1159 fprintf(f,"</tr><tr><th colspan=\"4\">Aggregation 1/%d</th>\n",(int)(0.5+i/line));
1160 fprintf(f,"<th colspan=\"%d\">%d traffic classes</th></tr>\n",keywordcount,total);
1161
1162 fputs("</table>\n",f);
1163 }
1164 else if(!dry_run && !just_flush)
1165 perror(html);
1166
1167 i=1;
1168 if(f)
1169 {
1170 unsigned long long total=0, total_direct=0, total_proxy=0, total_upload=0, tmp_sum=0;
1171 int active_classes=0;
1172 int colspan;
1173 FILE *iplog;
1174 struct Sum {unsigned long long l; int i; list(Sum);} *sum,*sums=NULL;
1175
1176 if(qos_proxy)
1177 colspan=12;
1178 else
1179 colspan=11;
1180
1181 fprintf(f,"<p><table border>\n<tr><th colspan=\"%d\">%s",colspan,title);
1182 fprintf(f," (%s)</th></tr>\n", d);
1183 fputs("<tr><td align=\"right\">#</td><td>hostname</td>\
1184 <td align=\"right\">credit</td>\
1185 <td align=\"right\">limit</td>\
1186 <td align=\"right\">total</td>\
1187 <td align=\"right\">direct</td>\n",f);
1188 if(qos_proxy)
1189 fputs("<td align=\"right\">proxy</td>\n",f);
1190 fputs("<td align=\"right\">upload</td>\
1191 <td align=\"right\">minimum</td>\
1192 <td align=\"right\">desired</td>\
1193 <td align=\"right\">maximum</td>\
1194 <td>prio</td></tr>\n",f);
1195
1196 every(ip,ips)
1197 {
1198 char *f1="", *f2="";
1199 if(ip->max<ip->desired)
1200 {
1201 f1="<font color=\"red\">";
1202 f2="</font>";
1203 }
1204 else if(ip->prio>1)
1205 {
1206 f1="<font color=\"brown\">";
1207 f2="</font>";
1208 }
1209
1210 #ifdef DEBUG
1211 printf("%03d. %-22s %10Lu (%d/%d)\n",i ,ip->name, ip->traffic, ip->min, ip->max);
1212 #endif
1213 fprintf(f,"<tr><td align=\"right\"><a name=\"%s\"></a>%d</td><td><a href=\"%s%s.log\">%s</a></td><td align=\"right\">%Lu M</td>\n",
1214 ip->name, i, log_url, ip->name, ip->name, ip->credit);
1215 fprintf(f,"<td align=\"right\"><font color=\"#%s\">%Lu M</font></td>",ip->keyword->html_color,ip->credit+(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20)));
1216 fprintf(f,"<td align=\"right\">%s%Lu M%s</td><td align=\"right\">%Lu M</td>\n", f1, ip->traffic, f2, ip->direct);
1217 if(qos_proxy)
1218 fprintf(f,"<td align=\"right\">%Lu M</td>\n", ip->proxy);
1219 fprintf(f,"<td align=\"right\">%Lu M</td>\n", ip->upload);
1220 fprintf(f,"<td align=\"right\">%d k</td><td align=\"right\">%d k</td><td align=\"right\">%s%d k%s</td><td>%s%d%s</td></tr>\n",ip->min,ip->desired,f1,ip->max,f2,f1,ip->prio,f2);
1221 total+=ip->traffic;
1222 total_direct+=ip->direct;
1223 total_proxy+=ip->proxy;
1224 total_upload+=ip->upload;
1225 if(ip->traffic>0)
1226 {
1227 active_classes++;
1228 tmp_sum+=ip->traffic;
1229 create(sum,Sum);
1230 sum->l=tmp_sum;
1231 sum->i=active_classes;
1232 insert(sum,sums,order_by,i);
1233 }
1234
1235 i++;
1236
1237 if(!just_preview)
1238 {
1239 sprintf(str,"%s%s.log",log_dir,ip->name);
1240 iplog=fopen(str,"a");
1241 if(iplog)
1242 {
1243 fprintf(iplog,"%ld\t%s\t%Lu\t%Lu\t%Lu\t%Lu\t%s",time(NULL),ip->name,ip->traffic, ip->direct, ip->proxy, ip->upload,d);
1244 fclose(iplog);
1245 }
1246 }
1247
1248 }
1249 fprintf(f,"<tr><th colspan=\"4 \"align=\"left\">SUMMARY:</td>");
1250 fprintf(f,"<th align=\"right\">%Lu M</th>\
1251 <th align=\"right\">%Lu M</th>\n", total, total_direct);
1252 if(qos_proxy)
1253 fprintf(f,"<th align=\"right\">%Lu M</th>\n", total_proxy);
1254 fprintf(f,"<th align=\"right\">%Lu M</th>", total_upload);
1255 fputs("<td colspan=\"4\"></td></th>\n</table>\n",f);
1256
1257 if(active_classes>10)
1258 {
1259 fputs("<a name=\"erp\"></a><p><table border><tr><th colspan=\"4\">Enterprise Research and Planning (ERP)</th></tr>\n",f);
1260 fputs("<tr><td colspan=\"2\">Active Classes</td><td colspan=\"2\">Data transfers</td></tr>\n",f);
1261 find (sum,sums,sum->l>=total/4)
1262 fprintf(f,"<tr><td>Top %d</td><td align=\"right\">%d %%</td><td align=\"right\">%Lu M</td><td align=\"right\">%Ld %%</td></tr>\n",sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total);
1263 find (sum,sums,sum->i==10)
1264 fprintf(f,"<tr><td>Top 10</td><td align=\"right\">%d %%</td><td align=\"right\">%Lu M</td><td align=\"right\">%Ld %%</td></tr>\n",(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total);
1265 find (sum,sums,sum->l>=total/2)
1266 fprintf(f,"<tr><td>Top %d</td><td align=\"right\">%d %%</td><td align=\"right\">%Lu M</td><td align=\"right\">%Ld %%</td></tr>\n",sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total);
1267 find (sum,sums,sum->i>=(active_classes+3)/4)
1268 fprintf(f,"<tr><td>Top %d</td><td align=\"right\">%d %%</td><td align=\"right\">%Lu M</td><td align=\"right\">%Ld %%</td></tr>\n",sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total);
1269 find (sum,sums,sum->i>=(active_classes+1)/2)
1270 fprintf(f,"<tr><td>Top %d</td><td align=\"right\">%d %%</td><td align=\"right\">%Lu M</td><td align=\"right\">%Ld %%</td></tr>\n",sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total);
1271 fprintf(f,"<tr><th align=\"left\">All %d</th><th align=\"right\">100 %%</th><th align=\"right\">%Lu M</th><th align=\"right\">100 %%</th></tr>\n",active_classes,total);
1272 fputs("</table>\n",f);
1273 }
1274 fprintf(f,"<small>Statistics generated by Prometheus QoS version %s<br>GPL+Copyright(C)2005 Michael Polak, <a href=\"http://www.arachne.cz/\">Arachne Labs</a></small>\n",version);
1275 fclose(f);
1276 }
1277
1278 if(just_preview)
1279 {
1280 puts("Statistics preview generated (-p switch) - now exiting ...");
1281 exit(0);
1282 }
1283
1284 /*-----------------------------------------------------------------*/
1285 puts("Generating iptables and tc classes ...");
1286 /*-----------------------------------------------------------------*/
1287
1288 i=0;
1289 printf("%-22s %-15s mark\n","name","ip");
1290 search(ip,ips,ip->mark>0)
1291 {
1292
1293 if(idxs)
1294 {
1295 char *buf;
1296 duplicate(ip->addr,buf);
1297 buf=hash_id(ip->addr,32-idxtable_bitmask1);
1298
1299 string(chain_forward,6+strlen(buf));
1300 strcpy(chain_forward,"forw_");
1301 strcat(chain_forward,buf);
1302
1303 string(chain_postrouting,6+strlen(buf));
1304 strcpy(chain_postrouting,"post_");
1305 strcat(chain_postrouting,buf);
1306
1307 free(buf);
1308 }
1309 else
1310 {
1311 chain_forward="FORWARD";
1312 chain_postrouting="POSTROUTING";
1313 }
1314
1315 printf("%-22s %-16s %04d ", ip->name, ip->addr, ip->mark);
1316
1317 /* -------------------------------------------------------- mark download */
1318
1319 sprintf(str,"-A %s -d %s/32 -o %s -j %s%d",chain_postrouting,ip->addr,lan,mark_iptables,ip->mark);
1320 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/
1321 /* -m limit --limit 1/s */
1322 save_line(str);
1323
1324 if(qos_proxy)
1325 {
1326 sprintf(str,"-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",chain_postrouting,proxy_ip,proxy_port,ip->addr,lan,mark_iptables,ip->mark);
1327 /*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);*/
1328 save_line(str);
1329 }
1330
1331 sprintf(str,"-A %s -d %s/32 -o %s -j ACCEPT",chain_postrouting,ip->addr,lan);
1332 save_line(str);
1333
1334 /* -------------------------------------------------------- mark upload */
1335 sprintf(str,"-A %s -s %s/32 -o %s -j %s%d",chain_forward,ip->addr,wan,mark_iptables,ip->mark);
1336 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/
1337 save_line(str);
1338
1339 sprintf(str,"-A %s -s %s/32 -o %s -j ACCEPT",chain_forward,ip->addr,wan);
1340 save_line(str);
1341
1342 if(ip->min)
1343 {
1344 /* -------------------------------------------------------- download class */
1345 printf("(down: %dk-%dk ", ip->min, ip->max);
1346
1347 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);
1348 safe_run(str);
1349
1350 if (strcmpi(ip->keyword->leaf_discipline, "none")){
1351 sprintf(str,"%s qdisc add dev %s parent 1:%d handle %d %s", tc, lan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/
1352 safe_run(str);
1353 }
1354
1355 if (filter_type == 1){
1356 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d", tc, lan, ip->mark, ip->mark);
1357 safe_run(str);
1358 }
1359
1360 /* -------------------------------------------------------- upload class */
1361 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),
1362 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));
1363
1364 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",
1365 tc, wan, ip->group, ip->mark,
1366 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),
1367 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);
1368 safe_run(str);
1369
1370 if (strcmpi(ip->keyword->leaf_discipline, "none")){
1371 sprintf(str,"%s qdisc add dev %s parent 1:%d handle %d %s",tc, wan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/
1372 safe_run(str);
1373 }
1374
1375 if (filter_type == 1){
1376 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",tc, wan, ip->mark, ip->mark);
1377 safe_run(str);
1378 }
1379 }
1380 else
1381 printf("(sharing %s)\n", ip->sharing);
1382 i++;
1383 }
1384
1385
1386 if(idxs)
1387 {
1388 chain_forward="forw_common";
1389 chain_postrouting="post_common";
1390 }
1391 else
1392 {
1393 chain_forward="FORWARD";
1394 chain_postrouting="POSTROUTING";
1395 }
1396
1397 /* -------------------------------------------------------- mark download */
1398
1399 if(qos_proxy)
1400 {
1401 sprintf(str,"-A %s -s %s -p tcp --sport %d -o %s -j MARK --set-mark 3",chain_postrouting,proxy_ip,proxy_port,lan);
1402 save_line(str);
1403 sprintf(str,"-A %s -s %s -p tcp --sport %d -o %s -j ACCEPT",chain_postrouting,proxy_ip,proxy_port,lan);
1404 save_line(str);
1405 }
1406 sprintf(str,"-A %s -o %s -j MARK --set-mark 3",chain_postrouting,lan);
1407 save_line(str);
1408 sprintf(str,"-A %s -o %s -j ACCEPT",chain_postrouting,lan);
1409 save_line(str);
1410
1411 /* -------------------------------------------------------- mark upload */
1412 sprintf(str,"-A %s -o %s -j MARK --set-mark 3",chain_forward,wan);
1413 save_line(str);
1414 sprintf(str,"-A %s -o %s -j ACCEPT",chain_forward,wan);
1415 save_line(str);
1416
1417 printf("Total IP count: %d\n", i);
1418
1419 /* ---------------------------------------- tc - free bandwith shared class */
1420 sprintf(str,"%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio 2",tc,lan,parent,free_min,free_max,burst);
1421 safe_run(str);
1422
1423 sprintf(str,"%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio 2",tc,wan,parent,free_min,free_max,burst);
1424 safe_run(str);
1425
1426 /* tc SFQ */
1427 if (strcmpi(qos_leaf, "none")){
1428 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s",tc,lan,qos_leaf);
1429 safe_run(str);
1430
1431 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s",tc,wan,qos_leaf);
1432 safe_run(str);
1433 }
1434
1435 /* tc handle 1 fw flowid */
1436 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3",tc,lan);
1437 safe_run(str);
1438
1439 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3",tc,wan);
1440 safe_run(str);
1441
1442 run_restore();
1443
1444 if (log_file) fclose(log_file);
1445 return 0;
1446
1447 /* that's all folks, thank you for reading it all the way up to this point ;-) */
1448 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */
1449 }
This page took 2.926663 seconds and 4 git commands to generate.