]>
git.proxmox.com Git - mirror_frr.git/blob - babeld/util.c
2 Copyright (c) 2007, 2008 by Juliusz Chroboczek
3 Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
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:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
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
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
42 #include "babel_main.h"
50 return -roughly(-value
);
54 return value
* 3 / 4 + random() % (value
/ 2);
59 timeval_minus(struct timeval
*d
,
60 const struct timeval
*s1
, const struct timeval
*s2
)
62 if(s1
->tv_usec
>= s2
->tv_usec
) {
63 d
->tv_usec
= s1
->tv_usec
- s2
->tv_usec
;
64 d
->tv_sec
= s1
->tv_sec
- s2
->tv_sec
;
66 d
->tv_usec
= s1
->tv_usec
+ 1000000 - s2
->tv_usec
;
67 d
->tv_sec
= s1
->tv_sec
- s2
->tv_sec
- 1;
72 timeval_minus_msec(const struct timeval
*s1
, const struct timeval
*s2
)
74 if(s1
->tv_sec
< s2
->tv_sec
)
78 if(s1
->tv_sec
- s2
->tv_sec
> 2000000)
81 if(s1
->tv_sec
> s2
->tv_sec
)
83 (unsigned)((unsigned)(s1
->tv_sec
- s2
->tv_sec
) * 1000 +
84 ((int)s1
->tv_usec
- s2
->tv_usec
) / 1000);
86 if(s1
->tv_usec
<= s2
->tv_usec
)
89 return (unsigned)(s1
->tv_usec
- s2
->tv_usec
) / 1000u;
94 timeval_add_msec(struct timeval
*d
, const struct timeval
*s
, int msecs
)
97 d
->tv_sec
= s
->tv_sec
+ msecs
/ 1000;
98 usecs
= s
->tv_usec
+ (msecs
% 1000) * 1000;
102 d
->tv_usec
= usecs
- 1000000;
108 set_timeout(struct timeval
*timeout
, int msecs
)
110 timeval_add_msec(timeout
, &babel_now
, roughly(msecs
));
113 /* returns <0 if "s1" < "s2", etc. */
115 timeval_compare(const struct timeval
*s1
, const struct timeval
*s2
)
117 if(s1
->tv_sec
< s2
->tv_sec
)
119 else if(s1
->tv_sec
> s2
->tv_sec
)
121 else if(s1
->tv_usec
< s2
->tv_usec
)
123 else if(s1
->tv_usec
> s2
->tv_usec
)
129 /* set d at min(d, s) */
130 /* {0, 0} represents infinity */
132 timeval_min(struct timeval
*d
, const struct timeval
*s
)
137 if(d
->tv_sec
== 0 || timeval_compare(d
, s
) > 0) {
142 /* set d to min(d, x) with x in [secs, secs+1] */
144 timeval_min_sec(struct timeval
*d
, time_t secs
)
146 if(d
->tv_sec
== 0 || d
->tv_sec
> secs
) {
148 d
->tv_usec
= random() % 1000000;
152 /* parse a float value in second and return the corresponding mili-seconds.
154 parse_msec("12.342345") returns 12342 */
156 parse_msec(const char *string
)
163 while(string
[i
] == ' ' || string
[i
] == '\t')
165 while(string
[i
] >= '0' && string
[i
] <= '9') {
166 in
= in
* 10 + string
[i
] - '0';
169 if(string
[i
] == '.') {
172 while(string
[i
] >= '0' && string
[i
] <= '9') {
173 fl
= fl
* 10 + string
[i
] - '0';
188 while(string
[i
] == ' ' || string
[i
] == '\t')
191 if(string
[i
] == '\0')
192 return in
* 1000 + fl
;
197 /* There's no good name for a positive int in C, call it nat. */
199 parse_nat(const char *string
)
204 l
= strtol(string
, &end
, 0);
206 while(*end
== ' ' || *end
== '\t')
211 if(l
< 0 || l
> INT_MAX
)
218 in_prefix(const unsigned char *restrict address
,
219 const unsigned char *restrict prefix
, unsigned char plen
)
226 if(memcmp(address
, prefix
, plen
/ 8) != 0)
232 m
= 0xFF << (8 - (plen
% 8));
234 return ((address
[plen
/ 8] & m
) == (prefix
[plen
/ 8] & m
));
238 mask_prefix(unsigned char *restrict ret
,
239 const unsigned char *restrict prefix
, unsigned char plen
)
242 memcpy(ret
, prefix
, 16);
247 memcpy(ret
, prefix
, plen
/ 8);
250 (prefix
[plen
/ 8] & ((0xFF << (8 - (plen
% 8))) & 0xFF));
254 const unsigned char v4prefix
[16] =
255 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
257 static const unsigned char llprefix
[16] =
261 format_address(const unsigned char *address
)
263 static char buf
[4][INET6_ADDRSTRLEN
];
266 if(v4mapped(address
))
267 inet_ntop(AF_INET
, address
+ 12, buf
[i
], INET6_ADDRSTRLEN
);
269 inet_ntop(AF_INET6
, address
, buf
[i
], INET6_ADDRSTRLEN
);
274 format_prefix(const unsigned char *prefix
, unsigned char plen
)
276 static char buf
[4][INET6_ADDRSTRLEN
+ 4];
280 if(plen
>= 96 && v4mapped(prefix
)) {
281 inet_ntop(AF_INET
, prefix
+ 12, buf
[i
], INET6_ADDRSTRLEN
);
283 snprintf(buf
[i
] + n
, INET6_ADDRSTRLEN
+ 4 - n
, "/%d", plen
- 96);
285 inet_ntop(AF_INET6
, prefix
, buf
[i
], INET6_ADDRSTRLEN
);
287 snprintf(buf
[i
] + n
, INET6_ADDRSTRLEN
+ 4 - n
, "/%d", plen
);
293 format_eui64(const unsigned char *eui
)
295 static char buf
[4][28];
298 snprintf(buf
[i
], 28, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
299 eui
[0], eui
[1], eui
[2], eui
[3],
300 eui
[4], eui
[5], eui
[6], eui
[7]);
305 format_thousands(unsigned int value
)
307 static char buf
[4][15];
310 snprintf(buf
[i
], 15, "%u.%.3u", value
/ 1000, value
% 1000);
315 parse_address(const char *address
, unsigned char *addr_r
, int *af_r
)
318 struct in6_addr ina6
;
321 rc
= inet_pton(AF_INET
, address
, &ina
);
323 v4tov6(addr_r
, (const unsigned char *)&ina
);
324 if(af_r
) *af_r
= AF_INET
;
328 rc
= inet_pton(AF_INET6
, address
, &ina6
);
330 memcpy(addr_r
, &ina6
, 16);
331 if(af_r
) *af_r
= AF_INET6
;
339 parse_eui64(const char *eui
, unsigned char *eui_r
)
342 n
= sscanf(eui
, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
343 &eui_r
[0], &eui_r
[1], &eui_r
[2], &eui_r
[3],
344 &eui_r
[4], &eui_r
[5], &eui_r
[6], &eui_r
[7]);
348 n
= sscanf(eui
, "%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx",
349 &eui_r
[0], &eui_r
[1], &eui_r
[2], &eui_r
[3],
350 &eui_r
[4], &eui_r
[5], &eui_r
[6], &eui_r
[7]);
354 n
= sscanf(eui
, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
355 &eui_r
[0], &eui_r
[1], &eui_r
[2],
356 &eui_r
[5], &eui_r
[6], &eui_r
[7]);
366 wait_for_fd(int direction
, int fd
, int msecs
)
372 tv
.tv_sec
= msecs
/ 1000;
373 tv
.tv_usec
= (msecs
% 1000) * 1000;
378 rc
= select(fd
+ 1, NULL
, &fds
, NULL
, &tv
);
380 rc
= select(fd
+ 1, &fds
, NULL
, NULL
, &tv
);
386 martian_prefix(const unsigned char *prefix
, int plen
)
389 (plen
>= 8 && prefix
[0] == 0xFF) ||
390 (plen
>= 10 && prefix
[0] == 0xFE && (prefix
[1] & 0xC0) == 0x80) ||
391 (plen
>= 128 && memcmp(prefix
, zeroes
, 15) == 0 &&
392 (prefix
[15] == 0 || prefix
[15] == 1)) ||
393 (plen
>= 96 && v4mapped(prefix
) &&
394 ((plen
>= 104 && (prefix
[12] == 127 || prefix
[12] == 0)) ||
395 (plen
>= 100 && (prefix
[12] & 0xE0) == 0xE0)));
399 linklocal(const unsigned char *address
)
401 return memcmp(address
, llprefix
, 8) == 0;
405 v4mapped(const unsigned char *address
)
407 return memcmp(address
, v4prefix
, 12) == 0;
411 v4tov6(unsigned char *dst
, const unsigned char *src
)
413 memcpy(dst
, v4prefix
, 12);
414 memcpy(dst
+ 12, src
, 4);
418 inaddr_to_uchar(unsigned char *dest
, const struct in_addr
*src
)
420 v4tov6(dest
, (const unsigned char *)src
);
421 assert(v4mapped(dest
));
425 uchar_to_inaddr(struct in_addr
*dest
, const unsigned char *src
)
427 assert(v4mapped(src
));
428 memcpy(dest
, src
+ 12, 4);
432 in6addr_to_uchar(unsigned char *dest
, const struct in6_addr
*src
)
434 memcpy(dest
, src
, 16);
438 uchar_to_in6addr(struct in6_addr
*dest
, const unsigned char *src
)
440 memcpy(dest
, src
, 16);