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