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