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