From aebcc506e2a5664687853ac73d914d7360f776bb Mon Sep 17 00:00:00 2001 From: Oliver Tappe Date: Thu, 10 Jul 2008 21:25:19 +0000 Subject: [PATCH] Corrected by previous assumption, since gethostbyname() has nothing to do with struct sockaddr_in - the real culprits were BNetAddress::GetAddr(sockaddr_in&) and BNetAddress::SetTo(const sockaddr_in&): * moved check_r5_compatibility() into r5_compatibility.h to make that function available to BNetAddress, too * adjusted sockaddr_in-handling methods of BNetAddress to deal with R5-addresses if in compatibility mode * removed is_r5_sockaddr() again, since it is no longer needed With this less hacky solution, Beam, NetPositive, NetworkTime and Vision still work. So, there's hope that the R5 compatibility layer is now complete. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26377 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/net/r5_compatibility.h | 27 ++++++++++++ src/kits/network/libnetapi/NetAddress.cpp | 23 ++++++++-- src/kits/network/socket.cpp | 53 ++--------------------- 3 files changed, 49 insertions(+), 54 deletions(-) diff --git a/headers/private/net/r5_compatibility.h b/headers/private/net/r5_compatibility.h index e567e7c817..7a16df9a83 100644 --- a/headers/private/net/r5_compatibility.h +++ b/headers/private/net/r5_compatibility.h @@ -44,4 +44,31 @@ extern addr_t __gNetworkEnd; extern addr_t __gNetAPIStart; extern addr_t __gNetAPIEnd; + +static inline bool +check_r5_compatibility() +{ + if (!__gR5Compatibility) + return false; + +#ifndef __INTEL__ + return false; +#else + + struct stack_frame { + struct stack_frame* previous; + addr_t return_address; + }; + + stack_frame* frame = (stack_frame*)get_stack_frame(); + if (frame->return_address >= __gNetworkStart + && frame->return_address < __gNetworkEnd) { + return false; + } + + return true; +#endif +} + + #endif // NET_R5_COMPATIBILITY_H diff --git a/src/kits/network/libnetapi/NetAddress.cpp b/src/kits/network/libnetapi/NetAddress.cpp index c96a0d57e1..0391d79913 100644 --- a/src/kits/network/libnetapi/NetAddress.cpp +++ b/src/kits/network/libnetapi/NetAddress.cpp @@ -17,6 +17,8 @@ * No trouts were harmed during the development of this class. */ +#include + #include #include #include @@ -184,13 +186,18 @@ BNetAddress::GetAddr(char* hostname, unsigned short* port) const status_t BNetAddress::GetAddr( struct sockaddr_in& sa ) const { if ( fInit != B_OK ) - { return B_NO_INIT; - } - sa.sin_family = fFamily; sa.sin_port = fPort; sa.sin_addr.s_addr = fAddress; + if (check_r5_compatibility()) { + r5_sockaddr_in* r5Addr = (r5_sockaddr_in *)&sa; + if (fFamily == AF_INET) + r5Addr->sin_family = R5_AF_INET; + else + r5Addr->sin_family = fFamily; + } else + sa.sin_family = fFamily; return B_OK; } @@ -358,10 +365,18 @@ BNetAddress::SetTo(const char* hostname, unsigned short port) status_t BNetAddress::SetTo(const struct sockaddr_in& addr) { - fFamily = addr.sin_family; fPort = addr.sin_port; fAddress = addr.sin_addr.s_addr; + if (check_r5_compatibility()) { + const r5_sockaddr_in* r5Addr = (const r5_sockaddr_in *)&addr; + if (r5Addr->sin_family == R5_AF_INET) + fFamily = AF_INET; + else + fFamily = r5Addr->sin_family; + } else + fFamily = addr.sin_family; + return fInit = B_OK; } diff --git a/src/kits/network/socket.cpp b/src/kits/network/socket.cpp index 97eef67748..ef66045ba1 100644 --- a/src/kits/network/socket.cpp +++ b/src/kits/network/socket.cpp @@ -22,53 +22,6 @@ #include -static inline bool -check_r5_compatibility() -{ - if (!__gR5Compatibility) - return false; - -#ifndef __INTEL__ - return false; -#else - - struct stack_frame { - struct stack_frame* previous; - addr_t return_address; - }; - - stack_frame* frame = (stack_frame*)get_stack_frame(); - if (frame->return_address >= __gNetworkStart - && frame->return_address < __gNetworkEnd) { - return false; - } - - return true; -#endif -} - - -static bool -is_r5_sockaddr(const struct sockaddr *_addr) -{ - /* r5_sockaddr_in structs do not contain sin_len, but have a larger - * sin_family instead (two bytes), so in a r5_sockaddr_in, the first two - * bytes will always be equal to R5_AF_INET, while for haiku's own - * sockaddr_in, that will never be the case, since the first byte contains - * the length which should never be zero. - * The only other case where this check could fail is when the address does - * not belong to the internet family at all. But even in that case we would - * not want to try to convert the addresses, as the conversion itself - * blindly casts the address to sockaddr_in, which would yield unpredictable - * results for other address families. - */ - const r5_sockaddr_in *addr = (r5_sockaddr_in *)_addr; - if (addr == NULL || addr->sin_family != R5_AF_INET) - return false; - - return true; -} - static void convert_from_r5_sockaddr(struct sockaddr *_to, const struct sockaddr *_from) { @@ -195,7 +148,7 @@ bind(int socket, const struct sockaddr *address, socklen_t addressLength) { struct sockaddr haikuAddr; - if (check_r5_compatibility() && is_r5_sockaddr(address)) { + if (check_r5_compatibility()) { convert_from_r5_sockaddr(&haikuAddr, address); address = &haikuAddr; addressLength = sizeof(struct sockaddr_in); @@ -217,7 +170,7 @@ connect(int socket, const struct sockaddr *address, socklen_t addressLength) { struct sockaddr haikuAddr; - if (check_r5_compatibility() && is_r5_sockaddr(address)) { + if (check_r5_compatibility()) { convert_from_r5_sockaddr(&haikuAddr, address); address = &haikuAddr; addressLength = sizeof(struct sockaddr_in); @@ -331,7 +284,7 @@ sendto(int socket, const void *data, size_t length, int flags, { struct sockaddr haikuAddr; - if (check_r5_compatibility() && is_r5_sockaddr(address)) { + if (check_r5_compatibility()) { convert_from_r5_sockaddr(&haikuAddr, address); address = &haikuAddr; addressLength = sizeof(struct sockaddr_in);