]> git.proxmox.com Git - mirror_frr.git/blob - babeld/util.c
doc: Add `show ipv6 rpf X:X::X:X` command to docs
[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 unsigned char *
220 mask_prefix(unsigned char *restrict ret,
221 const unsigned char *restrict prefix, unsigned char plen)
222 {
223 if (plen >= IPV6_MAX_BITLEN) {
224 memcpy(ret, prefix, IPV6_MAX_BYTELEN);
225 return ret;
226 }
227
228 memset(ret, 0, 16);
229 memcpy(ret, prefix, plen / 8);
230 if(plen % 8 != 0)
231 ret[plen / 8] =
232 (prefix[plen / 8] & ((0xFF << (8 - (plen % 8))) & 0xFF));
233 return ret;
234 }
235
236 const unsigned char v4prefix[16] =
237 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
238
239 static const unsigned char llprefix[16] =
240 {0xFE, 0x80};
241
242 const char *
243 format_address(const unsigned char *address)
244 {
245 static char buf[4][INET6_ADDRSTRLEN];
246 static int i = 0;
247 i = (i + 1) % 4;
248 if(v4mapped(address))
249 inet_ntop(AF_INET, address + 12, buf[i], INET6_ADDRSTRLEN);
250 else
251 inet_ntop(AF_INET6, address, buf[i], INET6_ADDRSTRLEN);
252 return buf[i];
253 }
254
255 const char *
256 format_prefix(const unsigned char *prefix, unsigned char plen)
257 {
258 static char buf[4][INET6_ADDRSTRLEN + 4];
259 static int i = 0;
260 int n;
261 i = (i + 1) % 4;
262 if(plen >= 96 && v4mapped(prefix)) {
263 inet_ntop(AF_INET, prefix + 12, buf[i], INET6_ADDRSTRLEN);
264 n = strlen(buf[i]);
265 snprintf(buf[i] + n, INET6_ADDRSTRLEN + 4 - n, "/%d", plen - 96);
266 } else {
267 inet_ntop(AF_INET6, prefix, buf[i], INET6_ADDRSTRLEN);
268 n = strlen(buf[i]);
269 snprintf(buf[i] + n, INET6_ADDRSTRLEN + 4 - n, "/%d", plen);
270 }
271 return buf[i];
272 }
273
274 const char *
275 format_eui64(const unsigned char *eui)
276 {
277 static char buf[4][28];
278 static int i = 0;
279 i = (i + 1) % 4;
280 snprintf(buf[i], 28, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
281 eui[0], eui[1], eui[2], eui[3],
282 eui[4], eui[5], eui[6], eui[7]);
283 return buf[i];
284 }
285
286 const char *
287 format_thousands(unsigned int value)
288 {
289 static char buf[4][15];
290 static int i = 0;
291 i = (i + 1) % 4;
292 snprintf(buf[i], 15, "%u.%.3u", value / 1000, value % 1000);
293 return buf[i];
294 }
295
296 int
297 parse_address(const char *address, unsigned char *addr_r, int *af_r)
298 {
299 struct in_addr ina;
300 struct in6_addr ina6;
301 int rc;
302
303 rc = inet_pton(AF_INET, address, &ina);
304 if(rc > 0) {
305 v4tov6(addr_r, (const unsigned char *)&ina);
306 if(af_r) *af_r = AF_INET;
307 return 0;
308 }
309
310 rc = inet_pton(AF_INET6, address, &ina6);
311 if(rc > 0) {
312 memcpy(addr_r, &ina6, IPV6_MAX_BYTELEN);
313 if (af_r)
314 *af_r = AF_INET6;
315 return 0;
316 }
317
318 return -1;
319 }
320
321 int
322 parse_eui64(const char *eui, unsigned char *eui_r)
323 {
324 int n;
325 n = sscanf(eui, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
326 &eui_r[0], &eui_r[1], &eui_r[2], &eui_r[3],
327 &eui_r[4], &eui_r[5], &eui_r[6], &eui_r[7]);
328 if(n == 8)
329 return 0;
330
331 n = sscanf(eui, "%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx",
332 &eui_r[0], &eui_r[1], &eui_r[2], &eui_r[3],
333 &eui_r[4], &eui_r[5], &eui_r[6], &eui_r[7]);
334 if(n == 8)
335 return 0;
336
337 n = sscanf(eui, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
338 &eui_r[0], &eui_r[1], &eui_r[2],
339 &eui_r[5], &eui_r[6], &eui_r[7]);
340 if(n == 6) {
341 eui_r[3] = 0xFF;
342 eui_r[4] = 0xFE;
343 return 0;
344 }
345 return -1;
346 }
347
348 int
349 wait_for_fd(int direction, int fd, int msecs)
350 {
351 fd_set fds;
352 int rc;
353 struct timeval tv;
354
355 tv.tv_sec = msecs / 1000;
356 tv.tv_usec = (msecs % 1000) * 1000;
357
358 FD_ZERO(&fds);
359 FD_SET(fd, &fds);
360 if(direction)
361 rc = select(fd + 1, NULL, &fds, NULL, &tv);
362 else
363 rc = select(fd + 1, &fds, NULL, NULL, &tv);
364
365 return rc;
366 }
367
368 int
369 martian_prefix(const unsigned char *prefix, int plen)
370 {
371 return
372 (plen >= 8 && prefix[0] == 0xFF) ||
373 (plen >= 10 && prefix[0] == 0xFE && (prefix[1] & 0xC0) == 0x80) ||
374 (plen >= 128 && memcmp(prefix, zeroes, 15) == 0 &&
375 (prefix[15] == 0 || prefix[15] == 1)) ||
376 (plen >= 96 && v4mapped(prefix) &&
377 ((plen >= 104 && (prefix[12] == 127 || prefix[12] == 0)) ||
378 (plen >= 100 && (prefix[12] & 0xE0) == 0xE0)));
379 }
380
381 int
382 linklocal(const unsigned char *address)
383 {
384 return memcmp(address, llprefix, 8) == 0;
385 }
386
387 int
388 v4mapped(const unsigned char *address)
389 {
390 return memcmp(address, v4prefix, 12) == 0;
391 }
392
393 void
394 v4tov6(unsigned char *dst, const unsigned char *src)
395 {
396 memcpy(dst, v4prefix, 12);
397 memcpy(dst + 12, src, 4);
398 }
399
400 void
401 inaddr_to_uchar(unsigned char *dest, const struct in_addr *src)
402 {
403 v4tov6(dest, (const unsigned char *)src);
404 assert(v4mapped(dest));
405 }
406
407 void
408 uchar_to_inaddr(struct in_addr *dest, const unsigned char *src)
409 {
410 assert(v4mapped(src));
411 memcpy(dest, src + 12, 4);
412 }
413
414 void
415 in6addr_to_uchar(unsigned char *dest, const struct in6_addr *src)
416 {
417 memcpy(dest, src, IPV6_MAX_BYTELEN);
418 }
419
420 void
421 uchar_to_in6addr(struct in6_addr *dest, const unsigned char *src)
422 {
423 memcpy(dest, src, IPV6_MAX_BYTELEN);
424 }
425
426 int
427 daemonise(void)
428 {
429 int rc;
430
431 fflush(stdout);
432 fflush(stderr);
433
434 rc = fork();
435 if(rc < 0)
436 return -1;
437
438 if(rc > 0)
439 exit(0);
440
441 rc = setsid();
442 if(rc < 0)
443 return -1;
444
445 return 1;
446 }