]>
git.proxmox.com Git - mirror_frr.git/blob - babeld/util.c
4facdabbc6e34deb3fbfc90f2f89d989267ad9ce
1 // SPDX-License-Identifier: MIT
3 Copyright (c) 2007, 2008 by Juliusz Chroboczek
4 Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
25 #include "lib/network.h"
27 #include "babel_main.h"
35 return -roughly(-value
);
39 return value
* 3 / 4 + frr_weak_random() % (value
/ 2);
44 timeval_minus(struct timeval
*d
,
45 const struct timeval
*s1
, const struct timeval
*s2
)
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
;
51 d
->tv_usec
= s1
->tv_usec
+ 1000000 - s2
->tv_usec
;
52 d
->tv_sec
= s1
->tv_sec
- s2
->tv_sec
- 1;
57 timeval_minus_msec(const struct timeval
*s1
, const struct timeval
*s2
)
59 if(s1
->tv_sec
< s2
->tv_sec
)
63 if(s1
->tv_sec
- s2
->tv_sec
> 2000000)
66 if(s1
->tv_sec
> s2
->tv_sec
)
68 (unsigned)((unsigned)(s1
->tv_sec
- s2
->tv_sec
) * 1000 +
69 ((int)s1
->tv_usec
- s2
->tv_usec
) / 1000);
71 if(s1
->tv_usec
<= s2
->tv_usec
)
74 return (unsigned)(s1
->tv_usec
- s2
->tv_usec
) / 1000u;
79 timeval_add_msec(struct timeval
*d
, const struct timeval
*s
, int msecs
)
82 d
->tv_sec
= s
->tv_sec
+ msecs
/ 1000;
83 usecs
= s
->tv_usec
+ (msecs
% 1000) * 1000;
87 d
->tv_usec
= usecs
- 1000000;
93 set_timeout(struct timeval
*timeout
, int msecs
)
95 timeval_add_msec(timeout
, &babel_now
, roughly(msecs
));
98 /* returns <0 if "s1" < "s2", etc. */
100 timeval_compare(const struct timeval
*s1
, const struct timeval
*s2
)
102 if(s1
->tv_sec
< s2
->tv_sec
)
104 else if(s1
->tv_sec
> s2
->tv_sec
)
106 else if(s1
->tv_usec
< s2
->tv_usec
)
108 else if(s1
->tv_usec
> s2
->tv_usec
)
114 /* set d at min(d, s) */
115 /* {0, 0} represents infinity */
117 timeval_min(struct timeval
*d
, const struct timeval
*s
)
122 if(d
->tv_sec
== 0 || timeval_compare(d
, s
) > 0) {
127 /* set d to min(d, x) with x in [secs, secs+1] */
129 timeval_min_sec(struct timeval
*d
, time_t secs
)
131 if(d
->tv_sec
== 0 || d
->tv_sec
> secs
) {
133 d
->tv_usec
= frr_weak_random() % 1000000;
137 /* parse a float value in second and return the corresponding mili-seconds.
139 parse_msec("12.342345") returns 12342 */
141 parse_msec(const char *string
)
148 while(string
[i
] == ' ' || string
[i
] == '\t')
150 while(string
[i
] >= '0' && string
[i
] <= '9') {
151 in
= in
* 10 + string
[i
] - '0';
154 if(string
[i
] == '.') {
157 while(string
[i
] >= '0' && string
[i
] <= '9') {
158 fl
= fl
* 10 + string
[i
] - '0';
173 while(string
[i
] == ' ' || string
[i
] == '\t')
176 if(string
[i
] == '\0')
177 return in
* 1000 + fl
;
182 /* There's no good name for a positive int in C, call it nat. */
184 parse_nat(const char *string
)
189 l
= strtol(string
, &end
, 0);
191 while(*end
== ' ' || *end
== '\t')
196 if(l
< 0 || l
> INT_MAX
)
203 mask_prefix(unsigned char *restrict ret
,
204 const unsigned char *restrict prefix
, unsigned char plen
)
206 if (plen
>= IPV6_MAX_BITLEN
) {
207 memcpy(ret
, prefix
, IPV6_MAX_BYTELEN
);
212 memcpy(ret
, prefix
, plen
/ 8);
215 (prefix
[plen
/ 8] & ((0xFF << (8 - (plen
% 8))) & 0xFF));
219 const unsigned char v4prefix
[16] =
220 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
222 static const unsigned char llprefix
[16] =
226 format_address(const unsigned char *address
)
228 static char buf
[4][INET6_ADDRSTRLEN
];
231 if(v4mapped(address
))
232 inet_ntop(AF_INET
, address
+ 12, buf
[i
], INET6_ADDRSTRLEN
);
234 inet_ntop(AF_INET6
, address
, buf
[i
], INET6_ADDRSTRLEN
);
239 format_prefix(const unsigned char *prefix
, unsigned char plen
)
241 static char buf
[4][INET6_ADDRSTRLEN
+ 4];
245 if(plen
>= 96 && v4mapped(prefix
)) {
246 inet_ntop(AF_INET
, prefix
+ 12, buf
[i
], INET6_ADDRSTRLEN
);
248 snprintf(buf
[i
] + n
, INET6_ADDRSTRLEN
+ 4 - n
, "/%d", plen
- 96);
250 inet_ntop(AF_INET6
, prefix
, buf
[i
], INET6_ADDRSTRLEN
);
252 snprintf(buf
[i
] + n
, INET6_ADDRSTRLEN
+ 4 - n
, "/%d", plen
);
258 format_eui64(const unsigned char *eui
)
260 static char buf
[4][28];
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]);
270 format_thousands(unsigned int value
)
272 static char buf
[4][15];
275 snprintf(buf
[i
], 15, "%u.%.3u", value
/ 1000, value
% 1000);
280 parse_address(const char *address
, unsigned char *addr_r
, int *af_r
)
283 struct in6_addr ina6
;
286 rc
= inet_pton(AF_INET
, address
, &ina
);
288 v4tov6(addr_r
, (const unsigned char *)&ina
);
289 if(af_r
) *af_r
= AF_INET
;
293 rc
= inet_pton(AF_INET6
, address
, &ina6
);
295 memcpy(addr_r
, &ina6
, IPV6_MAX_BYTELEN
);
305 parse_eui64(const char *eui
, unsigned char *eui_r
)
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]);
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]);
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]);
332 wait_for_fd(int direction
, int fd
, int msecs
)
338 tv
.tv_sec
= msecs
/ 1000;
339 tv
.tv_usec
= (msecs
% 1000) * 1000;
344 rc
= select(fd
+ 1, NULL
, &fds
, NULL
, &tv
);
346 rc
= select(fd
+ 1, &fds
, NULL
, NULL
, &tv
);
352 martian_prefix(const unsigned char *prefix
, int plen
)
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)));
365 linklocal(const unsigned char *address
)
367 return memcmp(address
, llprefix
, 8) == 0;
371 v4mapped(const unsigned char *address
)
373 return memcmp(address
, v4prefix
, 12) == 0;
377 v4tov6(unsigned char *dst
, const unsigned char *src
)
379 memcpy(dst
, v4prefix
, 12);
380 memcpy(dst
+ 12, src
, 4);
384 inaddr_to_uchar(unsigned char *dest
, const struct in_addr
*src
)
386 v4tov6(dest
, (const unsigned char *)src
);
387 assert(v4mapped(dest
));
391 uchar_to_inaddr(struct in_addr
*dest
, const unsigned char *src
)
393 assert(v4mapped(src
));
394 memcpy(dest
, src
+ 12, 4);
398 in6addr_to_uchar(unsigned char *dest
, const struct in6_addr
*src
)
400 memcpy(dest
, src
, IPV6_MAX_BYTELEN
);
404 uchar_to_in6addr(struct in6_addr
*dest
, const unsigned char *src
)
406 memcpy(dest
, src
, IPV6_MAX_BYTELEN
);