AmiTimeKeeper/net.c

207 lines
5.9 KiB
C

/*-
* Copyright (c) 2017-2021 Carsten Sonne Larsen <cs@innolan.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "config.h"
#include "net.h"
#include "net_getaddrinfo.h"
#include "message.h"
#include "string.h"
#include "logmod.h"
#define MODULENAME "Network"
int errno;
int gai_h_errno;
#ifdef AOS3
int h_errno;
#endif
static const char *bsdSocketName = "bsdsocket.library";
static const char *openSocketLibraryError = "No TCP/IP Stack running!";
static const char *openSocketResourceError = "Cannot open %s";
struct Library *SocketBase = NULL;
static bool roadshow = false;
#define BSDLIB_NAME ((STRPTR)bsdSocketName)
#define BSDLIB_REV 03L
static void GetStackName(void)
{
struct TagItem tags[] = {
{.ti_Tag = SBTM_GETVAL(SBTC_RELEASESTRPTR), .ti_Data = 0},
{.ti_Tag = TAG_END}};
if (SocketBaseTagList(tags) == 0)
{
const char *id = (char *)tags[0].ti_Data;
LogDebug("TCP/IP stack: %s", id);
if (StartsWith(id, "Roadshow"))
{
roadshow = true;
}
}
else
{
LogDebug("Using unknown TCP/IP stack");
}
}
int OpenSocketLibrary(void)
{
if (SocketBase != NULL)
{
return LIB_OK;
}
if (!(SocketBase = OpenLibrary((STRPTR)BSDLIB_NAME, BSDLIB_REV)))
{
LogError(openSocketLibraryError, BSDLIB_NAME, BSDLIB_REV);
return LIB_ERROR;
}
LogDebug("Opened %s", (char *)SocketBase->lib_IdString);
if (SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (int)&errno,
SBTM_SETVAL(SBTC_LOGTAGPTR), (IPTR)APP_SHORT_NAME,
SBTM_SETVAL(SBTC_HERRNOLONGPTR), (int)&h_errno, TAG_DONE))
{
LogError(openSocketResourceError, BSDLIB_NAME);
CloseLibrary(SocketBase);
return LIB_ERROR;
}
GetStackName();
return LIB_OK;
}
void CloseSocketLibrary(void)
{
if (SocketBase != NULL)
{
LogDebug("Closing %s", (char *)SocketBase->lib_IdString);
CloseLibrary(SocketBase);
SocketBase = NULL;
}
}
const char *GetErrorText(void)
{
switch (errno)
{
case ENOTSOCK:
return "Socket operation on non-socket";
case EDESTADDRREQ:
return "Destination address required";
case EMSGSIZE:
return "Message too long";
case EPROTOTYPE:
return "Protocol wrong type for socket";
case ENOPROTOOPT:
return "Protocol not available";
case EPROTONOSUPPORT:
return "Protocol not supported";
case ESOCKTNOSUPPORT:
return "Socket type not supported";
case EOPNOTSUPP:
return "Operation not supported";
case EPFNOSUPPORT:
return "Protocol family not supported";
case EAFNOSUPPORT:
return "Address family not supported by protocol family";
case EADDRINUSE:
return "Address already in use";
case EADDRNOTAVAIL:
return "Can't assign requested address";
case ENETDOWN:
return "Network is down";
case ENETUNREACH:
return "Network is unreachable";
case ENETRESET:
return "Network dropped connection on reset";
case ECONNABORTED:
return "Software caused connection abort";
case ECONNRESET:
return "Connection reset by peer";
case ENOBUFS:
return "No buffer space available";
case EISCONN:
return "Socket is already connected";
case ENOTCONN:
return "Socket is not connected";
case ESHUTDOWN:
return "Can't send after socket shutdown";
case ETIMEDOUT:
return "Operation timed out";
case ECONNREFUSED:
return "Connection refused";
case EHOSTDOWN:
return "Host is down";
case EHOSTUNREACH:
return "No route to host";
default:
return "Socket error";
}
}
const char *GetHostErrorText(void)
{
if (gai_h_errno != 0)
{
return gai_h_errno == EAI_SYSTEM
? (const char *)GetErrorText()
: (const char *)gai_strerror(gai_h_errno);
}
switch (h_errno)
{
case EAI_BADFLAGS:
return "Invalid value for ai_flags";
case EAI_NONAME:
return "Name or service is not known";
case EAI_AGAIN:
return "Temporary failure in name resolution";
case EAI_FAIL:
return "Non-recoverable failure in name resolution";
case EAI_FAMILY:
return "ai_family not supported";
case EAI_SOCKTYPE:
return "ai_socktype not supported";
case EAI_SERVICE:
return "Service not supported for ai_socktype";
case EAI_ADDRFAMILY:
return "Address family for name not supported";
case EAI_MEMORY:
return "Memory allocation failure";
case EAI_SYSTEM:
return GetErrorText();
default:
return "DNS error";
}
}