Commit 38d6a0f2 authored by David Woodhouse's avatar David Woodhouse

Add endian-specific word load/store functions

... and remove a subset of them, less optimally implemented, from ntlm.c
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 5f15c83f
......@@ -884,6 +884,13 @@ AC_CHECK_HEADER([if_tun.h],
AC_CHECK_HEADER([net/if_utun.h], AC_DEFINE([HAVE_NET_UTUN_H], 1, [Have net/utun.h]))
AC_CHECK_HEADER([alloca.h], AC_DEFINE([HAVE_ALLOCA_H], 1, [Have alloca.h]))
AC_CHECK_HEADER([endian.h],
[AC_DEFINE([ENDIAN_HDR], [<endian.h>], [endian header include path])],
[AC_CHECK_HEADER([sys/endian.h],
[AC_DEFINE([ENDIAN_HDR], [<sys/endian.h>])],
[AC_CHECK_HEADER([sys/isa_defs.h],
[AC_DEFINE([ENDIAN_HDR], [<sys/isa_defs.h>])])])])
if test "$ssl_library" = "openssl" || test "$ssl_library" = "both"; then
oldLIBS="$LIBS"
LIBS="$LIBS $OPENSSL_LIBS"
......
......@@ -826,32 +826,6 @@ static void ntlm_calc_response (const unsigned char key[21],
des (ks, results + 16);
}
static inline uint32_t load_le32(void *_p)
{
unsigned char *p = _p;
return (p[3] << 24) | (p[2] << 16) | p[1] << 8 | p[0];
}
static inline uint16_t load_le16(void *_p)
{
unsigned char *p = _p;
return p[1] << 8 | p[0];
}
static inline void store_le32(void *_p, uint32_t v)
{
unsigned char *p = _p;
p[0] = v;
p[1] = v >> 8;
p[2] = v >> 16;
p[3] = v >> 24;
}
static inline void store_le16(void *_p, uint16_t v)
{
unsigned char *p = _p;
p[0] = v;
p[1] = v >> 8;
}
#define NTLM_CHALLENGE_DOMAIN_OFFSET 12
#define NTLM_CHALLENGE_FLAGS_OFFSET 20
#define NTLM_CHALLENGE_NONCE_OFFSET 24
......
......@@ -939,4 +939,111 @@ extern const char *openconnect_version_str;
return; \
}
/* Let's stop open-coding big-endian and little-endian loads/stores.
*
* Start with a packed structure so that we can let the compiler
* decide whether the target CPU can cope with unaligned load/stores
* or not. Then there are three cases to handle:
* - For big-endian loads/stores, just use htons() et al.
* - For little-endian when we *know* the CPU is LE, just load/store
* - For little-endian otherwise, do the data acess byte-wise
*/
struct oc_packed_uint32_t {
uint32_t d;
} __attribute__((packed));
struct oc_packed_uint16_t {
uint16_t d;
} __attribute__((packed));
static inline uint32_t load_be32(const void *_p)
{
const struct oc_packed_uint32_t *p = _p;
return ntohl(p->d);
}
static inline uint16_t load_be16(const void *_p)
{
const struct oc_packed_uint16_t *p = _p;
return ntohs(p->d);
}
static inline void store_be32(void *_p, uint32_t d)
{
struct oc_packed_uint32_t *p = _p;
p->d = htonl(d);
}
static inline void store_be16(void *_p, uint16_t d)
{
struct oc_packed_uint16_t *p = _p;
p->d = htons(d);
}
/* It doesn't matter if we don't find one. It'll default to the
* "not known to be little-endian" case, and do the bytewise
* load/store. Modern compilers might even spot the pattern and
* optimise it (see GCC PR#55177 around comment 15). */
#ifdef ENDIAN_HDR
#include ENDIAN_HDR
#endif
#if defined(_WIN32) || \
(defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)) /* Solaris */ || \
(defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN) && defined(__BYTE_ORDER) \
&& __BYTE_ORDER == __LITTLE_ENDIAN) /* Linux */ || \
(defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) && defined(BYTE_ORDER) \
&& BYTE_ORDER == LITTLE_ENDIAN) /* *BSD */
static inline uint32_t load_le32(const void *_p)
{
const struct oc_packed_uint32_t *p = _p;
return p->d;
}
static inline uint16_t load_le16(const void *_p)
{
const struct oc_packed_uint16_t *p = _p;
return p->d;
}
static inline void store_le32(void *_p, uint32_t d)
{
struct oc_packed_uint32_t *p = _p;
p->d = d;
}
static inline void store_le16(void *_p, uint16_t d)
{
struct oc_packed_uint16_t *p = _p;
p->d = d;
}
#else
static inline uint32_t load_le32(const void *_p)
{
const unsigned char *p = _p;
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
}
static inline uint16_t load_le16(const void *_p)
{
const unsigned char *p = _p;
return p[0] | (p[1] << 8);
}
static inline void store_le32(void *_p, uint32_t d)
{
unsigned char *p = _p;
p[0] = d;
p[1] = d >> 8;
}
static inline void store_le16(void *_p, uint16_t d)
{
unsigned char *p = _p;
p[0] = d;
p[1] = d >> 8;
p[2] = d >> 16;
p[3] = d >> 24;
}
#endif /* !Not known to be little-endian */
#endif /* __OPENCONNECT_INTERNAL_H__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment