#pragma once
/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

/**
 * $Id: d356ecc559985cb943469f239bcb94297a126c47 $
 *
 * @file include/missing.h
 * @brief Replacements for functions that are or can be
 *	missing on some platforms.
 *	HAVE_* and WITH_* defines are substituted at
 *	build time by make with values from autoconf.h.
 *
 * @copyright 2015 The FreeRADIUS server project
 */
RCSIDH(missing_h, "$Id: d356ecc559985cb943469f239bcb94297a126c47 $")

#ifdef HAVE_STDINT_H
#  include <stdint.h>
#endif

#ifdef HAVE_STDDEF_H
#  include <stddef.h>
#endif

#ifdef HAVE_SYS_TYPES_H
#  include <sys/types.h>
#endif

#ifdef HAVE_INTTYPES_H
#  include <inttypes.h>
#endif

#ifdef HAVE_STRINGS_H
#  include <strings.h>
#endif

#ifdef HAVE_STRING_H
#  include <string.h>
#endif

#ifdef HAVE_NETDB_H
#  include <netdb.h>
#endif

#ifdef HAVE_NETINET_IN_H
#  include <netinet/in.h>
#endif

#ifdef HAVE_ARPA_INET_H
#  include <arpa/inet.h>
#endif

#ifdef HAVE_SYS_SELECT_H
#  include <sys/select.h>
#endif

#ifdef HAVE_SYS_SOCKET_H
#  include <sys/socket.h>
#endif

#ifdef HAVE_UNISTD_H
#  include <unistd.h>
#endif

#ifndef HAVE_VSNPRINTF
#  include <stdarg.h>
#endif

#ifdef HAVE_ERRNO_H
#  include <errno.h>
#endif

#include <limits.h>

/*
 *  Check for inclusion of <time.h>, versus <sys/time.h>
 *  Taken verbatim from the autoconf manual.
 */
#ifdef TIME_WITH_SYS_TIME
#  include <sys/time.h>
#  include <time.h>
#else
#  if HAVE_SYS_TIME_H
#    include <sys/time.h>
#  else
#    include <time.h>
#  endif
#endif

/*
 *	Don't look for winsock.h if we're on cygwin.
 */
#if !defined(__CYGWIN__) && defined(HAVE_WINSOCK_H)
#  include <winsock.h>
#endif

#ifdef __APPLE__
#undef DARWIN
#define DARWIN (1)
#endif

#ifdef __cplusplus
extern "C" {
#endif

#ifndef HAVE_SIG_T
typedef void (*sig_t)(int);
#endif

/*
 *	Functions from missing.c
 */
#ifndef HAVE_STRNCASECMP
int strncasecmp(char *s1, char *s2, int n);
#endif

#ifndef HAVE_STRCASECMP
int strcasecmp(char *s1, char *s2);
#endif

#ifndef HAVE_MEMRCHR
void *memrchr(const void *s, int c, size_t n);
#endif

#ifndef HAVE_STRSEP
char *strsep(char **stringp, char const *delim);
#endif

#ifndef HAVE_LOCALTIME_R
struct tm;
struct tm *localtime_r(time_t const *l_clock, struct tm *result);
#endif

#ifndef HAVE_CTIME_R
char *ctime_r(time_t const *l_clock, char *l_buf);
#endif

#ifndef HAVE_INET_PTON
int		inet_pton(int af, char const *src, void *dst);
#endif

#ifndef HAVE_INET_NTOP
char const	*inet_ntop(int af, void const *src, char *dst, size_t cnt);
#endif

#ifndef HAVE_SENDMMSG
struct mmsghdr {
	struct msghdr msg_hdr;  /* Message header */
	unsigned int  msg_len;  /* Number of bytes transmitted */
};
int sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags);
#endif

#ifndef HAVE_CLOSEFROM
void		closefrom(int fd);
#endif

#ifndef HAVE_MEMSET_EXPLICIT
void *memset_explicit(void *ptr, int ch, size_t len);
#endif

