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