]>
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 "lib/network.h"
44 #include "babel_main.h"
52 return -roughly(-value
);
56 return value
* 3 / 4 + frr_weak_random() % (value
/ 2);
61 timeval_minus(struct timeval
*d
,
62 const struct timeval
*s1
, const struct timeval
*s2
)
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
;
68 d
->tv_usec
= s1
->tv_usec
+ 1000000 - s2
->tv_usec
;
69 d
->tv_sec
= s1
->tv_sec
- s2
->tv_sec
- 1;
74 timeval_minus_msec(const struct timeval
*s1
, const struct timeval
*s2
)
76 if(s1
->tv_sec
< s2
->tv_sec
)
80 if(s1
->tv_sec
- s2
->tv_sec
> 2000000)
83 if(s1
->tv_sec
> s2
->tv_sec
)
85 (unsigned)((unsigned)(s1
->tv_sec
- s2
->tv_sec
) * 1000 +
86 ((int)s1
->tv_usec
- s2
->tv_usec
) / 1000);
88 if(s1
->tv_usec
<= s2
->tv_usec
)
91 return (unsigned)(s1
->tv_usec
- s2
->tv_usec
) / 1000u;
96 timeval_add_msec(struct timeval
*d
, const struct timeval
*s
, int msecs
)
99 d
->tv_sec
= s
->tv_sec
+ msecs
/ 1000;
100 usecs
= s
->tv_usec
+ (msecs
% 1000) * 1000;
101 if(usecs
< 1000000) {
104 d
->tv_usec
= usecs
- 1000000;
110 set_timeout(struct timeval
*timeout
, int msecs
)
112 timeval_add_msec(timeout
, &babel_now
, roughly(msecs
));
115 /* returns <0 if "s1" < "s2", etc. */
117 timeval_compare(const struct timeval
*s1
, const struct timeval
*s2
)
119 if(s1
->tv_sec
< s2
->tv_sec
)
121 else if(s1
->tv_sec
> s2
->tv_sec
)
123 else if(s1
->tv_usec
< s2
->tv_usec
)
125 else if(s1
->tv_usec
> s2
->tv_usec
)
131 /* set d at min(d, s) */
132 /* {0, 0} represents infinity */
134 timeval_min(struct timeval
*d
, const struct timeval
*s
)
139 if(d
->tv_sec
== 0 || timeval_compare(d
, s
) > 0) {
144 /* set d to min(d, x) with x in [secs, secs+1] */
146 timeval_min_sec(struct timeval
*d
, time_t secs
)
148 if(d
->tv_sec
== 0 || d
->tv_sec
> secs
) {
150 d
->tv_usec
= frr_weak_random() % 1000000;
154 /* parse a float value in second and return the corresponding mili-seconds.
156 parse_msec("12.342345") returns 12342 */
158 parse_msec(const char *string
)
165 while(string
[i
] == ' ' || string
[i
] == '\t')
167 while(string
[i
] >= '0' && string
[i
] <= '9') {
168 in
= in
* 10 + string
[i
] - '0';
171 if(string
[i
] == '.') {
174 while(string
[i
] >= '0' && string
[i
] <= '9') {
175 fl
= fl
* 10 + string
[i
] - '0';
190 while(string
[i
] == ' ' || string
[i
] == '\t')
193 if(string
[i
] == '\0')
194 return in
* 1000 + fl
;
199 /* There's no good name for a positive int in C, call it nat. */
201 parse_nat(const char *string
)
206 l
= strtol(string
, &end
, 0);
208 while(*end
== ' ' || *end
== '\t')
213 if(l
< 0 || l
> INT_MAX
)
220 in_prefix(const unsigned char *restrict address
,
221 const unsigned char *restrict prefix
, unsigned char plen
)
228 if(memcmp(address
, prefix
, plen
/ 8) != 0)
234 m
= 0xFF << (8 - (plen
% 8));
236 return ((address
[plen
/ 8] & m
) == (prefix
[plen
/ 8] & m
));
240 mask_prefix(unsigned char *restrict ret
,
241 const unsigned char *restrict prefix
, unsigned char plen
)
244 memcpy(ret
, prefix
, 16);
249 memcpy(ret
, prefix
, plen
/ 8);
252 (prefix
[plen
/ 8] & ((0xFF << (8 - (plen
% 8))) & 0xFF));
256 const unsigned char v4prefix
[16] =
257 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
259 static const unsigned char llprefix
[16] =
263 format_address(const unsigned char *address
)
265 static char buf
[4][INET6_ADDRSTRLEN
];
268 if(v4mapped(address
))
269 inet_ntop(AF_INET
, address
+ 12, buf
[i
], INET6_ADDRSTRLEN
);
271 inet_ntop(AF_INET6
, address
, buf
[i
], INET6_ADDRSTRLEN
);
276 format_prefix(const unsigned char *prefix
, unsigned char plen
)
278 static char buf
[4][INET6_ADDRSTRLEN
+ 4];
282 if(plen
>= 96 && v4mapped(prefix
)) {
283 inet_ntop(AF_INET
, prefix
+ 12, buf
[i
], INET6_ADDRSTRLEN
);
285 snprintf(buf
[i
] + n
, INET6_ADDRSTRLEN
+ 4 - n
, "/%d", plen
- 96);
287 inet_ntop(AF_INET6
, prefix
, buf
[i
], INET6_ADDRSTRLEN
);
289 snprintf(buf
[i
] + n
, INET6_ADDRSTRLEN
+ 4 - n
, "/%d", plen
);
295 format_eui64(const unsigned char *eui
)
297 static char buf
[4][28];
300 snprintf(buf
[i
], 28, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
301 eui
[0], eui
[1], eui
[2], eui
[3],
302 eui
[4], eui
[5], eui
[6], eui
[7]);
307 format_thousands(unsigned int value
)
309 static char buf
[4][15];
312 snprintf(buf
[i
], 15, "%u.%.3u", value
/ 1000, value
% 1000);
317 parse_address(const char *address
, unsigned char *addr_r
, int *af_r
)
320 struct in6_addr ina6
;
323 rc
= inet_pton(AF_INET
, address
, &ina
);
325 v4tov6(addr_r
, (const unsigned char *)&ina
);
326 if(af_r
) *af_r
= AF_INET
;
330 rc
= inet_pton(AF_INET6
, address
, &ina6
);
332 memcpy(addr_r
, &ina6
, 16);
333 if(af_r
) *af_r
= AF_INET6
;
341 parse_eui64(const char *eui
, unsigned char *eui_r
)
344 n
= sscanf(eui
, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
345 &eui_r
[0], &eui_r
[1], &eui_r
[2], &eui_r
[3],
346 &eui_r
[4], &eui_r
[5], &eui_r
[6], &eui_r
[7]);
350 n
= sscanf(eui
, "%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx",
351 &eui_r
[0], &eui_r
[1], &eui_r
[2], &eui_r
[3],
352 &eui_r
[4], &eui_r
[5], &eui_r
[6], &eui_r
[7]);
356 n
= sscanf(eui
, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
357 &eui_r
[0], &eui_r
[1], &eui_r
[2],
358 &eui_r
[5], &eui_r
[6], &eui_r
[7]);
368 wait_for_fd(int direction
, int fd
, int msecs
)
374 tv
.tv_sec
= msecs
/ 1000;
375 tv
.tv_usec
= (msecs
% 1000) * 1000;
380 rc
= select(fd
+ 1, NULL
, &fds
, NULL
, &tv
);
382 rc
= select(fd
+ 1, &fds
, NULL
, NULL
, &tv
);
388 martian_prefix(const unsigned char *prefix
, int plen
)
391 (plen
>= 8 && prefix
[0] == 0xFF) ||
392 (plen
>= 10 && prefix
[0] == 0xFE && (prefix
[1] & 0xC0) == 0x80) ||
393 (plen
>= 128 && memcmp(prefix
, zeroes
, 15) == 0 &&
394 (prefix
[15] == 0 || prefix
[15] == 1)) ||
395 (plen
>= 96 && v4mapped(prefix
) &&
396 ((plen
>= 104 && (prefix
[12] == 127 || prefix
[12] == 0)) ||
397 (plen
>= 100 && (prefix
[12] & 0xE0) == 0xE0)));
401 linklocal(const unsigned char *address
)
403 return memcmp(address
, llprefix
, 8) == 0;
407 v4mapped(const unsigned char *address
)
409 return memcmp(address
, v4prefix
, 12) == 0;
413 v4tov6(unsigned char *dst
, const unsigned char *src
)
415 memcpy(dst
, v4prefix
, 12);
416 memcpy(dst
+ 12, src
, 4);
420 inaddr_to_uchar(unsigned char *dest
, const struct in_addr
*src
)
422 v4tov6(dest
, (const unsigned char *)src
);
423 assert(v4mapped(dest
));
427 uchar_to_inaddr(struct in_addr
*dest
, const unsigned char *src
)
429 assert(v4mapped(src
));
430 memcpy(dest
, src
+ 12, 4);
434 in6addr_to_uchar(unsigned char *dest
, const struct in6_addr
*src
)
436 memcpy(dest
, src
, 16);
440 uchar_to_in6addr(struct in6_addr
*dest
, const unsigned char *src
)
442 memcpy(dest
, src
, 16);