]>
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
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
38 #include "babel_main.h"
46 return -roughly(-value
);
50 return value
* 3 / 4 + random() % (value
/ 2);
55 timeval_minus(struct timeval
*d
,
56 const struct timeval
*s1
, const struct timeval
*s2
)
58 if(s1
->tv_usec
>= s2
->tv_usec
) {
59 d
->tv_usec
= s1
->tv_usec
- s2
->tv_usec
;
60 d
->tv_sec
= s1
->tv_sec
- s2
->tv_sec
;
62 d
->tv_usec
= s1
->tv_usec
+ 1000000 - s2
->tv_usec
;
63 d
->tv_sec
= s1
->tv_sec
- s2
->tv_sec
- 1;
68 timeval_minus_msec(const struct timeval
*s1
, const struct timeval
*s2
)
70 if(s1
->tv_sec
< s2
->tv_sec
)
74 if(s1
->tv_sec
- s2
->tv_sec
> 2000000)
77 if(s1
->tv_sec
> s2
->tv_sec
)
79 (unsigned)((unsigned)(s1
->tv_sec
- s2
->tv_sec
) * 1000 +
80 ((int)s1
->tv_usec
- s2
->tv_usec
) / 1000);
82 if(s1
->tv_usec
<= s2
->tv_usec
)
85 return (unsigned)(s1
->tv_usec
- s2
->tv_usec
) / 1000u;
90 timeval_add_msec(struct timeval
*d
, const struct timeval
*s
, int msecs
)
93 d
->tv_sec
= s
->tv_sec
+ msecs
/ 1000;
94 usecs
= s
->tv_usec
+ (msecs
% 1000) * 1000;
98 d
->tv_usec
= usecs
- 1000000;
104 set_timeout(struct timeval
*timeout
, int msecs
)
106 timeval_add_msec(timeout
, &babel_now
, roughly(msecs
));
109 /* returns <0 if "s1" < "s2", etc. */
111 timeval_compare(const struct timeval
*s1
, const struct timeval
*s2
)
113 if(s1
->tv_sec
< s2
->tv_sec
)
115 else if(s1
->tv_sec
> s2
->tv_sec
)
117 else if(s1
->tv_usec
< s2
->tv_usec
)
119 else if(s1
->tv_usec
> s2
->tv_usec
)
125 /* set d at min(d, s) */
126 /* {0, 0} represents infinity */
128 timeval_min(struct timeval
*d
, const struct timeval
*s
)
133 if(d
->tv_sec
== 0 || timeval_compare(d
, s
) > 0) {
138 /* set d to min(d, x) with x in [secs, secs+1] */
140 timeval_min_sec(struct timeval
*d
, time_t secs
)
142 if(d
->tv_sec
== 0 || d
->tv_sec
> secs
) {
144 d
->tv_usec
= random() % 1000000;
148 /* parse a float value in second and return the corresponding mili-seconds.
150 parse_msec("12.342345") returns 12342 */
152 parse_msec(const char *string
)
159 while(string
[i
] == ' ' || string
[i
] == '\t')
161 while(string
[i
] >= '0' && string
[i
] <= '9') {
162 in
= in
* 10 + string
[i
] - '0';
165 if(string
[i
] == '.') {
168 while(string
[i
] >= '0' && string
[i
] <= '9') {
169 fl
= fl
* 10 + string
[i
] - '0';
184 while(string
[i
] == ' ' || string
[i
] == '\t')
187 if(string
[i
] == '\0')
188 return in
* 1000 + fl
;
193 /* There's no good name for a positive int in C, call it nat. */
195 parse_nat(const char *string
)
200 l
= strtol(string
, &end
, 0);
202 while(*end
== ' ' || *end
== '\t')
207 if(l
< 0 || l
> INT_MAX
)
214 in_prefix(const unsigned char *restrict address
,
215 const unsigned char *restrict prefix
, unsigned char plen
)
222 if(memcmp(address
, prefix
, plen
/ 8) != 0)
228 m
= 0xFF << (8 - (plen
% 8));
230 return ((address
[plen
/ 8] & m
) == (prefix
[plen
/ 8] & m
));
234 mask_prefix(unsigned char *restrict ret
,
235 const unsigned char *restrict prefix
, unsigned char plen
)
238 memcpy(ret
, prefix
, 16);
243 memcpy(ret
, prefix
, plen
/ 8);
246 (prefix
[plen
/ 8] & ((0xFF << (8 - (plen
% 8))) & 0xFF));
250 const unsigned char v4prefix
[16] =
251 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
253 static const unsigned char llprefix
[16] =
257 format_address(const unsigned char *address
)
259 static char buf
[4][INET6_ADDRSTRLEN
];
262 if(v4mapped(address
))
263 inet_ntop(AF_INET
, address
+ 12, buf
[i
], INET6_ADDRSTRLEN
);
265 inet_ntop(AF_INET6
, address
, buf
[i
], INET6_ADDRSTRLEN
);
270 format_prefix(const unsigned char *prefix
, unsigned char plen
)
272 static char buf
[4][INET6_ADDRSTRLEN
+ 4];
276 if(plen
>= 96 && v4mapped(prefix
)) {
277 inet_ntop(AF_INET
, prefix
+ 12, buf
[i
], INET6_ADDRSTRLEN
);
279 snprintf(buf
[i
] + n
, INET6_ADDRSTRLEN
+ 4 - n
, "/%d", plen
- 96);
281 inet_ntop(AF_INET6
, prefix
, buf
[i
], INET6_ADDRSTRLEN
);
283 snprintf(buf
[i
] + n
, INET6_ADDRSTRLEN
+ 4 - n
, "/%d", plen
);
289 format_eui64(const unsigned char *eui
)
291 static char buf
[4][28];
294 snprintf(buf
[i
], 28, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
295 eui
[0], eui
[1], eui
[2], eui
[3],
296 eui
[4], eui
[5], eui
[6], eui
[7]);
301 format_thousands(unsigned int value
)
303 static char buf
[4][15];
306 snprintf(buf
[i
], 15, "%u.%.3u", value
/ 1000, value
% 1000);
311 parse_address(const char *address
, unsigned char *addr_r
, int *af_r
)
314 struct in6_addr ina6
;
317 rc
= inet_pton(AF_INET
, address
, &ina
);
319 v4tov6(addr_r
, (const unsigned char *)&ina
);
320 if(af_r
) *af_r
= AF_INET
;
324 rc
= inet_pton(AF_INET6
, address
, &ina6
);
326 memcpy(addr_r
, &ina6
, 16);
327 if(af_r
) *af_r
= AF_INET6
;
335 parse_eui64(const char *eui
, unsigned char *eui_r
)
338 n
= sscanf(eui
, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
339 &eui_r
[0], &eui_r
[1], &eui_r
[2], &eui_r
[3],
340 &eui_r
[4], &eui_r
[5], &eui_r
[6], &eui_r
[7]);
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",
351 &eui_r
[0], &eui_r
[1], &eui_r
[2],
352 &eui_r
[5], &eui_r
[6], &eui_r
[7]);
362 wait_for_fd(int direction
, int fd
, int msecs
)
368 tv
.tv_sec
= msecs
/ 1000;
369 tv
.tv_usec
= (msecs
% 1000) * 1000;
374 rc
= select(fd
+ 1, NULL
, &fds
, NULL
, &tv
);
376 rc
= select(fd
+ 1, &fds
, NULL
, NULL
, &tv
);
382 martian_prefix(const unsigned char *prefix
, int plen
)
385 (plen
>= 8 && prefix
[0] == 0xFF) ||
386 (plen
>= 10 && prefix
[0] == 0xFE && (prefix
[1] & 0xC0) == 0x80) ||
387 (plen
>= 128 && memcmp(prefix
, zeroes
, 15) == 0 &&
388 (prefix
[15] == 0 || prefix
[15] == 1)) ||
389 (plen
>= 96 && v4mapped(prefix
) &&
390 ((plen
>= 104 && (prefix
[12] == 127 || prefix
[12] == 0)) ||
391 (plen
>= 100 && (prefix
[12] & 0xE0) == 0xE0)));
395 linklocal(const unsigned char *address
)
397 return memcmp(address
, llprefix
, 8) == 0;
401 v4mapped(const unsigned char *address
)
403 return memcmp(address
, v4prefix
, 12) == 0;
407 v4tov6(unsigned char *dst
, const unsigned char *src
)
409 memcpy(dst
, v4prefix
, 12);
410 memcpy(dst
+ 12, src
, 4);
414 inaddr_to_uchar(unsigned char *dest
, const struct in_addr
*src
)
416 v4tov6(dest
, (const unsigned char *)src
);
417 assert(v4mapped(dest
));
421 uchar_to_inaddr(struct in_addr
*dest
, const unsigned char *src
)
423 assert(v4mapped(src
));
424 memcpy(dest
, src
+ 12, 4);
428 in6addr_to_uchar(unsigned char *dest
, const struct in6_addr
*src
)
430 memcpy(dest
, src
, 16);
434 uchar_to_in6addr(struct in6_addr
*dest
, const unsigned char *src
)
436 memcpy(dest
, src
, 16);