#ifndef HAVE_SETLINEBUF
#  ifdef HAVE_SETVBUF
#    define setlinebuf(x) setvbuf(x, NULL, _IOLBF, 0)
#  else
#    define setlinebuf(x)     0
#  endif
#endif

#ifndef INADDR_ANY
#  define INADDR_ANY      ((uint32_t) 0x00000000)
#endif

#ifndef INADDR_LOOPBACK
#  define INADDR_LOOPBACK ((uint32_t) 0x7f000001) /* Inet 127.0.0.1 */
#endif

#ifndef INADDR_NONE
#  define INADDR_NONE     ((uint32_t) 0xffffffff)
#endif

#ifndef INADDRSZ
#  define INADDRSZ 4
#endif

#ifndef INET_ADDRSTRLEN
#  define INET_ADDRSTRLEN 16
#endif

#ifndef AF_UNSPEC
#  define AF_UNSPEC 0
#endif

#ifndef AF_INET6
#  define AF_INET6 10
#endif

#ifndef HAVE_STRUCT_IN6_ADDR
struct in6_addr
{
	union {
		uint8_t	u6_addr8[16];
		uint16_t u6_addr16[8];
		uint32_t u6_addr32[4];
	} in6_u;
#  define s6_addr	in6_u.u6_addr8
#  define s6_addr16	in6_u.u6_addr16
#  define s6_addr32	in6_u.u6_addr32
};

#  ifndef IN6ADDRSZ
#    define IN6ADDRSZ 16
#  endif

#  ifndef INET6_ADDRSTRLEN
#    define INET6_ADDRSTRLEN 46
#  endif

#  ifndef IN6ADDR_ANY_INIT
#    define IN6ADDR_ANY_INIT 		{{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}}
#  endif

#  ifndef IN6ADDR_LOOPBACK_INIT
#    define IN6ADDR_LOOPBACK_INIT 	{{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}}
#  endif

#  ifndef IN6_IS_ADDR_UNSPECIFIED
#    define IN6_IS_ADDR_UNSPECIFIED(a) \
	(((__const uint32_t *) (a))[0] == 0				      \
	 && ((__const uint32_t *) (a))[1] == 0				      \
	 && ((__const uint32_t *) (a))[2] == 0				      \
	 && ((__const uint32_t *) (a))[3] == 0)
#  endif

#  ifndef IN6_IS_ADDR_LOOPBACK
#    define IN6_IS_ADDR_LOOPBACK(a) \
	(((__const uint32_t *) (a))[0] == 0				      \
	 && ((__const uint32_t *) (a))[1] == 0				      \
	 && ((__const uint32_t *) (a))[2] == 0				      \
	 && ((__const uint32_t *) (a))[3] == htonl (1))
#  endif

#  ifndef IN6_IS_ADDR_MULTICAST
#    define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff)
#  endif

#  ifndef IN6_IS_ADDR_LINKLOCAL
#    define IN6_IS_ADDR_LINKLOCAL(a) \
	((((__const uint32_t *) (a))[0] & htonl (0xffc00000))		      \
	 == htonl (0xfe800000))
#  endif

#  ifndef IN6_IS_ADDR_SITELOCAL
#    define IN6_IS_ADDR_SITELOCAL(a) \
	((((__const uint32_t *) (a))[0] & htonl (0xffc00000))		      \
	 == htonl (0xfec00000))
#  endif

#  ifndef IN6_IS_ADDR_V4MAPPED
#    define IN6_IS_ADDR_V4MAPPED(a) \
	((((__const uint32_t *) (a))[0] == 0)				      \
	 && (((__const uint32_t *) (a))[1] == 0)			      \
	 && (((__const uint32_t *) (a))[2] == htonl (0xffff)))
#  endif

#  ifndef IN6_IS_ADDR_V4COMPAT
#    define IN6_IS_ADDR_V4COMPAT(a) \
	((((__const uint32_t *) (a))[0] == 0)				      \
	 && (((__const uint32_t *) (a))[1] == 0)			      \
	 && (((__const uint32_t *) (a))[2] == 0)			      \
	 && (ntohl (((__const uint32_t *) (a))[3]) > 1))
