version 1.0.0.-a - significat iptables parsing speed improvement
[svn/Prometheus-QoS/.git] / parsehosts.c
1 /* Modified by: xChaos, 20131220 */
2
3 #include "cll1-0.6.2.h"
4 #include "ipstruct.h"
5
6 #define FIRSTGROUPID 1024
7 #define FIRSTIPCLASS 2048
8
9 /* globals declared in prometheus.c */
10 extern struct IP *ips, *ip, *sharedip, *networks;
11 extern struct Group *groups, *group;
12 extern struct Keyword *keyword, *defaultkeyword, *keywords;
13 extern struct Macro *macro, *macros;
14 extern int class_count;
15 extern int ip_count;
16 extern int found_lmsid;
17 extern int free_min;
18 extern const int highest_priority;
19 extern char *ip6prefix;
20
21 void update_network(char *look_for, struct IP* ip);
22 /* implemented in networks.c */
23
24 /* This must be object oriented! This looks almost like constructor ;-) */
25 void TheIP(char *ipaddr, int is_network)
26 {
27 create(ip,IP);
28 ip->name = "";
29 ip->addr = ipaddr;
30 ip->sharing = NULL;
31 ip->prio = highest_priority+1;
32 ip->lmsid = -1;
33 ip->fixedprio = \
34 ip->aggregated = \
35 ip->mark = \
36 ip->min = \
37 ip->max = \
38 ip->desired = \
39 ip->credit = \
40 ip->upload = \
41 ip->proxy = \
42 ip->direct = \
43 ip->traffic = \
44 ip->traffic_down = \
45 ip->traffic_up = \
46 ip->pktsup = \
47 ip->pps_limit = \
48 ip->pktsdown = 0;
49 ip->keyword = keywords;
50 ip->v6 = (strchr(ip->addr,':')!=NULL);
51 ip->mask = ((ip->v6)?64:32);
52 if(is_network)
53 {
54 push(ip, networks);
55 }
56 else
57 {
58 push(ip, ips);
59 }
60 #ifdef MONITORINGTRHU_CTU
61 ip->technology_str = NULL;
62 ip->ruian_id_str = NULL;
63 #endif
64
65 ip_count++;
66 }
67
68 #ifdef MONITORINGTRHU_CTU
69 struct Technology *technologies = NULL, *technology = NULL;
70 #endif
71 struct IP *lastIP6range, *lastIP6uplink;
72
73 /* == This function strips extra characters after IPv4 address and stores it = */
74 void parse_and_append_ip(char *str, struct IP *listhead)
75 {
76 char *ptr, *ipaddr, *nextip6, *ip6buf;
77 char *ip6uplink = NULL, *ip6range = NULL, *ipname = NULL, *lmsid = NULL;
78
79 if(ip6prefix) /* Try this only if IPv6 subsystem is active... */
80 {
81 ptr = strstr(str, "::");
82 while(ptr && ptr-str > 4)
83 {
84 nextip6 = strstr(ptr + 2, "::");
85 ptr -= 4;
86 duplicate(ptr, ip6buf);
87 ptr = strstr(ip6buf, "::");
88 if(ptr)
89 {
90 if(*(ptr+2) == '+')
91 {
92 *(ptr+3) = 0; /* ends with ::+ */
93 ip6uplink = ip6buf;
94 }
95 else
96 {
97 *(ptr+2) = 0; /* ends with :: */
98 ip6range = ip6buf;
99 }
100 }
101 ptr = nextip6;
102 }
103 }
104
105 ptr = strchr(str, '{');
106 if(ptr)
107 {
108 lmsid = ++ptr;
109 while(*ptr and *ptr != '}')
110 {
111 ptr++;
112 }
113 *ptr = 0;
114 }
115
116 ptr = str;
117 while(*ptr and *ptr!=' ' and *ptr!=9)
118 {
119 ptr++;
120 }
121
122 *ptr = 0;
123 ipaddr = str;
124 ptr++;
125 while(*ptr and (*ptr==' ' or *ptr==9))
126 {
127 ptr++;
128 }
129 ipname = ptr;
130 while(*ptr and *ptr!=' ' and *ptr!=9)
131 {
132 ptr++;
133 }
134 *ptr=0;
135
136 if(ip6range)
137 {
138 concatenate(ip6prefix,ip6range,ptr);
139 ip6range=ptr;
140 if_exists(ip, ips, eq(ip->addr,ip6range)); /* check - allocated range must be unique */
141 else
142 {
143 TheIP(ip6range, FALSE);
144 }
145 ip->name = ip6range;
146 ip->keyword = defaultkeyword; /* settings for default keyword */
147 if(lmsid)
148 {
149 ip->lmsid = atoi(lmsid);
150 }
151 lastIP6range = ip;
152 }
153 else
154 {
155 lastIP6range = NULL;
156 }
157
158 /* it is ugly to copy+paste and search+replace, but... */
159 if(ip6uplink)
160 {
161 concatenate(ip6prefix,ip6uplink,ptr);
162 ip6uplink=ptr;
163 TheIP(ip6uplink, FALSE); /* always new IP - more IPs in single uplink network */
164 ip->name = ip6uplink;
165 ip->keyword = defaultkeyword; /* settings for default keyword */
166 if(lmsid)
167 {
168 ip->lmsid = atoi(lmsid);
169 }
170 lastIP6uplink = ip;
171 }
172 else
173 {
174 lastIP6uplink = NULL;
175 }
176
177 if_exists(ip, listhead, eq(ip->addr,ipaddr));
178 else
179 {
180 TheIP(ipaddr, (listhead==networks));
181 }
182 ip->name = ipname;
183 if(lmsid)
184 {
185 ip->lmsid = atoi(lmsid);
186 found_lmsid = TRUE;
187 }
188 }
189
190 /* == This function parses hosts style main configuration file == */
191 void parse_hosts(char *hosts)
192 {
193 int groupidx = FIRSTGROUPID;
194 char *str, *ptr;
195 char *substring;
196 struct IP *network;
197 int pktratio;
198
199 parse(hosts)
200 {
201 str = _;
202
203 if(*str < '0' or *str > '9')
204 {
205 /* any line starting with non-number is comment ...*/
206 continue;
207 }
208
209 ptr = strchr(str,'\r'); /* fore unix-style end of line */
210 if(ptr)
211 {
212 *ptr = 0;
213 }
214
215 /* first, expand (rewrite) any predefined macros, if found*/
216 for_each(macro, macros)
217 {
218 substring = strstr(str, macro->rewrite_from);
219 if(substring)
220 {
221 int l1, l3;
222 *substring = 0;
223 substring += strlen(macro->rewrite_from);
224 l1 = strlen(str);
225 l3 = strlen(substring);
226 string(ptr, l1 + strlen(macro->rewrite_to) + l3 + 1);
227 strcpy(ptr, str);
228 strcat(ptr, macro->rewrite_to);
229 strcat(ptr, substring);
230 str = ptr;
231 /* printf("REWRITE: %s -> %s\n",_,str); */
232 }
233 }
234
235 /* Does this IP share QoS class with some other ? */
236 substring = strstr(str, "sharing-");
237 if(substring)
238 {
239 substring += 8; /* "sharing-" */
240 parse_and_append_ip(str, ips);
241 ip->sharing = substring;
242 ip->keyword = defaultkeyword; /* settings for default keyword */
243 if(lastIP6range)
244 {
245 lastIP6range->sharing = substring;
246 lastIP6range = NULL;
247 }
248 if(lastIP6uplink)
249 {
250 lastIP6uplink->sharing = substring;
251 lastIP6uplink = NULL;
252 }
253 while(*substring and *substring != '\n')
254 {
255 substring++;
256 }
257 *substring = 0;
258 }
259 else
260 {
261 substring = strstr(str, "#255.");
262 if(substring and not strstr(str, "#255.255.255.255")) /* ignore /32 subnets */
263 {
264 /* netmask detected - save network*/
265 unsigned bit;
266 unsigned num, mask = 8;
267 substring += 5;
268 while(substring && *substring)
269 {
270 ptr = substring;
271 substring = strchr(substring, '.');
272 if(substring)
273 {
274 *substring = 0;
275 substring += 1;
276 }
277 num = atoi(ptr);
278 for(bit = 1; bit <=128 ; bit<<=1)
279 {
280 if(bit & num)
281 {
282 mask++;
283 }
284 }
285 }
286 parse_and_append_ip(str, networks);
287 ip->mask = mask;
288 }
289 else
290 {
291 /* Main branch - most IP addresses go here */
292 /*Do we have to create new QoS class for this IP ? */
293 if_exists(keyword,keywords,(substring=strstr(str,keyword->key)))
294 {
295 #ifdef MONITORINGTRHU_CTU
296 //special hack only to generate certain required CSV statistics for www.ctu.cz (regulation body)
297 char *found_at = strchr(str, '@');
298 char *ruian_id_str = NULL;
299 technology = NULL;
300 if(found_at)
301 {
302 int len;
303 char *found_ruian_end = strchr(found_at, ' ');
304 char *found_tech_str = found_at;
305 while(found_tech_str-- > str && *found_tech_str != ' ' && *found_tech_str != '#');
306 if(found_tech_str > str)
307 {
308 len = found_at - found_tech_str - 1;
309 for_each(technology, technologies)
310 if(!strncmp(technology->filename, found_tech_str + 1, len))
311 break;
312 if(!technology)
313 {
314 create(technology,Technology);
315 string(technology->filename, len + 1);
316 strncpy(technology->filename, found_tech_str + 1, len);
317 technology->filename[len] = 0;
318 push(technology, technologies);
319 }
320 if(found_ruian_end)
321 {
322 len = found_ruian_end - found_at - 1;
323 string(ruian_id_str, len + 1);
324 strncpy(ruian_id_str, found_at + 1, len);
325 ruian_id_str[len] = 0;
326 }
327 }
328 }
329 #endif
330 parse_and_append_ip(str, ips);
331 if(lastIP6range)
332 {
333 lastIP6range->sharing = ip->name;
334 lastIP6range = NULL;
335 }
336 if(lastIP6uplink)
337 {
338 lastIP6uplink->sharing = ip->name;
339 lastIP6uplink = NULL;
340 }
341 ip->keyword = keyword;
342 keyword->ip_count++;
343 ip->prio = keyword->default_prio;
344 substring += strlen(keyword->key)+1;
345 ptr = substring;
346 while(*ptr and *ptr != '-')
347 {
348 ptr++;
349 }
350 if(*ptr == '-')
351 {
352 *ptr=0;
353 ip->max = ip->desired = atoi(ptr+1);
354 }
355
356 ip->min = atoi(substring);
357 if(ip->min <= 0)
358 {
359 printf(" %s: Illegal value of minimum bandwidth 0 kbps, using %d kb/s\n",
360 str, free_min);
361 ip->min = free_min;
362 }
363
364 if(ip->max <= ip->min)
365 {
366 ip->fixedprio = TRUE;
367 ip->max = ip->min + ip->keyword->reserve_min;
368 }
369 else
370 {
371 ip->max -= ip->keyword->reserve_max;
372 if(ip->max < ip->min)
373 {
374 ip->max = ip->min;
375 }
376 }
377
378 /* avg MTU bytes * 8 >> 10 = in bits, max is in kb/s */
379 pktratio = (ip->keyword->allowed_avgmtu*8) >> 10;
380 if(pktratio > 0)
381 {
382 ip->pps_limit = ip->max/pktratio;
383 if(ip->pps_limit > 10000) /* this limit seems to be hardcoded in iptables */
384 {
385 ip->pps_limit = 0; /* do not apply packet limits */
386 }
387 }
388
389 ip->mark = FIRSTIPCLASS+1+class_count++;
390 update_network(ip->addr, ip);
391
392 #ifdef MONITORINGTRHU_CTU
393 if(technology)
394 {
395 ip->technology_str = technology->filename;
396 ip->ruian_id_str = ruian_id_str;
397 /* debug printf("[%s,%d,%s,%d]\n", ip->technology_str,ip->lmsid, ip->ruian_id_str, ip->max); */
398 }
399 #endif
400
401 if_exists(group,groups,(group->min == ip->min))
402 {
403 group->count++;
404 group->desired += ip->min;
405 ip->group = group->id;
406 }
407 else
408 {
409 create(group,Group);
410 group->min = ip->min;
411 group->id = groupidx++;
412 ip->group = group->id;
413
414 if(group->min < 8) group->min = 8;
415 /* Warning - this is maybe because of primitive tc namespace, can be fixed */
416 /* it is because class IDs are derived from min. bandwidth. - xCh */
417 //if(group->min>MAX_GUARANTED_KBPS) group->min=MAX_GUARANTED_KBPS;
418
419 group->count = 1;
420 group->desired = ip->min;
421 insert(group, groups, desc_order_by,min);
422 }
423 }//endif keyword-
424 }//endif netmask
425 }//endif sharing-
426 }
427 fail
428 {
429 perror(hosts);
430 exit(-1);
431 }
432 done; /* ugly macro end */
433 // TheIP("0.0.0.0", TRUE);
434 // ip->name = "TOTAL";
435 // ip->mask = 0;
436 }
This page took 0.440154 seconds and 4 git commands to generate.