From c2a5941f8897c4b374db1a3033832f7c08dd1a09 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Fri, 13 Apr 2012 16:44:00 -0400 Subject: [PATCH] Fall back to naive built-in byte-swap routines EL5 lacks htobe64 and friends. Using its byteswap.h requires an endianness check in our headers, which is fragile and compiler-dependent. It's a fair amount of code [1], and is only useful on EL5. So instead, let's include a fallback implementation of these functions, and use it whenever we can't find the (now-)standard Linux or OS X routines. The fallback is endianness-independent and should work on any platform. [1] https://github.com/rurban/mosh/commit/da1a5abd1e09f0c1e9295357bb480a643d9dc8e3 --- configure.ac | 2 +- src/crypto/byteorder.h | 72 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 2111c81..be6daf2 100644 --- a/configure.ac +++ b/configure.ac @@ -272,7 +272,7 @@ AC_CHECK_DECL([htobe64], [AC_CHECK_DECL([OSSwapHostToBigInt64], [AC_DEFINE([HAVE_OSX_SWAP], [1], [Define if OSSwapHostToBigInt64 and friends exist.])], - [AC_MSG_ERROR([Unable to find byte swapping functions])], + [AC_MSG_WARN([Unable to find byte swapping functions; using built-in routines.])], [[#include ]])], [[#if defined(HAVE_ENDIAN_H) #include diff --git a/src/crypto/byteorder.h b/src/crypto/byteorder.h index 549ff4d..a341427 100644 --- a/src/crypto/byteorder.h +++ b/src/crypto/byteorder.h @@ -27,12 +27,84 @@ # elif defined(HAVE_SYS_ENDIAN_H) # include # endif + #elif HAVE_OSX_SWAP # include # define htobe64 OSSwapHostToBigInt64 # define be64toh OSSwapBigToHostInt64 # define htobe16 OSSwapHostToBigInt16 # define be16toh OSSwapBigToHostInt16 + +#else + +/* Use our fallback implementation, which is correct for any endianness. */ + +#include + +/* Make sure they aren't macros */ +#undef htobe64 +#undef be64toh +#undef htobe16 +#undef be16toh + +/* Use unions rather than casts, to comply with strict aliasing rules. */ + +inline uint64_t htobe64( uint64_t x ) { + uint8_t xs[ 8 ] = { + ( x >> 56 ) & 0xFF, + ( x >> 48 ) & 0xFF, + ( x >> 40 ) & 0xFF, + ( x >> 32 ) & 0xFF, + ( x >> 24 ) & 0xFF, + ( x >> 16 ) & 0xFF, + ( x >> 8 ) & 0xFF, + x & 0xFF }; + union { + const uint8_t *p8; + const uint64_t *p64; + } u; + u.p8 = xs; + return *u.p64; +} + +inline uint64_t be64toh( uint64_t x ) { + union { + const uint8_t *p8; + const uint64_t *p64; + } u; + u.p64 = &x; + return ( uint64_t( u.p8[ 0 ] ) << 56 ) + | ( uint64_t( u.p8[ 1 ] ) << 48 ) + | ( uint64_t( u.p8[ 2 ] ) << 40 ) + | ( uint64_t( u.p8[ 3 ] ) << 32 ) + | ( uint64_t( u.p8[ 4 ] ) << 24 ) + | ( uint64_t( u.p8[ 5 ] ) << 16 ) + | ( uint64_t( u.p8[ 6 ] ) << 8 ) + | ( uint64_t( u.p8[ 7 ] ) ); +} + +inline uint16_t htobe16( uint16_t x ) { + uint8_t xs[ 2 ] = { + ( x >> 8 ) & 0xFF, + x & 0xFF }; + union { + const uint8_t *p8; + const uint16_t *p16; + } u; + u.p8 = xs; + return *u.p16; +} + +inline uint16_t be16toh( uint16_t x ) { + union { + const uint8_t *p8; + const uint16_t *p16; + } u; + u.p16 = &x; + return ( uint16_t( u.p8[ 0 ] ) << 8 ) + | ( uint16_t( u.p8[ 1 ] ) ); +} + #endif #endif