#  endif

#  ifndef IN6_ARE_ADDR_EQUAL
#    define IN6_ARE_ADDR_EQUAL(a,b) \
	((((__const uint32_t *) (a))[0] == ((__const uint32_t *) (b))[0])     \
	 && (((__const uint32_t *) (a))[1] == ((__const uint32_t *) (b))[1])  \
	 && (((__const uint32_t *) (a))[2] == ((__const uint32_t *) (b))[2])  \
	 && (((__const uint32_t *) (a))[3] == ((__const uint32_t *) (b))[3]))
#  endif
#endif /* HAVE_STRUCT_IN6_ADDR */

/*
 *	Functions from getaddrinfo.c
 */

#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
struct sockaddr_storage
{
    uint16_t ss_family;		/* Address family, etc.  */
    char ss_padding[128 - (sizeof(uint16_t))];
};
#endif

#ifndef HAVE_STRUCT_ADDRINFO
/* for old netdb.h */
#  ifndef EAI_SERVICE
#    define EAI_MEMORY      2
#    define EAI_FAMILY      5	/* ai_family not supported */
#    define EAI_NONAME      8	/* hostname nor servname provided, or not known */
#    define EAI_SERVICE     9	/* servname not supported for ai_socktype */
#  endif

/* dummy value for old netdb.h */
#  ifndef AI_PASSIVE
#    define AI_PASSIVE      1
#    define AI_CANONNAME    2
#    define AI_NUMERICHOST  4
#    define NI_NUMERICHOST  2
#    define NI_NAMEREQD     4
#    define NI_NUMERICSERV  8

struct addrinfo
{
  int ai_flags;			/* Input flags.  */
  int ai_family;		/* Protocol family for socket.  */
  int ai_socktype;		/* Socket type.  */
  int ai_protocol;		/* Protocol for socket.  */
  socklen_t ai_addrlen;		/* Length of socket address.  */
  struct sockaddr *ai_addr;	/* Socket address for socket.  */
  char *ai_canonname;		/* Canonical name for service location.  */
  struct addrinfo *ai_next;	/* Pointer to next in list.  */
};

#  endif /* AI_PASSIVE */
#endif /* HAVE_STRUCT_ADDRINFO */

/* Translate name of a service location and/or a service name to set of
   socket addresses. */
#ifndef HAVE_GETADDRINFO
int getaddrinfo(char const *__name, char const *__service,
		struct addrinfo const *__req,
		struct addrinfo **__pai);

/* Free `addrinfo' structure AI including associated storage.  */
void freeaddrinfo (struct addrinfo *__ai);

/* Convert error return from getaddrinfo() to a string.  */
char const *gai_strerror (int __ecode);
#endif

/* Translate a socket address to a location and service name. */
#ifndef HAVE_GETNAMEINFO
int getnameinfo(struct sockaddr const *__sa,
		socklen_t __salen, char *__host,
		size_t __hostlen, char *__serv,
		size_t __servlen, unsigned int __flags);
#endif

/*
 *	Functions from snprintf.c
 */
#ifndef HAVE_VSNPRINTF
int vsnprintf(char *str, size_t count, char const *fmt, va_list arg);
#endif

#ifndef HAVE_SNPRINTF
int snprintf(char *str, size_t count, char const *fmt, ...);
#endif

/**
 *	Functions from strl{cat,cpy}.c
 *
 * @hidecallergraph
 */
#ifndef HAVE_STRLCPY
size_t strlcpy(char *dst, char const *src, size_t siz);
#endif

#ifndef HAVE_STRLCAT
size_t strlcat(char *dst, char const *src, size_t siz);
#endif

#ifndef INT16SZ
#  define INT16SZ (2)
#endif

#ifndef HAVE_GMTIME_R
struct tm *gmtime_r(time_t const *l_clock, struct tm *result);
#endif

#ifndef HAVE_VDPRINTF
int vdprintf (int fd, char const *format, va_list args);
#endif

