json.c
[svn/Prometheus-QoS/.git] / prometheus.c
... / ...
CommitLineData
1 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2 /* Prometheus QoS - you can "steal fire" from your ISP */\r
3/* "fair-per-IP" quality of service (QoS) utility */\r
4/* requires Linux 2.4.x or 2.6.x with HTB support */\r
5/* Copyright(C) 2005-2012 Michael Polak, Arachne Labs */\r
6/* iptables-restore support Copyright(C) 2007-2008 ludva */\r
7/* Credit: CZFree.Net,Martin Devera,Netdave,Aquarius,Gandalf */\r
8/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
9\r
10/* Modified by: xChaos, 20121011\r
11 ludva, 20080415\r
12 \r
13 Prometheus QoS is free software; you can redistribute it and/or\r
14 modify it under the terms of the GNU General Public License as \r
15 published by the Free Software Foundation; either version 2.1 of \r
16 the License, or (at your option) any later version.\r
17\r
18 Prometheus QoS is distributed in the hope that it will be useful,\r
19 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
21 General Public License for more details.\r
22\r
23 You should have received a copy of the GNU General Public License\r
24 along with Prometheus Qos; if not, write to the Free Software\r
25 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA \r
26 \r
27 GNU General Public License is located in file COPYING */\r
28\r
29#define STRLEN 512\r
30#undef DEBUG\r
31\r
32#include "cll1-0.6.2.h"\r
33#include "ipstruct.h"\r
34\r
35const char *version = "0.8.3-g";\r
36\r
37/* Version numbers: 0.8.3 is development releases ("beta"), 0.8.4 will be "stable" */\r
38/* Debian(RPM) package versions/patchlevels: 0.7.9-2, 0.8.0-1, 0.8.0-2, etc. */\r
39/* C source code development versions ("beta"): 0.7.9-a, 0.8.1-b, etc. */\r
40/* C source code release versions: 0.8.0, 0.8.2, 0.8.4, etc. */\r
41\r
42const char *stats_html_signature = "<span class=\"small\">Statistics generated by Prometheus QoS version %s<br />GPL+Copyright(C)2005-2012 Michael Polak, <a target=\"_blank\" href=\"http://www.arachne.cz/\">Arachne Labs</a></span>\n";\r
43\r
44/* ======= Help screen is hopefuly self-documenting part of code :-) ======= */\r
45\r
46void help(void)\r
47{\r
48 puts("Command line switches:\n\\r
49\n\\r
50-d Dry run (preview tc and iptables commands on stdout)\n\\r
51-r Run (reset all statistics and start shaping - daily usage)\n\\r
52-p just generate Preview of data transfer statistics and exit (after -r)\n\\r
53-s start Shaping FUP limits (keeps data transfer stat like -p) (after -r)\n\\r
54-n run Now (like -r delay - overrides qos-free-delay keyword, after boot)\n\\r
55-f just Flush iptables and tc classes and exit (stop shaping, no QiS)\n\\r
56-9 emergency iptables flush (like -f, but dumps data transfer statistics)\n\\r
57\n\\r
58-c filename force alternative /etc/prometheus/prometheus.conf filename\n\\r
59-h filename force alternative /etc/hosts filename (overrides hosts keyword)\n\\r
60-l Mmm YYYY generate HTML summary of Logged traffic (Mmm=Jan-Dec) (and exit)\n\\r
61-m generate HTML summary of traffic for yesterday's Month (and exit)\n\\r
62-y generate HTML summary of traffic for yesterday's Year (and exit)\n\\r
63-? --help show this help scree (and exit)\n\\r
64-v --version show Version number of this utility (and exit)\n");\r
65}\r
66\r
67/* ======= All path names are defined here (for RPM patch) ======= */\r
68\r
69const char *tc = "/sbin/tc"; /* requires tc with HTB support */\r
70const char *iptables = "/sbin/iptables"; /* requires iptables utility */\r
71const char *iptablessave = "/sbin/iptables-save"; /* not yet required */\r
72const char *iptablesrestore = "/sbin/iptables-restore"; /* requires iptables-restore */\r
73const char *ls = "/bin/ls"; /* this is not user configurable :-) */\r
74\r
75char *config = "/etc/prometheus/prometheus.conf"; /* main configuration file */\r
76char *hosts = "/etc/prometheus/hosts"; /* per-IP bandwidth definition file */\r
77\r
78char *iptablesfile = "/var/spool/prometheus.iptables"; /* temporary file for iptables-restore*/\r
79char *credit = "/var/lib/misc/prometheus.credit"; /* credit log file */\r
80char *classmap = "/var/lib/misc/prometheus.classes"; /* credit log file */\r
81char *html = "/var/www/traffic.html"; /* hall of fame - html version */\r
82char *preview = "/var/www/preview.html"; /* hall of fame preview - html version */\r
83char *json_traffic = "/var/www/logs/traffic.json"; /* hall of fame - json version */\r
84char *json_preview = "/var/www/logs/preview.json"; /* hall of fame preview - json version */\r
85char *cmdlog = "/var/log/prometheuslog"; /* command log filename */\r
86char *log_dir = "/var/www/logs/"; /* log directory pathname, ended with slash */\r
87char *log_url = "/logs/"; /* log directory relative URI prefix (partial URL) */\r
88char *html_log_dir = "/var/www/logs/html/";\r
89\r
90char *jquery_url = "http://code.jquery.com/jquery-latest.js";\r
91char *lms_url = "/lms/?m=customerinfo&amp;id=";\r
92int use_jquery_popups = 1;\r
93int row_odd_even = 0; /*<tr class="odd/even"> */\r
94 \r
95/* === Configuraration file values defaults - stored in global variables ==== */\r
96\r
97int filter_type = 1; /*1 mark, 2 classify*/\r
98char *mark = "MARK";\r
99char *mark_iptables = "MARK --set-mark ";\r
100int dry_run = 0; /* preview - use puts() instead of system() */\r
101char *iptablespreamble = "*mangle\n:PREROUTING ACCEPT [0:0]\n:POSTROUTING ACCEPT [0:0]\n:INPUT ACCEPT [0:0]\n:OUTPUT ACCEPT [0:0]\n:FORWARD ACCEPT [0:0]";\r
102FILE *iptables_file = NULL;\r
103int enable_credit = 1; /* enable credit file */\r
104int use_credit = 0; /* use credit file (if enabled)*/\r
105char *title = "Hall of Fame - Greatest Suckers"; /* hall of fame title */\r
106int hall_of_fame = 1; /* enable hall of fame */\r
107char *lan = "eth0"; /* LAN interface */\r
108char *lan_medium = "100Mbit"; /* 10Mbit/100Mbit ethernet */\r
109char *wan = "eth1"; /* WAN/ISP interface */\r
110char *wan_medium = "100Mbit"; /* 10Mbit/100Mbit ethernet */\r
111char *qos_leaf = "sfq perturb 5"; /* leaf discipline */\r
112char *qos_free_zone = NULL; /* QoS free zone */\r
113int qos_proxy = 1; /* include proxy port to QoS */\r
114int found_lmsid = 0; /* show links to users in LMS information system */\r
115int include_upload = 1; /* upload+download=total traffic */\r
116char *proxy_ip = "192.168.1.1/32"; /* our IP with proxy port */\r
117int proxy_port = 3128; /* proxy port number */\r
118long long int line = 1024; /* WAN/ISP download in kbps */\r
119long long int up = 1024; /* WAN/ISP upload in kbps */\r
120int free_min = 32; /* minimum guaranted bandwidth for all undefined hosts */\r
121int free_max = 64; /* maximum allowed bandwidth for all undefined hosts */\r
122int qos_free_delay = 0; /* seconds to sleep before applying new QoS rules */\r
123int digital_divide = 2; /* controls digital divide weirdness ratio, 1...3 */ \r
124int max_nesting = 3; /* maximum nesting of HTB clases, built-in maximum seems to be 4 */\r
125int htb_r2q = 256; /* should work for leaf values 512 kbps to 8 Mbps */\r
126int burst = 8; /* HTB burst (in kbits) */\r
127int burst_main = 64;\r
128int burst_group = 32;\r
129int magic_treshold = 8; /* reduce ceil by X*magic_treshhold kbps (hard shaping) */\r
130int keywordcount = 0;\r
131int class_count = 0;\r
132int ip_count = 0;\r
133/* not yet implemented:\r
134int fixed_packets = 0; maximum number of pps per IP address (not class!) \r
135int packet_limit = 5; maximum number of pps to htn CEIL, not rate !!! \r
136*/\r
137FILE *log_file = NULL;\r
138char *kwd = "via-prometheus"; /* /etc/hosts comment, eg. #qos-64-128 */\r
139\r
140const int highest_priority = 0; /* highest HTB priority (HTB built-in value is 0) */\r
141const int lowest_priority = 7; /* lowest HTB priority (HTB built-in value is 7) */\r
142const int idxtable_treshold1 = 24; /* this is no longer configurable */\r
143const int idxtable_treshold2 = 12; /* this is no longer configurable */\r
144const int idxtable_bitmask1 = 3; /* this is no longer configurable */\r
145const int idxtable_bitmask2 = 3; /* this is no longer configurable */\r
146\r
147struct IP *ips = NULL, *ip, *sharedip;\r
148struct Group *groups = NULL, *group;\r
149struct Keyword *keyword, *defaultkeyword=NULL, *keywords=NULL;\r
150\r
151void parse_ip_log(int argc, char **argv);\r
152/* implemented in parselog.c */\r
153\r
154void parse_hosts(char *hosts);\r
155/* implemented in parsehosts.c */\r
156\r
157void write_json_traffic(char *json);\r
158/* implemented in json.c */\r
159\r
160const char *tr_odd_even(void)\r
161{\r
162 row_odd_even = 1 - row_odd_even;\r
163 if(row_odd_even)\r
164 {\r
165 return "<tr class=\"even\">\n";\r
166 }\r
167 else\r
168 {\r
169 return "<tr class=\"odd\">\n";\r
170 }\r
171}\r
172\r
173/* ==== This is C<<1 stuff - learn C<<1 first! https://dev.arachne.cz/svn/cll1h ==== */\r
174\r
175struct Index\r
176{\r
177 char *addr;\r
178 char *id;\r
179 struct Index *parent;\r
180 int bitmask;\r
181 int children;\r
182 list(Index);\r
183} *idxs=NULL, *idx, *metaindex;\r
184\r
185void TheIP(void);\r
186/* function implemented in parsehosts.c */\r
187\r
188/* ====== iptables indexes are used to reduce complexity to log8(N) ===== */\r
189\r
190char *index_id(char *ip, int bitmask);\r
191/* function implemented in ipv4subnets.c */\r
192\r
193char *subnet_id(char *ip, int bitmask);\r
194/* function implemented in ipv4subnets.c */\r
195\r
196/* ================= Let's parse configuration file here ================ */\r
197\r
198void reject_config_and_exit(char *filename)\r
199{\r
200 printf("Configuration file %s rejected - abnormal exit.",filename);\r
201 exit(-1);\r
202}\r
203\r
204void get_config(char *config_filename)\r
205{\r
206 char *cnf="mark";\r
207 \r
208 printf("Configured keywords: ");\r
209 parse(config_filename)\r
210 {\r
211 option("keyword",kwd);\r
212 if(kwd)\r
213 {\r
214 printf("%s ",kwd);\r
215\r
216 create(keyword,Keyword);\r
217 keyword->key=kwd;\r
218 keyword->asymetry_ratio=1; /* ratio for ADSL-like upload */\r
219 keyword->asymetry_fixed=0; /* fixed treshold for ADSL-like upload */\r
220 keyword->data_limit=8; /* hard shaping: apply magic_treshold if max*data_limit MB exceeded */\r
221 keyword->data_prio=4; /* soft shaping (qos): reduce HTB prio if max*data_prio MB exceeded */\r
222 keyword->fixed_limit=0; /* fixed data limit for setting lower HTB ceil */\r
223 keyword->fixed_prio=0; /* fixed data limit for setting lower HTB prio */\r
224 keyword->reserve_min=8; /* bonus for nominal HTB rate bandwidth (in kbps) */\r
225 keyword->reserve_max=0; /* malus for nominal HTB ceil (in kbps) */\r
226 keyword->default_prio=highest_priority+1;\r
227 keyword->html_color="000000";\r
228 keyword->ip_count=0;\r
229 keyword->leaf_discipline="";\r
230\r
231 push(keyword,keywords);\r
232 if(!defaultkeyword) defaultkeyword=keyword;\r
233 keywordcount++;\r
234 \r
235 kwd=NULL;\r
236 }\r
237 else\r
238 {\r
239 for_each(keyword,keywords)\r
240 {\r
241 int l=strlen(keyword->key);\r
242\r
243 if(!strncmp(keyword->key,_,l) && strlen(_)>l+2)\r
244 {\r
245 char *tmptr=_; /* <---- l+1 ----> */\r
246 _+=l+1; /* via-prometheus-asymetry-ratio, etc. */\r
247 ioption("asymetry-ratio",keyword->asymetry_ratio);\r
248 ioption("asymetry-treshold",keyword->asymetry_fixed);\r
249 ioption("magic-relative-limit",keyword->data_limit);\r
250 ioption("magic-relative-prio",keyword->data_prio);\r
251 loption("magic-fixed-limit",keyword->fixed_limit);\r
252 loption("magic-fixed-prio",keyword->fixed_prio);\r
253 ioption("htb-default-prio",keyword->default_prio);\r
254 ioption("htb-rate-bonus",keyword->reserve_min);\r
255 ioption("htb-ceil-malus",keyword->reserve_max);\r
256 option("leaf-discipline",keyword->leaf_discipline);\r
257 option("html-color",keyword->html_color);\r
258 _=tmptr;\r
259 \r
260 if(keyword->data_limit || keyword->fixed_limit || \r
261 keyword->data_prio || keyword->fixed_prio)\r
262 {\r
263 use_credit=1; \r
264 }\r
265 }\r
266 }\r
267 }\r
268\r
269 option("tc",tc);\r
270 option("iptables",iptables);\r
271 option("iptables-save",iptablessave); /* new */\r
272 option("iptables-restore",iptablesrestore); /* new */\r
273 option("iptables-in-filename",iptablesfile); /* new */\r
274 option("hosts",hosts);\r
275 option("lan-interface",lan);\r
276 option("wan-interface",wan);\r
277 option("lan-medium",lan_medium);\r
278 option("wan-medium",wan_medium);\r
279 lloption("wan-download",line);\r
280 lloption("wan-upload",up);\r
281 ioption("hall-of-fame-enable",hall_of_fame);\r
282 option("hall-of-fame-title",title);\r
283 option("hall-of-fame-filename",html);\r
284 option("json-filename",json_traffic);\r
285 option("hall-of-fame-preview",preview);\r
286 option("json-preview",json_preview);\r
287 option("log-filename",cmdlog);\r
288 option("credit-filename",credit);\r
289 option("classmap-filename",classmap);\r
290 ioption("credit-enable",enable_credit);\r
291 option("log-traffic-directory",log_dir);\r
292 option("log-traffic-html-directory",html_log_dir);\r
293 option("log-traffic-url-path",log_url);\r
294 option("jquery-url",jquery_url);\r
295 option("lms-url",lms_url);\r
296 ioption("use-jquery-popups",use_jquery_popups);\r
297 option("qos-free-zone",qos_free_zone);\r
298 ioption("qos-free-delay",qos_free_delay);\r
299 ioption("qos-proxy-enable",qos_proxy);\r
300 option("qos-proxy-ip",proxy_ip);\r
301 option("htb-leaf-discipline",qos_leaf);\r
302 ioption("qos-proxy-port",proxy_port);\r
303 ioption("free-rate",free_min);\r
304 ioption("free-ceil",free_max);\r
305 ioption("htb-burst",burst);\r
306 ioption("htb-burst-main",burst_main);\r
307 ioption("htb-burst-group",burst_group);\r
308 ioption("htb-nesting-limit",max_nesting);\r
309 ioption("htb-r2q",htb_r2q);\r
310 ioption("magic-include-upload",include_upload);\r
311 ioption("magic-treshold",magic_treshold); \r
312 option("filter-type", cnf); \r
313/* not yet implemented:\r
314 ioption("magic-fixed-packets",fixed_packets);\r
315 ioption("magic-relative-packets",packet_limit);\r
316*/\r
317 }\r
318 fail\r
319 { \r
320 perror(config_filename);\r
321 puts("Warning - using built-in defaults instead ...");\r
322 }\r
323 done; /* ugly macro end */\r
324 printf("\n");\r
325 \r
326 /* leaf discipline for keywords */\r
327 for_each(keyword,keywords)\r
328 {\r
329 if(!strcmpi(keyword->leaf_discipline, ""))\r
330 {\r
331 keyword->leaf_discipline = qos_leaf;\r
332 }\r
333 }\r
334\r
335 if(strcmpi(cnf, "mark"))\r
336 {\r
337 filter_type = 2;\r
338 mark = "CLASSIFY";\r
339 mark_iptables = "CLASSIFY --set-class 1:";\r
340 }\r
341 else\r
342 {\r
343 filter_type = 1;\r
344 mark = "MARK";\r
345 mark_iptables = "MARK --set-mark ";\r
346 }\r
347\r
348 /* are supplied values meaningful ?*/\r
349 if(line<=0 || up<=0)\r
350 {\r
351 puts("Illegal value of LAN or WAN bandwidth: 0 kbps.");\r
352 reject_config_and_exit(config_filename);\r
353 }\r
354}\r
355\r
356/* ===================== traffic analyser - uses iptables ================ */ \r
357\r
358void get_traffic_statistics(void)\r
359{\r
360 char *str,*cmd;\r
361 int downloadflag=0;\r
362\r
363 textfile(Pipe,str) *line,*lines=NULL;\r
364 string(str,STRLEN);\r
365 string(cmd,STRLEN);\r
366\r
367 sprintf(cmd,"%s -L -v -x -n -t mangle",iptables);\r
368 shell(cmd);\r
369 input(str,STRLEN)\r
370 {\r
371 create(line,Pipe);\r
372 line->str=str;\r
373 string(str,STRLEN);\r
374 append(line,lines);\r
375 }\r
376\r
377 for_each(line,lines)\r
378 {\r
379 int col, accept=0,proxyflag=0,valid=1,setchainname=0,commonflag=0; \r
380 unsigned long long traffic=0;\r
381 unsigned long pkts=0;\r
382 char *ipaddr=NULL,*ptr;\r
383 \r
384 /* debug puts(line->str); */\r
385 valid_columns(ptr,line->str,' ',col) \r
386 if(valid) switch(col)\r
387 { \r
388 case 1: if(eq(ptr,"Chain"))\r
389 {\r
390 setchainname=1;\r
391 }\r
392 else if(eq(ptr,"pkts")) \r
393 {\r
394 valid=0;\r
395 }\r
396 else\r
397 {\r
398 sscanf(ptr,"%lu",&pkts); \r
399 }\r
400 break;\r
401 case 2: if(setchainname)\r
402 {\r
403 if(!strncmp(ptr,"post_",5) || eq(ptr,"POSTROUTING"))\r
404 {\r
405 downloadflag = 1; \r
406 }\r
407 else \r
408 {\r
409 if(!strncmp(ptr,"forw_",5) || eq(ptr,"FORWARD"))\r
410 {\r
411 downloadflag = 0;\r
412 }\r
413 } \r
414 if(eq(ptr,"post_common") || eq(ptr,"forw_common"))\r
415 {\r
416 commonflag = 1;\r
417 }\r
418 }\r
419 else\r
420 {\r
421 sscanf(ptr,"%Lu",&traffic); \r
422 traffic += (1<<19);\r
423 traffic >>= 20;\r
424 }\r
425 break;\r
426 case 3: if((strncmp(ptr,"post_",5) && strncmp(ptr,"forw_",5)) || commonflag)\r
427 {\r
428 accept=eq(ptr,mark);\r
429 }\r
430 /*if(filter_type==1) accept=eq(ptr,"MARK"); else accept=eq(ptr,"CLASSIFY");*/\r
431 break;\r
432 case 8: if(downloadflag)\r
433 { \r
434 if(strstr(proxy_ip,ptr))\r
435 {\r
436 proxyflag=1; \r
437 }\r
438 }\r
439 else\r
440 {\r
441 ipaddr=ptr; \r
442 }\r
443 break;\r
444 case 9: if(downloadflag)ipaddr=ptr;break;\r
445 }\r
446 \r
447 if(accept && traffic>0 && ipaddr)\r
448 {\r
449 if(proxyflag)\r
450 {\r
451 printf("(proxy) ");\r
452 }\r
453 else if(!downloadflag)\r
454 {\r
455 printf("(upload) ");\r
456 }\r
457 printf("IP %s: %Lu MB (%ld pkts)\n", ipaddr, traffic, pkts);\r
458\r
459 if_exists(ip,ips,eq(ip->addr,ipaddr)); \r
460 else \r
461 {\r
462 TheIP();\r
463 ip->addr=ipaddr;\r
464 if(eq(ip->addr,"0.0.0.0/0"))\r
465 {\r
466 ip->name="(unregistered)";\r
467 ip->min=free_min;\r
468 ip->max=ip->desired=free_max;\r
469 }\r
470 }\r
471 \r
472 if(downloadflag)\r
473 {\r
474 if(proxyflag)\r
475 {\r
476 ip->proxy=traffic;\r
477 }\r
478 else\r
479 {\r
480 ip->traffic+=traffic;\r
481 }\r
482 ip->direct=ip->traffic-ip->upload-ip->proxy;\r
483 ip->pktsdown=pkts;\r
484 }\r
485 else\r
486 {\r
487 ip->upload=traffic;\r
488 ip->pktsup=pkts;\r
489 if(include_upload)\r
490 {\r
491 ip->traffic+=traffic;\r
492 }\r
493 else \r
494 {\r
495 if(traffic>ip->traffic)\r
496 {\r
497 ip->traffic=traffic; \r
498 }\r
499 }\r
500 }\r
501 } \r
502 }\r
503 free(cmd);\r
504}\r
505 \r
506/* ========== This function executes, logs OR ALSO prints command ========== */\r
507\r
508void safe_run(char *cmd)\r
509{\r
510 if(dry_run)\r
511 {\r
512 printf("\n=>%s\n",cmd);\r
513 }\r
514 else\r
515 {\r
516 system(cmd);\r
517 }\r
518 if(log_file)\r
519 {\r
520 fprintf(log_file,"%s\n",cmd);\r
521 }\r
522}\r
523\r
524void save_line(char *line)\r
525{\r
526 fprintf(iptables_file,"%s\n",line);\r
527}\r
528\r
529void run_restore(void)\r
530{\r
531 char *restor;\r
532 string(restor,STRLEN);\r
533\r
534 /*-----------------------------------------------------------------*/\r
535 printf("Running %s <%s ...\n", iptablesrestore, iptablesfile);\r
536 /*-----------------------------------------------------------------*/\r
537 \r
538 save_line("COMMIT");\r
539 fclose(iptables_file);\r
540 if(dry_run) \r
541 {\r
542 parse(iptablesfile)\r
543 {\r
544 printf("%s\n",_);\r
545 }\r
546 done; /* ugly macro end */\r
547 }\r
548\r
549 sprintf(restor,"%s <%s",iptablesrestore, iptablesfile);\r
550 safe_run(restor);\r
551 \r
552 free(restor);\r
553}\r
554\r
555char *parse_datafile_line(char *str)\r
556{\r
557 char *ptr=strchr(str,' ');\r
558\r
559 if(ptr)\r
560 {\r
561 *ptr=0;\r
562 ptr++;\r
563 return ptr;\r
564 } \r
565 else \r
566 {\r
567 return NULL;\r
568 }\r
569}\r
570\r
571void append_log(struct IP *self) /*using global variables*/\r
572{\r
573 char *d, *str;\r
574 FILE *f; \r
575\r
576 date(d); /* this is typical cll1.h macro - prints current date */ \r
577 string(str,STRLEN); \r
578 sprintf(str,"%s/%s.log", log_dir, self->name);\r
579 f=fopen(str,"a");\r
580 if(f > 0)\r
581 {\r
582 fprintf(f,"%ld\t%s\t%Lu\t%Lu\t%Lu\t%Lu\t%d\t%d\t%d\t%d\t%s",\r
583 time(NULL), self->name, self->traffic, self->direct, self->proxy,\r
584 self->upload, self->min, self->max, self->desired, self->lmsid, d); /* d = date*/\r
585 fclose(f);\r
586 }\r
587 else\r
588 {\r
589 perror(str);\r
590 }\r
591}\r
592\r
593/*-----------------------------------------------------------------*/\r
594/* Are you looking for int main(int argc, char **argv) ? :-)) */\r
595/*-----------------------------------------------------------------*/\r
596\r
597program\r
598{\r
599 int i=0; /* just plain old Fortran style integer :-) */\r
600 FILE *f=NULL; /* everything is just stream of bytes... */\r
601 char *str, *ptr, *d; /* LET A$=B$ :-) */\r
602 char *substring;\r
603\r
604 int parent=1;\r
605 int just_flush=FALSE; /* deactivates all previous actions */\r
606 int nodelay=FALSE;\r
607 int just_preview=FALSE; /* preview - generate just stats */\r
608 int start_shaping=FALSE; /* apply FUP - requires classmap file */\r
609 int just_logs=FALSE; /* just parse logs */\r
610 int run=FALSE;\r
611 int total=0;\r
612 \r
613 char *chain_forward, *chain_postrouting;\r
614 char *althosts=NULL;\r
615 \r
616 printf("\n\\r
617Prometheus QoS - \"fair-per-IP\" Quality of Service setup utility.\n\\r
618Version %s - Copyright (C)2005-2012 Michael Polak, Arachne Labs\n\\r
619iptables-restore & burst tunning & classify modification by Ludva\n\\r
620Credit: CZFree.Net, Martin Devera, Netdave, Aquarius, Gandalf\n\n",version);\r
621\r
622 /*----- Boring... we have to check command line options first: ----*/ \r
623 arguments\r
624 {\r
625 argument("-c") { nextargument(config); }\r
626 argument("-h") { nextargument(althosts);}\r
627 argument("-d") { run=TRUE; dry_run=TRUE; }\r
628 argument("-f") { run=TRUE; just_flush=TRUE; }\r
629 argument("-9") { run=TRUE; just_flush=9; }\r
630 argument("-p") { run=TRUE; just_preview=TRUE; }\r
631 argument("-s") { run=TRUE; just_preview=TRUE; start_shaping=TRUE; }\r
632 argument("-r") { run=TRUE; }\r
633 argument("-n") { run=TRUE; nodelay=TRUE; }\r
634 argument("-l") { just_logs=TRUE; }\r
635 argument("-m") { just_logs=TRUE; }\r
636 argument("-y") { just_logs=TRUE; }\r
637 argument("-?") { help(); exit(0); }\r
638 argument("--help") { help(); exit(0); }\r
639 argument("-v") { exit(0); } \r
640 argument("--version") { exit(0); } \r
641 }\r
642 \r
643 if(dry_run)\r
644 {\r
645 puts("*** THIS IS JUST DRY RUN ! ***\n");\r
646 }\r
647\r
648 date(d); /* this is typical cll1.h macro - prints current date */\r
649\r
650 /*-----------------------------------------------------------------*/\r
651 printf("Parsing configuration file %s ...\n", config);\r
652 /*-----------------------------------------------------------------*/\r
653 get_config(config);\r
654 \r
655 if(just_logs)\r
656 {\r
657 parse_ip_log(argc,argv);\r
658 exit(0);\r
659 }\r
660 else if(not run)\r
661 {\r
662 help();\r
663 exit(0);\r
664 }\r
665\r
666 if(althosts)\r
667 {\r
668 hosts=althosts;\r
669 }\r
670\r
671 if(just_flush<9)\r
672 {\r
673 /*-----------------------------------------------------------------*/\r
674 puts("Parsing iptables verbose output ...");\r
675 /*-----------------------------------------------------------------*/\r
676 get_traffic_statistics();\r
677 }\r
678\r
679 /*-----------------------------------------------------------------*/\r
680 printf("Parsing class defintion file %s ...\n", hosts);\r
681 /*-----------------------------------------------------------------*/\r
682 parse_hosts(hosts);\r
683\r
684 /*-----------------------------------------------------------------*/\r
685 /* cll1.h - let's allocate brand new character buffer... */\r
686 /*-----------------------------------------------------------------*/\r
687 string(str,STRLEN); \r
688\r
689 /*-----------------------------------------------------------------*/\r
690 puts("Resolving shared connections ...");\r
691 /*-----------------------------------------------------------------*/\r
692 for_each(ip,ips) if(ip->sharing)\r
693 {\r
694 for_each(sharedip,ips) if(eq(sharedip->name,ip->sharing))\r
695 {\r
696 sharedip->traffic+=ip->traffic;\r
697 ip->traffic=0;\r
698 ip->mark=sharedip->mark; \r
699 ip->lmsid=sharedip->lmsid;\r
700 break;\r
701 }\r
702 if(not sharedip)\r
703 {\r
704 printf("Unresolved shared connection: %s %s sharing-%s\n",\r
705 ip->addr, ip->name, ip->sharing);\r
706 }\r
707 }\r
708\r
709 if(enable_credit && just_flush<9)\r
710 {\r
711 /*-----------------------------------------------------------------*/\r
712 printf("Parsing credit file %s ...\n", credit);\r
713 /*-----------------------------------------------------------------*/\r
714 parse(credit)\r
715 {\r
716 ptr=parse_datafile_line(_);\r
717 if(ptr)\r
718 {\r
719 if_exists(ip,ips,eq(ip->addr,_))\r
720 {\r
721 sscanf(ptr,"%Lu",&(ip->credit));\r
722 }\r
723 }\r
724 }\r
725 done; /* ugly macro end */\r
726 }\r
727\r
728 if(!just_preview)\r
729 {\r
730 /*-----------------------------------------------------------------*/\r
731 puts("Initializing iptables and tc classes ...");\r
732 /*-----------------------------------------------------------------*/\r
733 \r
734 iptables_file=fopen(iptablesfile,"w");\r
735 if(iptables_file == NULL)\r
736 {\r
737 puts("Cannot open iptablesfile!");\r
738 exit(-1);\r
739 }\r
740 \r
741 log_file=fopen(cmdlog,"w");\r
742 if(log_file == NULL) \r
743 {\r
744 puts("Cannot open logfile!");\r
745 exit(-1);\r
746 }\r
747 \r
748 save_line(iptablespreamble);\r
749 run_restore();\r
750 \r
751 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,lan);\r
752 safe_run(str);\r
753\r
754 sprintf(str,"%s qdisc del dev %s root 2>/dev/null",tc,wan);\r
755 safe_run(str);\r
756 \r
757 iptables_file=fopen(iptablesfile,"w");\r
758 save_line(iptablespreamble);\r
759\r
760 if(qos_free_zone && *qos_free_zone!='0')\r
761 {\r
762 char *chain;\r
763 \r
764 sprintf(str,"-A FORWARD -d %s -o %s -j ACCEPT", qos_free_zone, wan);\r
765 save_line(str);\r
766 \r
767 if(qos_proxy)\r
768 {\r
769 save_line(":post_noproxy - [0:0]");\r
770 sprintf(str,"-A POSTROUTING ! -p tcp -o %s -j post_noproxy", lan);\r
771 save_line(str); \r
772 sprintf(str,"-A POSTROUTING ! -s %s -o %s -j post_noproxy", proxy_ip, lan);\r
773 save_line(str); \r
774 sprintf(str,"-A POSTROUTING -s %s -p tcp ! --sport %d -o %s -j post_noproxy", proxy_ip, proxy_port, lan);\r
775 save_line(str); \r
776\r
777 chain="post_noproxy"; \r
778 }\r
779 else\r
780 {\r
781 chain="POSTROUTING";\r
782 }\r
783 \r
784 sprintf(str,"-A %s -s %s -o %s -j ACCEPT", chain, qos_free_zone, lan);\r
785 save_line(str);\r
786 }\r
787 \r
788 if(ip_count>idxtable_treshold1 && !just_flush)\r
789 {\r
790 int idxcount=0, bitmask=32-idxtable_bitmask1; /* default net mask: 255.255.255.240 */\r
791 char *subnet, *buf;\r
792 /*-----------------------------------------------------------------*/\r
793 printf("Detected %d addresses - indexing iptables rules to improve performance...\n",ip_count);\r
794 /*-----------------------------------------------------------------*/\r
795\r
796 save_line(":post_common - [0:0]");\r
797 save_line(":forw_common - [0:0]");\r
798\r
799 for_each(ip,ips) if(ip->addr && *(ip->addr) && !eq(ip->addr,"0.0.0.0/0"))\r
800 {\r
801 buf=index_id(ip->addr,bitmask);\r
802 if_exists(idx,idxs,eq(idx->id,buf))\r
803 {\r
804 idx->children++;\r
805 }\r
806 else\r
807 {\r
808 create(idx,Index);\r
809 idx->addr=ip->addr;\r
810 idx->id=buf;\r
811 idx->bitmask=bitmask;\r
812 idx->parent=NULL;\r
813 idx->children=0;\r
814 idxcount++;\r
815 push(idx,idxs);\r
816 }\r
817 }\r
818\r
819 /* brutal perfomance optimalization */\r
820 while(idxcount>idxtable_treshold2 && bitmask>2*idxtable_bitmask2)\r
821 {\r
822 bitmask-=idxtable_bitmask2;\r
823 idxcount=0;\r
824\r
825 for_each(idx,idxs) if(idx->parent == NULL)\r
826 {\r
827 buf=index_id(idx->addr,bitmask);\r
828 if_exists(metaindex,idxs,eq(metaindex->id,buf))\r
829 {\r
830 metaindex->children++;\r
831 }\r
832 else\r
833 {\r
834 create(metaindex,Index);\r
835 metaindex->addr=idx->addr;\r
836 metaindex->id=buf;\r
837 metaindex->bitmask=bitmask;\r
838 metaindex->parent=NULL;\r
839 metaindex->children=0;\r
840 idxcount++;\r
841 push(metaindex,idxs);\r
842 }\r
843 idx->parent=metaindex;\r
844 }\r
845 }\r
846\r
847 /* this should slightly optimize throughout ... */\r
848 sort(idx,idxs,desc_order_by,children);\r
849 sort(idx,idxs,order_by,bitmask);\r
850\r
851 i=0;\r
852 for_each(idx,idxs)\r
853 {\r
854 subnet=subnet_id(idx->addr,idx->bitmask);\r
855 printf("%d: %s/%d\n",\r
856 ++i, subnet, idx->bitmask);\r
857 \r
858 sprintf(str,":post_%s - [0:0]", idx->id);\r
859 save_line(str);\r
860\r
861 sprintf(str,":forw_%s - [0:0]", idx->id);\r
862 save_line(str);\r
863\r
864 if(idx->parent)\r
865 {\r
866 string(buf,strlen(idx->parent->id)+6);\r
867 sprintf(buf,"post_%s",idx->parent->id);\r
868 }\r
869 else\r
870 {\r
871 buf="POSTROUTING";\r
872 }\r
873\r
874 sprintf(str,"-A %s -d %s/%d -o %s -j post_%s", buf, subnet, idx->bitmask, lan, idx->id);\r
875 save_line(str);\r
876\r
877 sprintf(str,"-A %s -d %s/%d -o %s -j post_common", buf, subnet, idx->bitmask, lan);\r
878 save_line(str);\r
879\r
880 if(idx->parent)\r
881 {\r
882 string(buf,strlen(idx->parent->id)+6);\r
883 sprintf(buf,"forw_%s",idx->parent->id);\r
884 }\r
885 else\r
886 {\r
887 buf="FORWARD";\r
888 }\r
889\r
890 sprintf(str,"-A %s -s %s/%d -o %s -j forw_%s", buf, subnet, idx->bitmask, wan, idx->id);\r
891 save_line(str);\r
892\r
893 sprintf(str,"-A %s -s %s/%d -o %s -j forw_common", buf, subnet, idx->bitmask, wan);\r
894 save_line(str);\r
895 }\r
896 printf("Total indexed iptables chains created: %d\n", i);\r
897\r
898 sprintf(str,"-A FORWARD -o %s -j forw_common", wan);\r
899 save_line(str);\r
900 \r
901 sprintf(str,"-A POSTROUTING -o %s -j post_common", lan);\r
902 save_line(str);\r
903 }\r
904 \r
905 }\r
906\r
907 if(just_flush)\r
908 {\r
909 fclose(iptables_file);\r
910 if(log_file)\r
911 { \r
912 fclose(log_file);\r
913 }\r
914 puts("Just flushed iptables and tc classes - now exiting ...");\r
915 exit(0);\r
916 }\r
917\r
918 if(!just_preview)\r
919 {\r
920 if(!dry_run && !nodelay && qos_free_delay)\r
921 {\r
922 printf("Flushed iptables and tc classes - now sleeping for %d seconds...\n",qos_free_delay);\r
923 sleep(qos_free_delay);\r
924 }\r
925\r
926 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",\r
927 tc,lan,htb_r2q);\r
928 safe_run(str);\r
929\r
930 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
931 tc,lan,lan_medium,lan_medium,burst_main,highest_priority);\r
932 safe_run(str);\r
933\r
934 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
935 tc,lan,line,line,burst_main,highest_priority);\r
936 safe_run(str);\r
937\r
938 sprintf(str,"%s qdisc add dev %s root handle 1: htb r2q %d default 1",tc,wan,htb_r2q);\r
939 safe_run(str);\r
940\r
941 sprintf(str, "%s class add dev %s parent 1: classid 1:2 htb rate %s ceil %s burst %dk prio %d",\r
942 tc,wan,wan_medium,wan_medium,burst_main,highest_priority);\r
943 safe_run(str);\r
944\r
945 sprintf(str, "%s class add dev %s parent 1:2 classid 1:1 htb rate %Ldkbit ceil %Ldkbit burst %dk prio %d",\r
946 tc,wan,up,up,burst_main,highest_priority);\r
947 safe_run(str);\r
948 }\r
949\r
950 /*-----------------------------------------------------------------*/\r
951 puts("Locating heavy downloaders and generating root classes ...");\r
952 /*-----------------------------------------------------------------*/\r
953 sort(ip,ips,desc_order_by,traffic); \r
954\r
955 /*-----------------------------------------------------------------*/\r
956 /* sub-scope - local variables */ \r
957 {\r
958 long long int rate = line;\r
959 long long int max = line;\r
960 int group_count = 0;\r
961 FILE *credit_file = NULL;\r
962 \r
963 if(!just_preview && !dry_run && enable_credit)\r
964 {\r
965 credit_file = fopen(credit,"w");\r
966 }\r
967 \r
968 for_each(group,groups)\r
969 {\r
970 if(!just_preview)\r
971 {\r
972 //download\r
973 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
974 tc, lan, parent, group->id, rate, max, burst_group, highest_priority+1, group->desired);\r
975 safe_run(str);\r
976 \r
977 //upload\r
978 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
979 tc, wan, parent, group->id, rate*up/line, max*up/line, burst_group, highest_priority+1, group->desired);\r
980 safe_run(str);\r
981 }\r
982 \r
983 if(group_count++ < max_nesting)\r
984 {\r
985 parent = group->id;\r
986 }\r
987 \r
988 rate -= digital_divide*group->min;\r
989 if(rate < group->min)\r
990 {\r
991 rate = group->min;\r
992 }\r
993 \r
994 /*shaping of aggresive downloaders, with credit file support */\r
995 if(use_credit)\r
996 {\r
997 int group_rate = group->min, priority_sequence = lowest_priority;\r
998 \r
999 for_each(ip, ips) if(ip->min == group->min && ip->max > ip->min)\r
1000 {\r
1001 if( ip->keyword->data_limit && !ip->fixedprio \r
1002 && ( ip->traffic>ip->credit\r
1003 + (ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))) )\r
1004 {\r
1005 if(group_rate<ip->max)\r
1006 {\r
1007 ip->max=group_rate;\r
1008 }\r
1009 group_rate+=magic_treshold;\r
1010 ip->prio=lowest_priority;\r
1011 if(ip->prio<highest_priority+2)\r
1012 {\r
1013 ip->prio=highest_priority+2;\r
1014 }\r
1015 }\r
1016 else\r
1017 {\r
1018 if( ip->keyword->data_prio \r
1019 && !ip->fixedprio \r
1020 && ( ip->traffic>ip->credit\r
1021 + (ip->min*ip->keyword->data_prio+(ip->keyword->fixed_prio<<20))) )\r
1022 {\r
1023 ip->prio=priority_sequence--;\r
1024 if(ip->prio<highest_priority+1)\r
1025 {\r
1026 ip->prio=highest_priority+1;\r
1027 }\r
1028 }\r
1029 \r
1030 if(credit_file)\r
1031 {\r
1032 unsigned long long lcredit=0;\r
1033 \r
1034 if((ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))>ip->traffic)\r
1035 {\r
1036 lcredit=(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20))-ip->traffic;\r
1037 }\r
1038 fprintf(credit_file,"%s %Lu\n",ip->addr,lcredit);\r
1039 }\r
1040 }\r
1041 } \r
1042 }\r
1043 }\r
1044 if(credit_file)\r
1045 {\r
1046 fclose(credit_file);\r
1047 }\r
1048 }\r
1049\r
1050 if(just_preview)\r
1051 {\r
1052 if(start_shaping)\r
1053 {\r
1054 printf("Reading %s and applying Fair Use Policy rules ... \n", classmap);\r
1055 parse(classmap)\r
1056 {\r
1057 ptr=strchr(_,' ');\r
1058 if(ptr)\r
1059 {\r
1060 *ptr=0;\r
1061 ptr++;\r
1062 if_exists(ip,ips,eq(ip->addr,_))\r
1063 {\r
1064 ip->mark=atoi(ptr);\r
1065 if(ip->max < ip->desired) /* apply FUP limit immediately.... */\r
1066 {\r
1067 printf("Applying limit for %-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
1068 printf("(down: %dk-%dk ", ip->min, ip->max); \r
1069 sprintf(str, "%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
1070 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
1071 safe_run(str);\r
1072 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1073 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
1074 sprintf(str,"%s class change dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1075 tc, wan, ip->group, ip->mark,\r
1076 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1077 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1078 safe_run(str);\r
1079 }\r
1080 }\r
1081 }\r
1082 }\r
1083 fail\r
1084 { \r
1085 perror(classmap);\r
1086 puts("Warning - classmap file not fund, just generating preview ...");\r
1087 start_shaping=FALSE;\r
1088 }\r
1089 done; /* ugly macro end */\r
1090 }\r
1091 html=preview;\r
1092 json_traffic=json_preview;\r
1093 }\r
1094\r
1095 if(!dry_run && !just_flush)\r
1096 {\r
1097 /*-----------------------------------------------------------------*/\r
1098 printf("Writing json traffic overview %s ... ", json_traffic);\r
1099 /*-----------------------------------------------------------------*/\r
1100 write_json_traffic(json_traffic);\r
1101 }\r
1102\r
1103 f=fopen(html,"w");\r
1104 if(f > 0)\r
1105 {\r
1106 int count=1;\r
1107 i=0;\r
1108\r
1109 /*-----------------------------------------------------------------*/\r
1110 printf("Sorting data and generating statistics page %s ...\n", html);\r
1111 /*-----------------------------------------------------------------*/\r
1112\r
1113 if(use_jquery_popups)\r
1114 {\r
1115 fprintf(f,"<script type=\"text/javascript\" src=\"%s\"></script>\n", jquery_url);\r
1116 }\r
1117 fputs("<table class=\"decorated last\">\n\\r
1118<caption>Bandwidth classes</caption>\n\\r
1119<thead><tr>\n\\r
1120<th style=\"text-align: right\">#</th>\n\\r
1121<th style=\"text-align: right\">group</th>\n\\r
1122<th style=\"text-align: right\">IPs</th>\n\\r
1123<th style=\"text-align: right\">requested</th>\n",f);\r
1124 fprintf(f,"<th colspan=\"%d\">data limits</th>\n", keywordcount);\r
1125 fputs("</tr></thead><tbody>\n",f);\r
1126\r
1127 row_odd_even = 0;\r
1128 for_each(group, groups) \r
1129 { \r
1130#ifdef DEBUG\r
1131 printf("%d kb/s group: %d bandwidth requested: %d kb/s\n",group->min,group->count,group->desired);\r
1132#endif\r
1133 fprintf(f, "%s<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d&nbsp;kb/s</td>",\r
1134 tr_odd_even(), count, group->min);\r
1135 fprintf(f, "<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d&nbsp;kb/s</td>",\r
1136 group->count, group->desired);\r
1137\r
1138 for_each(keyword, keywords) if(keyword->ip_count)\r
1139 {\r
1140 fprintf(f,"<td style=\"text-align: right\"><span style=\"color:#%s\">%d&nbsp;MB</span></td>",\r
1141 keyword->html_color, group->min*keyword->data_limit);\r
1142 } \r
1143 i += group->desired; \r
1144 total += group->count;\r
1145 count++; \r
1146 }\r
1147#ifdef DEBUG\r
1148 printf("Total groups: %d Total bandwidth requested: %d kb/s\nAGGREGATION: 1/%d\n",\r
1149 count, i, i/line);\r
1150#endif\r
1151 fprintf(f,"</tr></tbody>\n\\r
1152<thead><tr>\n\\r
1153<th colspan=\"2\" style=\"text-align: left\">Line %Ld kb/s</td>",line);\r
1154 fprintf(f,"<th style=\"text-align: right\">%d</td><th style=\"text-align: right\">%d kb/s</td>",total,i);\r
1155\r
1156 for_each(keyword, keywords) if(keyword->ip_count)\r
1157 {\r
1158 fprintf(f,"<th style=\"text-align: right\">%d IPs</th>",keyword->ip_count);\r
1159 }\r
1160 fprintf(f,"</tr><tr><th colspan=\"4\">Aggregation 1/%d</th>\n", (int)(0.5+i/line));\r
1161 fprintf(f,"<th colspan=\"%d\">%d traffic classes</th></tr>\n", keywordcount, total);\r
1162\r
1163 fputs("</thead></table>\n",f);\r
1164 }\r
1165 else if(!dry_run && !just_flush)\r
1166 {\r
1167 perror(html);\r
1168 }\r
1169\r
1170 i=0;\r
1171 if(f > 0)\r
1172 {\r
1173 unsigned long long total_traffic=0, total_direct=0, total_proxy=0, total_upload=0, tmp_sum=0;\r
1174 int active_classes=0;\r
1175 int colspan=12;\r
1176 struct Sum {unsigned long long l; int i; list(Sum);} *sum,*sums=NULL;\r
1177 int limit_count=0, prio_count=0;\r
1178 int popup_button=0;\r
1179\r
1180 if(qos_proxy)\r
1181 {\r
1182 colspan++;\r
1183 }\r
1184 \r
1185 fprintf(f,"<p><table class=\"decorated last\">\n<caption>%s",title);\r
1186 fprintf(f," (%s)</caption>\n", d);\r
1187 fputs("<thead><tr>\n<th colspan=\"3\">&nbsp;</th>\n",f);\r
1188 fputs("<th style=\"text-align: right\">credit</th>\n\\r
1189<th style=\"text-align: right\">FUP</th>\n\\r
1190<th style=\"text-align: right\">total</th>\n\\r
1191<th style=\"text-align: right\">down</th>\n",f);\r
1192 if(qos_proxy)\r
1193 {\r
1194 fputs("<th style=\"text-align: right\">proxy</th>\n",f);\r
1195 }\r
1196 fputs("<th style=\"text-align: right\">up</th>\n\\r
1197<th style=\"text-align: right\">min</th>\n\\r
1198<th style=\"text-align: right\">max</th>\n\\r
1199<th style=\"text-align: right\">limit</th>\n\\r
1200<th>&nbsp;</th>\n\\r
1201</tr><tr>\n\\r
1202<th style=\"text-align: right\">#</th>\n\\r
1203<th>hostname [+sharing]</th>\n\\r
1204<th style=\"text-align: right\">LMS</th>\n\\r
1205<th style=\"text-align: right\">MB</th>\n\\r
1206<th style=\"text-align: right\">MB</th>\n\\r
1207<th style=\"text-align: right\">MB</th>\n\\r
1208<th style=\"text-align: right\">MB</th>\n\\r
1209<th style=\"text-align: right\">MB</th>\n\\r
1210<th style=\"text-align: right\">kb/s</th>\n\\r
1211<th style=\"text-align: right\">kb/s</th>\n\\r
1212<th style=\"text-align: right\">kb/s</th>\n\\r
1213<th>prio</th>\n\\r
1214</tr></thead><tbody>\n",f); \r
1215\r
1216 row_odd_even = 0;\r
1217 for_each(ip,ips) if(!use_jquery_popups || !ip->sharing)\r
1218 {\r
1219 char *f1="", *f2="";\r
1220 i++;\r
1221\r
1222 if(ip->max < ip->desired) \r
1223 { \r
1224 f1="<span style=\"color:red\">"; \r
1225 f2="</span>"; \r
1226 limit_count++; \r
1227 } \r
1228 else if(ip->prio > highest_priority+1) \r
1229 { \r
1230 f1="<span style=\"color:brown\">"; \r
1231 f2="</span>"; \r
1232 prio_count++; \r
1233 } \r
1234\r
1235#ifdef DEBUG\r
1236 printf("%03d. %-22s %10Lu (%d/%d)\n",i ,ip->name, ip->traffic, ip->min, ip->max); \r
1237#endif\r
1238 /* hostnames -------------------------------------- */\r
1239 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
1240 tr_odd_even(), ip->name, i, log_url, ip->name, ip->name);\r
1241\r
1242 if(use_jquery_popups)\r
1243 {\r
1244 fprintf(f,"<span id=\"sharing_%d\" style=\"display:none\">",i);\r
1245 popup_button=0;\r
1246 for_each(sharedip, ips) if(eq(ip->name, sharedip->sharing))\r
1247 {\r
1248 fprintf(f,"<br /><a class=\"blue\" target=\"_blank\" href=\"%s%s.log\">%s</a>\n", log_url, sharedip->name, sharedip->name);\r
1249 popup_button++;\r
1250 }\r
1251 fputs("</span>\n",f);\r
1252 if(popup_button)\r
1253 {\r
1254 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
1255 i, i, i, popup_button);\r
1256 }\r
1257 }\r
1258 fputs("</td>\n",f);\r
1259 /* ----------------------------------------------- */\r
1260\r
1261 if(found_lmsid)\r
1262 {\r
1263 fputs("<td style=\"text-align: right\">",f);\r
1264 if(ip->lmsid > 0)\r
1265 {\r
1266 fprintf(f,"<a class=\"blue\" target=\"_blank\" href=\"%s%d\">%04d</a>\n", lms_url, ip->lmsid, ip->lmsid);\r
1267 }\r
1268 else if(ip->lmsid == 0)\r
1269 {\r
1270 fputs("-------",f);\r
1271 }\r
1272 fputs("</td>\n",f);\r
1273 }\r
1274 fprintf(f,"<td style=\"text-align: right\">%Lu</td>\n", ip->credit);\r
1275 fprintf(f,"<td style=\"text-align: right\"><span style=\"color:#%s\">%Lu</span></td>",\r
1276 ip->keyword->html_color,\r
1277 ip->credit+(ip->min*ip->keyword->data_limit+(ip->keyword->fixed_limit<<20)));\r
1278 fprintf(f,"<td style=\"text-align: right\">%s%Lu%s", f1, ip->traffic, f2);\r
1279\r
1280 /* download --------------------------------------- */\r
1281 fprintf(f,"</td><td style=\"text-align: right\">%Lu", ip->direct);\r
1282 if(use_jquery_popups)\r
1283 {\r
1284 fprintf(f,"<span id=\"download_%d\" style=\"display:none\">",i);\r
1285 for_each(sharedip, ips) if(eq(ip->name, sharedip->sharing))\r
1286 {\r
1287 fprintf(f,"<br />%Lu", sharedip->direct);\r
1288 }\r
1289 fputs("</span>\n",f);\r
1290 }\r
1291 fputs("</td>\n",f);\r
1292 /* ----------------------------------------------- */\r
1293\r
1294 if(qos_proxy)\r
1295 {\r
1296 fprintf(f,"<td style=\"text-align: right\">%Lu</td>\n", ip->proxy);\r
1297 }\r
1298 /* upload ---------------------------------------- */\r
1299 fprintf(f,"<td style=\"text-align: right\">%Lu", ip->upload);\r
1300 if(use_jquery_popups)\r
1301 {\r
1302 fprintf(f,"<span id=\"upload_%d\" style=\"display:none\">",i);\r
1303 for_each(sharedip,ips) if(eq(ip->name, sharedip->sharing))\r
1304 {\r
1305 fprintf(f,"<br />%Lu", sharedip->upload);\r
1306 }\r
1307 fputs("</span>\n",f);\r
1308 }\r
1309 fputs("</td>\n",f);\r
1310 /* ----------------------------------------------- */\r
1311\r
1312 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1313<td style=\"text-align: right\">%d</td>\n\\r
1314<td style=\"text-align: right\">%s%d%s</td>\n\\r
1315<td>%s%d%s</td></tr>\n",\r
1316 ip->min, ip->desired, \r
1317 f1, ip->max, f2, \r
1318 f1, ip->prio, f2);\r
1319\r
1320 total_traffic+=ip->traffic;\r
1321 total_direct+=ip->direct;\r
1322 total_proxy+=ip->proxy;\r
1323 total_upload+=ip->upload;\r
1324 if(ip->traffic>0)\r
1325 {\r
1326 active_classes++;\r
1327 tmp_sum+=ip->traffic;\r
1328 create(sum,Sum);\r
1329 sum->l=tmp_sum;\r
1330 sum->i=active_classes;\r
1331 insert(sum,sums,order_by,i);\r
1332 }\r
1333\r
1334 if(!just_preview)\r
1335 {\r
1336 append_log(ip);\r
1337 for_each(sharedip,ips) if(eq(ip->name, sharedip->sharing))\r
1338 {\r
1339 append_log(sharedip);\r
1340 }\r
1341 }\r
1342 }\r
1343 fprintf(f,"</tbody><thead><tr>\n\\r
1344<th colspan=\"%d\" style=\"text-align: left\">%d CLASSES</th>", colspan-7, i);\r
1345 fprintf(f,"<th style=\"text-align: right\">%Lu</th><th style=\"text-align: right\">%Lu</th>\n", total_traffic, total_direct);\r
1346 if(qos_proxy)\r
1347 {\r
1348 fprintf(f,"<th style=\"text-align: right\">%Lu</th>\n", total_proxy);\r
1349 }\r
1350 fprintf(f,"<th style=\"text-align: right\">%Lu</th>", total_upload);\r
1351 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
1352\r
1353 row_odd_even = 0;\r
1354 if(active_classes>10)\r
1355 {\r
1356 int top20_count=0,top20_perc1=0;\r
1357 long long top20_perc2=0;\r
1358 unsigned long long top20_sum=0l;\r
1359 \r
1360 fputs("<a name=\"erp\"></a><p><table class=\"decorated last\"><caption>Enterprise Resource Planning (ERP)</caption>\n",f);\r
1361 fputs("<thead><tr>\n\\r
1362<th>Analytic category</th>\n\\r
1363<th colspan=\"2\" style=\"text-align: center\">Active Classes</th>\n\\r
1364<th colspan=\"2\" style=\"text-align: center\">Data transfers</th>\n\\r
1365</tr></thead><tbody>\n",f);\r
1366\r
1367 if_exists(sum,sums,sum->l>=total_traffic/4)\r
1368 {\r
1369 fprintf(f,"%s<td>Top 25%% of traffic</td>\n", tr_odd_even());\r
1370 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1371<td style=\"text-align: right\">%d %%</td>\n\\r
1372<td style=\"text-align: right\">%Lu MB</td>\n\\r
1373<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
1374 sum->i, (100*sum->i+50)/active_classes, sum->l, (100*sum->l+50)/total_traffic);\r
1375 }\r
1376 \r
1377 if_exists(sum,sums,sum->i==10)\r
1378 {\r
1379 fprintf(f,"%s<td>Top 10 downloaders</td>\n", tr_odd_even());\r
1380 fprintf(f,"<td style=\"text-align: right\"><strong>10</strong></td>\n\\r
1381<td style=\"text-align: right\">%d %%</td>\n\\r
1382<td style=\"text-align: right\">%Lu MB</td>\n\\r
1383<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
1384 (100*sum->i+50)/active_classes, sum->l, (100*sum->l+50)/total_traffic);\r
1385 }\r
1386\r
1387 if_exists(sum,sums,sum->l>=total_traffic/2)\r
1388 {\r
1389 fprintf(f,"%s<td>Top 50%% of traffic</td>\n", tr_odd_even());\r
1390 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1391<td style=\"text-align: right\">%d %%</td>\n\\r
1392<td style=\"text-align: right\">%Lu MB</td>\n\\r
1393<td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",\r
1394 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
1395 }\r
1396\r
1397 if_exists(sum,sums,sum->l>=4*total_traffic/5)\r
1398 {\r
1399 fprintf(f,"%s<td>Top 80%% of traffic</td>\n", tr_odd_even());\r
1400 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1401<td style=\"text-align: right\">%d %%</td>\n\\r
1402<td style=\"text-align: right\">%Lu MB</td>\n\\r
1403<td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",\r
1404 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
1405 }\r
1406\r
1407 if_exists(sum,sums,sum->i>=(active_classes+1)/5)\r
1408 {\r
1409 fprintf(f,"%s<td>Top 20%% downloaders</td>\n", tr_odd_even());\r
1410 top20_count=sum->i;\r
1411 top20_perc1=(100*sum->i+50)/active_classes;\r
1412 top20_sum=sum->l;\r
1413 top20_perc2=(100*sum->l+50)/total_traffic;\r
1414 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1415<td style=\"text-align: right\"><strong>%d %%</strong></td>\n\\r
1416<td style=\"text-align: right\">%Lu MB</td>\n\\r
1417<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
1418 top20_count,top20_perc1,top20_sum,top20_perc2);\r
1419 }\r
1420\r
1421 if_exists(sum,sums,sum->i>=(active_classes+1)/4)\r
1422 {\r
1423 fprintf(f,"%s<td>Top 25%% downloaders</td>\n", tr_odd_even());\r
1424 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1425<td style=\"text-align: right\">%d %%</td>\n\\r
1426<td style=\"text-align: right\">%Lu MB</td>\n\\r
1427<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
1428 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
1429 }\r
1430\r
1431 if_exists(sum,sums,sum->i>=(active_classes+1)/2)\r
1432 {\r
1433 fprintf(f,"%s<td>Top 50%% downloaders</td>\n", tr_odd_even());\r
1434 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1435<td style=\"text-align: right\"><strong>%d %%</strong></td>\n\\r
1436<td style=\"text-align: right\">%Lu MB</td>\n\\r
1437<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
1438 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
1439 }\r
1440\r
1441 if_exists(sum,sums,sum->i>=4*(active_classes+1)/5)\r
1442 {\r
1443 fprintf(f,"%s<td>Top 80%% downloaders</td>\n", tr_odd_even());\r
1444 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
1445<td style=\"text-align: right\">%d %%</td>\n\\r
1446<td style=\"text-align: right\">%Lu MB</td>\n\\r
1447<td style=\"text-align: right\">%Ld %%</td></tr></tbody>\n",\r
1448 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
1449 }\r
1450\r
1451 fprintf(f,"<thead><tr><th><a class=\"blue\" target=\"_blank\" href=\"%sERP.log\">All users, all traffic</a></th>\n", log_url);\r
1452 fprintf(f,"<th style=\"text-align: right\">%d</th>\n\\r
1453<th style=\"text-align: right\">100 %%</th>\n\\r
1454<th style=\"text-align: right\">%Lu MB</th>\n\\r
1455<th style=\"text-align: right\">100 %%</th></tr>\n",active_classes,total_traffic);\r
1456 fputs("</thead></table>\n", f);\r
1457\r
1458 /* write basic ERP data to log directory */\r
1459 if(!just_preview)\r
1460 {\r
1461 FILE *iplog;\r
1462 sprintf(str,"%s/ERP.log",log_dir);\r
1463 iplog=fopen(str,"a");\r
1464 if(iplog)\r
1465 {\r
1466 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
1467 time(NULL), top20_count, top20_perc1, top20_sum, top20_perc2, \r
1468 active_classes, total_traffic, i, limit_count, prio_count, d); /* d = date*/\r
1469 fclose(iplog);\r
1470 }\r
1471 else\r
1472 {\r
1473 perror(str);\r
1474 }\r
1475 }\r
1476 }\r
1477\r
1478 fprintf(f, stats_html_signature, version);\r
1479 fclose(f);\r
1480 }\r
1481\r
1482 if(just_preview)\r
1483 {\r
1484 char swchar='p';\r
1485 if(start_shaping)\r
1486 {\r
1487 swchar='s';\r
1488 }\r
1489 printf("Statistics preview generated (-%c switch) - now exiting ...\n", swchar);\r
1490 exit(0);\r
1491 } \r
1492\r
1493 i=0;\r
1494#ifdef DEBUG\r
1495 printf("%-22s %-15s mark\n","name","ip");\r
1496#endif\r
1497\r
1498 printf("Writing %s ... ", classmap); \r
1499 f = fopen(classmap, "w"); \r
1500 if(f < 0)\r
1501 {\r
1502 perror(classmap);\r
1503 }\r
1504\r
1505 /*-----------------------------------------------------------------*/\r
1506 puts("Generating iptables and tc classes ... ");\r
1507 /*-----------------------------------------------------------------*/\r
1508\r
1509 for_each(ip, ips) if(ip->mark > 0)\r
1510 {\r
1511 if(idxs)\r
1512 {\r
1513 char *buf;\r
1514 duplicate(ip->addr,buf);\r
1515 buf=index_id(ip->addr,32-idxtable_bitmask1); \r
1516 \r
1517 string(chain_forward,6+strlen(buf));\r
1518 strcpy(chain_forward,"forw_");\r
1519 strcat(chain_forward,buf);\r
1520\r
1521 string(chain_postrouting,6+strlen(buf));\r
1522 strcpy(chain_postrouting,"post_");\r
1523 strcat(chain_postrouting,buf);\r
1524 \r
1525 free(buf);\r
1526 }\r
1527 else\r
1528 {\r
1529 chain_forward="FORWARD";\r
1530 chain_postrouting="POSTROUTING";\r
1531 }\r
1532\r
1533#ifdef DEBUG\r
1534 printf("%-22s %-16s %04d ", ip->name, ip->addr, ip->mark); \r
1535#endif\r
1536\r
1537 /* -------------------------------------------------------- mark download */\r
1538 \r
1539 sprintf(str, "-A %s -d %s/32 -o %s -j %s%d",\r
1540 chain_postrouting, ip->addr, lan, mark_iptables, ip->mark);\r
1541 /*sprintf(str,"-A %s -d %s/32 -o %s -j MARK --set-mark %d",chain_postrouting,ip->addr,lan,ip->mark);*/\r
1542 /* -m limit --limit 1/s */ \r
1543 save_line(str);\r
1544\r
1545 if(qos_proxy)\r
1546 {\r
1547 sprintf(str, "-A %s -s %s -p tcp --sport %d -d %s/32 -o %s -j %s%d",\r
1548 chain_postrouting, proxy_ip, proxy_port, ip->addr, lan, mark_iptables, ip->mark);\r
1549 /*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
1550 save_line(str);\r
1551 }\r
1552\r
1553 sprintf(str, "-A %s -d %s/32 -o %s -j ACCEPT",\r
1554 chain_postrouting, ip->addr, lan);\r
1555 save_line(str);\r
1556\r
1557 /* -------------------------------------------------------- mark upload */\r
1558 sprintf(str, "-A %s -s %s/32 -o %s -j %s%d", \r
1559 chain_forward, ip->addr, wan, mark_iptables, ip->mark);\r
1560 /* sprintf(str,"-A %s -s %s/32 -o %s -j MARK --set-mark %d",chain_forward,ip->addr,wan,ip->mark);*/\r
1561 save_line(str);\r
1562\r
1563 sprintf(str, "-A %s -s %s/32 -o %s -j ACCEPT",\r
1564 chain_forward, ip->addr, wan);\r
1565 save_line(str);\r
1566\r
1567 if(ip->min)\r
1568 {\r
1569 /* -------------------------------------------------------- download class */\r
1570#ifdef DEBUG\r
1571 printf("(down: %dk-%dk ", ip->min, ip->max); \r
1572#endif\r
1573\r
1574 sprintf(str, "%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d", \r
1575 tc, lan, ip->group, ip->mark,ip->min,ip->max, burst, ip->prio);\r
1576 safe_run(str);\r
1577\r
1578 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
1579 {\r
1580 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s", \r
1581 tc, lan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
1582 safe_run(str);\r
1583 }\r
1584\r
1585 if(filter_type == 1)\r
1586 {\r
1587 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
1588 tc, lan, ip->mark, ip->mark);\r
1589 safe_run(str);\r
1590 }\r
1591\r
1592 /* -------------------------------------------------------- upload class */\r
1593#ifdef DEBUG\r
1594 printf("up: %dk-%dk)\n", (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), \r
1595 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed));\r
1596#endif\r
1597\r
1598 sprintf(str,"%s class add dev %s parent 1:%d classid 1:%d htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1599 tc, wan, ip->group, ip->mark,\r
1600 (int)((ip->min/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed),\r
1601 (int)((ip->max/ip->keyword->asymetry_ratio)-ip->keyword->asymetry_fixed), burst, ip->prio);\r
1602 safe_run(str);\r
1603 \r
1604 if(strcmpi(ip->keyword->leaf_discipline, "none"))\r
1605 {\r
1606 sprintf(str, "%s qdisc add dev %s parent 1:%d handle %d %s",\r
1607 tc, wan, ip->mark, ip->mark, ip->keyword->leaf_discipline); /*qos_leaf*/\r
1608 safe_run(str);\r
1609 } \r
1610\r
1611 if(filter_type == 1)\r
1612 {\r
1613 sprintf(str, "%s filter add dev %s parent 1:0 protocol ip handle %d fw flowid 1:%d",\r
1614 tc, wan, ip->mark, ip->mark);\r
1615 safe_run(str);\r
1616 }\r
1617 \r
1618 if(f > 0)\r
1619 {\r
1620 fprintf(f, "%s %d\n", ip->addr, ip->mark);\r
1621 }\r
1622 }\r
1623 else\r
1624 {\r
1625#ifdef DEBUG\r
1626 printf("(sharing %s)\n", ip->sharing);\r
1627#endif\r
1628 }\r
1629 i++;\r
1630 }\r
1631 if(f > 0)\r
1632 {\r
1633 puts("done.");\r
1634 fclose(f);\r
1635 }\r
1636 \r
1637 if(idxs)\r
1638 {\r
1639 chain_forward = "forw_common";\r
1640 chain_postrouting = "post_common";\r
1641 }\r
1642 else\r
1643 {\r
1644 chain_forward = "FORWARD";\r
1645 chain_postrouting = "POSTROUTING";\r
1646 }\r
1647 /* -------------------------------- classify or reject free download */\r
1648 {\r
1649 char *final_chain = "DROP"; /* REJECT would be better, but it is impossible in mangle */\r
1650 if(free_min)\r
1651 {\r
1652 final_chain = "ACCEPT";\r
1653 }\r
1654 if(qos_proxy)\r
1655 {\r
1656 if(free_min)\r
1657 {\r
1658 sprintf(str,"-A %s -s %s -p tcp --sport %d -o %s -j %s%d",\r
1659 chain_postrouting,proxy_ip,proxy_port,lan,mark_iptables,3);\r
1660 save_line(str);\r
1661 }\r
1662 sprintf(str,"-A %s -s %s -p tcp --sport %d -o %s -j %s",\r
1663 chain_postrouting,proxy_ip,proxy_port,lan,final_chain);\r
1664 save_line(str);\r
1665 }\r
1666 if(free_min)\r
1667 {\r
1668 sprintf(str,"-A %s -o %s -j %s%d", chain_postrouting, lan, mark_iptables, 3);\r
1669 save_line(str);\r
1670 }\r
1671 sprintf(str,"-A %s -o %s -j %s", chain_postrouting, lan, final_chain);\r
1672 save_line(str);\r
1673 /* ------------------------------- classify or reject free upload */\r
1674 if(free_min)\r
1675 {\r
1676 sprintf(str,"-A %s -o %s -j %s%d", chain_forward, wan, mark_iptables, 3);\r
1677 save_line(str);\r
1678 }\r
1679 sprintf(str,"-A %s -o %s -j %s", chain_forward, wan, final_chain);\r
1680 save_line(str);\r
1681 }\r
1682\r
1683 if(free_min) /* allocate free bandwith if it is not zero... */ \r
1684 {\r
1685 /*-----------------------------------------------------------------*/\r
1686 puts("Generating free bandwith classes ...");\r
1687 /*-----------------------------------------------------------------*/\r
1688 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1689 tc, lan, parent, free_min, free_max,burst, lowest_priority);\r
1690 safe_run(str);\r
1691 sprintf(str, "%s class add dev %s parent 1:%d classid 1:3 htb rate %dkbit ceil %dkbit burst %dk prio %d",\r
1692 tc, wan, parent, free_min, free_max, burst, lowest_priority);\r
1693 safe_run(str);\r
1694 /* tc SFQ */\r
1695 if(strcmpi(qos_leaf, "none"))\r
1696 {\r
1697 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, lan, qos_leaf);\r
1698 safe_run(str);\r
1699 \r
1700 sprintf(str,"%s qdisc add dev %s parent 1:3 handle 3 %s", tc, wan, qos_leaf);\r
1701 safe_run(str);\r
1702 } \r
1703 /* tc handle 1 fw flowid */\r
1704 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, lan);\r
1705 safe_run(str);\r
1706\r
1707 sprintf(str,"%s filter add dev %s parent 1:0 protocol ip handle 3 fw flowid 1:3", tc, wan);\r
1708 safe_run(str);\r
1709 }\r
1710 printf("Total IP count: %d\n", i);\r
1711 run_restore(); \r
1712 if(log_file)\r
1713 {\r
1714 fclose(log_file);\r
1715 }\r
1716 return 0;\r
1717 /* that's all folks, thank you for reading it all the way up to this point ;-) */\r
1718 /* bad luck C<<1 is not yet finished, I promise no sprintf() next time... */\r
1719}\r
This page took 0.292269 seconds and 4 git commands to generate.