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