]>
git.proxmox.com Git - ceph.git/blob - ceph/src/common/ipaddr.cc
41add2de24e61b267ce8859aadc1e66d0cd3d6e6
6 #if defined(__FreeBSD__)
8 #include <sys/socket.h>
9 #include <netinet/in.h>
12 #include "include/ipaddr.h"
14 static void netmask_ipv4(const struct in_addr
*addr
,
15 unsigned int prefix_len
,
16 struct in_addr
*out
) {
19 if (prefix_len
>= 32) {
20 // also handle 32 in this branch, because >>32 is not defined by
24 mask
= htonl(~(~uint32_t(0) >> prefix_len
));
26 out
->s_addr
= addr
->s_addr
& mask
;
30 const struct sockaddr
*find_ipv4_in_subnet(const struct ifaddrs
*addrs
,
31 const struct sockaddr_in
*net
,
32 unsigned int prefix_len
) {
33 struct in_addr want
, temp
;
35 netmask_ipv4(&net
->sin_addr
, prefix_len
, &want
);
37 for (; addrs
!= NULL
; addrs
= addrs
->ifa_next
) {
39 if (addrs
->ifa_addr
== NULL
)
42 if (strcmp(addrs
->ifa_name
, "lo") == 0)
45 if (addrs
->ifa_addr
->sa_family
!= net
->sin_family
)
48 struct in_addr
*cur
= &((struct sockaddr_in
*)addrs
->ifa_addr
)->sin_addr
;
49 netmask_ipv4(cur
, prefix_len
, &temp
);
51 if (temp
.s_addr
== want
.s_addr
) {
52 return addrs
->ifa_addr
;
60 static void netmask_ipv6(const struct in6_addr
*addr
,
61 unsigned int prefix_len
,
62 struct in6_addr
*out
) {
66 memcpy(out
->s6_addr
, addr
->s6_addr
, prefix_len
/8);
68 out
->s6_addr
[prefix_len
/8] = addr
->s6_addr
[prefix_len
/8] & ~( 0xFF >> (prefix_len
% 8) );
69 if (prefix_len
/8 < 15)
70 memset(out
->s6_addr
+prefix_len
/8+1, 0, 16-prefix_len
/8-1);
74 const struct sockaddr
*find_ipv6_in_subnet(const struct ifaddrs
*addrs
,
75 const struct sockaddr_in6
*net
,
76 unsigned int prefix_len
) {
77 struct in6_addr want
, temp
;
79 netmask_ipv6(&net
->sin6_addr
, prefix_len
, &want
);
81 for (; addrs
!= NULL
; addrs
= addrs
->ifa_next
) {
83 if (addrs
->ifa_addr
== NULL
)
86 if (strcmp(addrs
->ifa_name
, "lo") == 0)
89 if (addrs
->ifa_addr
->sa_family
!= net
->sin6_family
)
92 struct in6_addr
*cur
= &((struct sockaddr_in6
*)addrs
->ifa_addr
)->sin6_addr
;
93 netmask_ipv6(cur
, prefix_len
, &temp
);
95 if (IN6_ARE_ADDR_EQUAL(&temp
, &want
))
96 return addrs
->ifa_addr
;
103 const struct sockaddr
*find_ip_in_subnet(const struct ifaddrs
*addrs
,
104 const struct sockaddr
*net
,
105 unsigned int prefix_len
) {
106 switch (net
->sa_family
) {
108 return find_ipv4_in_subnet(addrs
, (struct sockaddr_in
*)net
, prefix_len
);
111 return find_ipv6_in_subnet(addrs
, (struct sockaddr_in6
*)net
, prefix_len
);
118 bool parse_network(const char *s
, struct sockaddr_storage
*network
, unsigned int *prefix_len
) {
119 char *slash
= strchr((char*)s
, '/');
124 if (*(slash
+1) == '\0') {
125 // slash is the last character
130 long int num
= strtol(slash
+1, &end
, 10);
132 // junk after the prefix_len
140 // copy the part before slash to get nil termination
141 char *addr
= (char*)alloca(slash
-s
+ 1);
142 strncpy(addr
, s
, slash
-s
);
143 addr
[slash
-s
] = '\0';
145 // caller expects ports etc to be zero
146 memset(network
, 0, sizeof(*network
));
148 // try parsing as ipv4
150 ok
= inet_pton(AF_INET
, addr
, &((struct sockaddr_in
*)network
)->sin_addr
);
152 network
->ss_family
= AF_INET
;
156 // try parsing as ipv6
157 ok
= inet_pton(AF_INET6
, addr
, &((struct sockaddr_in6
*)network
)->sin6_addr
);
159 network
->ss_family
= AF_INET6
;