]> git.proxmox.com Git - mirror_frr.git/blob - babeld/util.c
Merge pull request #5881 from patrasar/2386420
[mirror_frr.git] / babeld / util.c
1 /*
2 Copyright (c) 2007, 2008 by Juliusz Chroboczek
3 Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 THE SOFTWARE.
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <string.h>
31 #include <sys/time.h>
32 #include <time.h>
33 #include <stdio.h>
34 #include <unistd.h>
35 #include <limits.h>
36
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
41
42 #include "lib/network.h"
43
44 #include "babel_main.h"
45 #include "babeld.h"
46 #include "util.h"
47
48 int
49 roughly(int value)
50 {
51 if(value < 0)
52 return -roughly(-value);
53 else if(value <= 1)
54 return value;
55 else
56 return value * 3 / 4 + frr_weak_random() % (value / 2);
57 }
58
59 /* d = s1 - s2 */
60 void
61 timeval_minus(struct timeval *d,
62 const struct timeval *s1, const struct timeval *s2)
63 {
64 if(s1->tv_usec >= s2->tv_usec) {
65 d->tv_usec = s1->tv_usec - s2->tv_usec;
66 d->tv_sec = s1->tv_sec - s2->tv_sec;
67 } else {
68 d->tv_usec = s1->tv_usec + 1000000 - s2->tv_usec;
69 d->tv_sec = s1->tv_sec - s2->tv_sec - 1;
70 }
71 }
72
73 unsigned
74 timeval_minus_msec(const struct timeval *s1, const struct timeval *s2)
75 {
76 if(s1->tv_sec < s2->tv_sec)
77 return 0;
78
79 /* Avoid overflow. */
80 if(s1->tv_sec - s2->tv_sec > 2000000)
81 return 2000000000;
82
83 if(s1->tv_sec > s2->tv_sec)
84 return
85 (unsigned)((unsigned)(s1->tv_sec - s2->tv_sec) * 1000 +
86 ((int)s1->tv_usec - s2->tv_usec) / 1000);
87
88 if(s1->tv_usec <= s2->tv_usec)
89 return 0;
90
91 return (unsigned)(s1->tv_usec - s2->tv_usec) / 1000u;
92 }
93
94 /* d = s + msecs */
95 void
96 timeval_add_msec(struct timeval *d, const struct timeval *s, int msecs)
97 {
98 int usecs;
99 d->tv_sec = s->tv_sec + msecs / 1000;
100 usecs = s->tv_usec + (msecs % 1000) * 1000;
101 if(usecs < 1000000) {
102 d->tv_usec = usecs;
103 } else {
104 d->tv_usec = usecs - 1000000;
105 d->tv_sec++;
106 }
107 }
108
109 void
110 set_timeout(struct timeval *timeout, int msecs)
111 {
112 timeval_add_msec(timeout, &babel_now, roughly(msecs));
113 }
114
115 /* returns <0 if "s1" < "s2", etc. */
116 int
117 timeval_compare(const struct timeval *s1, const struct timeval *s2)
118 {
119 if(s1->tv_sec < s2->tv_sec)
120 return -1;
121 else if(s1->tv_sec > s2->tv_sec)
122 return 1;
123 else if(s1->tv_usec < s2->tv_usec)
124 return -1;
125 else if(s1->tv_usec > s2->tv_usec)
126 return 1;
127 else
128 return 0;
129 }
130
131 /* set d at min(d, s) */
132 /* {0, 0} represents infinity */
133 void
134 timeval_min(struct timeval *d, const struct timeval *s)
135 {
136 if(s->tv_sec == 0)
137 return;
138
139 if(d->tv_sec == 0 || timeval_compare(d, s) > 0) {
140 *d = *s;
141 }
142 }
143
144 /* set d to min(d, x) with x in [secs, secs+1] */
145 void
146 timeval_min_sec(struct timeval *d, time_t secs)
147 {
148 if(d->tv_sec == 0 || d->tv_sec > secs) {
149 d->tv_sec = secs;
150 d->tv_usec = frr_weak_random() % 1000000;
151 }
152 }
153
154 /* parse a float value in second and return the corresponding mili-seconds.
155 For example:
156 parse_msec("12.342345") returns 12342 */
157 int
158 parse_msec(const char *string)
159 {
160 unsigned int in, fl;
161 int i, j;
162
163 in = fl = 0;
164 i = 0;
165 while(string[i] == ' ' || string[i] == '\t')
166 i++;
167 while(string[i] >= '0' && string[i] <= '9') {
168 in = in * 10 + string[i] - '0';
169 i++;
170 }
171 if(string[i] == '.') {
172 i++;
173 j = 0;
174 while(string[i] >= '0' && string[i] <= '9') {
175 fl = fl * 10 + string[i] - '0';
176 i++;
177 j++;
178 }
179
180 while(j > 3) {
181 fl /= 10;
182 j--;
183 }
184 while(j < 3) {
185 fl *= 10;
186 j++;
187 }
188 }
189
190 while(string[i] == ' ' || string[i] == '\t')
191 i++;
192
193 if(string[i] == '\0')
194 return in * 1000 + fl;
195
196 return -1;
197 }
198
199 /* There's no good name for a positive int in C, call it nat. */
200 int
201 parse_nat(const char *string)
202 {
203 long l;
204 char *end;
205
206 l = strtol(string, &end, 0);
207
208 while(*end == ' ' || *end == '\t')
209 end++;
210 if(*end != '\0')
211 return -1;
212
213 if(l < 0 || l > INT_MAX)
214 return -1;
215
216 return (int)l;
217 }
218
219 int
220 in_prefix(const unsigned char *restrict address,
221 const unsigned char *restrict prefix, unsigned char plen)
222 {
223 unsigned char m;
224
225 if(plen > 128)
226 plen = 128;
227
228 if(memcmp(address, prefix, plen / 8) != 0)
229 return 0;
230
231 if(plen % 8 == 0)
232 return 1;
233
234 m = 0xFF << (8 - (plen % 8));
235
236 return ((address[plen / 8] & m) == (prefix[plen / 8] & m));
237 }
238
239 unsigned char *
240 mask_prefix(unsigned char *restrict ret,
241 const unsigned char *restrict prefix, unsigned char plen)
242 {
243 if(plen >= 128) {
244 memcpy(ret, prefix, 16);
245 return ret;
246 }
247
248 memset(ret, 0, 16);
249 memcpy(ret, prefix, plen / 8);
250 if(plen % 8 != 0)
251 ret[plen / 8] =
252 (prefix[plen / 8] & ((0xFF << (8 - (plen % 8))) & 0xFF));
253 return ret;
254 }
255
256 const unsigned char v4prefix[16] =
257 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
258
259 static const unsigned char llprefix[16] =
260 {0xFE, 0x80};
261
262 const char *
263 format_address(const unsigned char *address)
264 {
265 static char buf[4][INET6_ADDRSTRLEN];
266 static int i = 0;
267 i = (i + 1) % 4;
268 if(v4mapped(address))
269 inet_ntop(AF_INET, address + 12, buf[i], INET6_ADDRSTRLEN);
270 else
271 inet_ntop(AF_INET6, address, buf[i], INET6_ADDRSTRLEN);
272 return buf[i];
273 }
274
275 const char *
276 format_prefix(const unsigned char *prefix, unsigned char plen)
277 {
278 static char buf[4][INET6_ADDRSTRLEN + 4];
279 static int i = 0;
280 int n;
281 i = (i + 1) % 4;
282 if(plen >= 96 && v4mapped(prefix)) {
283 inet_ntop(AF_INET, prefix + 12, buf[i], INET6_ADDRSTRLEN);
284 n = strlen(buf[i]);
285 snprintf(buf[i] + n, INET6_ADDRSTRLEN + 4 - n, "/%d", plen - 96);
286 } else {
287 inet_ntop(AF_INET6, prefix, buf[i], INET6_ADDRSTRLEN);
288 n = strlen(buf[i]);
289 snprintf(buf[i] + n, INET6_ADDRSTRLEN + 4 - n, "/%d", plen);
290 }
291 return buf[i];
292 }
293
294 const char *
295 format_eui64(const unsigned char *eui)
296 {
297 static char buf[4][28];
298 static int i = 0;
299 i = (i + 1) % 4;
300 snprintf(buf[i], 28, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
301 eui[0], eui[1], eui[2], eui[3],
302 eui[4], eui[5], eui[6], eui[7]);
303 return buf[i];
304 }
305
306 const char *
307 format_thousands(unsigned int value)
308 {
309 static char buf[4][15];
310 static int i = 0;
311 i = (i + 1) % 4;
312 snprintf(buf[i], 15, "%u.%.3u", value / 1000, value % 1000);
313 return buf[i];
314 }
315
316 int
317 parse_address(const char *address, unsigned char *addr_r, int *af_r)
318 {
319 struct in_addr ina;
320 struct in6_addr ina6;
321 int rc;
322
323 rc = inet_pton(AF_INET, address, &ina);
324 if(rc > 0) {
325 v4tov6(addr_r, (const unsigned char *)&ina);
326 if(af_r) *af_r = AF_INET;
327 return 0;
328 }
329
330 rc = inet_pton(AF_INET6, address, &ina6);
331 if(rc > 0) {
332 memcpy(addr_r, &ina6, 16);
333 if(af_r) *af_r = AF_INET6;
334 return 0;
335 }
336
337 return -1;
338 }
339
340 int
341 parse_eui64(const char *eui, unsigned char *eui_r)
342 {
343 int n;
344 n = sscanf(eui, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
345 &eui_r[0], &eui_r[1], &eui_r[2], &eui_r[3],
346 &eui_r[4], &eui_r[5], &eui_r[6], &eui_r[7]);
347 if(n == 8)
348 return 0;
349
350 n = sscanf(eui, "%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx",
351 &eui_r[0], &eui_r[1], &eui_r[2], &eui_r[3],
352 &eui_r[4], &eui_r[5], &eui_r[6], &eui_r[7]);
353 if(n == 8)
354 return 0;
355
356 n = sscanf(eui, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
357 &eui_r[0], &eui_r[1], &eui_r[2],
358 &eui_r[5], &eui_r[6], &eui_r[7]);
359 if(n == 6) {
360 eui_r[3] = 0xFF;
361 eui_r[4] = 0xFE;
362 return 0;
363 }
364 return -1;
365 }
366
367 int
368 wait_for_fd(int direction, int fd, int msecs)
369 {
370 fd_set fds;
371 int rc;
372 struct timeval tv;
373
374 tv.tv_sec = msecs / 1000;
375 tv.tv_usec = (msecs % 1000) * 1000;
376
377 FD_ZERO(&fds);
378 FD_SET(fd, &fds);
379 if(direction)
380 rc = select(fd + 1, NULL, &fds, NULL, &tv);
381 else
382 rc = select(fd + 1, &fds, NULL, NULL, &tv);
383
384 return rc;
385 }
386
387 int
388 martian_prefix(const unsigned char *prefix, int plen)
389 {
390 return
391 (plen >= 8 && prefix[0] == 0xFF) ||
392 (plen >= 10 && prefix[0] == 0xFE && (prefix[1] & 0xC0) == 0x80) ||
393 (plen >= 128 && memcmp(prefix, zeroes, 15) == 0 &&
394 (prefix[15] == 0 || prefix[15] == 1)) ||
395 (plen >= 96 && v4mapped(prefix) &&
396 ((plen >= 104 && (prefix[12] == 127 || prefix[12] == 0)) ||
397 (plen >= 100 && (prefix[12] & 0xE0) == 0xE0)));
398 }
399
400 int
401 linklocal(const unsigned char *address)
402 {
403 return memcmp(address, llprefix, 8) == 0;
404 }
405
406 int
407 v4mapped(const unsigned char *address)
408 {
409 return memcmp(address, v4prefix, 12) == 0;
410 }
411
412 void
413 v4tov6(unsigned char *dst, const unsigned char *src)
414 {
415 memcpy(dst, v4prefix, 12);
416 memcpy(dst + 12, src, 4);
417 }
418
419 void
420 inaddr_to_uchar(unsigned char *dest, const struct in_addr *src)
421 {
422 v4tov6(dest, (const unsigned char *)src);
423 assert(v4mapped(dest));
424 }
425
426 void
427 uchar_to_inaddr(struct in_addr *dest, const unsigned char *src)
428 {
429 assert(v4mapped(src));
430 memcpy(dest, src + 12, 4);
431 }
432
433 void
434 in6addr_to_uchar(unsigned char *dest, const struct in6_addr *src)
435 {
436 memcpy(dest, src, 16);
437 }
438
439 void
440 uchar_to_in6addr(struct in6_addr *dest, const unsigned char *src)
441 {
442 memcpy(dest, src, 16);
443 }
444
445 int
446 daemonise(void)
447 {
448 int rc;
449
450 fflush(stdout);
451 fflush(stderr);
452
453 rc = fork();
454 if(rc < 0)
455 return -1;
456
457 if(rc > 0)
458 exit(0);
459
460 rc = setsid();
461 if(rc < 0)
462 return -1;
463
464 return 1;
465 }