From: Kefu Chai Date: Sun, 10 Sep 2017 13:38:56 +0000 (+0800) Subject: msg/msg_types: fix the denc of sockaddr_storage on freebsd/osx X-Git-Tag: v13.0.1~880^2~11 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=3eff8a65c7f9db4136ba550a9966095b3c359ad3;p=ceph.git msg/msg_types: fix the denc of sockaddr_storage on freebsd/osx the layout of sockaddr_in and sockaddr_in6 are different on GNU/Linux and FreeBSD/OSX: - on GNU/Linux, sockaddr does not have sa_len, - on GNU/Linux, sockaddr* use a 16 bit integer for sa_family, but on FreeBSD, a 32bit integer is used. so we need to be more care when memcpy() between sockaddr_storage() and ceph_sockaddr_storage(). Signed-off-by: Kefu Chai --- diff --git a/src/msg/msg_types.h b/src/msg/msg_types.h index 292a0de367f..9569fcf5101 100644 --- a/src/msg/msg_types.h +++ b/src/msg/msg_types.h @@ -178,7 +178,16 @@ static inline void encode(const sockaddr_storage& a, bufferlist& bl) { ::encode_raw(ss, bl); #elif defined(__FreeBSD__) || defined(__APPLE__) ceph_sockaddr_storage ss{}; - ::memcpy(&ss, &(a.ss_family), std::min(sizeof(ss), (size_t)a.ss_len)); + auto src = (unsigned char const *)&a; + auto dst = (unsigned char *)&ss; + src += sizeof(a.ss_len); + ss.ss_family = a.ss_family; + src += sizeof(a.ss_family); + dst += sizeof(ss.ss_family); + const auto copy_size = std::min((unsigned char*)(&a + 1) - src, + (unsigned char*)(&ss + 1) - dst); + ::memcpy(dst, src, copy_size); + ::encode(ss, bl); #else ceph_sockaddr_storage ss{}; ::memset(&ss, '\0', sizeof(ss)); @@ -193,20 +202,16 @@ static inline void decode(sockaddr_storage& a, bufferlist::iterator& bl) { #elif defined(__FreeBSD__) || defined(__APPLE__) ceph_sockaddr_storage ss{}; ::decode(ss, bl); - auto const ss_len = std::min(sizeof(ss), sizeof(a)) - sizeof(a.ss_len); - ::memcpy(&(a.ss_family), &ss, ss_len); - sockaddr *sa = (sockaddr*)&a; - switch (sa->sa_family) { - case AF_INET: - a.ss_len = sizeof(sockaddr_in); - break; - case AF_INET6: - a.ss_len = sizeof(sockaddr_in6); - break; - default: - a.ss_len = sizeof(sockaddr); - break; - } + auto src = (unsigned char const *)&ss; + auto dst = (unsigned char *)&a; + a.ss_len = 0; + dst += sizeof(a.ss_len); + a.ss_family = ss.ss_family; + src += sizeof(ss.ss_family); + dst += sizeof(a.ss_family); + auto const copy_size = std::min((unsigned char*)(&ss + 1) - src, + (unsigned char*)(&a + 1) - dst); + ::memcpy(dst, src, copy_size); #else ceph_sockaddr_storage ss{}; ::decode(ss, bl);