]>
git.proxmox.com Git - ceph.git/blob - ceph/src/common/ipaddr.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
8 #if defined(__FreeBSD__)
10 #include <sys/socket.h>
11 #include <netinet/in.h>
14 #include "include/ipaddr.h"
15 #include "msg/msg_types.h"
16 #include "common/pick_address.h"
20 void netmask_ipv4(const struct in_addr
*addr
,
21 unsigned int prefix_len
,
22 struct in_addr
*out
) {
25 if (prefix_len
>= 32) {
26 // also handle 32 in this branch, because >>32 is not defined by
30 mask
= htonl(~(~uint32_t(0) >> prefix_len
));
32 out
->s_addr
= addr
->s_addr
& mask
;
35 bool matches_ipv4_in_subnet(const struct ifaddrs
& addrs
,
36 const struct sockaddr_in
* net
,
37 unsigned int prefix_len
)
39 if (addrs
.ifa_addr
== nullptr)
42 if (addrs
.ifa_addr
->sa_family
!= net
->sin_family
)
45 netmask_ipv4(&net
->sin_addr
, prefix_len
, &want
);
46 struct in_addr
*cur
= &((struct sockaddr_in
*)addrs
.ifa_addr
)->sin_addr
;
48 netmask_ipv4(cur
, prefix_len
, &temp
);
49 return temp
.s_addr
== want
.s_addr
;
52 void netmask_ipv6(const struct in6_addr
*addr
,
53 unsigned int prefix_len
,
54 struct in6_addr
*out
) {
58 memcpy(out
->s6_addr
, addr
->s6_addr
, prefix_len
/8);
60 out
->s6_addr
[prefix_len
/8] = addr
->s6_addr
[prefix_len
/8] & ~( 0xFF >> (prefix_len
% 8) );
61 if (prefix_len
/8 < 15)
62 memset(out
->s6_addr
+prefix_len
/8+1, 0, 16-prefix_len
/8-1);
65 bool matches_ipv6_in_subnet(const struct ifaddrs
& addrs
,
66 const struct sockaddr_in6
* net
,
67 unsigned int prefix_len
)
69 if (addrs
.ifa_addr
== nullptr)
72 if (addrs
.ifa_addr
->sa_family
!= net
->sin6_family
)
75 netmask_ipv6(&net
->sin6_addr
, prefix_len
, &want
);
77 struct in6_addr
*cur
= &((struct sockaddr_in6
*)addrs
.ifa_addr
)->sin6_addr
;
78 if (IN6_IS_ADDR_LINKLOCAL(cur
))
80 netmask_ipv6(cur
, prefix_len
, &temp
);
81 return IN6_ARE_ADDR_EQUAL(&temp
, &want
);
84 bool parse_network(const char *s
, struct sockaddr_storage
*network
, unsigned int *prefix_len
) {
85 char *slash
= strchr((char*)s
, '/');
90 if (*(slash
+1) == '\0') {
91 // slash is the last character
96 long int num
= strtol(slash
+1, &end
, 10);
98 // junk after the prefix_len
106 // copy the part before slash to get nil termination
107 char *addr
= (char*)alloca(slash
-s
+ 1);
108 strncpy(addr
, s
, slash
-s
);
109 addr
[slash
-s
] = '\0';
111 // caller expects ports etc to be zero
112 memset(network
, 0, sizeof(*network
));
114 // try parsing as ipv4
116 ok
= inet_pton(AF_INET
, addr
, &((struct sockaddr_in
*)network
)->sin_addr
);
118 network
->ss_family
= AF_INET
;
122 // try parsing as ipv6
123 ok
= inet_pton(AF_INET6
, addr
, &((struct sockaddr_in6
*)network
)->sin6_addr
);
125 network
->ss_family
= AF_INET6
;
132 bool parse_network(const char *s
,
133 entity_addr_t
*network
,
134 unsigned int *prefix_len
)
137 bool ret
= parse_network(s
, &ss
, prefix_len
);
139 network
->set_type(entity_addr_t::TYPE_LEGACY
);
140 network
->set_sockaddr((sockaddr
*)&ss
);
145 bool network_contains(
146 const struct entity_addr_t
& network
,
147 unsigned int prefix_len
,
148 const struct entity_addr_t
& addr
)
150 if (addr
.get_family() != network
.get_family()) {
153 switch (network
.get_family()) {
158 &((const sockaddr_in
*)network
.get_sockaddr())->sin_addr
, prefix_len
, &a
);
160 &((const sockaddr_in
*)addr
.get_sockaddr())->sin_addr
, prefix_len
, &b
);
161 if (memcmp(&a
, &b
, sizeof(a
)) == 0) {
168 struct in6_addr a
, b
;
170 &((const sockaddr_in6
*)network
.get_sockaddr())->sin6_addr
, prefix_len
, &a
);
172 &((const sockaddr_in6
*)addr
.get_sockaddr())->sin6_addr
, prefix_len
, &b
);
173 if (memcmp(&a
, &b
, sizeof(a
)) == 0) {