#ifndef HAVE_CLOCK_GETTIME
enum {
	CLOCK_REALTIME,
	CLOCK_MONOTONIC
};
int clock_gettime(int clk_id, struct timespec *t);
#endif

/*
 *	These are linux specific
 */
#ifndef CLOCK_REALTIME_COARSE
#  define CLOCK_REALTIME_COARSE CLOCK_REALTIME
#endif
#ifndef CLOCK_MONOTONIC_COARSE
#  define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC
#endif

/*
 *	Work around different ctime_r styles
 */
#if defined(CTIMERSTYLE) && (CTIMERSTYLE == SOLARISSTYLE)
#  define CTIME_R(a,b,c) ctime_r(a,b,c)
#  define ASCTIME_R(a,b,c) asctime_r(a,b,c)
#else
#  define CTIME_R(a,b,c) ctime_r(a,b)
#  define ASCTIME_R(a,b,c) asctime_r(a,b)
#endif

#ifdef WIN32
#  undef interface
#  undef mkdir
#  define mkdir(_d, _p) mkdir(_d)
#  define FR_DIR_SEP '\\'
#  define FR_DIR_IS_RELATIVE(p) ((*p && (p[1] != ':')) || ((*p != '\\') && (*p != '\\')))
#else
#  define FR_DIR_SEP '/'
#  define FR_DIR_IS_RELATIVE(p) ((*p) != '/')
#endif

#ifndef offsetof
#  define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif

#ifndef SSIZE_MIN
#  define SSIZE_MIN LONG_MIN
#endif

/*
 *	This is really hacky. Any code needing to perform operations on 128bit integers,
 *	or return 128BIT integers should check for HAVE_128BIT_INTEGERS.
 */
#ifndef HAVE_UINT128_T
#  ifdef HAVE___UINT128_T
#    define HAVE_128BIT_INTEGERS
#    define uint128_t __uint128_t
#    define int128_t __int128_t
#  else
typedef struct {
	union {
		uint8_t v[16];
		struct {
#ifndef WORDS_BIGENDIAN
			uint64_t l;
			uint64_t h;
#else
			uint64_t h;
			uint64_t l;
#endif
		};
	};
} uint128_t;
typedef struct {
	union {
		uint8_t v[16];
		struct {
#ifndef WORDS_BIGENDIAN
			uint64_t l;
			int64_t h;
#else
			int64_t h;
			uint64_t l;
#endif
		};
	};
} int128_t;
#  endif
#else
#  define HAVE_128BIT_INTEGERS
#endif

/* abcd efgh -> dcba hgfe -> hgfe dcba */
#ifndef HAVE_HTONLL
#  ifndef WORDS_BIGENDIAN
#    ifdef HAVE_BUILTIN_BSWAP64
#      define ntohll(x) ((uint64_t)__builtin_bswap64(x))
#    else
#      define ntohll(x) (((uint64_t)ntohl((uint32_t)(x >> 32))) | (((uint64_t)ntohl(((uint32_t) x)) << 32)))
#    endif
#  else
#    define ntohll(x) (x)
#  endif
#  define htonll(x) ntohll(x)
#endif

#ifndef HAVE_HTONLLL
#  ifndef WORDS_BIGENDIAN
#    ifdef HAVE_128BIT_INTEGERS
#      define ntohlll(x) (((uint128_t)ntohll((uint64_t)(x >> 64))) | (((uint128_t)ntohll(((uint64_t) x)) << 64)))
#    else
static inline uint128_t ntohlll(uint128_t const num)
{
	uint64_t const *p = (uint64_t const *) &num;
	uint64_t ret[2];

	/* swapsies */
	ret[1] = ntohll(p[0]);
	ret[0] = ntohll(p[1]);

	return *(uint128_t *)ret;
}
#    endif
#  else
#    define ntohlll(x) (x)
#  endif
#  define htonlll(x) ntohlll(x)
#endif

#ifndef HAVE_SIG_T
typedef void(*sig_t)(int);
#endif

#ifdef __cplusplus
}
#endif
