json improvements
[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, 20120612\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 256\r
30#define FIRSTGROUPID 1024\r
31#define FIRSTIPCLASS 2048\r
32#undef DEBUG\r
33\r
34#include "cll1-0.6.2.h"\r
35\r
36const char *version = "0.8.3-f";\r
37\r
38/* Version numbers: 0.8.3 is development releases ("beta"), 0.8.4 will be "stable" */\r
39/* Debian(RPM) package versions/patchlevels: 0.7.9-2, 0.8.0-1, 0.8.0-2, etc. */\r
40/* C source code development versions ("beta"): 0.7.9-a, 0.8.1-b, etc. */\r
41/* C source code release versions: 0.8.0, 0.8.2, 0.8.4, etc. */\r
42\r
43const 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
44\r
45/* ======= All path names are defined here (for RPM patch) ======= */\r
46\r
47const char *tc = "/sbin/tc"; /* requires tc with HTB support */\r
48const char *iptables = "/sbin/iptables"; /* requires iptables utility */\r
49const char *iptablessave = "/sbin/iptables-save"; /* not yet required */\r
50const char *iptablesrestore = "/sbin/iptables-restore"; /* requires iptables-restore */\r
51const char *ls = "/bin/ls"; /* this is not user configurable :-) */\r
52\r
53char *config = "/etc/prometheus/prometheus.conf"; /* main configuration file */\r
54char *hosts = "/etc/prometheus/hosts"; /* per-IP bandwidth definition file */\r
55\r
56char *iptablesfile = "/var/spool/prometheus.iptables"; /* temporary file for iptables-restore*/\r
57char *credit = "/var/lib/misc/prometheus.credit"; /* credit log file */\r
58char *classmap = "/var/lib/misc/prometheus.classes"; /* credit log file */\r
59char *html = "/var/www/traffic.html"; /* hall of fame - html version */\r
60char *preview = "/var/www/preview.html"; /* hall of fame preview - html version */\r
61char *json = "/var/www/logs/traffic.json"; /* hall of fame - json version */\r
62char *json_preview = "/var/www/logs/preview.json"; /* hall of fame preview - json version */\r
63char *cmdlog = "/var/log/prometheuslog"; /* command log filename */\r
64char *log_dir = "/var/www/logs/"; /* log directory pathname, ended with slash */\r
65char *log_url = "/logs/"; /* log directory relative URI prefix (partial URL) */\r
66char *html_log_dir = "/var/www/logs/html/";\r
67\r
68char *jquery_url = "http://code.jquery.com/jquery-latest.js";\r
69char *lms_url = "/lms/?m=customerinfo&amp;id=";\r
70int use_jquery_popups = 1;\r
71int row_odd_even = 0; /*<tr class="odd/even"> */\r
72\r
73\r
74const char *tr_odd_even(void)\r
75{\r
76 row_odd_even = 1 - row_odd_even;\r
77 if(row_odd_even)\r
78 {\r
79 return "<tr class=\"even\">\n";\r
80 }\r
81 else\r
82 {\r
83 return "<tr class=\"odd\">\n";\r
84 }\r
85}\r
86\r
87/* ======= Help screen is hopefuly self-documenting part of code :-) ======= */\r
88\r
89void help(void)\r
90{\r
91 puts("Command line switches:\n\\r
92\n\\r
93-d Dry run (preview tc and iptables commands on stdout)\n\\r
94-r Run (reset all statistics and start shaping - daily usage)\n\\r
95-p just generate Preview of data transfer statistics and exit (after -r)\n\\r
96-s start Shaping FUP limits (keeps data transfer stat like -p) (after -r)\n\\r
97-n run Now (like -r delay - overrides qos-free-delay keyword, after boot)\n\\r
98-f just Flush iptables and tc classes and exit (stop shaping, no QiS)\n\\r
99-9 emergency iptables flush (like -f, but dumps data transfer statistics)\n\\r
100\n\\r
101-c filename force alternative /etc/prometheus/prometheus.conf filename\n\\r
102-h filename force alternative /etc/hosts filename (overrides hosts keyword)\n\\r
103-l Mmm YYYY generate HTML summary of Logged traffic (Mmm=Jan-Dec) (and exit)\n\\r
104-m generate HTML summary of traffic for yesterday's Month (and exit)\n\\r
105-y generate HTML summary of traffic for yesterday's Year (and exit)\n\\r
106-? --help show this help scree (and exit)\n\\r
107-v --version show Version number of this utility (and exit)\n");\r
108}\r
109\r
110/* === Configuraration file values defaults - stored in global variables ==== */\r
111\r
112int filter_type = 1; /*1 mark, 2 classify*/\r
113char *mark = "MARK";\r
114char *mark_iptables = "MARK --set-mark ";\r
115int dry_run = 0; /* preview - use puts() instead of system() */\r
116char *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
117FILE *iptables_file = NULL;\r
118int enable_credit = 1; /* enable credit file */\r
119int use_credit = 0; /* use credit file (if enabled)*/\r
120char *title = "Hall of Fame - Greatest Suckers"; /* hall of fame title */\r
121int hall_of_fame = 1; /* enable hall of fame */\r
122char *lan = "eth0"; /* LAN interface */\r
123char *lan_medium = "100Mbit"; /* 10Mbit/100Mbit ethernet */\r
124char *wan = "eth1"; /* WAN/ISP interface */\r
125char *wan_medium = "100Mbit"; /* 10Mbit/100Mbit ethernet */\r
126char *qos_leaf = "sfq perturb 5"; /* leaf discipline */\r
127char *qos_free_zone = NULL; /* QoS free zone */\r
128int qos_proxy = 1; /* include proxy port to QoS */\r
129int found_lmsid = 0; /* show links to users in LMS information system */\r
130int include_upload = 1; /* upload+download=total traffic */\r
131char *proxy_ip = "192.168.1.1/32"; /* our IP with proxy port */\r
132int proxy_port = 3128; /* proxy port number */\r
133long long int line = 1024; /* WAN/ISP download in kbps */\r
134long long int up = 1024; /* WAN/ISP upload in kbps */\r
135int free_min = 32; /* minimum guaranted bandwidth for all undefined hosts */\r
136int free_max = 64; /* maximum allowed bandwidth for all undefined hosts */\r
137int qos_free_delay = 0; /* seconds to sleep before applying new QoS rules */\r
138int digital_divide = 2; /* controls digital divide weirdness ratio, 1...3 */ \r
139int max_nesting = 3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */\r
140int htb_r2q = 256; /* should work for leaf values 512 kbps to 8 Mbps */\r
141int burst = 8; /* HTB burst (in kbits) */\r
142int burst_main = 64;\r
143int burst_group = 32;\r
144int magic_treshold = 8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */\r
145int keywordcount = 0;\r
146/* not yet implemented:\r
147int fixed_packets = 0; maximum number of pps per IP address (not class!) \r
148int packet_limit = 5; maximum number of pps to htn CEIL, not rate !!! \r
149*/\r
150FILE *log_file = NULL;\r
151char *kwd = "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */\r
152\r
153const int highest_priority = 0; /* highest HTB priority (HTB built-in value is 0) */\r
154const int lowest_priority = 7; /* lowest HTB priority (HTB built-in value is 7) */\r
155const int idxtable_treshold1 = 24; /* this is no longer configurable */\r
156const int idxtable_treshold2 = 12; /* this is no longer configurable */\r
157const int idxtable_bitmask1 = 3; /* this is no longer configurable */\r
158const int idxtable_bitmask2 = 3; /* this is no longer configurable */\r
159\r
160/* ==== This is C<<1 stuff - learn C<<1 first! https://dev.arachne.cz/svn/cll1h ==== */\r
161\r
162struct IP\r
163{\r
164 char *addr;\r
165 char *name;\r
166 char *sharing;\r
167 int min;\r
168 int desired;\r
169 int max;\r
170 int mark;\r
171 int prio;\r
172 int fixedprio;\r
173 int group;\r
174 int lmsid;\r
175 unsigned long long direct;\r
176 unsigned long long proxy;\r
177 unsigned long long upload;\r
178 unsigned long long traffic;\r
179 unsigned long long credit;\r
180 unsigned long pktsup;\r
181 unsigned long pktsdown;\r
182 struct Keyword *keyword;\r
183 list(IP);\r
184} *ips=NULL, *ip, *sharedip;\r
185\r
186struct Group\r
187{\r
188 int min;\r
189 int count;\r
190 int desired;\r
191 int id;\r
192 list(Group);\r
193} *groups=NULL, *group;\r
194\r
195struct Index\r
196{\r
197 char *addr;\r
198 char *id;\r
199 struct Index *parent;\r
200 int bitmask;\r
201 int children;\r
202 list(Index);\r
203} *idxs=NULL, *idx, *metaindex;\r
204\r
205struct Keyword\r
206{\r
207 char *key;\r
208 \r
209 int asymetry_ratio; /* ratio for ADSL-like upload */\r
210 int asymetry_fixed; /* fixed treshold for ADSL-like upload */\r
211 int data_limit; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */\r
212 int data_prio; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */\r
213 long fixed_limit; /* fixed data limit for setting lower HTB ceil */\r
214 long fixed_prio; /* fixed data lmit for setting lower HTB prio */\r
215 int reserve_min; /* bonus for nominal HTB rate bandwidth (in kbps) */\r
216 int reserve_max; /* malus for nominal HTB ceil (in kbps) */\r
217// int divide_max; /* relative malus: new_ceil=rate+(old_ceil-rate)/divide_max */\r
218// int htb_ceil_bonus_divide; /* relative bonus: new_ceil=old_ceil+old_ceil/htb_ceil_bonus_divide */\r
219 int default_prio; /* default HTB priority for this keyword */\r
220 char *html_color;\r
221 int ip_count;\r
222 char *leaf_discipline;\r
223 \r
224 list(Keyword);\r
225} *keyword,*defaultkeyword=NULL,*keywords=NULL;\r
226\r
227/* Damned, this must be object oriented! This looks almost like constructor ;-) */\r
228\r
229void TheIP(void)\r
230{\r
231 create(ip,IP);\r
232 ip->name = "";\r
233 ip->addr = "";\r
234 ip->sharing = NULL;\r
235 ip->prio = highest_priority+1;\r
236 ip->lmsid = -1;\r
237 ip->fixedprio = \\r
238 ip->mark = \\r
239 ip->min = \\r
240 ip->max = \\r
241 ip->desired = \\r
242 ip->credit = \\r
243 ip->upload = \\r
244 ip->proxy = \\r
245 ip->direct = \\r
246 ip->traffic = \\r
247 ip->pktsup = \\r
248 ip->pktsdown = 0;\r
249 ip->keyword = keywords;\r
250 push(ip,ips);\r
251}\r
252\r
253/* ====== iptables indexes are used to reduce complexity to log8(N) ===== */\r
254\r
255char *very_ugly_ipv4_code(char *inip,int bitmask,int format_as_chainname)\r
256{\r
257 /* warning: this function was debugged only for bitmask values 20,24,28 !!!*/\r
258 int dot=0, n;\r
259 char *ip,*outip,*outptr,*fmt;\r
260\r
261 duplicate(inip,ip);\r
262 /* debug printf("(%s,%d) -> ",ip,bitmask); */\r
263\r
264 if(ip && *ip && bitmask>=0 && bitmask<=32)\r
265 {\r
266 string(outip,strlen(ip)+10); /*fuck unicode? assertion: 10>strlen("_%d_%d") */\r
267 }\r
268 else \r
269 {\r
270 /* should never exit here */\r
271 return "undefined";\r
272 }\r
273 outptr=outip;\r
274 while(ip && *ip)\r
275 {\r
276 if(*ip=='.')\r
277 {\r
278 if(dot<(bitmask/8-1)) \r
279 {\r
280 if(format_as_chainname)\r
281 {\r
282 *outptr='_';\r
283 }\r
284 else\r
285 {\r
286 *outptr='.';\r
287 }\r
288 outptr++;\r
289 dot++;\r
290 }\r
291 else\r
292 {\r
293 char *cutdot=strchr(ip+1,'.'); /*for bitmask<24*/ \r
294 if(cutdot)\r
295 {\r
296 *cutdot = '\0';\r
297 }\r
298 \r
299 if(format_as_chainname)\r
300 {\r
301 fmt = "_%d_%d";\r
302 }\r
303 else\r
304 {\r
305 fmt = ".%d";\r
306 }\r
307 \r
308 if(bitmask%8)\r
309 {\r
310 n = atoi(ip+1)-atoi(ip+1)%(1<<(8-bitmask%8));\r
311 }\r
312 else\r
313 {\r
314 n = 0;\r
315 }\r
316\r
317 /*debug printf("%d/%d => [_%d_%d]\n",atoi(ip+1),bitmask,n,bitmask); */\r
318 sprintf(outptr,fmt,n,bitmask);\r
319 if(!format_as_chainname)\r
320 {\r
321 while(bitmask<24)\r
322 {\r
323 strcat(outip,".0");\r
324 bitmask+=8;\r
325 }\r
326 }\r
327 /* debug printf("[%s]\n",outip); */\r
328 return outip;\r
329 }\r
330 }\r
331 else \r
332 {\r
333 *outptr=*ip;\r
334 outptr++;\r
335 }\r
336 ip++;\r
337 }\r
338 /*should never exit here*/\r
339 *outptr='\0';\r
340 return outip;\r
341}\r
342\r
343char *hash_id(char *ip,int bitmask)\r
344{ \r
345 return very_ugly_ipv4_code(ip,bitmask,1);\r
346}\r
347\r
348char *subnet_id(char *ip,int bitmask)\r
349{\r
350 return very_ugly_ipv4_code(ip,bitmask,0);\r
351}\r
352\r
353/* ================= Let's parse configuration file here =================== */\r
354\r
355void reject_config_and_exit(char *filename)\r
356{\r
357 printf("Configuration file %s rejected - abnormal exit.",filename);\r
358 exit(-1);\r
359}\r
360\r
361void get_config(char *config_filename)\r
362{\r
363 char *cnf="mark";\r
364 \r
365 printf("Configured keywords: ");\r
366 parse(config_filename)\r
367 {\r
368 option("keyword",kwd);\r
369 if(kwd)\r
370 {\r
371 printf("%s ",kwd);\r
372\r
373 create(keyword,Keyword);\r
374 keyword->key=kwd;\r
375 keyword->asymetry_ratio=1; /* ratio for ADSL-like upload */\r
376 keyword->asymetry_fixed=0; /* fixed treshold for ADSL-like upload */\r
377 keyword->data_limit=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */\r
378 keyword->data_prio=4; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */\r
379 keyword->fixed_limit=0; /* fixed data limit for setting lower HTB ceil */\r
380 keyword->fixed_prio=0; /* fixed data limit for setting lower HTB prio */\r
381 keyword->reserve_min=8; /* bonus for nominal HTB rate bandwidth (in kbps) */\r
382 keyword->reserve_max=0; /* malus for nominal HTB ceil (in kbps) */\r
383 keyword->default_prio=highest_priority+1;\r
384 keyword->html_color="000000";\r
385 keyword->ip_count=0;\r
386 keyword->leaf_discipline="";\r
387\r
388 push(keyword,keywords);\r
389 if(!defaultkeyword) defaultkeyword=keyword;\r
390 keywordcount++;\r
391 \r
392 kwd=NULL;\r
393 }\r
394 else\r
395 {\r
396 for_each(keyword,keywords)\r
397 {\r
398 int l=strlen(keyword->key);\r
399\r
400 if(!strncmp(keyword->key,_,l) && strlen(_)>l+2)\r
401 {\r
402 char *tmptr=_; /* <---- l+1 ----> */\r
403 _+=l+1; /* via-prometheus-asymetry-ratio, etc. */\r
404 ioption("asymetry-ratio",keyword->asymetry_ratio);\r
405 ioption("asymetry-treshold",keyword->asymetry_fixed);\r
406 ioption("magic-relative-limit",keyword->data_limit);\r
407 ioption("magic-relative-prio",keyword->data_prio);\r
408 loption("magic-fixed-limit",keyword->fixed_limit);\r
409 loption("magic-fixed-prio",keyword->fixed_prio);\r
410 ioption("htb-default-prio",keyword->default_prio);\r
411 ioption("htb-rate-bonus",keyword->reserve_min);\r
412 ioption("htb-ceil-malus",keyword->reserve_max);\r
413 option("leaf-discipline",keyword->leaf_discipline);\r
414 option("html-color",keyword->html_color);\r
415 _=tmptr;\r
416 \r
417 if(keyword->data_limit || keyword->fixed_limit || \r
418 keyword->data_prio || keyword->fixed_prio)\r
419 {\r
420 use_credit=1; \r
421 }\r
422 }\r
423 }\r
424 }\r
425\r
426 option("tc",tc);\r
427 option("iptables",iptables);\r
428 option("iptables-save",iptablessave); /* new */\r
429 option("iptables-restore",iptablesrestore); /* new */\r
430 option("iptables-in-filename",iptablesfile); /* new */\r
431 option("hosts",hosts);\r
432 option("lan-interface",lan);\r
433 option("wan-interface",wan);\r
434 option("lan-medium",lan_medium);\r
435 option("wan-medium",wan_medium);\r
436 lloption("wan-download",line);\r
437 lloption("wan-upload",up);\r
438 ioption("hall-of-fame-enable",hall_of_fame);\r
439 option("hall-of-fame-title",title);\r
440 option("hall-of-fame-filename",html);\r
441 option("json-filename",json);\r
442 option("hall-of-fame-preview",preview);\r
443 option("json-preview",json_preview);\r
444 option("log-filename",cmdlog);\r
445 option("credit-filename",credit);\r
446 option("classmap-filename",classmap);\r
447 ioption("credit-enable",enable_credit);\r
448 option("log-traffic-directory",log_dir);\r
449 option("log-traffic-html-directory",html_log_dir);\r
450 option("log-traffic-url-path",log_url);\r
451 option("jquery-url",jquery_url);\r
452 option("lms-url",lms_url);\r
453 ioption("use-jquery-popups",use_jquery_popups);\r
454 option("qos-free-zone",qos_free_zone);\r
455 ioption("qos-free-delay",qos_free_delay);\r
456 ioption("qos-proxy-enable",qos_proxy);\r
457 option("qos-proxy-ip",proxy_ip);\r
458 option("htb-leaf-discipline",qos_leaf);\r
459 ioption("qos-proxy-port",proxy_port);\r
460 ioption("free-rate",free_min);\r
461 ioption("free-ceil",free_max);\r
462 ioption("htb-burst",burst);\r
463 ioption("htb-burst-main",burst_main);\r
464 ioption("htb-burst-group",burst_group);\r
465 ioption("htb-nesting-limit",max_nesting);\r
466 ioption("htb-r2q",htb_r2q);\r
467 ioption("magic-include-upload",include_upload);\r
468 ioption("magic-treshold",magic_treshold); \r
469 option("filter-type", cnf); \r
470/* not yet implemented:\r
471 ioption("magic-fixed-packets",fixed_packets);\r
472 ioption("magic-relative-packets",packet_limit);\r
473*/\r
474 }\r
475 fail\r
476 { \r
477 perror(config_filename);\r
478 puts("Warning - using built-in defaults instead ...");\r
479 }\r
480 done; /* ugly macro end */\r
481 printf("\n");\r
482 \r
483 /* leaf discipline for keywords */\r
484 for_each(keyword,keywords)\r
485 {\r
486 if(!strcmpi(keyword->leaf_discipline, ""))\r
487 {\r
488 keyword->leaf_discipline = qos_leaf;\r
489 }\r
490 }\r
491\r
492 if(strcmpi(cnf, "mark"))\r
493 {\r
494 filter_type = 2;\r
495 mark = "CLASSIFY";\r
496 mark_iptables = "CLASSIFY --set-class 1:";\r
497 }\r
498 else\r
499 {\r
500 filter_type = 1;\r
501 mark = "MARK";\r
502 mark_iptables = "MARK --set-mark ";\r
503 }\r
504\r
505 /* are supplied values meaningful ?*/\r
506 if(line<=0 || up<=0)\r
507 {\r
508 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");\r
509 reject_config_and_exit(config_filename);\r
510 }\r
511}\r
512\r
513/* ===================== traffic analyser - uses iptables ================ */ \r
514\r
515void get_traffic_statistics(void)\r
516{\r
517 char *str,*cmd;\r
518 int downloadflag=0;\r
519\r
520 textfile(Pipe,str) *line,*lines=NULL;\r
521 string(str,STRLEN);\r
522 string(cmd,STRLEN);\r
523\r
524 sprintf(cmd,"%s -L -v -x -n -t mangle",iptables);\r
525 shell(cmd);\r
526 input(str,STRLEN)\r
527 {\r
528 create(line,Pipe);\r
529 line->str=str;\r
530 string(str,STRLEN);\r
531 append(line,lines);\r
532 }\r
533\r
534 for_each(line,lines)\r
535 {\r
536 int col, accept=0,proxyflag=0,valid=1,setchainname=0,commonflag=0; \r
537 unsigned long long traffic=0;\r
538 unsigned long pkts=0;\r
539 char *ipaddr=NULL,*ptr;\r
540 \r
541 /* debug puts(line->str); */\r
542 valid_columns(ptr,line->str,' ',col) \r
543 if(valid) switch(col)\r
544 { \r
545 case 1: if(eq(ptr,"Chain"))\r
546 {\r
547 setchainname=1;\r
548 }\r
549 else if(eq(ptr,"pkts")) \r
550 {\r
551 valid=0;\r
552 }\r
553 else\r
554 {\r
555 sscanf(ptr,"%lu",&pkts); \r
556 }\r
557 break;\r
558 case 2: if(setchainname)\r
559 {\r
560 if(!strncmp(ptr,"post_",5) || eq(ptr,"POSTROUTING"))\r
561 {\r
562 downloadflag = 1; \r
563 }\r
564 else \r
565 {\r
566 if(!strncmp(ptr,"forw_",5) || eq(ptr,"FORWARD"))\r
567 {\r
568 downloadflag = 0;\r
569 }\r
570 } \r
571 if(eq(ptr,"post_common") || eq(ptr,"forw_common"))\r
572 {\r
573 commonflag = 1;\r
574 }\r
575 }\r
576 else\r
577 {\r
578 sscanf(ptr,"%Lu",&traffic); \r
579 traffic += (1<<19);\r
580 traffic >>= 20;\r
581 }\r
582 break;\r
583 case 3: if((strncmp(ptr,"post_",5) && strncmp(ptr,"forw_",5)) || commonflag)\r
584 {\r
585 accept=eq(ptr,mark);\r
586 }\r
587 /*if(filter_type==1) accept=eq(ptr,"MARK"); else accept=eq(ptr,"CLASSIFY");*/\r
588 break;\r
589 case 8: if(downloadflag)\r
590 { \r
591 if(strstr(proxy_ip,ptr))\r
592 {\r
593 proxyflag=1; \r
594 }\r
595 }\r
596 else\r
597 {\r
598 ipaddr=ptr; \r
599 }\r
600 break;\r
601 case 9: if(downloadflag)ipaddr=ptr;break;\r
602 }\r
603 \r
604 if(accept && traffic>0 && ipaddr)\r
605 {\r
606 if(proxyflag)\r
607 {\r
608 printf("(proxy) ");\r
609 }\r
610 else if(!downloadflag)\r
611 {\r
612 printf("(upload) ");\r
613 }\r
614 printf("IP %s: %Lu MB (%ld pkts)\n", ipaddr, traffic, pkts);\r
615\r
616 if_exists(ip,ips,eq(ip->addr,ipaddr)); \r
617 else \r
618 {\r
619 TheIP();\r
620 ip->addr=ipaddr;\r
621 if(eq(ip->addr,"0.0.0.0/0"))\r
622 {\r
623 ip->name="(unregistered)";\r
624 ip->min=free_min;\r
625 ip->max=ip->desired=free_max;\r
626 }\r
627 }\r
628 \r
629 if(downloadflag)\r
630 {\r
631 if(proxyflag)\r
632 {\r
633 ip->proxy=traffic;\r
634 }\r
635 else\r
636 {\r
637 ip->traffic+=traffic;\r
638 }\r
639 ip->direct=ip->traffic-ip->upload-ip->proxy;\r
640 ip->pktsdown=pkts;\r
641 }\r
642 else\r
643 {\r
644 ip->upload=traffic;\r
645 ip->pktsup=pkts;\r
646 if(include_upload)\r
647 {\r
648 ip->traffic+=traffic;\r
649 }\r
650 else \r
651 {\r
652 if(traffic>ip->traffic)\r
653 {\r
654 ip->traffic=traffic; \r
655 }\r
656 }\r
657 }\r
658 } \r
659 }\r
660 free(cmd);\r
661}\r
662 \r
663/* ========== This function executes, logs OR ALSO prints command ========== */\r
664\r
665void safe_run(char *cmd)\r
666{\r
667 if(dry_run)\r
668 {\r
669 printf("\n=>%s\n",cmd);\r
670 }\r
671 else\r
672 {\r
673 system(cmd);\r
674 }\r
675 if(log_file)\r
676 {\r
677 fprintf(log_file,"%s\n",cmd);\r
678 }\r
679}\r
680\r
681void save_line(char *line)\r
682{\r
683 fprintf(iptables_file,"%s\n",line);\r
684}\r
685\r
686void run_restore(void)\r
687{\r
688 char *restor;\r
689 string(restor,STRLEN);\r
690\r
691 /*-----------------------------------------------------------------*/\r
692 printf("Running %s <%s ...\n", iptablesrestore, iptablesfile);\r
693 /*-----------------------------------------------------------------*/\r
694 \r
695 save_line("COMMIT");\r
696 fclose(iptables_file);\r
697 if(dry_run) \r
698 {\r
699 parse(iptablesfile)\r
700 {\r
701 printf("%s\n",_);\r
702 }\r
703 done; /* ugly macro end */\r
704 }\r
705\r
706 sprintf(restor,"%s <%s",iptablesrestore, iptablesfile);\r
707 safe_run(restor);\r
708 \r
709 free(restor);\r
710}\r
711\r
712/* == This function strips extra characters after IP address and stores it = */\r
713\r
714void parse_ip(char *str)\r
715{\r
716 char *ptr,*ipaddr=NULL,*ipname=NULL,*lmsid=NULL;\r
717\r
718 ptr=strchr(str,'{');\r
719 if(ptr)\r
720 {\r
721 lmsid=++ptr;\r
722 while(*ptr && *ptr!='}')\r
723 {\r
724 ptr++;\r
725 }\r
726 *ptr=0;\r
727 }\r
728 \r
729 ptr=str;\r
730 while(*ptr && *ptr!=' ' && *ptr!=9)\r
731 {\r
732 ptr++;\r
733 }\r
734 \r
735 *ptr=0;\r
736 ipaddr=str;\r
737 ptr++;\r
738 while(*ptr && (*ptr==' ' || *ptr==9))\r
739 {\r
740 ptr++;\r
741 }\r
742 ipname=ptr; \r
743 while(*ptr && *ptr!=' ' && *ptr!=9)\r
744 {\r
745 ptr++;\r
746 }\r
747 *ptr=0;\r
748\r
749 if_exists(ip,ips,eq(ip->addr,ipaddr));\r
750 else\r
751 {\r
752 TheIP();\r
753 }\r
754 ip->addr=ipaddr;\r
755 ip->name=ipname;\r
756 if(lmsid)\r
757 {\r
758 ip->lmsid=atoi(lmsid);\r
759 found_lmsid=1;\r
760 }\r
761}\r
762\r
763char *parse_datafile_line(char *str)\r
764{\r
765 char *ptr=strchr(str,' ');\r
766\r
767 if(ptr)\r
768 {\r
769 *ptr=0;\r
770 ptr++;\r
771 return ptr;\r
772 } \r
773 else \r
774 {\r
775 return NULL;\r
776 }\r
777}\r
778\r
779struct IpLog\r
780{\r
781 char *name;\r
782 long traffic;\r
783 long guaranted;\r
784 int i;\r
785 int lmsid;\r
786 long l;\r
787 list(IpLog);\r
788} *iplog,*iplogs;\r
789\r
790void parse_ip_log(int argc, char **argv) \r
791{\r
792 char *month, *year, *str, *name="(undefined)", *ptr, *ptr2, *filename;\r
793 long traffic=0l, traffic_month, total=0, guaranted;\r
794 int col, col2, y_ok, m_ok, accept_month, i=1, any_month=0, lmsid;\r
795 char mstr[4], ystr[5];\r
796 FILE *f; \r
797 string(str,STRLEN);\r
798 string(filename,STRLEN);\r
799\r
800 if(argv[1][1]=='l') /* -l */\r
801 {\r
802 if(argc<4)\r
803 {\r
804 puts("Missing parameter(s)!\nUsage: prometheus -l Mmm YYYY (Mmm=Jan-Dec or Year, YYYY=year)");\r
805 exit(-1);\r
806 }\r
807 else\r
808 {\r
809 month=argv[2];\r
810 if(eq(month,"Year")) any_month=1;\r
811 year=argv[3];\r
812 }\r
813 }\r
814 else\r
815 { \r
816 time_t t = time(NULL) - 3600*24 ; /* yesterday's timestamp*/\r
817 struct tm *timep = localtime(&t); \r
818\r
819 if(argv[1][1]=='m') /* -m yestarday - month */\r
820 {\r
821 strftime(mstr, 4, "%b", timep);\r
822 month=mstr;\r
823 strftime(ystr, 5, "%Y", timep);\r
824 year=ystr; \r
825 }\r
826 else /* -y yesterday - year */\r
827 {\r
828 month="Year";\r
829 any_month=1;\r
830 strftime(ystr, 5, "%Y", timep);\r
831 year=ystr;\r
832 }\r
833 }\r
834 printf("Analysing traffic for %s %s ...\n",month,year);\r
835\r
836 /* sorry... next release of C<<1 header file will include for_path_files(name,path) { } macro */\r
837 sprintf(str,"%s %s/",ls,log_dir);\r
838 shell(str);\r
839 input(str,STRLEN) \r
840 {\r
841 if(strstr(str,".log"))\r
842 {\r
843 ptr=strrchr(str,'\n');\r
844 if(ptr) *ptr='\0';\r
845 sprintf(filename,"%s/%s",log_dir,str);\r
846 printf("Parsing %s ...",filename);\r
847 accept_month=0;\r
848 traffic_month=0;\r
849 guaranted=0;\r
850 lmsid=-1;\r
851 parse(filename)\r
852 {\r
853 y_ok=m_ok=0; \r
854 valid_columns(ptr,_,'\t',col) switch(col)\r
855 {\r
856 case 2: name = ptr;break;\r
857 case 3: traffic = atol(ptr);break;\r
858 /* column number - was 7, now 11...*/\r
859 case 7:\r
860 case 8:\r
861 case 9:\r
862 case 10:\r
863 case 11: if(isalpha(*ptr)) /* character, not numeric string = date, just one*/\r
864 {\r
865 valid_columns(ptr2,ptr,' ',col2) switch(col2)\r
866 {\r
867 case 2: if(any_month || eq(ptr2,month)) m_ok = 1; break;\r
868 case 5: if(eq(ptr2,year)) y_ok = 1; break;\r
869 }\r
870 }\r
871 else\r
872 {\r
873 if(col == 7) guaranted = atol(ptr);\r
874 if(col == 10) lmsid = atoi(ptr);\r
875 }\r
876 }\r
877 \r
878 if(y_ok && m_ok) \r
879 {\r
880 traffic_month += traffic;\r
881 accept_month = 1;\r
882 }\r
883 }\r
884 done; /* ugly macro end */ \r
885\r
886 if(accept_month)\r
887 {\r
888 create(iplog,IpLog);\r
889 iplog->name = name;\r
890 iplog->guaranted = guaranted;\r
891 iplog->traffic = traffic_month;\r
892 iplog->lmsid = lmsid;\r
893 insert(iplog,iplogs,desc_order_by,traffic);\r
894 printf(" %ld MB\n",iplog->traffic);\r
895 }\r
896 else\r
897 {\r
898 puts(" no records.");\r
899 }\r
900 }\r
901 }\r
902 sprintf(str,"%s/%s-%s.html",html_log_dir,year,month);\r
903 printf("Writing %s ... ",str);\r
904 f=fopen(str,"w");\r
905 if(f > 0)\r
906 {\r
907 fprintf(f, "<table class=\"decorated last\"><thead>\n\\r
908<tr><th colspan=\"2\">%s %s</th>\n\\r
909<th style=\"text-align: right\">lms</th>\n\\r
910<th colspan=\"2\">Data transfers</th>\n\\r
911<th style=\"text-align: right\">Min.speed</th>\n\\r
912</tr></thead><tbody>\n ",\r
913 month, year);\r
914\r
915 row_odd_even = 0;\r
916 for_each(iplog, iplogs)\r
917 {\r
918 if(iplog->traffic)\r
919 {\r
920 fprintf(f, "%s<td style=\"text-align: right\">%d</td>\n\\r
921<td style=\"text-align: left\"><a class=\"blue\" target=\"_blank\" href=\"%s%s.log\">%s</td>\n\\r
922<td style=\"text-align: right\">", \r
923 tr_odd_even(), i++, log_url, iplog->name, iplog->name); \r
924 if(iplog->lmsid > 0)\r
925 {\r
926 /*base URL will be configurable soon ... */\r
927 fprintf(f, "<a class=\"blue\" target=\"_blank\" href=\"%s%d\">%04d</a>\n", lms_url, iplog->lmsid, iplog->lmsid);\r
928 }\r
929 else if(iplog->lmsid == 0)\r
930 {\r
931 fputs("-------",f);\r
932 } \r
933 fprintf(f, "<td style=\"text-align: right\">%ld&nbsp;MB</td>\n\\r
934 <td style=\"text-align: right\"><strong>%ld&nbsp;GB</strong></td>\n\\r
935 <td style=\"text-align: right\">%ld&nbsp;kb/s</th></tr>\n",\r
936 iplog->traffic, iplog->traffic>>10, iplog->guaranted);\r
937 total+=iplog->traffic>>10;\r
938 iplog->i=i;\r
939 iplog->l=total;\r
940 }\r
941 }\r
942 fprintf(f,"</tbody><thead><tr>\\r
943 <th colspan=\"3\" style=\"text-align: left\">Total:</th>\\r
944 <th colspan=\"2\" style=\"text-align: right\"><strong>%ld&nbsp;GB</strong></th>\\r
945 <th style=\"text-align: right\"><strong>%Ld&nbsp;kb/s</strong></th></tr>\n", total, line);\r
946 fputs("</thead></table>\n", f);\r
947\r
948 row_odd_even = 0;\r
949 if(i>10)\r
950 {\r
951 fputs("<a name=\"erp\"></a><p><table class=\"decorated last\">\n\\r
952<caption>Enterprise Resource Planning (ERP)</caption>\n\\r
953<thead><tr>\n\\r
954<th>Analytic category</th>\n\\r
955<th colspan=\"2\" style=\"text-align: center\">Active Classes</th>\n\\r
956<th colspan=\"2\" style=\"text-align: center\">Data transfers</th>\n\\r
957</tr></thead><tbody>\n",f);\r
958\r
959 if_exists(iplog,iplogs,iplog->l>=total/4)\r
960 {\r
961 fprintf(f,"%s<td>Top 25%% of traffic</td>\n", tr_odd_even());\r
962 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
963<td style=\"text-align: right\">%d %%</td>\n\\r
964<td style=\"text-align: right\">%ld GB</td>\n\\r
965<td style=\"text-align: right\">%d %%</td></tr>\n",\r
966 iplog->i, (100*iplog->i+50)/i, iplog->l, (int)((100*iplog->l+50)/total));\r
967 }\r
968 \r
969 if_exists(iplog,iplogs,iplog->i==10)\r
970 {\r
971 fprintf(f,"%s<td>Top 10 downloaders</td>\n", tr_odd_even());\r
972 fprintf(f,"<td style=\"text-align: right\"><strong>10</strong></td>\n\\r
973<td style=\"text-align: right\">%d %%</td>\n\\r
974<td style=\"text-align: right\">%ld GB</td>\n\\r
975<td style=\"text-align: right\">%d %%</td></tr>\n",\r
976 (100*iplog->i+50)/i, iplog->l, (int)((100*iplog->l+50)/total));\r
977 }\r
978\r
979 if_exists(iplog,iplogs,iplog->l>=total/2)\r
980 {\r
981 fprintf(f,"%s<td>Top 50%% of traffic</td>\n", tr_odd_even());\r
982 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
983<td style=\"text-align: right\">%d %%</td>\n\\r
984<td style=\"text-align: right\">%ld GB</td>\n\\r
985<td style=\"text-align: right\"><strong>%d %%</strong></td></tr>\n",\r
986 iplog->i,(100*iplog->i+50)/i,iplog->l,(int)((100*iplog->l+50)/total));\r
987 }\r
988\r
989 if_exists(iplog,iplogs,iplog->l>=4*total/5)\r
990 {\r
991 fprintf(f,"%s<td>Top 80%% of traffic</td>\n",tr_odd_even());\r
992 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
993<td style=\"text-align: right\">%d %%</td>\n\\r
994<td style=\"text-align: right\">%ld GB</td>\n\\r
995<td style=\"text-align: right\"><strong>%d %%</strong></td></tr>\n",\r
996 iplog->i, (100*iplog->i+50)/i, iplog->l, (int)((100*iplog->l+50)/total));\r
997 }\r
998\r
999 if_exists (iplog,iplogs,iplog->i>=i/5)\r
1000 {\r
1001 fprintf(f,"%s<td>Top 20%% downloaders</td>\n",tr_odd_even());\r
1002 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1003<td style=\"text-align: right\"><strong>%d %%</strong></td>\n\\r
1004<td style=\"text-align: right\">%ld GB</td>\n\\r
1005<td style=\"text-align: right\">%d %%</td></tr>\n",\r
1006 iplog->i, (100*iplog->i+50)/i, iplog->l, (int)((100*iplog->l+50)/total));\r
1007 }\r
1008\r
1009 if_exists(iplog,iplogs,iplog->i>=i/4)\r
1010 {\r
1011 fprintf(f,"%s<td>Top 25%% downloaders</td>\n", tr_odd_even());\r
1012 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1013<td style=\"text-align: right\">%d %%</td>\n\\r
1014<td style=\"text-align: right\">%ld GB</td>\n\\r
1015<td style=\"text-align: right\">%d %%</td></tr>\n",\r
1016 iplog->i, (100*iplog->i+50)/i, iplog->l, (int)((100*iplog->l+50)/total));\r
1017 }\r
1018\r
1019 if_exists(iplog,iplogs,iplog->i>=i/2)\r
1020 {\r
1021 fprintf(f,"%s<td>Top 50%% downloaders</td>\n",tr_odd_even());\r
1022 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1023<td style=\"text-align: right\"><strong>%d %%</strong></td>\n\\r
1024<td style=\"text-align: right\">%ld GB</td>\n\\r
1025<td style=\"text-align: right\">%d %%</td></tr>\n",\r
1026 iplog->i, (100*iplog->i+50)/i, iplog->l, (int)((100*iplog->l+50)/total));\r
1027 }\r
1028\r
1029 if_exists(iplog,iplogs,iplog->i>=4*i/5)\r
1030 {\r
1031 fprintf(f,"%s<td>Top 80%% downloaders</td>\n",tr_odd_even());\r
1032 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1033<td style=\"text-align: right\">%d %%</td>\n\\r
1034<td style=\"text-align: right\">%ld GB</td>\n\\r
1035<td style=\"text-align: right\">%d %%</td></tr>\n",\r
1036 iplog->i, (100*iplog->i+50)/i, iplog->l, (int)((100*iplog->l+50)/total));\r
1037 }\r
1038\r
1039 fprintf(f,"</tbody><thead><tr><th><a class=\"blue\" target=\"_blank\" href=\"%sERP.log\">All users, all traffic</a></th>\n", log_url);\r
1040 fprintf(f,"<th style=\"text-align: right\">%d</th>\n\\r
1041<th style=\"text-align: right\">100 %%</th>\n\\r
1042<th style=\"text-align: right\">%ld GB</th>\n\\r
1043<th style=\"text-align: right\">100 %%</th></tr>\n",i-1,total);\r
1044 fputs("</thead></table>\n", f);\r
1045 }\r
1046\r
1047 fprintf(f, stats_html_signature, version);\r
1048 fclose(f);\r
1049 puts("done.");\r
1050 }\r
1051 else\r
1052 {\r
1053 perror(str);\r
1054 }\r
1055}\r
1056\r
1057void append_log(struct IP *self) /*using global variables*/\r
1058{\r
1059 char *d, *str;\r
1060 FILE *f; \r
1061\r
1062 date(d); /* this is typical cll1.h macro - prints current date */ \r
1063 string(str,STRLEN); \r
1064 sprintf(str,"%s/%s.log", log_dir, self->name);\r
1065 f=fopen(str,"a");\r
1066 if(f > 0)\r
1067 {\r
1068 fprintf(f,"%ld\t%s\t%Lu\t%Lu\t%Lu\t%Lu\t%d\t%d\t%d\t%d\t%s",\r
1069 time(NULL), self->name, self->traffic, self->direct, self->proxy,\r
1070 self->upload, self->min, self->max, self->desired, self->lmsid, d); /* d = date*/\r
1071 fclose(f);\r
1072 }\r
1073 else\r
1074 {\r
1075 perror(str);\r
1076 }\r
1077}\r
1078\r
1079\r
1080/*-----------------------------------------------------------------*/\r
1081/* Are you looking for int main(int argc, char **argv) ? :-)) */\r
1082/*-----------------------------------------------------------------*/\r
1083\r
1084program\r
1085{\r
1086 int i=0; /* just plain old Fortran style integer :-) */\r
1087 FILE *f=NULL; /* everything is just stream of bytes... */\r
1088 char *str, *ptr, *d; /* LET A$=B$ :-) */\r
1089 char *substring;\r
1090 int class_count=0,ip_count=0;\r
1091 int parent=1;\r
1092 int just_flush=FALSE; /* deactivates all previous actions */\r
1093 int nodelay=FALSE;\r
1094 int just_preview=FALSE; /* preview - generate just stats */\r
1095 int start_shaping=FALSE; /* apply FUP - requires classmap file */\r
1096 int just_logs=FALSE; /* just parse logs */\r
1097 int run=FALSE;\r
1098 int total=0;\r
1099 \r
1100 char *chain_forward, *chain_postrouting;\r
1101 char *althosts=NULL;\r
1102 \r
1103 printf("\n\\r
1104Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\\r
1105Version %s - Copyright (C)2005-2012 Michael Polak, Arachne Labs\n\\r
1106iptables-restore & burst tunning & classify modification by Ludva\n\\r
1107Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version);\r
1108\r
1109 /*----- Boring... we have to check command line options first: ----*/ \r
1110 arguments\r
1111 {\r
1112 argument("-c") { nextargument(config); }\r
1113 argument("-h") { nextargument(althosts);}\r
1114 argument("-d") { run=TRUE; dry_run=TRUE; }\r
1115 argument("-f") { run=TRUE; just_flush=TRUE; }\r
1116 argument("-9") { run=TRUE; just_flush=9; }\r
1117 argument("-p") { run=TRUE; just_preview=TRUE; }\r
1118 argument("-s") { run=TRUE; just_preview=TRUE; start_shaping=TRUE; }\r
1119 argument("-r") { run=TRUE; }\r
1120 argument("-n") { run=TRUE; nodelay=TRUE; }\r
1121 argument("-l") { just_logs=TRUE; }\r
1122 argument("-m") { just_logs=TRUE; }\r
1123 argument("-y") { just_logs=TRUE; }\r
1124 argument("-?") { help(); exit(0); }\r
1125 argument("--help") { help(); exit(0); }\r
1126 argument("-v") { exit(0); } \r
1127 argument("--version") { exit(0); } \r
1128 }\r
1129 \r
1130 if(dry_run)\r
1131 {\r
1132 puts("*** THIS IS JUST DRY RUN ! ***\n");\r
1133 }\r
1134\r
1135 date(d); /* this is typical cll1.h macro - prints current date */\r
1136\r
1137 /*-----------------------------------------------------------------*/\r
1138 printf("Parsing configuration file %s ...\n", config);\r
1139 /*-----------------------------------------------------------------*/\r
1140 get_config(config);\r
1141 \r
1142 if(just_logs)\r
1143 {\r
1144 parse_ip_log(argc,argv);\r
1145 exit(0);\r
1146 }\r
1147 else if(not run)\r
1148 {\r
1149 help();\r
1150 exit(0);\r
1151 }\r
1152\r
1153 if(althosts)\r
1154 {\r
1155 hosts=althosts;\r
1156 }\r
1157\r
1158 if(just_flush<9)\r
1159 {\r
1160 /*-----------------------------------------------------------------*/\r
1161 puts("Parsing iptables verbose output ...");\r
1162 /*-----------------------------------------------------------------*/\r
1163 get_traffic_statistics();\r
1164 }\r
1165\r
1166 /*-----------------------------------------------------------------*/\r
1167 printf("Parsing class defintion file %s ...\n", hosts);\r
1168 /*-----------------------------------------------------------------*/\r
1169 int groupidx = FIRSTGROUPID;\r
1170 parse(hosts)\r
1171 {\r
1172 str=_;\r
1173\r
1174 if(*str<'0' || *str>'9')\r
1175 {\r
1176 /* any line starting with non-number is comment ...*/\r
1177 continue;\r
1178 }\r
1179 \r
1180 //Does this IP share QoS class with some other ?\r
1181 substring=strstr(str,"sharing-");\r
1182 if(substring)\r
1183 { \r
1184 substring+=8; //"sharing-"\r
1185 parse_ip(str);\r
1186 ip_count++;\r
1187 ip->sharing=substring;\r
1188 ip->keyword=defaultkeyword; /* settings for default keyword */\r
1189 while(*substring && *substring!='\n')\r
1190 {\r
1191 substring++;\r
1192 }\r
1193 *substring=0; \r
1194 }\r
1195 else\r
1196 {\r
1197 //Do we have to create new QoS class for this IP ?\r
1198\r
1199 if_exists(keyword,keywords,(substring=strstr(str,keyword->key)))\r
1200 {\r
1201 parse_ip(str);\r
1202 ip_count++;\r
1203 ip->keyword=keyword;\r
1204 keyword->ip_count++;\r
1205 ip->prio=keyword->default_prio;\r
1206 substring+=strlen(keyword->key)+1;\r
1207 ptr=substring;\r
1208 while(*ptr && *ptr!='-')\r
1209 {\r
1210 ptr++;\r
1211 }\r
1212 if(*ptr=='-')\r
1213 {\r
1214 *ptr=0;\r
1215 ip->max = ip->desired=atoi(ptr+1);\r
1216 }\r
1217 ip->min = atoi(substring);\r
1218 if(ip->min <= 0)\r
1219 {\r
1220 printf(" %s: Illegal value of minimum bandwidth 0 kbps, using %d kb/s\n",\r
1221 str, free_min);\r
1222 ip->min = free_min;\r
1223 }\r
1224 if(ip->max <= ip->min)\r
1225 {\r
1226 ip->fixedprio = 1;\r
1227 ip->max = ip->min+ip->keyword->reserve_min;\r
1228 }\r
1229 else \r
1230 {\r
1231 ip->max -= ip->keyword->reserve_max;\r
1232 if(ip->max<ip->min)\r
1233 {\r
1234 ip->max=ip->min;\r
1235 }\r
1236 }\r
1237 ip->mark=FIRSTIPCLASS+1+class_count++;\r
1238\r
1239 if_exists(group,groups,group->min==ip->min) \r
1240 { \r
1241 group->count++; \r
1242 group->desired += ip->min;\r
1243 ip->group = group->id; \r
1244 }\r
1245 else\r
1246 {\r
1247 create(group,Group);\r
1248 group->min = ip->min;\r
1249 group->id = groupidx++;\r
1250 ip->group = group->id;\r
1251\r
1252 if(group->min<8) group->min=8;\r
1253 /* Warning - this is maybe because of primitive tc namespace, can be fixed */\r
1254 /* it is because class IDs are derived from min. bandwidth. - xCh */\r
1255 //if(group->min>MAX_GUARANTED_KBPS) group->min=MAX_GUARANTED_KBPS;\r
1256 \r
1257 group->count=1;\r
1258 group->desired=ip->min; \r
1259 insert(group,groups,desc_order_by,min);\r
1260 }\r
1261 }//endif keyword-\r
1262 }//endif sharing-\r
1263 }\r
1264 fail\r
1265 {\r
1266 perror(hosts);\r
1267 exit(-1);\r
1268 }\r
1269 done; /* ugly macro end */\r
1270\r
1271 /*-----------------------------------------------------------------*/\r
1272 /* cll1.h - let's allocate brand new character buffer... */\r
1273 /*-----------------------------------------------------------------*/\r
1274 string(str,STRLEN); \r
1275\r
1276 /*-----------------------------------------------------------------*/\r
1277 puts("Resolving shared connections ...");\r
1278 /*-----------------------------------------------------------------*/\r
1279 for_each(ip,ips) if(ip->sharing)\r
1280 {\r
1281 for_each(sharedip,ips) if(eq(sharedip->name,ip->sharing))\r
1282 {\r
1283 sharedip->traffic+=ip->traffic;\r
1284 ip->traffic=0;\r
1285 ip->mark=sharedip->mark; \r
1286 ip->lmsid=sharedip->lmsid;\r
1287 break;\r
1288 }\r
1289 if(!sharedip)\r
1290 {\r
1291 printf("Unresolved shared connection: %s %s sharing-%s\n",\r
1292 ip->addr, ip->name, ip->sharing);\r
1293 }\r
1294 }\r
1295\r
1296 if(enable_credit && just_flush<9)\r
1297 {\r
1298 /*-----------------------------------------------------------------*/\r
1299 printf("Parsing credit file %s ...\n", credit);\r
1300 /*-----------------------------------------------------------------*/\r
1301 parse(credit)\r
1302 {\r
1303 ptr=parse_datafile_line(_);\r
1304 if(ptr)\r
1305 {\r
1306 if_exists(ip,ips,eq(ip->addr,_))\r
1307 {\r
1308 sscanf(ptr,"%Lu",&(ip->credit));\r
1309 }\r
1310 }\r
1311 }\r
1312 done; /* ugly macro end */\r
1313 }\r
1314\r
1315 if(!just_preview)\r
1316 {\r
1317 /*-----------------------------------------------------------------*/\r
1318 puts("Initializing iptables and tc classes ...");\r
1319 /*-----------------------------------------------------------------*/\r
1320 \r
1321 iptables_file=fopen(iptablesfile,"w");\r
1322 if(iptables_file == NULL)\r
1323 {\r
1324 puts("Cannot open iptablesfile!");\r
1325 exit(-1);\r
1326 }\r
1327 \r
1328 log_file=fopen(cmdlog,"w");\r
1329 if(log_file == NULL) \r
1330 {\r
1331 puts("Cannot open logfile!");\r
1332 exit(-1);\r
1333 }\r
1334 \r
1335 save_line(iptablespreamble);\r
1336 run_restore();\r
1337 \r
1338 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,lan);\r
1339 safe_run(str);\r
1340\r
1341 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,wan);\r
1342 safe_run(str);\r
1343 \r
1344 iptables_file=fopen(iptablesfile,"w");\r
1345 save_line(iptablespreamble);\r
1346\r
1347 if(qos_free_zone && *qos_free_zone!='0')\r
1348 {\r
1349 char *chain;\r
1350 \r
1351 sprintf(str,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone, wan);\r
1352 save_line(str);\r
1353 \r
1354 if(qos_proxy)\r
1355 {\r
1356 save_line(":post_noproxy - [0:0]");\r
1357 sprintf(str,"-A POSTROUTING -p ! tcp -o %s -j post_noproxy", lan);\r
1358 save_line(str); \r
1359 sprintf(str,"-A POSTROUTING -s ! %s -o %s -j post_noproxy", proxy_ip, lan);\r
1360 save_line(str); \r
1361 sprintf(str,"-A POSTROUTING -s %s -p tcp --sport ! %d -o %s -j post_noproxy", proxy_ip, proxy_port, lan);\r
1362 save_line(str); \r
1363\r
1364 chain="post_noproxy"; \r
1365 }\r
1366 else\r
1367 {\r
1368 chain="POSTROUTING";\r
1369 }\r
1370 \r
1371 sprintf(str,"-A %s -s %s -o %s -j ACCEPT", chain, qos_free_zone, lan);\r
1372 save_line(str);\r
1373 }\r
1374 \r
1375 if(ip_count>idxtable_treshold1 && !just_flush)\r
1376 {\r
1377 int idxcount=0, bitmask=32-idxtable_bitmask1; /* default net mask: 255.255.255.240 */\r
1378 char *subnet, *buf;\r
1379 /*-----------------------------------------------------------------*/\r
1380 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count);\r
1381 /*-----------------------------------------------------------------*/\r
1382\r
1383 save_line(":post_common - [0:0]");\r
1384 save_line(":forw_common - [0:0]");\r
1385\r
1386 for_each(ip,ips) if(ip->addr && *(ip->addr) && !eq(ip->addr,"0.0.0.0/0"))\r
1387 {\r
1388 buf=hash_id(ip->addr,bitmask);\r
1389 if_exists(idx,idxs,eq(idx->id,buf))\r
1390 {\r
1391 idx->children++;\r
1392 }\r
1393 else\r
1394 {\r
1395 create(idx,Index);\r
1396 idx->addr=ip->addr;\r
1397 idx->id=buf;\r
1398 idx->bitmask=bitmask;\r
1399 idx->parent=NULL;\r
1400 idx->children=0;\r
1401 idxcount++;\r
1402 push(idx,idxs);\r
1403 }\r
1404 }\r
1405\r
1406 /* brutal perfomance optimalization */\r
1407 while(idxcount>idxtable_treshold2 && bitmask>2*idxtable_bitmask2)\r
1408 {\r
1409 bitmask-=idxtable_bitmask2;\r
1410 idxcount=0;\r
1411\r
1412 for_each(idx,idxs) if(idx->parent == NULL)\r
1413 {\r
1414 buf=hash_id(idx->addr,bitmask);\r
1415 if_exists(metaindex,idxs,eq(metaindex->id,buf))\r
1416 {\r
1417 metaindex->children++;\r
1418 }\r
1419 else\r
1420 {\r
1421 create(metaindex,Index);\r
1422 metaindex->addr=idx->addr;\r
1423 metaindex->id=buf;\r
1424 metaindex->bitmask=bitmask;\r
1425 metaindex->parent=NULL;\r
1426 metaindex->children=0;\r
1427 idxcount++;\r
1428 push(metaindex,idxs);\r
1429 }\r
1430 idx->parent=metaindex;\r
1431 }\r
1432 }\r
1433\r
1434 /* this should slightly optimize throughout ... */\r
1435 sort(idx,idxs,desc_order_by,children);\r
1436 sort(idx,idxs,order_by,bitmask);\r
1437\r
1438 i=0;\r
1439 for_each(idx,idxs)\r
1440 {\r
1441 subnet=subnet_id(idx->addr,idx->bitmask);\r
1442 printf("%d: %s/%d\n",\r
1443 ++i, subnet, idx->bitmask);\r
1444 \r
1445 sprintf(str,":post_%s - [0:0]", idx->id);\r
1446 save_line(str);\r
1447\r
1448 sprintf(str,":forw_%s - [0:0]", idx->id);\r
1449 save_line(str);\r
1450\r
1451 if(idx->parent)\r
1452 {\r
1453 string(buf,strlen(idx->parent->id)+6);\r
1454 sprintf(buf,"post_%s",idx->parent->id);\r
1455 }\r
1456 else\r
1457 {\r
1458 buf="POSTROUTING";\r
1459 }\r
1460\r
1461 sprintf(str,"-A %s -d %s/%d -o %s -j post_%s", buf, subnet, idx->bitmask, lan, idx->id);\r
1462 save_line(str);\r
1463\r
1464 sprintf(str,"-A %s -d %s/%d -o %s -j post_common", buf, subnet, idx->bitmask, lan);\r
1465 save_line(str);\r
1466\r
1467 if(idx->parent)\r
1468 {\r
1469 string(buf,strlen(idx->parent->id)+6);\r
1470 sprintf(buf,"forw_%s",idx->parent->id);\r
1471 }\r
1472 else\r
1473 {\r
1474 buf="FORWARD";\r
1475 }\r
1476\r
1477 sprintf(str,"-A %s -s %s/%d -o %s -j forw_%s", buf, subnet, idx->bitmask, wan, idx->id);\r
1478 save_line(str);\r
1479\r
1480 sprintf(str,"-A %s -s %s/%d -o %s -j forw_common", buf, subnet, idx->bitmask, wan);\r
1481 save_line(str);\r
1482 }\r
1483 printf("Total indexed iptables chains created: %d\n", i);\r
1484\r
1485 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);\r
1486 save_line(str);\r
1487 \r
1488 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);\r
1489 save_line(str);\r
1490 }\r
1491 \r
1492 }\r
1493\r
1494 if(just_flush)\r
1495 {\r
1496 fclose(iptables_file);\r
1497 if(log_file)\r
1498 { \r
1499 fclose(log_file);\r
1500 }\r
1501 puts("Just flushed iptables and tc classes - now exiting ...");\r
1502 exit(0);\r
1503 }\r
1504\r
1505 if(!just_preview)\r
1506 {\r
1507 if(!dry_run && !nodelay && qos_free_delay)\r
1508 {\r
1509 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay);\r
1510 sleep(qos_free_delay);\r
1511 }\r
1512\r
1513 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",\r
1514 tc,lan,htb_r2q);\r
1515 safe_run(str);\r
1516\r
1517 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
1518 tc,lan,lan_medium,lan_medium,burst_main,highest_priority);\r
1519 safe_run(str);\r
1520\r
1521 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
1522 tc,lan,line,line,burst_main,highest_priority);\r
1523 safe_run(str);\r
1524\r
1525 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc,wan,htb_r2q);\r
1526 safe_run(str);\r
1527\r
1528 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
1529 tc,wan,wan_medium,wan_medium,burst_main,highest_priority);\r
1530 safe_run(str);\r
1531\r
1532 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
1533 tc,wan,up,up,burst_main,highest_priority);\r
1534 safe_run(str);\r
1535 }\r
1536\r
1537 /*-----------------------------------------------------------------*/\r
1538 puts("Locating heavy downloaders and generating root classes ...");\r
1539 /*-----------------------------------------------------------------*/\r
1540 sort(ip,ips,desc_order_by,traffic); \r
1541\r
1542 /*-----------------------------------------------------------------*/\r
1543 /* sub-scope - local variables */ \r
1544 {\r
1545 long long int rate = line;\r
1546 long long int max = line;\r
1547 int group_count = 0;\r
1548 FILE *credit_file = NULL;\r
1549 \r
1550 if(!just_preview && !dry_run && enable_credit)\r
1551 {\r
1552 credit_file = fopen(credit,"w");\r
1553 }\r
1554 \r
1555 for_each(group,groups)\r
1556 {\r
1557 if(!just_preview)\r
1558 {\r
1559 //download\r
1560 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
1561 tc, lan, parent, group->id, rate, max, burst_group, highest_priority+1, group->desired);\r
1562 safe_run(str);\r
1563 \r
1564 //upload\r
1565 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
1566 tc, wan, parent, group->id, rate*up/line, max*up/line, burst_group, highest_priority+1, group->desired);\r
1567 safe_run(str);\r
1568 }\r
1569 \r
1570 if(group_count++ < max_nesting)\r
1571 {\r
1572 parent = group->id;\r
1573 }\r
1574 \r
1575 rate -= digital_divide*group->min;\r
1576 if(rate < group->min)\r
1577 {\r
1578 rate = group->min;\r
1579 }\r
1580 \r
1581 /*shaping of aggresive downloaders, with credit file support */\r
1582 if(use_credit)\r
1583 {\r
1584 int group_rate = group->min, priority_sequence = lowest_priority;\r
1585 \r
1586 for_each(ip, ips) if(ip->min == group->min && ip->max > ip->min)\r
1587 {\r
1588 if( ip->keyword->data_limit && !ip->fixedprio \r
1589 && ( ip->traffic>ip->credit\r
1590 + (ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))) )\r
1591 {\r
1592 if(group_rate<ip->max)\r
1593 {\r
1594 ip->max=group_rate;\r
1595 }\r
1596 group_rate+=magic_treshold;\r
1597 ip->prio=lowest_priority;\r
1598 if(ip->prio<highest_priority+2)\r
1599 {\r
1600 ip->prio=highest_priority+2;\r
1601 }\r
1602 }\r
1603 else\r
1604 {\r
1605 if( ip->keyword->data_prio \r
1606 && !ip->fixedprio \r
1607 && ( ip->traffic>ip->credit\r
1608 + (ip->min*ip->keyword->data_prio+(ip->keyword->fixed_prio<<20))) )\r
1609 {\r
1610 ip->prio=priority_sequence--;\r
1611 if(ip->prio<highest_priority+1)\r
1612 {\r
1613 ip->prio=highest_priority+1;\r
1614 }\r
1615 }\r
1616 \r
1617 if(credit_file)\r
1618 {\r
1619 unsigned long long lcredit=0;\r
1620 \r
1621 if((ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))>ip->traffic)\r
1622 {\r
1623 lcredit=(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))-ip->traffic;\r
1624 }\r
1625 fprintf(credit_file,"%s %Lu\n",ip->addr,lcredit);\r
1626 }\r
1627 }\r
1628 } \r
1629 }\r
1630 }\r
1631 if(credit_file)\r
1632 {\r
1633 fclose(credit_file);\r
1634 }\r
1635 }\r
1636\r
1637 if(just_preview)\r
1638 {\r
1639 if(start_shaping)\r
1640 {\r
1641 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap);\r
1642 parse(classmap)\r
1643 {\r
1644 ptr=strchr(_,' ');\r
1645 if(ptr)\r
1646 {\r
1647 *ptr=0;\r
1648 ptr++;\r
1649 if_exists(ip,ips,eq(ip->addr,_))\r
1650 {\r
1651 ip->mark=atoi(ptr);\r
1652 if(ip->max < ip->desired) /* apply FUP limit immediately.... */\r
1653 {\r
1654 printf("Applying limit for %-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
1655 printf("(down: %dk-%dk ", ip->min, ip->max); \r
1656 sprintf(str, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
1657 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
1658 safe_run(str);\r
1659 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1660 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
1661 sprintf(str,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1662 tc, wan, ip->group, ip->mark,\r
1663 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1664 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1665 safe_run(str);\r
1666 }\r
1667 }\r
1668 }\r
1669 }\r
1670 fail\r
1671 { \r
1672 perror(classmap);\r
1673 puts("Warning - classmap file not fund, just generating preview ...");\r
1674 start_shaping=FALSE;\r
1675 }\r
1676 done; /* ugly macro end */\r
1677 }\r
1678 html=preview;\r
1679 json=json_preview;\r
1680 }\r
1681\r
1682 if(!dry_run && !just_flush)\r
1683 {\r
1684 /*-----------------------------------------------------------------*/\r
1685 printf("Writing json overview %s ... ", json);\r
1686 /*-----------------------------------------------------------------*/\r
1687 f=fopen(json, "w");\r
1688 if(f > 0)\r
1689 {\r
1690 int jsoncount=0;\r
1691 fprintf(f, "{\n");\r
1692 for_each(ip, ips)\r
1693 {\r
1694 if( ip->lmsid > 0 \r
1695 && (ip->traffic || ip->direct || ip->proxy || ip->upload))\r
1696 {\r
1697 if(jsoncount)\r
1698 {\r
1699 fprintf(f, ",\n");\r
1700 }\r
1701 fprintf(f, " \"%s\":{ \"lms\": %d, \"ip\":\"%s\", \"total\":%Lu, \"down\":%Lu, \"proxy\":%Lu, \"up\":%Lu, \"min\":%d, \"max\":%d, \"limit\":%d }",\r
1702 ip->name, ip->lmsid, ip->addr, ip->traffic, ip->direct, ip->proxy, ip->upload, ip->min, ip->desired, ip->max);\r
1703 jsoncount++;\r
1704 }\r
1705 }\r
1706 fprintf(f, "}\n");\r
1707 fclose(f);\r
1708 puts("done.");\r
1709 }\r
1710 else\r
1711 {\r
1712 perror(json);\r
1713 }\r
1714 }\r
1715\r
1716 f=fopen(html,"w");\r
1717 if(f > 0)\r
1718 {\r
1719 int count=1;\r
1720 i=0;\r
1721\r
1722 /*-----------------------------------------------------------------*/\r
1723 printf("Sorting data and generating statistics page %s ...\n", html);\r
1724 /*-----------------------------------------------------------------*/\r
1725\r
1726 if(use_jquery_popups)\r
1727 {\r
1728 fprintf(f,"<script type=\"text/javascript\" src=\"%s\"></script>\n", jquery_url);\r
1729 }\r
1730 fputs("<table class=\"decorated last\">\n\\r
1731<caption>Bandwidth classes</caption>\n\\r
1732<thead><tr>\n\\r
1733<th style=\"text-align: right\">#</th>\n\\r
1734<th style=\"text-align: right\">group</th>\n\\r
1735<th style=\"text-align: right\">IPs</th>\n\\r
1736<th style=\"text-align: right\">requested</th>\n",f);\r
1737 fprintf(f,"<th colspan=\"%d\">data limits</th>\n", keywordcount);\r
1738 fputs("</tr></thead><tbody>\n",f);\r
1739\r
1740 row_odd_even = 0;\r
1741 for_each(group, groups) \r
1742 { \r
1743#ifdef DEBUG\r
1744 printf("%d kb/s group: %d bandwidth requested: %d kb/s\n",group->min,group->count,group->desired);\r
1745#endif\r
1746 fprintf(f, "%s<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d&nbsp;kb/s</td>",\r
1747 tr_odd_even(), count, group->min);\r
1748 fprintf(f, "<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d&nbsp;kb/s</td>",\r
1749 group->count, group->desired);\r
1750\r
1751 for_each(keyword, keywords) if(keyword->ip_count)\r
1752 {\r
1753 fprintf(f,"<td style=\"text-align: right\"><span style=\"color:#%s\">%d&nbsp;MB</span></td>",\r
1754 keyword->html_color, group->min*keyword->data_limit);\r
1755 } \r
1756 i += group->desired; \r
1757 total += group->count;\r
1758 count++; \r
1759 }\r
1760#ifdef DEBUG\r
1761 printf("Total groups: %d Total bandwidth requested: %d kb/s\nAGGREGATION: 1/%d\n",\r
1762 count, i, i/line);\r
1763#endif\r
1764 fprintf(f,"</tr></tbody>\n\\r
1765<thead><tr>\n\\r
1766<th colspan=\"2\" style=\"text-align: left\">Line %Ld kb/s</td>",line);\r
1767 fprintf(f,"<th style=\"text-align: right\">%d</td><th style=\"text-align: right\">%d kb/s</td>",total,i);\r
1768\r
1769 for_each(keyword, keywords) if(keyword->ip_count)\r
1770 {\r
1771 fprintf(f,"<th style=\"text-align: right\">%d IPs</th>",keyword->ip_count);\r
1772 }\r
1773 fprintf(f,"</tr><tr><th colspan=\"4\">Aggregation 1/%d</th>\n", (int)(0.5+i/line));\r
1774 fprintf(f,"<th colspan=\"%d\">%d traffic classes</th></tr>\n", keywordcount, total);\r
1775\r
1776 fputs("</thead></table>\n",f);\r
1777 }\r
1778 else if(!dry_run && !just_flush)\r
1779 {\r
1780 perror(html);\r
1781 }\r
1782\r
1783 i=0;\r
1784 if(f > 0)\r
1785 {\r
1786 unsigned long long total_traffic=0, total_direct=0, total_proxy=0, total_upload=0, tmp_sum=0;\r
1787 int active_classes=0;\r
1788 int colspan=12;\r
1789 struct Sum {unsigned long long l; int i; list(Sum);} *sum,*sums=NULL;\r
1790 int limit_count=0, prio_count=0;\r
1791 int popup_button=0;\r
1792\r
1793 if(qos_proxy)\r
1794 {\r
1795 colspan++;\r
1796 }\r
1797 \r
1798 fprintf(f,"<p><table class=\"decorated last\">\n<caption>%s",title);\r
1799 fprintf(f," (%s)</caption>\n", d);\r
1800 fputs("<thead><tr>\n<th colspan=\"3\">&nbsp;</th>\n",f);\r
1801 fputs("<th style=\"text-align: right\">credit</th>\n\\r
1802<th style=\"text-align: right\">FUP</th>\n\\r
1803<th style=\"text-align: right\">total</th>\n\\r
1804<th style=\"text-align: right\">down</th>\n",f);\r
1805 if(qos_proxy)\r
1806 {\r
1807 fputs("<th style=\"text-align: right\">proxy</th>\n",f);\r
1808 }\r
1809 fputs("<th style=\"text-align: right\">up</th>\n\\r
1810<th style=\"text-align: right\">min</th>\n\\r
1811<th style=\"text-align: right\">max</th>\n\\r
1812<th style=\"text-align: right\">limit</th>\n\\r
1813<th>&nbsp;</th>\n\\r
1814</tr><tr>\n\\r
1815<th style=\"text-align: right\">#</th>\n\\r
1816<th>hostname [+sharing]</th>\n\\r
1817<th style=\"text-align: right\">LMS</th>\n\\r
1818<th style=\"text-align: right\">MB</th>\n\\r
1819<th style=\"text-align: right\">MB</th>\n\\r
1820<th style=\"text-align: right\">MB</th>\n\\r
1821<th style=\"text-align: right\">MB</th>\n\\r
1822<th style=\"text-align: right\">MB</th>\n\\r
1823<th style=\"text-align: right\">kb/s</th>\n\\r
1824<th style=\"text-align: right\">kb/s</th>\n\\r
1825<th style=\"text-align: right\">kb/s</th>\n\\r
1826<th>prio</th>\n\\r
1827</tr></thead><tbody>\n",f); \r
1828\r
1829 row_odd_even = 0;\r
1830 for_each(ip,ips) if(!use_jquery_popups || !ip->sharing)\r
1831 {\r
1832 char *f1="", *f2="";\r
1833 i++;\r
1834\r
1835 if(ip->max < ip->desired) \r
1836 { \r
1837 f1="<span style=\"color:red\">"; \r
1838 f2="</span>"; \r
1839 limit_count++; \r
1840 } \r
1841 else if(ip->prio > highest_priority+1) \r
1842 { \r
1843 f1="<span style=\"color:brown\">"; \r
1844 f2="</span>"; \r
1845 prio_count++; \r
1846 } \r
1847\r
1848#ifdef DEBUG\r
1849 printf("%03d. %-22s %10Lu (%d/%d)\n",i ,ip->name, ip->traffic, ip->min, ip->max); \r
1850#endif\r
1851 /* hostnames -------------------------------------- */\r
1852 fprintf(f,"%s<td style=\"text-align: right\"><a name=\"%s\"></a>%d</td><td><a class=\"blue\" target=\"_blank\" href=\"%s%s.log\">%s</a>\n", \r
1853 tr_odd_even(), ip->name, i, log_url, ip->name, ip->name);\r
1854\r
1855 if(use_jquery_popups)\r
1856 {\r
1857 fprintf(f,"<span id=\"sharing_%d\" style=\"display:none\">",i);\r
1858 popup_button=0;\r
1859 for_each(sharedip, ips) if(eq(ip->name, sharedip->sharing))\r
1860 {\r
1861 fprintf(f,"<br /><a class=\"blue\" target=\"_blank\" href=\"%s%s.log\">%s</a>\n", log_url, sharedip->name, sharedip->name);\r
1862 popup_button++;\r
1863 }\r
1864 fputs("</span>\n",f);\r
1865 if(popup_button)\r
1866 {\r
1867 fprintf(f,"<span>[<a class=\"blue\" href=\"#\" onClick=\"$(this).parent().hide();$(\'#sharing_%d\').show();$(\'#download_%d\').show();$(\'#upload_%d\').show();return(false);\" style=\"cursor: pointer;\">+%d</a>]</span>",\r
1868 i, i, i, popup_button);\r
1869 }\r
1870 }\r
1871 fputs("</td>\n",f);\r
1872 /* ----------------------------------------------- */\r
1873\r
1874 if(found_lmsid)\r
1875 {\r
1876 fputs("<td style=\"text-align: right\">",f);\r
1877 if(ip->lmsid > 0)\r
1878 {\r
1879 fprintf(f,"<a class=\"blue\" target=\"_blank\" href=\"%s%d\">%04d</a>\n", lms_url, ip->lmsid, ip->lmsid);\r
1880 }\r
1881 else if(ip->lmsid == 0)\r
1882 {\r
1883 fputs("-------",f);\r
1884 }\r
1885 fputs("</td>\n",f);\r
1886 }\r
1887 fprintf(f,"<td style=\"text-align: right\">%Lu</td>\n", ip->credit);\r
1888 fprintf(f,"<td style=\"text-align: right\"><span style=\"color:#%s\">%Lu</span></td>",\r
1889 ip->keyword->html_color,\r
1890 ip->credit+(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20)));\r
1891 fprintf(f,"<td style=\"text-align: right\">%s%Lu%s", f1, ip->traffic, f2);\r
1892\r
1893 /* download --------------------------------------- */\r
1894 fprintf(f,"</td><td style=\"text-align: right\">%Lu", ip->direct);\r
1895 if(use_jquery_popups)\r
1896 {\r
1897 fprintf(f,"<span id=\"download_%d\" style=\"display:none\">",i);\r
1898 for_each(sharedip, ips) if(eq(ip->name, sharedip->sharing))\r
1899 {\r
1900 fprintf(f,"<br />%Lu", sharedip->direct);\r
1901 }\r
1902 fputs("</span>\n",f);\r
1903 }\r
1904 fputs("</td>\n",f);\r
1905 /* ----------------------------------------------- */\r
1906\r
1907 if(qos_proxy)\r
1908 {\r
1909 fprintf(f,"<td style=\"text-align: right\">%Lu</td>\n", ip->proxy);\r
1910 }\r
1911 /* upload ---------------------------------------- */\r
1912 fprintf(f,"<td style=\"text-align: right\">%Lu", ip->upload);\r
1913 if(use_jquery_popups)\r
1914 {\r
1915 fprintf(f,"<span id=\"upload_%d\" style=\"display:none\">",i);\r
1916 for_each(sharedip,ips) if(eq(ip->name, sharedip->sharing))\r
1917 {\r
1918 fprintf(f,"<br />%Lu", sharedip->upload);\r
1919 }\r
1920 fputs("</span>\n",f);\r
1921 }\r
1922 fputs("</td>\n",f);\r
1923 /* ----------------------------------------------- */\r
1924\r
1925 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1926<td style=\"text-align: right\">%d</td>\n\\r
1927<td style=\"text-align: right\">%s%d%s</td>\n\\r
1928<td>%s%d%s</td></tr>\n",\r
1929 ip->min, ip->desired, \r
1930 f1, ip->max, f2, \r
1931 f1, ip->prio, f2);\r
1932\r
1933 total_traffic+=ip->traffic;\r
1934 total_direct+=ip->direct;\r
1935 total_proxy+=ip->proxy;\r
1936 total_upload+=ip->upload;\r
1937 if(ip->traffic>0)\r
1938 {\r
1939 active_classes++;\r
1940 tmp_sum+=ip->traffic;\r
1941 create(sum,Sum);\r
1942 sum->l=tmp_sum;\r
1943 sum->i=active_classes;\r
1944 insert(sum,sums,order_by,i);\r
1945 }\r
1946\r
1947 if(!just_preview)\r
1948 {\r
1949 append_log(ip);\r
1950 for_each(sharedip,ips) if(eq(ip->name, sharedip->sharing))\r
1951 {\r
1952 append_log(sharedip);\r
1953 }\r
1954 }\r
1955 }\r
1956 fprintf(f,"</tbody><thead><tr>\n\\r
1957<th colspan=\"%d\" style=\"text-align: left\">%d CLASSES</th>", colspan-7, i);\r
1958 fprintf(f,"<th style=\"text-align: right\">%Lu</th><th style=\"text-align: right\">%Lu</th>\n", total_traffic, total_direct);\r
1959 if(qos_proxy)\r
1960 {\r
1961 fprintf(f,"<th style=\"text-align: right\">%Lu</th>\n", total_proxy);\r
1962 }\r
1963 fprintf(f,"<th style=\"text-align: right\">%Lu</th>", total_upload);\r
1964 fprintf(f,"<th colspan=\"4\"><span style=\"color:red\">LIMIT %dx</span> <span style=\"color:brown\">LOW-PRIO %dx</span></th></tr>\n</thead></table>\n",limit_count,prio_count);\r
1965\r
1966 row_odd_even = 0;\r
1967 if(active_classes>10)\r
1968 {\r
1969 int top20_count=0,top20_perc1=0;\r
1970 long long top20_perc2=0;\r
1971 unsigned long long top20_sum=0l;\r
1972 \r
1973 fputs("<a name=\"erp\"></a><p><table class=\"decorated last\"><caption>Enterprise Resource Planning (ERP)</caption>\n",f);\r
1974 fputs("<thead><tr>\n\\r
1975<th>Analytic category</th>\n\\r
1976<th colspan=\"2\" style=\"text-align: center\">Active Classes</th>\n\\r
1977<th colspan=\"2\" style=\"text-align: center\">Data transfers</th>\n\\r
1978</tr></thead><tbody>\n",f);\r
1979\r
1980 if_exists(sum,sums,sum->l>=total_traffic/4)\r
1981 {\r
1982 fprintf(f,"%s<td>Top 25%% of traffic</td>\n", tr_odd_even());\r
1983 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1984<td style=\"text-align: right\">%d %%</td>\n\\r
1985<td style=\"text-align: right\">%Lu MB</td>\n\\r
1986<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
1987 sum->i, (100*sum->i+50)/active_classes, sum->l, (100*sum->l+50)/total_traffic);\r
1988 }\r
1989 \r
1990 if_exists(sum,sums,sum->i==10)\r
1991 {\r
1992 fprintf(f,"%s<td>Top 10 downloaders</td>\n", tr_odd_even());\r
1993 fprintf(f,"<td style=\"text-align: right\"><strong>10</strong></td>\n\\r
1994<td style=\"text-align: right\">%d %%</td>\n\\r
1995<td style=\"text-align: right\">%Lu MB</td>\n\\r
1996<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
1997 (100*sum->i+50)/active_classes, sum->l, (100*sum->l+50)/total_traffic);\r
1998 }\r
1999\r
2000 if_exists(sum,sums,sum->l>=total_traffic/2)\r
2001 {\r
2002 fprintf(f,"%s<td>Top 50%% of traffic</td>\n", tr_odd_even());\r
2003 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
2004<td style=\"text-align: right\">%d %%</td>\n\\r
2005<td style=\"text-align: right\">%Lu MB</td>\n\\r
2006<td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",\r
2007 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
2008 }\r
2009\r
2010 if_exists(sum,sums,sum->l>=4*total_traffic/5)\r
2011 {\r
2012 fprintf(f,"%s<td>Top 80%% of traffic</td>\n", tr_odd_even());\r
2013 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
2014<td style=\"text-align: right\">%d %%</td>\n\\r
2015<td style=\"text-align: right\">%Lu MB</td>\n\\r
2016<td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",\r
2017 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
2018 }\r
2019\r
2020 if_exists(sum,sums,sum->i>=(active_classes+1)/5)\r
2021 {\r
2022 fprintf(f,"%s<td>Top 20%% downloaders</td>\n", tr_odd_even());\r
2023 top20_count=sum->i;\r
2024 top20_perc1=(100*sum->i+50)/active_classes;\r
2025 top20_sum=sum->l;\r
2026 top20_perc2=(100*sum->l+50)/total_traffic;\r
2027 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
2028<td style=\"text-align: right\"><strong>%d %%</strong></td>\n\\r
2029<td style=\"text-align: right\">%Lu MB</td>\n\\r
2030<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
2031 top20_count,top20_perc1,top20_sum,top20_perc2);\r
2032 }\r
2033\r
2034 if_exists(sum,sums,sum->i>=(active_classes+1)/4)\r
2035 {\r
2036 fprintf(f,"%s<td>Top 25%% downloaders</td>\n", tr_odd_even());\r
2037 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
2038<td style=\"text-align: right\">%d %%</td>\n\\r
2039<td style=\"text-align: right\">%Lu MB</td>\n\\r
2040<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
2041 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
2042 }\r
2043\r
2044 if_exists(sum,sums,sum->i>=(active_classes+1)/2)\r
2045 {\r
2046 fprintf(f,"%s<td>Top 50%% downloaders</td>\n", tr_odd_even());\r
2047 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
2048<td style=\"text-align: right\"><strong>%d %%</strong></td>\n\\r
2049<td style=\"text-align: right\">%Lu MB</td>\n\\r
2050<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
2051 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
2052 }\r
2053\r
2054 if_exists(sum,sums,sum->i>=4*(active_classes+1)/5)\r
2055 {\r
2056 fprintf(f,"%s<td>Top 80%% downloaders</td>\n", tr_odd_even());\r
2057 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
2058<td style=\"text-align: right\">%d %%</td>\n\\r
2059<td style=\"text-align: right\">%Lu MB</td>\n\\r
2060<td style=\"text-align: right\">%Ld %%</td></tr></tbody>\n",\r
2061 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
2062 }\r
2063\r
2064 fprintf(f,"<thead><tr><th><a class=\"blue\" target=\"_blank\" href=\"%sERP.log\">All users, all traffic</a></th>\n", log_url);\r
2065 fprintf(f,"<th style=\"text-align: right\">%d</th>\n\\r
2066<th style=\"text-align: right\">100 %%</th>\n\\r
2067<th style=\"text-align: right\">%Lu MB</th>\n\\r
2068<th style=\"text-align: right\">100 %%</th></tr>\n",active_classes,total_traffic);\r
2069 fputs("</thead></table>\n", f);\r
2070\r
2071 /* write basic ERP data to log directory */\r
2072 if(!just_preview)\r
2073 {\r
2074 FILE *iplog;\r
2075 sprintf(str,"%s/ERP.log",log_dir);\r
2076 iplog=fopen(str,"a");\r
2077 if(iplog)\r
2078 {\r
2079 fprintf(iplog,"%ld\t%d\t%d %%\t%Lu M\t%Ld %%\tACTIVE %d\tTRAFFIC %Lu M\tCLASSES %d\tFUP-LIMIT %d\tLOW-PRIO %d\t%s",\r
2080 time(NULL), top20_count, top20_perc1, top20_sum, top20_perc2, \r
2081 active_classes, total_traffic, i, limit_count, prio_count, d); /* d = date*/\r
2082 fclose(iplog);\r
2083 }\r
2084 else\r
2085 {\r
2086 perror(str);\r
2087 }\r
2088 }\r
2089 }\r
2090\r
2091 fprintf(f, stats_html_signature, version);\r
2092 fclose(f);\r
2093 }\r
2094\r
2095 if(just_preview)\r
2096 {\r
2097 char swchar='p';\r
2098 if(start_shaping)\r
2099 {\r
2100 swchar='s';\r
2101 }\r
2102 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar);\r
2103 exit(0);\r
2104 } \r
2105\r
2106 i=0;\r
2107#ifdef DEBUG\r
2108 printf("%-22s %-15s mark\n","name","ip");\r
2109#endif\r
2110\r
2111 printf("Writing %s ... ", classmap); \r
2112 f = fopen(classmap, "w"); \r
2113 if(f < 0)\r
2114 {\r
2115 perror(classmap);\r
2116 }\r
2117\r
2118 /*-----------------------------------------------------------------*/\r
2119 puts("Generating iptables and tc classes ... ");\r
2120 /*-----------------------------------------------------------------*/\r
2121\r
2122 for_each(ip, ips) if(ip->mark > 0)\r
2123 {\r
2124 if(idxs)\r
2125 {\r
2126 char *buf;\r
2127 duplicate(ip->addr,buf);\r
2128 buf=hash_id(ip->addr,32-idxtable_bitmask1); \r
2129 \r
2130 string(chain_forward,6+strlen(buf));\r
2131 strcpy(chain_forward,"forw_");\r
2132 strcat(chain_forward,buf);\r
2133\r
2134 string(chain_postrouting,6+strlen(buf));\r
2135 strcpy(chain_postrouting,"post_");\r
2136 strcat(chain_postrouting,buf);\r
2137 \r
2138 free(buf);\r
2139 }\r
2140 else\r
2141 {\r
2142 chain_forward="FORWARD";\r
2143 chain_postrouting="POSTROUTING";\r
2144 }\r
2145\r
2146#ifdef DEBUG\r
2147 printf("%-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
2148#endif\r
2149\r
2150 /* -------------------------------------------------------- mark download */\r
2151 \r
2152 sprintf(str, "-A %s -d %s/32 -o %s -j %s%d",\r
2153 chain_postrouting, ip->addr, lan, mark_iptables, ip->mark);\r
2154 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/\r
2155 /* -m limit --limit 1/s */ \r
2156 save_line(str);\r
2157\r
2158 if(qos_proxy)\r
2159 {\r
2160 sprintf(str, "-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",\r
2161 chain_postrouting, proxy_ip, proxy_port, ip->addr, lan, mark_iptables, ip->mark);\r
2162 /*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
2163 save_line(str);\r
2164 }\r
2165\r
2166 sprintf(str, "-A %s -d %s/32 -o %s -j ACCEPT",\r
2167 chain_postrouting, ip->addr, lan);\r
2168 save_line(str);\r
2169\r
2170 /* -------------------------------------------------------- mark upload */\r
2171 sprintf(str, "-A %s -s %s/32 -o %s -j %s%d", \r
2172 chain_forward, ip->addr, wan, mark_iptables, ip->mark);\r
2173 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/\r
2174 save_line(str);\r
2175\r
2176 sprintf(str, "-A %s -s %s/32 -o %s -j ACCEPT",\r
2177 chain_forward, ip->addr, wan);\r
2178 save_line(str);\r
2179\r
2180 if(ip->min)\r
2181 {\r
2182 /* -------------------------------------------------------- download class */\r
2183#ifdef DEBUG\r
2184 printf("(down: %dk-%dk ", ip->min, ip->max); \r
2185#endif\r
2186\r
2187 sprintf(str, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
2188 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
2189 safe_run(str);\r
2190\r
2191 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
2192 {\r
2193 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s", \r
2194 tc, lan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
2195 safe_run(str);\r
2196 }\r
2197\r
2198 if(filter_type == 1)\r
2199 {\r
2200 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
2201 tc, lan, ip->mark, ip->mark);\r
2202 safe_run(str);\r
2203 }\r
2204\r
2205 /* -------------------------------------------------------- upload class */\r
2206#ifdef DEBUG\r
2207 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
2208 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
2209#endif\r
2210\r
2211 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
2212 tc, wan, ip->group, ip->mark,\r
2213 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
2214 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
2215 safe_run(str);\r
2216 \r
2217 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
2218 {\r
2219 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s",\r
2220 tc, wan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
2221 safe_run(str);\r
2222 } \r
2223\r
2224 if(filter_type == 1)\r
2225 {\r
2226 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
2227 tc, wan, ip->mark, ip->mark);\r
2228 safe_run(str);\r
2229 }\r
2230 \r
2231 if(f > 0)\r
2232 {\r
2233 fprintf(f, "%s %d\n", ip->addr, ip->mark);\r
2234 }\r
2235 }\r
2236 else\r
2237 {\r
2238#ifdef DEBUG\r
2239 printf("(sharing %s)\n", ip->sharing);\r
2240#endif\r
2241 }\r
2242 i++;\r
2243 }\r
2244 if(f > 0)\r
2245 {\r
2246 puts("done.");\r
2247 fclose(f);\r
2248 }\r
2249 \r
2250 if(idxs)\r
2251 {\r
2252 chain_forward = "forw_common";\r
2253 chain_postrouting = "post_common";\r
2254 }\r
2255 else\r
2256 {\r
2257 chain_forward = "FORWARD";\r
2258 chain_postrouting = "POSTROUTING";\r
2259 }\r
2260 /* -------------------------------- classify or reject free download */\r
2261 {\r
2262 char *final_chain = "DROP"; /* REJECT would be better, but it is impossible in mangle */\r
2263 if(free_min)\r
2264 {\r
2265 final_chain = "ACCEPT";\r
2266 }\r
2267 if(qos_proxy)\r
2268 {\r
2269 if(free_min)\r
2270 {\r
2271 sprintf(str,"-A %s -s %s -p tcp --sport %d -o %s -j %s%d",\r
2272 chain_postrouting,proxy_ip,proxy_port,lan,mark_iptables,3);\r
2273 save_line(str);\r
2274 }\r
2275 sprintf(str,"-A %s -s %s -p tcp --sport %d -o %s -j %s",\r
2276 chain_postrouting,proxy_ip,proxy_port,lan,final_chain);\r
2277 save_line(str);\r
2278 }\r
2279 if(free_min)\r
2280 {\r
2281 sprintf(str,"-A %s -o %s -j %s%d", chain_postrouting, lan, mark_iptables, 3);\r
2282 save_line(str);\r
2283 }\r
2284 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
2285 save_line(str);\r
2286 /* ------------------------------- classify or reject free upload */\r
2287 if(free_min)\r
2288 {\r
2289 sprintf(str,"-A %s -o %s -j %s%d", chain_forward, wan, mark_iptables, 3);\r
2290 save_line(str);\r
2291 }\r
2292 sprintf(str,"-A %s -o %s -j %s", chain_forward, wan, final_chain);\r
2293 save_line(str);\r
2294 }\r
2295\r
2296 if(free_min) /* allocate free bandwith if it is not zero... */ \r
2297 {\r
2298 /*-----------------------------------------------------------------*/\r
2299 puts("Generating free bandwith classes ...");\r
2300 /*-----------------------------------------------------------------*/\r
2301 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
2302 tc, lan, parent, free_min, free_max,burst, lowest_priority);\r
2303 safe_run(str);\r
2304 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
2305 tc, wan, parent, free_min, free_max, burst, lowest_priority);\r
2306 safe_run(str);\r
2307 /* tc SFQ */\r
2308 if(strcmpi(qos_leaf, "none"))\r
2309 {\r
2310 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, lan, qos_leaf);\r
2311 safe_run(str);\r
2312 \r
2313 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, wan, qos_leaf);\r
2314 safe_run(str);\r
2315 } \r
2316 /* tc handle 1 fw flowid */\r
2317 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, lan);\r
2318 safe_run(str);\r
2319\r
2320 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, wan);\r
2321 safe_run(str);\r
2322 }\r
2323 printf("Total IP count: %d\n", i);\r
2324 run_restore(); \r
2325 if(log_file)\r
2326 {\r
2327 fclose(log_file);\r
2328 }\r
2329 return 0;\r
2330 /* that's all folks, thank you for reading it all the way up to this point ;-) */\r
2331 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */\r
2332}\r
This page took 0.431088 seconds and 4 git commands to generate.