]>
git.proxmox.com Git - mirror_frr.git/blob - babeld/util.c
2 * This file is free software: you may copy, redistribute and/or modify it
3 * under the terms of the GNU General Public License as published by the
4 * Free Software Foundation, either version 2 of the License, or (at your
5 * option) any later version.
7 * This file is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 * This file incorporates work covered by the following copyright and
18 Copyright (c) 2007, 2008 by Juliusz Chroboczek
19 Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
21 Permission is hereby granted, free of charge, to any person obtaining a copy
22 of this software and associated documentation files (the "Software"), to deal
23 in the Software without restriction, including without limitation the rights
24 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 copies of the Software, and to permit persons to whom the Software is
26 furnished to do so, subject to the following conditions:
28 The above copyright notice and this permission notice shall be included in
29 all copies or substantial portions of the Software.
31 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
48 #include <sys/types.h>
49 #include <sys/socket.h>
50 #include <netinet/in.h>
51 #include <arpa/inet.h>
53 #include "babel_main.h"
58 roughly(unsigned value
)
60 return value
* 3 / 4 + random() % (value
/ 2);
65 timeval_minus(struct timeval
*d
,
66 const struct timeval
*s1
, const struct timeval
*s2
)
68 if(s1
->tv_usec
>= s2
->tv_usec
) {
69 d
->tv_usec
= s1
->tv_usec
- s2
->tv_usec
;
70 d
->tv_sec
= s1
->tv_sec
- s2
->tv_sec
;
72 d
->tv_usec
= s1
->tv_usec
+ 1000000 - s2
->tv_usec
;
73 d
->tv_sec
= s1
->tv_sec
- s2
->tv_sec
- 1;
78 timeval_minus_msec(const struct timeval
*s1
, const struct timeval
*s2
)
80 if(s1
->tv_sec
< s2
->tv_sec
)
84 if(s1
->tv_sec
- s2
->tv_sec
> 2000000)
87 if(s1
->tv_sec
> s2
->tv_sec
)
89 (unsigned)((unsigned)(s1
->tv_sec
- s2
->tv_sec
) * 1000 +
90 ((int)s1
->tv_usec
- s2
->tv_usec
) / 1000);
92 if(s1
->tv_usec
<= s2
->tv_usec
)
95 return (unsigned)(s1
->tv_usec
- s2
->tv_usec
) / 1000u;
100 timeval_add_msec(struct timeval
*d
, const struct timeval
*s
, const int msecs
)
103 d
->tv_sec
= s
->tv_sec
+ msecs
/ 1000;
104 usecs
= s
->tv_usec
+ (msecs
% 1000) * 1000;
105 if(usecs
< 1000000) {
108 d
->tv_usec
= usecs
- 1000000;
114 set_timeout(struct timeval
*timeout
, int msecs
)
116 timeval_add_msec(timeout
, &babel_now
, roughly(msecs
));
119 /* returns <0 if "s1" < "s2", etc. */
121 timeval_compare(const struct timeval
*s1
, const struct timeval
*s2
)
123 if(s1
->tv_sec
< s2
->tv_sec
)
125 else if(s1
->tv_sec
> s2
->tv_sec
)
127 else if(s1
->tv_usec
< s2
->tv_usec
)
129 else if(s1
->tv_usec
> s2
->tv_usec
)
135 /* set d at min(d, s) */
136 /* {0, 0} represents infinity */
138 timeval_min(struct timeval
*d
, const struct timeval
*s
)
143 if(d
->tv_sec
== 0 || timeval_compare(d
, s
) > 0) {
148 /* set d to min(d, x) with x in [secs, secs+1] */
150 timeval_min_sec(struct timeval
*d
, time_t secs
)
152 if(d
->tv_sec
== 0 || d
->tv_sec
> secs
) {
154 d
->tv_usec
= random() % 1000000;
158 /* parse a float value in second and return the corresponding mili-seconds.
160 parse_msec("12.342345") returns 12342 */
162 parse_msec(const char *string
)
169 while(string
[i
] == ' ' || string
[i
] == '\t')
171 while(string
[i
] >= '0' && string
[i
] <= '9') {
172 in
= in
* 10 + string
[i
] - '0';
175 if(string
[i
] == '.') {
178 while(string
[i
] >= '0' && string
[i
] <= '9') {
179 fl
= fl
* 10 + string
[i
] - '0';
194 while(string
[i
] == ' ' || string
[i
] == '\t')
197 if(string
[i
] == '\0')
198 return in
* 1000 + fl
;
204 in_prefix(const unsigned char *restrict address
,
205 const unsigned char *restrict prefix
, unsigned char plen
)
212 if(memcmp(address
, prefix
, plen
/ 8) != 0)
218 m
= 0xFF << (8 - (plen
% 8));
220 return ((address
[plen
/ 8] & m
) == (prefix
[plen
/ 8] & m
));
224 mask_prefix(unsigned char *restrict ret
,
225 const unsigned char *restrict prefix
, unsigned char plen
)
228 memcpy(ret
, prefix
, 16);
233 memcpy(ret
, prefix
, plen
/ 8);
236 (prefix
[plen
/ 8] & ((0xFF << (8 - (plen
% 8))) & 0xFF));
240 static const unsigned char v4prefix
[16] =
241 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
243 static const unsigned char llprefix
[16] =
247 format_address(const unsigned char *address
)
249 static char buf
[4][INET6_ADDRSTRLEN
];
252 if(v4mapped(address
))
253 inet_ntop(AF_INET
, address
+ 12, buf
[i
], INET6_ADDRSTRLEN
);
255 inet_ntop(AF_INET6
, address
, buf
[i
], INET6_ADDRSTRLEN
);
260 format_prefix(const unsigned char *prefix
, unsigned char plen
)
262 static char buf
[4][INET6_ADDRSTRLEN
+ 4];
266 if(plen
>= 96 && v4mapped(prefix
)) {
267 inet_ntop(AF_INET
, prefix
+ 12, buf
[i
], INET6_ADDRSTRLEN
);
269 snprintf(buf
[i
] + n
, INET6_ADDRSTRLEN
+ 4 - n
, "/%d", plen
- 96);
271 inet_ntop(AF_INET6
, prefix
, buf
[i
], INET6_ADDRSTRLEN
);
273 snprintf(buf
[i
] + n
, INET6_ADDRSTRLEN
+ 4 - n
, "/%d", plen
);
279 format_eui64(const unsigned char *eui
)
281 static char buf
[4][28];
284 snprintf(buf
[i
], 28, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
285 eui
[0], eui
[1], eui
[2], eui
[3],
286 eui
[4], eui
[5], eui
[6], eui
[7]);
290 const char *format_bool(const int b
) {
291 return b
? "true" : "false";
295 parse_address(const char *address
, unsigned char *addr_r
, int *af_r
)
298 struct in6_addr ina6
;
301 rc
= inet_pton(AF_INET
, address
, &ina
);
303 memcpy(addr_r
, v4prefix
, 12);
304 memcpy(addr_r
+ 12, &ina
, 4);
305 if(af_r
) *af_r
= AF_INET
;
309 rc
= inet_pton(AF_INET6
, address
, &ina6
);
311 memcpy(addr_r
, &ina6
, 16);
312 if(af_r
) *af_r
= AF_INET6
;
320 parse_eui64(const char *eui
, unsigned char *eui_r
)
323 n
= sscanf(eui
, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
324 &eui_r
[0], &eui_r
[1], &eui_r
[2], &eui_r
[3],
325 &eui_r
[4], &eui_r
[5], &eui_r
[6], &eui_r
[7]);
329 n
= sscanf(eui
, "%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx",
330 &eui_r
[0], &eui_r
[1], &eui_r
[2], &eui_r
[3],
331 &eui_r
[4], &eui_r
[5], &eui_r
[6], &eui_r
[7]);
335 n
= sscanf(eui
, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
336 &eui_r
[0], &eui_r
[1], &eui_r
[2],
337 &eui_r
[5], &eui_r
[6], &eui_r
[7]);
347 wait_for_fd(int direction
, int fd
, int msecs
)
353 tv
.tv_sec
= msecs
/ 1000;
354 tv
.tv_usec
= (msecs
% 1000) * 1000;
359 rc
= select(fd
+ 1, NULL
, &fds
, NULL
, &tv
);
361 rc
= select(fd
+ 1, &fds
, NULL
, NULL
, &tv
);
367 martian_prefix(const unsigned char *prefix
, int plen
)
370 (plen
>= 8 && prefix
[0] == 0xFF) ||
371 (plen
>= 10 && prefix
[0] == 0xFE && (prefix
[1] & 0xC0) == 0x80) ||
372 (plen
>= 128 && memcmp(prefix
, zeroes
, 15) == 0 &&
373 (prefix
[15] == 0 || prefix
[15] == 1)) ||
374 (plen
>= 96 && v4mapped(prefix
) &&
375 ((plen
>= 104 && (prefix
[12] == 127 || prefix
[12] == 0)) ||
376 (plen
>= 100 && (prefix
[12] & 0xE0) == 0xE0)));
380 linklocal(const unsigned char *address
)
382 return memcmp(address
, llprefix
, 8) == 0;
386 v4mapped(const unsigned char *address
)
388 return memcmp(address
, v4prefix
, 12) == 0;
392 v4tov6(unsigned char *dst
, const unsigned char *src
)
394 memcpy(dst
, v4prefix
, 12);
395 memcpy(dst
+ 12, src
, 4);
399 inaddr_to_uchar(unsigned char *dest
, const struct in_addr
*src
)
401 memcpy(dest
, v4prefix
, 12);
402 memcpy(dest
+ 12, src
, 4);
403 assert(v4mapped(dest
));
407 uchar_to_inaddr(struct in_addr
*dest
, const unsigned char *src
)
409 assert(v4mapped(src
));
410 memcpy(dest
, src
+ 12, 4);
414 in6addr_to_uchar(unsigned char *dest
, const struct in6_addr
*src
)
416 memcpy(dest
, src
, 16);
420 uchar_to_in6addr(struct in6_addr
*dest
, const unsigned char *src
)
422 memcpy(dest
, src
, 16);