]> git.proxmox.com Git - mirror_frr.git/blame - babeld/util.c
babeld: Drop in_prefix() function
[mirror_frr.git] / babeld / util.c
CommitLineData
ca10883e
DS
1/*
2Copyright (c) 2007, 2008 by Juliusz Chroboczek
3Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
22*/
23
b45ac5f5
DL
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
ca10883e
DS
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
5920b3eb
RZ
42#include "lib/network.h"
43
ca10883e
DS
44#include "babel_main.h"
45#include "babeld.h"
46#include "util.h"
47
48int
49roughly(int value)
50{
51 if(value < 0)
52 return -roughly(-value);
53 else if(value <= 1)
54 return value;
55 else
5920b3eb 56 return value * 3 / 4 + frr_weak_random() % (value / 2);
ca10883e
DS
57}
58
59/* d = s1 - s2 */
60void
61timeval_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
73unsigned
74timeval_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 */
95void
96timeval_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
109void
110set_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. */
116int
117timeval_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 */
133void
134timeval_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] */
145void
146timeval_min_sec(struct timeval *d, time_t secs)
147{
148 if(d->tv_sec == 0 || d->tv_sec > secs) {
149 d->tv_sec = secs;
5920b3eb 150 d->tv_usec = frr_weak_random() % 1000000;
ca10883e
DS
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 */
157int
158parse_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. */
200int
201parse_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
ca10883e
DS
219unsigned char *
220mask_prefix(unsigned char *restrict ret,
221 const unsigned char *restrict prefix, unsigned char plen)
222{
223 if(plen >= 128) {
224 memcpy(ret, prefix, 16);
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
236const unsigned char v4prefix[16] =
237 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
238
239static const unsigned char llprefix[16] =
240 {0xFE, 0x80};
241
242const char *
243format_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
255const char *
256format_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
274const char *
275format_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
286const char *
287format_thousands(unsigned int value)
288{
289 static char buf[4][15];
290 static int i = 0;
291 i = (i + 1) % 4;
2ec42b85 292 snprintf(buf[i], 15, "%u.%.3u", value / 1000, value % 1000);
ca10883e
DS
293 return buf[i];
294}
295
296int
297parse_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, 16);
313 if(af_r) *af_r = AF_INET6;
314 return 0;
315 }
316
317 return -1;
318}
319
320int
321parse_eui64(const char *eui, unsigned char *eui_r)
322{
323 int n;
324 n = sscanf(eui, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
325 &eui_r[0], &eui_r[1], &eui_r[2], &eui_r[3],
326 &eui_r[4], &eui_r[5], &eui_r[6], &eui_r[7]);
327 if(n == 8)
328 return 0;
329
330 n = sscanf(eui, "%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx",
331 &eui_r[0], &eui_r[1], &eui_r[2], &eui_r[3],
332 &eui_r[4], &eui_r[5], &eui_r[6], &eui_r[7]);
333 if(n == 8)
334 return 0;
335
336 n = sscanf(eui, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
337 &eui_r[0], &eui_r[1], &eui_r[2],
338 &eui_r[5], &eui_r[6], &eui_r[7]);
339 if(n == 6) {
340 eui_r[3] = 0xFF;
341 eui_r[4] = 0xFE;
342 return 0;
343 }
344 return -1;
345}
346
347int
348wait_for_fd(int direction, int fd, int msecs)
349{
350 fd_set fds;
351 int rc;
352 struct timeval tv;
353
354 tv.tv_sec = msecs / 1000;
355 tv.tv_usec = (msecs % 1000) * 1000;
356
357 FD_ZERO(&fds);
358 FD_SET(fd, &fds);
359 if(direction)
360 rc = select(fd + 1, NULL, &fds, NULL, &tv);
361 else
362 rc = select(fd + 1, &fds, NULL, NULL, &tv);
363
364 return rc;
365}
366
367int
368martian_prefix(const unsigned char *prefix, int plen)
369{
370 return
371 (plen >= 8 && prefix[0] == 0xFF) ||
372 (plen >= 10 && prefix[0] == 0xFE && (prefix[1] & 0xC0) == 0x80) ||
373 (plen >= 128 && memcmp(prefix, zeroes, 15) == 0 &&
374 (prefix[15] == 0 || prefix[15] == 1)) ||
375 (plen >= 96 && v4mapped(prefix) &&
376 ((plen >= 104 && (prefix[12] == 127 || prefix[12] == 0)) ||
377 (plen >= 100 && (prefix[12] & 0xE0) == 0xE0)));
378}
379
380int
381linklocal(const unsigned char *address)
382{
383 return memcmp(address, llprefix, 8) == 0;
384}
385
386int
387v4mapped(const unsigned char *address)
388{
389 return memcmp(address, v4prefix, 12) == 0;
390}
391
392void
393v4tov6(unsigned char *dst, const unsigned char *src)
394{
395 memcpy(dst, v4prefix, 12);
396 memcpy(dst + 12, src, 4);
397}
398
399void
400inaddr_to_uchar(unsigned char *dest, const struct in_addr *src)
401{
402 v4tov6(dest, (const unsigned char *)src);
403 assert(v4mapped(dest));
404}
405
406void
407uchar_to_inaddr(struct in_addr *dest, const unsigned char *src)
408{
409 assert(v4mapped(src));
410 memcpy(dest, src + 12, 4);
411}
412
413void
414in6addr_to_uchar(unsigned char *dest, const struct in6_addr *src)
415{
416 memcpy(dest, src, 16);
417}
418
419void
420uchar_to_in6addr(struct in6_addr *dest, const unsigned char *src)
421{
422 memcpy(dest, src, 16);
423}
424
425int
4d762f26 426daemonise(void)
ca10883e
DS
427{
428 int rc;
429
430 fflush(stdout);
431 fflush(stderr);
432
433 rc = fork();
434 if(rc < 0)
435 return -1;
436
437 if(rc > 0)
438 exit(0);
439
440 rc = setsid();
441 if(rc < 0)
442 return -1;
443
444 return 1;
445}