]> git.proxmox.com Git - mirror_frr.git/blame - babeld/util.c
Merge pull request #13484 from sri-mohan1/srib-ldpd
[mirror_frr.git] / babeld / util.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: MIT
ca10883e
DS
2/*
3Copyright (c) 2007, 2008 by Juliusz Chroboczek
4Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
ca10883e
DS
5*/
6
b45ac5f5
DL
7#ifdef HAVE_CONFIG_H
8#include "config.h"
9#endif
10
ca10883e
DS
11#include <stdlib.h>
12#include <stdarg.h>
13#include <string.h>
14#include <sys/time.h>
15#include <time.h>
16#include <stdio.h>
17#include <unistd.h>
18#include <limits.h>
19
20#include <sys/types.h>
21#include <sys/socket.h>
22#include <netinet/in.h>
23#include <arpa/inet.h>
24
5920b3eb
RZ
25#include "lib/network.h"
26
ca10883e
DS
27#include "babel_main.h"
28#include "babeld.h"
29#include "util.h"
30
31int
32roughly(int value)
33{
34 if(value < 0)
35 return -roughly(-value);
36 else if(value <= 1)
37 return value;
38 else
5920b3eb 39 return value * 3 / 4 + frr_weak_random() % (value / 2);
ca10883e
DS
40}
41
42/* d = s1 - s2 */
43void
44timeval_minus(struct timeval *d,
45 const struct timeval *s1, const struct timeval *s2)
46{
47 if(s1->tv_usec >= s2->tv_usec) {
48 d->tv_usec = s1->tv_usec - s2->tv_usec;
49 d->tv_sec = s1->tv_sec - s2->tv_sec;
50 } else {
51 d->tv_usec = s1->tv_usec + 1000000 - s2->tv_usec;
52 d->tv_sec = s1->tv_sec - s2->tv_sec - 1;
53 }
54}
55
56unsigned
57timeval_minus_msec(const struct timeval *s1, const struct timeval *s2)
58{
59 if(s1->tv_sec < s2->tv_sec)
60 return 0;
61
62 /* Avoid overflow. */
63 if(s1->tv_sec - s2->tv_sec > 2000000)
64 return 2000000000;
65
66 if(s1->tv_sec > s2->tv_sec)
67 return
68 (unsigned)((unsigned)(s1->tv_sec - s2->tv_sec) * 1000 +
69 ((int)s1->tv_usec - s2->tv_usec) / 1000);
70
71 if(s1->tv_usec <= s2->tv_usec)
72 return 0;
73
74 return (unsigned)(s1->tv_usec - s2->tv_usec) / 1000u;
75}
76
77/* d = s + msecs */
78void
79timeval_add_msec(struct timeval *d, const struct timeval *s, int msecs)
80{
81 int usecs;
82 d->tv_sec = s->tv_sec + msecs / 1000;
83 usecs = s->tv_usec + (msecs % 1000) * 1000;
84 if(usecs < 1000000) {
85 d->tv_usec = usecs;
86 } else {
87 d->tv_usec = usecs - 1000000;
88 d->tv_sec++;
89 }
90}
91
92void
93set_timeout(struct timeval *timeout, int msecs)
94{
95 timeval_add_msec(timeout, &babel_now, roughly(msecs));
96}
97
98/* returns <0 if "s1" < "s2", etc. */
99int
100timeval_compare(const struct timeval *s1, const struct timeval *s2)
101{
102 if(s1->tv_sec < s2->tv_sec)
103 return -1;
104 else if(s1->tv_sec > s2->tv_sec)
105 return 1;
106 else if(s1->tv_usec < s2->tv_usec)
107 return -1;
108 else if(s1->tv_usec > s2->tv_usec)
109 return 1;
110 else
111 return 0;
112}
113
114/* set d at min(d, s) */
115/* {0, 0} represents infinity */
116void
117timeval_min(struct timeval *d, const struct timeval *s)
118{
119 if(s->tv_sec == 0)
120 return;
121
122 if(d->tv_sec == 0 || timeval_compare(d, s) > 0) {
123 *d = *s;
124 }
125}
126
127/* set d to min(d, x) with x in [secs, secs+1] */
128void
129timeval_min_sec(struct timeval *d, time_t secs)
130{
131 if(d->tv_sec == 0 || d->tv_sec > secs) {
132 d->tv_sec = secs;
5920b3eb 133 d->tv_usec = frr_weak_random() % 1000000;
ca10883e
DS
134 }
135}
136
137/* parse a float value in second and return the corresponding mili-seconds.
138 For example:
139 parse_msec("12.342345") returns 12342 */
140int
141parse_msec(const char *string)
142{
143 unsigned int in, fl;
144 int i, j;
145
146 in = fl = 0;
147 i = 0;
148 while(string[i] == ' ' || string[i] == '\t')
149 i++;
150 while(string[i] >= '0' && string[i] <= '9') {
151 in = in * 10 + string[i] - '0';
152 i++;
153 }
154 if(string[i] == '.') {
155 i++;
156 j = 0;
157 while(string[i] >= '0' && string[i] <= '9') {
158 fl = fl * 10 + string[i] - '0';
159 i++;
160 j++;
161 }
162
163 while(j > 3) {
164 fl /= 10;
165 j--;
166 }
167 while(j < 3) {
168 fl *= 10;
169 j++;
170 }
171 }
172
173 while(string[i] == ' ' || string[i] == '\t')
174 i++;
175
176 if(string[i] == '\0')
177 return in * 1000 + fl;
178
179 return -1;
180}
181
182/* There's no good name for a positive int in C, call it nat. */
183int
184parse_nat(const char *string)
185{
186 long l;
187 char *end;
188
189 l = strtol(string, &end, 0);
190
191 while(*end == ' ' || *end == '\t')
192 end++;
193 if(*end != '\0')
194 return -1;
195
196 if(l < 0 || l > INT_MAX)
197 return -1;
198
199 return (int)l;
200}
201
ca10883e
DS
202unsigned char *
203mask_prefix(unsigned char *restrict ret,
204 const unsigned char *restrict prefix, unsigned char plen)
205{
8643c2e5
DA
206 if (plen >= IPV6_MAX_BITLEN) {
207 memcpy(ret, prefix, IPV6_MAX_BYTELEN);
208 return ret;
ca10883e
DS
209 }
210
211 memset(ret, 0, 16);
212 memcpy(ret, prefix, plen / 8);
213 if(plen % 8 != 0)
214 ret[plen / 8] =
215 (prefix[plen / 8] & ((0xFF << (8 - (plen % 8))) & 0xFF));
216 return ret;
217}
218
219const unsigned char v4prefix[16] =
220 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
221
222static const unsigned char llprefix[16] =
223 {0xFE, 0x80};
224
225const char *
226format_address(const unsigned char *address)
227{
228 static char buf[4][INET6_ADDRSTRLEN];
229 static int i = 0;
230 i = (i + 1) % 4;
231 if(v4mapped(address))
232 inet_ntop(AF_INET, address + 12, buf[i], INET6_ADDRSTRLEN);
233 else
234 inet_ntop(AF_INET6, address, buf[i], INET6_ADDRSTRLEN);
235 return buf[i];
236}
237
238const char *
239format_prefix(const unsigned char *prefix, unsigned char plen)
240{
241 static char buf[4][INET6_ADDRSTRLEN + 4];
242 static int i = 0;
243 int n;
244 i = (i + 1) % 4;
245 if(plen >= 96 && v4mapped(prefix)) {
246 inet_ntop(AF_INET, prefix + 12, buf[i], INET6_ADDRSTRLEN);
247 n = strlen(buf[i]);
248 snprintf(buf[i] + n, INET6_ADDRSTRLEN + 4 - n, "/%d", plen - 96);
249 } else {
250 inet_ntop(AF_INET6, prefix, buf[i], INET6_ADDRSTRLEN);
251 n = strlen(buf[i]);
252 snprintf(buf[i] + n, INET6_ADDRSTRLEN + 4 - n, "/%d", plen);
253 }
254 return buf[i];
255}
256
257const char *
258format_eui64(const unsigned char *eui)
259{
260 static char buf[4][28];
261 static int i = 0;
262 i = (i + 1) % 4;
263 snprintf(buf[i], 28, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
264 eui[0], eui[1], eui[2], eui[3],
265 eui[4], eui[5], eui[6], eui[7]);
266 return buf[i];
267}
268
269const char *
270format_thousands(unsigned int value)
271{
272 static char buf[4][15];
273 static int i = 0;
274 i = (i + 1) % 4;
2ec42b85 275 snprintf(buf[i], 15, "%u.%.3u", value / 1000, value % 1000);
ca10883e
DS
276 return buf[i];
277}
278
279int
280parse_address(const char *address, unsigned char *addr_r, int *af_r)
281{
282 struct in_addr ina;
283 struct in6_addr ina6;
284 int rc;
285
286 rc = inet_pton(AF_INET, address, &ina);
287 if(rc > 0) {
288 v4tov6(addr_r, (const unsigned char *)&ina);
289 if(af_r) *af_r = AF_INET;
290 return 0;
291 }
292
293 rc = inet_pton(AF_INET6, address, &ina6);
294 if(rc > 0) {
8643c2e5
DA
295 memcpy(addr_r, &ina6, IPV6_MAX_BYTELEN);
296 if (af_r)
297 *af_r = AF_INET6;
298 return 0;
ca10883e
DS
299 }
300
301 return -1;
302}
303
304int
305parse_eui64(const char *eui, unsigned char *eui_r)
306{
307 int n;
308 n = sscanf(eui, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
309 &eui_r[0], &eui_r[1], &eui_r[2], &eui_r[3],
310 &eui_r[4], &eui_r[5], &eui_r[6], &eui_r[7]);
311 if(n == 8)
312 return 0;
313
314 n = sscanf(eui, "%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx",
315 &eui_r[0], &eui_r[1], &eui_r[2], &eui_r[3],
316 &eui_r[4], &eui_r[5], &eui_r[6], &eui_r[7]);
317 if(n == 8)
318 return 0;
319
320 n = sscanf(eui, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
321 &eui_r[0], &eui_r[1], &eui_r[2],
322 &eui_r[5], &eui_r[6], &eui_r[7]);
323 if(n == 6) {
324 eui_r[3] = 0xFF;
325 eui_r[4] = 0xFE;
326 return 0;
327 }
328 return -1;
329}
330
331int
332wait_for_fd(int direction, int fd, int msecs)
333{
334 fd_set fds;
335 int rc;
336 struct timeval tv;
337
338 tv.tv_sec = msecs / 1000;
339 tv.tv_usec = (msecs % 1000) * 1000;
340
341 FD_ZERO(&fds);
342 FD_SET(fd, &fds);
343 if(direction)
344 rc = select(fd + 1, NULL, &fds, NULL, &tv);
345 else
346 rc = select(fd + 1, &fds, NULL, NULL, &tv);
347
348 return rc;
349}
350
351int
352martian_prefix(const unsigned char *prefix, int plen)
353{
354 return
355 (plen >= 8 && prefix[0] == 0xFF) ||
356 (plen >= 10 && prefix[0] == 0xFE && (prefix[1] & 0xC0) == 0x80) ||
357 (plen >= 128 && memcmp(prefix, zeroes, 15) == 0 &&
358 (prefix[15] == 0 || prefix[15] == 1)) ||
359 (plen >= 96 && v4mapped(prefix) &&
360 ((plen >= 104 && (prefix[12] == 127 || prefix[12] == 0)) ||
361 (plen >= 100 && (prefix[12] & 0xE0) == 0xE0)));
362}
363
364int
365linklocal(const unsigned char *address)
366{
367 return memcmp(address, llprefix, 8) == 0;
368}
369
370int
371v4mapped(const unsigned char *address)
372{
373 return memcmp(address, v4prefix, 12) == 0;
374}
375
376void
377v4tov6(unsigned char *dst, const unsigned char *src)
378{
379 memcpy(dst, v4prefix, 12);
380 memcpy(dst + 12, src, 4);
381}
382
383void
384inaddr_to_uchar(unsigned char *dest, const struct in_addr *src)
385{
386 v4tov6(dest, (const unsigned char *)src);
387 assert(v4mapped(dest));
388}
389
390void
391uchar_to_inaddr(struct in_addr *dest, const unsigned char *src)
392{
393 assert(v4mapped(src));
394 memcpy(dest, src + 12, 4);
395}
396
397void
398in6addr_to_uchar(unsigned char *dest, const struct in6_addr *src)
399{
8643c2e5 400 memcpy(dest, src, IPV6_MAX_BYTELEN);
ca10883e
DS
401}
402
403void
404uchar_to_in6addr(struct in6_addr *dest, const unsigned char *src)
405{
8643c2e5 406 memcpy(dest, src, IPV6_MAX_BYTELEN);
ca10883e
DS
407}
408
409int
4d762f26 410daemonise(void)
ca10883e
DS
411{
412 int rc;
413
414 fflush(stdout);
415 fflush(stderr);
416
417 rc = fork();
418 if(rc < 0)
419 return -1;
420
421 if(rc > 0)
422 exit(0);
423
424 rc = setsid();
425 if(rc < 0)
426 return -1;
427
428 return 1;
429}