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