]>
git.proxmox.com Git - mirror_frr.git/blob - ldpd/util.c
4 * Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
5 * Copyright (c) 2012 Alexander Bluhm <bluhm@openbsd.org>
6 * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
7 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28 mask2prefixlen(in_addr_t ina
)
33 return (33 - ffs(ntohl(ina
)));
37 mask2prefixlen6(struct sockaddr_in6
*sa_in6
)
39 uint8_t l
= 0, *ap
, *ep
;
42 * sin6_len is the size of the sockaddr so substract the offset of
43 * the possibly truncated sin6_addr struct.
45 ap
= (uint8_t *)&sa_in6
->sin6_addr
;
46 ep
= (uint8_t *)sa_in6
+ sockaddr_len((struct sockaddr
*)sa_in6
);
47 for (; ap
< ep
; ap
++) {
48 /* this "beauty" is adopted from sbin/route/show.c ... */
77 fatalx("non contiguous inet6 netmask");
85 prefixlen2mask(uint8_t prefixlen
)
90 return (htonl(0xffffffff << (32 - prefixlen
)));
94 prefixlen2mask6(uint8_t prefixlen
)
96 static struct in6_addr mask
;
99 memset(&mask
, 0, sizeof(mask
));
100 for (i
= 0; i
< prefixlen
/ 8; i
++)
101 mask
.s6_addr
[i
] = 0xff;
104 mask
.s6_addr
[prefixlen
/ 8] = 0xff00 >> i
;
110 ldp_applymask(int af
, union ldpd_addr
*dest
, const union ldpd_addr
*src
,
113 struct in6_addr mask
;
118 dest
->v4
.s_addr
= src
->v4
.s_addr
& prefixlen2mask(prefixlen
);
121 memset(&mask
, 0, sizeof(mask
));
122 for (i
= 0; i
< prefixlen
/ 8; i
++)
123 mask
.s6_addr
[i
] = 0xff;
126 mask
.s6_addr
[prefixlen
/ 8] = 0xff00 >> i
;
128 for (i
= 0; i
< 16; i
++)
129 dest
->v6
.s6_addr
[i
] = src
->v6
.s6_addr
[i
] &
133 fatalx("ldp_applymask: unknown af");
138 ldp_addrcmp(int af
, const union ldpd_addr
*a
, const union ldpd_addr
*b
)
142 if (a
->v4
.s_addr
== b
->v4
.s_addr
)
144 return ((ntohl(a
->v4
.s_addr
) > ntohl(b
->v4
.s_addr
)) ? 1 : -1);
146 return (memcmp(&a
->v6
, &b
->v6
, sizeof(struct in6_addr
)));
148 fatalx("ldp_addrcmp: unknown af");
153 ldp_addrisset(int af
, const union ldpd_addr
*addr
)
159 if (addr
->v4
.s_addr
!= INADDR_ANY
)
163 if (!IN6_IS_ADDR_UNSPECIFIED(&addr
->v6
))
167 fatalx("ldp_addrisset: unknown af");
174 ldp_prefixcmp(int af
, const union ldpd_addr
*a
, const union ldpd_addr
*b
,
177 in_addr_t mask
, aa
, ba
;
185 if (prefixlen
> IPV4_MAX_BITLEN
)
186 fatalx("ldp_prefixcmp: bad IPv4 prefixlen");
187 mask
= htonl(prefixlen2mask(prefixlen
));
188 aa
= htonl(a
->v4
.s_addr
) & mask
;
189 ba
= htonl(b
->v4
.s_addr
) & mask
;
194 if (prefixlen
> IPV6_MAX_BITLEN
)
195 fatalx("ldp_prefixcmp: bad IPv6 prefixlen");
196 for (i
= 0; i
< prefixlen
/ 8; i
++)
197 if (a
->v6
.s6_addr
[i
] != b
->v6
.s6_addr
[i
])
198 return (a
->v6
.s6_addr
[i
] - b
->v6
.s6_addr
[i
]);
202 if ((a
->v6
.s6_addr
[prefixlen
/ 8] & m
) !=
203 (b
->v6
.s6_addr
[prefixlen
/ 8] & m
))
204 return ((a
->v6
.s6_addr
[prefixlen
/ 8] & m
) -
205 (b
->v6
.s6_addr
[prefixlen
/ 8] & m
));
209 fatalx("ldp_prefixcmp: unknown af");
215 bad_addr_v4(struct in_addr addr
)
217 uint32_t a
= ntohl(addr
.s_addr
);
219 if (((a
>> IN_CLASSA_NSHIFT
) == 0) ||
220 ((a
>> IN_CLASSA_NSHIFT
) == IN_LOOPBACKNET
) ||
221 IN_MULTICAST(a
) || IN_BADCLASS(a
))
228 bad_addr_v6(struct in6_addr
*addr
)
230 if (IN6_IS_ADDR_UNSPECIFIED(addr
) ||
231 IN6_IS_ADDR_LOOPBACK(addr
) ||
232 IN6_IS_ADDR_MULTICAST(addr
) ||
233 IN6_IS_ADDR_SITELOCAL(addr
) ||
234 IN6_IS_ADDR_V4MAPPED(addr
) ||
235 IN6_IS_ADDR_V4COMPAT(addr
))
242 bad_addr(int af
, union ldpd_addr
*addr
)
246 return (bad_addr_v4(addr
->v4
));
248 return (bad_addr_v6(&addr
->v6
));
250 fatalx("bad_addr: unknown af");
255 embedscope(struct sockaddr_in6
*sin6
)
259 if (IN6_IS_SCOPE_EMBED(&sin6
->sin6_addr
)) {
260 memcpy(&tmp16
, &sin6
->sin6_addr
.s6_addr
[2], sizeof(tmp16
));
262 log_warnx("%s: address %s already has embedded scope %u",
263 __func__
, log_sockaddr(sin6
), ntohs(tmp16
));
265 tmp16
= htons(sin6
->sin6_scope_id
);
266 memcpy(&sin6
->sin6_addr
.s6_addr
[2], &tmp16
, sizeof(tmp16
));
267 sin6
->sin6_scope_id
= 0;
272 recoverscope(struct sockaddr_in6
*sin6
)
276 if (sin6
->sin6_scope_id
!= 0)
277 log_warnx("%s: address %s already has scope id %u",
278 __func__
, log_sockaddr(sin6
), sin6
->sin6_scope_id
);
280 if (IN6_IS_SCOPE_EMBED(&sin6
->sin6_addr
)) {
281 memcpy(&tmp16
, &sin6
->sin6_addr
.s6_addr
[2], sizeof(tmp16
));
282 sin6
->sin6_scope_id
= ntohs(tmp16
);
283 sin6
->sin6_addr
.s6_addr
[2] = 0;
284 sin6
->sin6_addr
.s6_addr
[3] = 0;
289 addscope(struct sockaddr_in6
*sin6
, uint32_t id
)
291 if (sin6
->sin6_scope_id
!= 0)
292 log_warnx("%s: address %s already has scope id %u", __func__
,
293 log_sockaddr(sin6
), sin6
->sin6_scope_id
);
295 if (IN6_IS_SCOPE_EMBED(&sin6
->sin6_addr
))
296 sin6
->sin6_scope_id
= id
;
300 clearscope(struct in6_addr
*in6
)
302 if (IN6_IS_SCOPE_EMBED(in6
)) {
309 addr2sa(int af
, const union ldpd_addr
*addr
, uint16_t port
, union sockunion
*su
)
311 struct sockaddr_in
*sa_in
= &su
->sin
;
312 struct sockaddr_in6
*sa_in6
= &su
->sin6
;
314 memset(su
, 0, sizeof(*su
));
317 sa_in
->sin_family
= AF_INET
;
318 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
319 sa_in
->sin_len
= sizeof(struct sockaddr_in
);
321 sa_in
->sin_addr
= addr
->v4
;
322 sa_in
->sin_port
= htons(port
);
325 sa_in6
->sin6_family
= AF_INET6
;
326 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
327 sa_in6
->sin6_len
= sizeof(struct sockaddr_in6
);
329 sa_in6
->sin6_addr
= addr
->v6
;
330 sa_in6
->sin6_port
= htons(port
);
333 fatalx("addr2sa: unknown af");
338 sa2addr(struct sockaddr
*sa
, int *af
, union ldpd_addr
*addr
, in_port_t
*port
)
340 struct sockaddr_in
*sa_in
= (struct sockaddr_in
*)sa
;
341 struct sockaddr_in6
*sa_in6
= (struct sockaddr_in6
*)sa
;
344 memset(addr
, 0, sizeof(*addr
));
345 switch (sa
->sa_family
) {
350 addr
->v4
= sa_in
->sin_addr
;
352 *port
= sa_in
->sin_port
;
358 addr
->v6
= sa_in6
->sin6_addr
;
360 *port
= sa_in6
->sin6_port
;
363 fatalx("sa2addr: unknown af");
368 sockaddr_len(struct sockaddr
*sa
)
370 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
373 switch (sa
->sa_family
) {
375 return (sizeof(struct sockaddr_in
));
377 return (sizeof(struct sockaddr_in6
));
379 fatalx("sockaddr_len: unknown af");