- merged HAL code from lib60870 (release/2.3.3)

v1.6
Michael Zillgith 8 months ago
parent 221a1f8615
commit 899a2bbe2e

@ -1,7 +1,7 @@
/*
* socket_hal.h
*
* Copyright 2013-2022 Michael Zillgith
* Copyright 2013-2024 Michael Zillgith
*
* This file is part of Platform Abstraction Layer (libpal)
* for libiec61850, libmms, and lib60870.

@ -1,7 +1,7 @@
/*
* time.c
*
* Copyright 2013-2022 Michael Zillgith
* Copyright 2013-2024 Michael Zillgith
*
* This file is part of Platform Abstraction Layer (libpal)
* for libiec61850, libmms, and lib60870.
@ -68,6 +68,22 @@ Hal_getTimeInNs(void);
PAL_API bool
Hal_setTimeInNs(nsSinceEpoch nsTime);
/**
* Get the monotonic time or system tick time in ms
*
* \return the system time with millisecond resolution.
*/
PAL_API msSinceEpoch
Hal_getMonotonicTimeInMs(void);
/**
* Get the monotonic time or system tick in nanoseconds.
*
* \return the system time with nanosecond resolution.
*/
PAL_API nsSinceEpoch
Hal_getMonotonicTimeInNs(void);
/*! @} */
/*! @} */

@ -65,3 +65,4 @@ Memory_free(void* memb)
{
free(memb);
}

@ -1,33 +1,33 @@
/*
* socket_bsd.c
*
* Copyright 2013-2021 Michael Zillgith
* Copyright 2013-2024 Michael Zillgith
*
* This file is part of Platform Abstraction Layer (libpal)
* for libiec61850, libmms, and lib60870.
*/
#include "hal_socket.h"
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/tcp.h> // required for TCP keepalive
#include <signal.h>
#include <poll.h>
#include <signal.h>
#include "linked_list.h"
#include "hal_thread.h"
#include "lib_memory.h"
#include "linked_list.h"
#ifndef DEBUG_SOCKET
#define DEBUG_SOCKET 0
@ -41,22 +41,26 @@
#define MSG_NOSIGNAL 0
#endif
struct sSocket {
struct sSocket
{
int fd;
uint32_t connectTimeout;
};
struct sServerSocket {
struct sServerSocket
{
int fd;
int backLog;
};
struct sUdpSocket {
struct sUdpSocket
{
int fd;
int namespace; /* IPv4: AF_INET; IPv6: AF_INET6 */
};
struct sHandleSet {
struct sHandleSet
{
LinkedList sockets;
bool pollfdIsUpdated;
struct pollfd* fds;
@ -68,7 +72,8 @@ Handleset_new(void)
{
HandleSet self = (HandleSet)GLOBAL_MALLOC(sizeof(struct sHandleSet));
if (self) {
if (self)
{
self->sockets = LinkedList_create();
self->pollfdIsUpdated = false;
self->fds = NULL;
@ -81,8 +86,10 @@ Handleset_new(void)
void
Handleset_reset(HandleSet self)
{
if (self) {
if (self->sockets) {
if (self)
{
if (self->sockets)
{
LinkedList_destroyStatic(self->sockets);
self->sockets = LinkedList_create();
self->pollfdIsUpdated = false;
@ -93,7 +100,8 @@ Handleset_reset(HandleSet self)
void
Handleset_addSocket(HandleSet self, const Socket sock)
{
if (self != NULL && sock != NULL && sock->fd != -1) {
if (self != NULL && sock != NULL && sock->fd != -1)
{
LinkedList_add(self->sockets, sock);
self->pollfdIsUpdated = false;
}
@ -102,7 +110,8 @@ Handleset_addSocket(HandleSet self, const Socket sock)
void
Handleset_removeSocket(HandleSet self, const Socket sock)
{
if (self && self->sockets && sock) {
if (self && self->sockets && sock)
{
LinkedList_remove(self->sockets, sock);
self->pollfdIsUpdated = false;
}
@ -112,8 +121,10 @@ int
Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
{
/* check if pollfd array is updated */
if (self->pollfdIsUpdated == false) {
if (self->fds) {
if (self->pollfdIsUpdated == false)
{
if (self->fds)
{
GLOBAL_FREEMEM(self->fds);
self->fds = NULL;
}
@ -124,13 +135,16 @@ Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
int i;
for (i = 0; i < self->nfds; i++) {
for (i = 0; i < self->nfds; i++)
{
LinkedList sockElem = LinkedList_get(self->sockets, i);
if (sockElem) {
if (sockElem)
{
Socket sock = (Socket)LinkedList_getData(sockElem);
if (sock) {
if (sock)
{
self->fds[i].fd = sock->fd;
self->fds[i].events = POLL_IN;
}
@ -140,17 +154,20 @@ Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
self->pollfdIsUpdated = true;
}
if (self->fds && self->nfds > 0) {
if (self->fds && self->nfds > 0)
{
int result = poll(self->fds, self->nfds, timeoutMs);
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: poll error (errno: %i)\n", errno);
}
return result;
}
else {
else
{
/* there is no socket to wait for */
return 0;
}
@ -159,7 +176,8 @@ Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
void
Handleset_destroy(HandleSet self)
{
if (self) {
if (self)
{
if (self->sockets)
LinkedList_destroyStatic(self->sockets);
@ -199,11 +217,13 @@ prepareAddress(const char* address, int port, struct sockaddr_in* sockaddr)
memset((char*)sockaddr, 0, sizeof(struct sockaddr_in));
if (address != NULL) {
if (address != NULL)
{
struct hostent* server;
server = gethostbyname(address);
if (server == NULL) return false;
if (server == NULL)
return false;
memcpy((char*)&sockaddr->sin_addr.s_addr, (char*)server->h_addr, server->h_length);
}
@ -238,10 +258,12 @@ TcpServerSocket_create(const char* address, int port)
int fd;
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) >= 0) {
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) >= 0)
{
struct sockaddr_in serverAddress;
if (!prepareAddress(address, port, &serverAddress)) {
if (!prepareAddress(address, port, &serverAddress))
{
close(fd);
return NULL;
}
@ -249,14 +271,16 @@ TcpServerSocket_create(const char* address, int port)
int optionReuseAddr = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&optionReuseAddr, sizeof(int));
if (bind(fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) >= 0) {
if (bind(fd, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) >= 0)
{
serverSocket = (ServerSocket)GLOBAL_MALLOC(sizeof(struct sServerSocket));
serverSocket->fd = fd;
serverSocket->backLog = 2;
setSocketNonBlocking((Socket)serverSocket);
}
else {
else
{
close(fd);
return NULL;
}
@ -271,7 +295,6 @@ ServerSocket_listen(ServerSocket self)
listen(self->fd, self->backLog);
}
/* CHANGED TO MAKE NON-BLOCKING --> RETURNS NULL IF NO CONNECTION IS PENDING */
Socket
ServerSocket_accept(ServerSocket self)
@ -282,17 +305,20 @@ ServerSocket_accept(ServerSocket self)
fd = accept(self->fd, NULL, NULL);
if (fd >= 0) {
if (fd >= 0)
{
conSocket = (Socket)GLOBAL_CALLOC(1, sizeof(struct sSocket));
if (conSocket) {
if (conSocket)
{
conSocket->fd = fd;
setSocketNonBlocking(conSocket);
activateTcpNoDelay(conSocket);
}
else {
else
{
/* out of memory */
close(fd);
@ -313,7 +339,8 @@ ServerSocket_setBacklog(ServerSocket self, int backlog)
static void
closeAndShutdownSocket(int socketFd)
{
if (socketFd != -1) {
if (socketFd != -1)
{
if (DEBUG_SOCKET)
printf("socket_linux.c: call shutdown for %i!\n", socketFd);
@ -346,10 +373,12 @@ TcpSocket_create()
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock != -1) {
if (sock != -1)
{
self = (Socket)GLOBAL_MALLOC(sizeof(struct sSocket));
if (self) {
if (self)
{
self->fd = sock;
self->connectTimeout = 5000;
@ -358,7 +387,8 @@ TcpSocket_create()
int result = setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT, &tcpUserTimeout, sizeof(tcpUserTimeout));
#endif
}
else {
else
{
/* out of memory */
close(sock);
@ -366,7 +396,8 @@ TcpSocket_create()
printf("SOCKET: out of memory\n");
}
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to create socket (errno=%i)\n", errno);
}
@ -390,7 +421,8 @@ Socket_bind(Socket self, const char* srcAddress, int srcPort)
int result = bind(self->fd, (struct sockaddr*)&localAddress, sizeof(localAddress));
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to bind TCP socket (errno=%i)\n", errno);
@ -422,9 +454,11 @@ Socket_connectAsync(Socket self, const char* address, int port)
fcntl(self->fd, F_SETFL, O_NONBLOCK);
if (connect(self->fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0) {
if (connect(self->fd, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0)
{
if (errno != EINPROGRESS) {
if (errno != EINPROGRESS)
{
self->fd = -1;
return false;
}
@ -446,14 +480,16 @@ Socket_checkAsyncConnectState(Socket self)
int selectVal = select(self->fd + 1, NULL, &fdSet, NULL, &timeout);
if (selectVal == 1) {
if (selectVal == 1)
{
/* Check if connection is established */
int so_error;
socklen_t len = sizeof so_error;
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len) >= 0) {
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len) >= 0)
{
if (so_error == 0)
return SOCKET_STATE_CONNECTED;
@ -461,10 +497,12 @@ Socket_checkAsyncConnectState(Socket self)
return SOCKET_STATE_FAILED;
}
else if (selectVal == 0) {
else if (selectVal == 0)
{
return SOCKET_STATE_CONNECTING;
}
else {
else
{
return SOCKET_STATE_FAILED;
}
}
@ -483,14 +521,16 @@ Socket_connect(Socket self, const char* address, int port)
FD_ZERO(&fdSet);
FD_SET(self->fd, &fdSet);
if (select(self->fd + 1, NULL, &fdSet , NULL, &timeout) == 1) {
if (select(self->fd + 1, NULL, &fdSet, NULL, &timeout) == 1)
{
/* Check if connection is established */
int so_error;
socklen_t len = sizeof so_error;
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len) >= 0) {
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len) >= 0)
{
if (so_error == 0)
return true;
@ -511,13 +551,15 @@ convertAddressToStr(struct sockaddr_storage* addr)
bool isIPv6;
if (addr->ss_family == AF_INET) {
if (addr->ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)addr;
port = ntohs(ipv4Addr->sin_port);
inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN);
isIPv6 = false;
}
else if (addr->ss_family == AF_INET6) {
else if (addr->ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)addr;
port = ntohs(ipv6Addr->sin6_port);
inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN);
@ -542,7 +584,8 @@ Socket_getPeerAddress(Socket self)
struct sockaddr_storage addr;
socklen_t addrLen = sizeof(addr);
if (getpeername(self->fd, (struct sockaddr*) &addr, &addrLen) == 0) {
if (getpeername(self->fd, (struct sockaddr*)&addr, &addrLen) == 0)
{
return convertAddressToStr(&addr);
}
else
@ -555,7 +598,8 @@ Socket_getLocalAddress(Socket self)
struct sockaddr_storage addr;
socklen_t addrLen = sizeof(addr);
if (getsockname(self->fd, (struct sockaddr*) &addr, &addrLen) == 0) {
if (getsockname(self->fd, (struct sockaddr*)&addr, &addrLen) == 0)
{
return convertAddressToStr(&addr);
}
else
@ -575,13 +619,15 @@ Socket_getPeerAddressStatic(Socket self, char* peerAddressString)
bool isIPv6;
if (addr.ss_family == AF_INET) {
if (addr.ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)&addr;
port = ntohs(ipv4Addr->sin_port);
inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN);
isIPv6 = false;
}
else if (addr.ss_family == AF_INET6) {
else if (addr.ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)&addr;
port = ntohs(ipv6Addr->sin6_port);
inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN);
@ -609,10 +655,12 @@ Socket_read(Socket self, uint8_t* buf, int size)
if (read_bytes == 0)
return -1;
if (read_bytes == -1) {
if (read_bytes == -1)
{
int error = errno;
switch (error) {
switch (error)
{
case EAGAIN:
return 0;
@ -663,21 +711,25 @@ UdpSocket_createUsingNamespace(int namespace)
int sock = socket(namespace, SOCK_DGRAM, IPPROTO_UDP);
if (sock != -1) {
if (sock != -1)
{
self = (UdpSocket)GLOBAL_MALLOC(sizeof(struct sSocket));
if (self) {
if (self)
{
self->fd = sock;
self->namespace = namespace;
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to allocate memory\n");
close(sock);
}
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to create UDP socket (errno=%i)\n", errno);
}
@ -700,36 +752,42 @@ UdpSocket_createIpV6()
bool
UdpSocket_addGroupMembership(UdpSocket self, const char* multicastAddress)
{
if (self->namespace == AF_INET) {
if (self->namespace == AF_INET)
{
struct ip_mreq mreq;
if (!inet_aton(multicastAddress, &(mreq.imr_multiaddr))) {
if (!inet_aton(multicastAddress, &(mreq.imr_multiaddr)))
{
printf("SOCKET: Invalid IPv4 multicast address\n");
return false;
}
else {
else
{
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(self->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
if (setsockopt(self->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1)
{
printf("SOCKET: failed to set IPv4 multicast group (errno: %i)\n", errno);
return false;
}
}
return true;
}
else if (self->namespace == AF_INET6) {
else if (self->namespace == AF_INET6)
{
struct ipv6_mreq mreq;
if (inet_pton(AF_INET6, multicastAddress, &(mreq.ipv6mr_multiaddr)) < 1) {
if (inet_pton(AF_INET6, multicastAddress, &(mreq.ipv6mr_multiaddr)) < 1)
{
printf("SOCKET: failed to set IPv6 multicast group (errno: %i)\n", errno);
return false;
}
mreq.ipv6mr_interface = 0;
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1)
{
printf("SOCKET: failed to set IPv6 multicast group (errno: %i)\n", errno);
return false;
}
@ -743,16 +801,20 @@ UdpSocket_addGroupMembership(UdpSocket self, const char* multicastAddress)
bool
UdpSocket_setMulticastTtl(UdpSocket self, int ttl)
{
if (self->namespace == AF_INET) {
if (setsockopt(self->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == -1) {
if (self->namespace == AF_INET)
{
if (setsockopt(self->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == -1)
{
printf("SOCKET: failed to set IPv4 multicast TTL (errno: %i)\n", errno);
return false;
}
return true;
}
else if (self->namespace == AF_INET6) {
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) == -1) {
else if (self->namespace == AF_INET6)
{
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) == -1)
{
printf("SOCKET: failed to set IPv6 multicast TTL(hops) (errno: %i)\n", errno);
return false;
}
@ -769,7 +831,8 @@ UdpSocket_bind(UdpSocket self, const char* address, int port)
// TODO add support for IPv6
struct sockaddr_in localAddress;
if (!prepareAddress(address, port, &localAddress)) {
if (!prepareAddress(address, port, &localAddress))
{
close(self->fd);
self->fd = 0;
return false;
@ -777,7 +840,8 @@ UdpSocket_bind(UdpSocket self, const char* address, int port)
int result = bind(self->fd, (struct sockaddr*)&localAddress, sizeof(localAddress));
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to bind UDP socket (errno=%i)\n", errno);
@ -796,7 +860,8 @@ UdpSocket_sendTo(UdpSocket self, const char* address, int port, uint8_t* msg, in
// TODO add support for IPv6
struct sockaddr_in remoteAddress;
if (!prepareAddress(address, port, &remoteAddress)) {
if (!prepareAddress(address, port, &remoteAddress))
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to lookup remote address %s\n", address);
@ -806,14 +871,17 @@ UdpSocket_sendTo(UdpSocket self, const char* address, int port, uint8_t* msg, in
int result = sendto(self->fd, msg, msgSize, 0, (struct sockaddr*)&remoteAddress, sizeof(remoteAddress));
if (result == msgSize) {
if (result == msgSize)
{
return true;
}
else if (result == -1) {
else if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to send UDP message (errno=%i)\n", errno);
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to send UDP message (insufficient data sent)\n");
}
@ -831,23 +899,27 @@ UdpSocket_receiveFrom(UdpSocket self, char* address, int maxAddrSize, uint8_t* m
int result = recvfrom(self->fd, msg, msgSize, MSG_DONTWAIT, (struct sockaddr*)&remoteAddress, &structSize);
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to receive UDP message (errno=%i)\n", errno);
}
if (address) {
if (address)
{
bool isIPv6;
char addrString[INET6_ADDRSTRLEN + 7];
int port;
if (remoteAddress.ss_family == AF_INET) {
if (remoteAddress.ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)&remoteAddress;
port = ntohs(ipv4Addr->sin_port);
inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN);
isIPv6 = false;
}
else if (remoteAddress.ss_family == AF_INET6) {
else if (remoteAddress.ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)&remoteAddress;
port = ntohs(ipv6Addr->sin6_port);
inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN);
@ -862,18 +934,21 @@ UdpSocket_receiveFrom(UdpSocket self, char* address, int maxAddrSize, uint8_t* m
snprintf(address, maxAddrSize, "%s:%i", addrString, port);
}
if (address) {
if (address)
{
bool isIPv6;
char addrString[INET6_ADDRSTRLEN + 7];
int port;
if (remoteAddress.ss_family == AF_INET) {
if (remoteAddress.ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)&remoteAddress;
port = ntohs(ipv4Addr->sin_port);
inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN);
isIPv6 = false;
}
else if (remoteAddress.ss_family == AF_INET6) {
else if (remoteAddress.ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)&remoteAddress;
port = ntohs(ipv6Addr->sin6_port);
inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN);

@ -8,49 +8,52 @@
*/
#include "hal_socket.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <netinet/tcp.h> /* required for TCP keepalive */
#include <linux/version.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h> /* required for TCP keepalive */
#include <stdio.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define _GNU_SOURCE
#include <signal.h>
#include <poll.h>
#include <signal.h>
#include "linked_list.h"
#include "hal_thread.h"
#include "lib_memory.h"
#include "linked_list.h"
#ifndef DEBUG_SOCKET
#define DEBUG_SOCKET 0
#endif
struct sSocket {
struct sSocket
{
int fd;
uint32_t connectTimeout;
};
struct sServerSocket {
struct sServerSocket
{
int fd;
int backLog;
};
struct sUdpSocket {
struct sUdpSocket
{
int fd;
int namespace; /* IPv4: AF_INET; IPv6: AF_INET6 */
};
struct sHandleSet {
struct sHandleSet
{
LinkedList sockets;
bool pollfdIsUpdated;
struct pollfd* fds;
@ -62,7 +65,8 @@ Handleset_new(void)
{
HandleSet self = (HandleSet)GLOBAL_MALLOC(sizeof(struct sHandleSet));
if (self) {
if (self)
{
self->sockets = LinkedList_create();
self->pollfdIsUpdated = false;
self->fds = NULL;
@ -75,8 +79,10 @@ Handleset_new(void)
void
Handleset_reset(HandleSet self)
{
if (self) {
if (self->sockets) {
if (self)
{
if (self->sockets)
{
LinkedList_destroyStatic(self->sockets);
self->sockets = LinkedList_create();
self->pollfdIsUpdated = false;
@ -87,7 +93,8 @@ Handleset_reset(HandleSet self)
void
Handleset_addSocket(HandleSet self, const Socket sock)
{
if (self != NULL && sock != NULL && sock->fd != -1) {
if (self != NULL && sock != NULL && sock->fd != -1)
{
LinkedList_add(self->sockets, sock);
self->pollfdIsUpdated = false;
@ -97,7 +104,8 @@ Handleset_addSocket(HandleSet self, const Socket sock)
void
Handleset_removeSocket(HandleSet self, const Socket sock)
{
if (self && self->sockets && sock) {
if (self && self->sockets && sock)
{
LinkedList_remove(self->sockets, sock);
self->pollfdIsUpdated = false;
}
@ -107,8 +115,10 @@ int
Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
{
/* check if pollfd array is updated */
if (self->pollfdIsUpdated == false) {
if (self->fds) {
if (self->pollfdIsUpdated == false)
{
if (self->fds)
{
GLOBAL_FREEMEM(self->fds);
self->fds = NULL;
}
@ -119,13 +129,16 @@ Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
int i;
for (i = 0; i < self->nfds; i++) {
for (i = 0; i < self->nfds; i++)
{
LinkedList sockElem = LinkedList_get(self->sockets, i);
if (sockElem) {
if (sockElem)
{
Socket sock = (Socket)LinkedList_getData(sockElem);
if (sock) {
if (sock)
{
self->fds[i].fd = sock->fd;
self->fds[i].events = POLL_IN;
}
@ -135,21 +148,25 @@ Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
self->pollfdIsUpdated = true;
}
if (self->fds && self->nfds > 0) {
if (self->fds && self->nfds > 0)
{
int result = poll(self->fds, self->nfds, timeoutMs);
if (result == -1 && errno == EINTR) {
if (result == -1 && errno == EINTR)
{
result = 0;
}
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: poll error (errno: %i)\n", errno);
}
return result;
}
else {
else
{
/* there is no socket to wait for */
return 0;
}
@ -158,7 +175,8 @@ Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
void
Handleset_destroy(HandleSet self)
{
if (self) {
if (self)
{
if (self->sockets)
LinkedList_destroyStatic(self->sockets);
@ -178,26 +196,30 @@ Socket_activateTcpKeepAlive(Socket self, int idleTime, int interval, int count)
optval = 1;
if (setsockopt(self->fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen)) {
if (setsockopt(self->fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen))
{
if (DEBUG_SOCKET)
printf("SOCKET: Failed to enable TCP keepalive\n");
}
#if defined TCP_KEEPCNT
optval = idleTime;
if (setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen)) {
if (setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen))
{
if (DEBUG_SOCKET)
printf("SOCKET: Failed to set TCP keepalive TCP_KEEPIDLE parameter\n");
}
optval = interval;
if (setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen)) {
if (setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen))
{
if (DEBUG_SOCKET)
printf("SOCKET: Failed to set TCP keepalive TCP_KEEPINTVL parameter\n");
}
optval = count;
if (setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen)) {
if (setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen))
{
if (DEBUG_SOCKET)
printf("SOCKET: Failed to set TCP keepalive TCP_KEEPCNT parameter\n");
}
@ -213,7 +235,8 @@ prepareAddress(const char* address, int port, struct sockaddr_in* sockaddr)
memset((char*)sockaddr, 0, sizeof(struct sockaddr_in));
if (address != NULL) {
if (address != NULL)
{
struct addrinfo addressHints;
struct addrinfo* lookupResult;
int result;
@ -222,7 +245,8 @@ prepareAddress(const char* address, int port, struct sockaddr_in* sockaddr)
addressHints.ai_family = AF_INET;
result = getaddrinfo(address, NULL, &addressHints, &lookupResult);
if (result != 0) {
if (result != 0)
{
if (DEBUG_SOCKET)
printf("SOCKET: getaddrinfo failed (code=%i)\n", result);
@ -270,10 +294,12 @@ TcpServerSocket_create(const char* address, int port)
int fd;
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) >= 0) {
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) >= 0)
{
struct sockaddr_in serverAddress;
if (!prepareAddress(address, port, &serverAddress)) {
if (!prepareAddress(address, port, &serverAddress))
{
close(fd);
return NULL;
}
@ -285,7 +311,8 @@ TcpServerSocket_create(const char* address, int port)
int tcpUserTimeout = 10000;
int result = setsockopt(fd, SOL_TCP, TCP_USER_TIMEOUT, &tcpUserTimeout, sizeof(tcpUserTimeout));
if (result < 0) {
if (result < 0)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to set TCP_USER_TIMEOUT\n");
}
@ -293,14 +320,16 @@ TcpServerSocket_create(const char* address, int port)
#warning "TCP_USER_TIMEOUT not supported by linux kernel"
#endif
if (bind(fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) >= 0) {
if (bind(fd, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) >= 0)
{
serverSocket = (ServerSocket)GLOBAL_MALLOC(sizeof(struct sServerSocket));
serverSocket->fd = fd;
serverSocket->backLog = 2;
setSocketNonBlocking((Socket)serverSocket);
}
else {
else
{
close(fd);
return NULL;
}
@ -312,7 +341,8 @@ TcpServerSocket_create(const char* address, int port)
void
ServerSocket_listen(ServerSocket self)
{
if (listen(self->fd, self->backLog) == -1) {
if (listen(self->fd, self->backLog) == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: listen failed (errno: %i)\n", errno);
}
@ -328,17 +358,20 @@ ServerSocket_accept(ServerSocket self)
fd = accept(self->fd, NULL, NULL);
if (fd >= 0) {
if (fd >= 0)
{
conSocket = (Socket)GLOBAL_CALLOC(1, sizeof(struct sSocket));
if (conSocket) {
if (conSocket)
{
conSocket->fd = fd;
setSocketNonBlocking(conSocket);
activateTcpNoDelay(conSocket);
}
else {
else
{
/* out of memory */
close(fd);
@ -346,7 +379,8 @@ ServerSocket_accept(ServerSocket self)
printf("SOCKET: out of memory\n");
}
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: accept failed (errno=%i)\n", errno);
}
@ -363,7 +397,8 @@ ServerSocket_setBacklog(ServerSocket self, int backlog)
static void
closeAndShutdownSocket(int socketFd)
{
if (socketFd != -1) {
if (socketFd != -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: call shutdown for %i!\n", socketFd);
@ -371,14 +406,16 @@ closeAndShutdownSocket(int socketFd)
/* shutdown is required to unblock read or accept in another thread! */
int result = shutdown(socketFd, SHUT_RDWR);
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: shutdown error: %i\n", errno);
}
result = close(socketFd);
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: close error: %i\n", errno);
}
@ -406,10 +443,12 @@ TcpSocket_create()
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock != -1) {
if (sock != -1)
{
self = (Socket)GLOBAL_MALLOC(sizeof(struct sSocket));
if (self) {
if (self)
{
self->fd = sock;
self->connectTimeout = 5000;
@ -417,13 +456,15 @@ TcpSocket_create()
int tcpUserTimeout = 10000;
int result = setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT, &tcpUserTimeout, sizeof(tcpUserTimeout));
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to set TCP_USER_TIMEOUT (errno=%i)\n", errno);
}
#endif
}
else {
else
{
/* out of memory */
close(sock);
@ -431,7 +472,8 @@ TcpSocket_create()
printf("SOCKET: out of memory\n");
}
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to create socket (errno=%i)\n", errno);
}
@ -455,7 +497,8 @@ Socket_bind(Socket self, const char* srcAddress, int srcPort)
int result = bind(self->fd, (struct sockaddr*)&localAddress, sizeof(localAddress));
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to bind TCP socket (errno=%i)\n", errno);
@ -483,10 +526,13 @@ Socket_connectAsync(Socket self, const char* address, int port)
fcntl(self->fd, F_SETFL, O_NONBLOCK);
if (connect(self->fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0) {
if (connect(self->fd, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0)
{
if (errno != EINPROGRESS) {
if (close(self->fd) == -1) {
if (errno != EINPROGRESS)
{
if (close(self->fd) == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to close socket (errno: %i)\n", errno);
}
@ -509,14 +555,16 @@ Socket_checkAsyncConnectState(Socket self)
int result = poll(fds, 1, 0);
if (result == 1) {
if (result == 1)
{
/* Check if connection is established */
int so_error;
socklen_t len = sizeof so_error;
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len) >= 0) {
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len) >= 0)
{
if (so_error == 0)
return SOCKET_STATE_CONNECTED;
@ -524,10 +572,12 @@ Socket_checkAsyncConnectState(Socket self)
return SOCKET_STATE_FAILED;
}
else if (result == 0) {
else if (result == 0)
{
return SOCKET_STATE_CONNECTING;
}
else {
else
{
return SOCKET_STATE_FAILED;
}
}
@ -545,14 +595,16 @@ Socket_connect(Socket self, const char* address, int port)
int result = poll(fds, 1, self->connectTimeout);
if (result == 1) {
if (result == 1)
{
/* Check if connection is established */
int so_error;
socklen_t len = sizeof so_error;
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len) >= 0) {
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len) >= 0)
{
if (so_error == 0)
return true;
@ -573,13 +625,15 @@ convertAddressToStr(struct sockaddr_storage* addr)
bool isIPv6;
if (addr->ss_family == AF_INET) {
if (addr->ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)addr;
port = ntohs(ipv4Addr->sin_port);
inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN);
isIPv6 = false;
}
else if (addr->ss_family == AF_INET6) {
else if (addr->ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)addr;
port = ntohs(ipv6Addr->sin6_port);
inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN);
@ -604,7 +658,8 @@ Socket_getPeerAddress(Socket self)
struct sockaddr_storage addr;
socklen_t addrLen = sizeof(addr);
if (getpeername(self->fd, (struct sockaddr*) &addr, &addrLen) == 0) {
if (getpeername(self->fd, (struct sockaddr*)&addr, &addrLen) == 0)
{
return convertAddressToStr(&addr);
}
else
@ -617,7 +672,8 @@ Socket_getLocalAddress(Socket self)
struct sockaddr_storage addr;
socklen_t addrLen = sizeof(addr);
if (getsockname(self->fd, (struct sockaddr*) &addr, &addrLen) == 0) {
if (getsockname(self->fd, (struct sockaddr*)&addr, &addrLen) == 0)
{
return convertAddressToStr(&addr);
}
else
@ -629,21 +685,30 @@ Socket_getPeerAddressStatic(Socket self, char* peerAddressString)
{
struct sockaddr_storage addr;
socklen_t addrLen = sizeof(addr);
memset(&addr, 0, sizeof(addr));
if (getpeername(self->fd, (struct sockaddr*)&addr, &addrLen) == -1)
{
if (DEBUG_SOCKET)
printf("DEBUG_SOCKET: getpeername -> errno: %i\n", errno);
getpeername(self->fd, (struct sockaddr*) &addr, &addrLen);
return NULL;
}
char addrString[INET6_ADDRSTRLEN + 7];
int port;
bool isIPv6;
if (addr.ss_family == AF_INET) {
if (addr.ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)&addr;
port = ntohs(ipv4Addr->sin_port);
inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN);
isIPv6 = false;
}
else if (addr.ss_family == AF_INET6) {
else if (addr.ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)&addr;
port = ntohs(ipv6Addr->sin6_port);
inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN);
@ -671,10 +736,12 @@ Socket_read(Socket self, uint8_t* buf, int size)
if (read_bytes == 0)
return -1;
if (read_bytes == -1) {
if (read_bytes == -1)
{
int error = errno;
switch (error) {
switch (error)
{
case EAGAIN:
return 0;
@ -702,11 +769,14 @@ Socket_write(Socket self, uint8_t* buf, int size)
/* MSG_NOSIGNAL - prevent send to signal SIGPIPE when peer unexpectedly closed the socket */
int retVal = send(self->fd, buf, size, MSG_NOSIGNAL | MSG_DONTWAIT);
if (retVal == -1) {
if (errno == EAGAIN) {
if (retVal == -1)
{
if (errno == EAGAIN)
{
return 0;
}
else {
else
{
if (DEBUG_SOCKET)
printf("DEBUG_SOCKET: send returned error (errno=%i)\n", errno);
}
@ -736,21 +806,25 @@ UdpSocket_createUsingNamespace(int namespace)
int sock = socket(namespace, SOCK_DGRAM, IPPROTO_UDP);
if (sock != -1) {
if (sock != -1)
{
self = (UdpSocket)GLOBAL_MALLOC(sizeof(struct sSocket));
if (self) {
if (self)
{
self->fd = sock;
self->namespace = namespace;
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to allocate memory\n");
close(sock);
}
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to create UDP socket (errno=%i)\n", errno);
}
@ -773,36 +847,42 @@ UdpSocket_createIpV6()
bool
UdpSocket_addGroupMembership(UdpSocket self, const char* multicastAddress)
{
if (self->namespace == AF_INET) {
if (self->namespace == AF_INET)
{
struct ip_mreq mreq;
if (!inet_aton(multicastAddress, &(mreq.imr_multiaddr))) {
if (!inet_aton(multicastAddress, &(mreq.imr_multiaddr)))
{
printf("SOCKET: Invalid IPv4 multicast address\n");
return false;
}
else {
else
{
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(self->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
if (setsockopt(self->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1)
{
printf("SOCKET: failed to set IPv4 multicast group (errno: %i)\n", errno);
return false;
}
}
return true;
}
else if (self->namespace == AF_INET6) {
else if (self->namespace == AF_INET6)
{
struct ipv6_mreq mreq;
if (inet_pton(AF_INET6, multicastAddress, &(mreq.ipv6mr_multiaddr)) < 1) {
if (inet_pton(AF_INET6, multicastAddress, &(mreq.ipv6mr_multiaddr)) < 1)
{
printf("SOCKET: failed to set IPv6 multicast group (errno: %i)\n", errno);
return false;
}
mreq.ipv6mr_interface = 0;
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1)
{
printf("SOCKET: failed to set IPv6 multicast group (errno: %i)\n", errno);
return false;
}
@ -816,16 +896,20 @@ UdpSocket_addGroupMembership(UdpSocket self, const char* multicastAddress)
bool
UdpSocket_setMulticastTtl(UdpSocket self, int ttl)
{
if (self->namespace == AF_INET) {
if (setsockopt(self->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == -1) {
if (self->namespace == AF_INET)
{
if (setsockopt(self->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == -1)
{
printf("SOCKET: failed to set IPv4 multicast TTL (errno: %i)\n", errno);
return false;
}
return true;
}
else if (self->namespace == AF_INET6) {
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) == -1) {
else if (self->namespace == AF_INET6)
{
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) == -1)
{
printf("SOCKET: failed to set IPv6 multicast TTL(hops) (errno: %i)\n", errno);
return false;
}
@ -842,7 +926,8 @@ UdpSocket_bind(UdpSocket self, const char* address, int port)
// TODO add support for IPv6
struct sockaddr_in localAddress;
if (!prepareAddress(address, port, &localAddress)) {
if (!prepareAddress(address, port, &localAddress))
{
close(self->fd);
self->fd = 0;
return false;
@ -850,7 +935,8 @@ UdpSocket_bind(UdpSocket self, const char* address, int port)
int result = bind(self->fd, (struct sockaddr*)&localAddress, sizeof(localAddress));
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to bind UDP socket (errno=%i)\n", errno);
@ -869,7 +955,8 @@ UdpSocket_sendTo(UdpSocket self, const char* address, int port, uint8_t* msg, in
// TODO add support for IPv6
struct sockaddr_in remoteAddress;
if (!prepareAddress(address, port, &remoteAddress)) {
if (!prepareAddress(address, port, &remoteAddress))
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to lookup remote address %s\n", address);
@ -879,14 +966,17 @@ UdpSocket_sendTo(UdpSocket self, const char* address, int port, uint8_t* msg, in
int result = sendto(self->fd, msg, msgSize, 0, (struct sockaddr*)&remoteAddress, sizeof(remoteAddress));
if (result == msgSize) {
if (result == msgSize)
{
return true;
}
else if (result == -1) {
else if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to send UDP message (errno=%i)\n", errno);
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to send UDP message (insufficient data sent)\n");
}
@ -904,23 +994,27 @@ UdpSocket_receiveFrom(UdpSocket self, char* address, int maxAddrSize, uint8_t* m
int result = recvfrom(self->fd, msg, msgSize, MSG_DONTWAIT, (struct sockaddr*)&remoteAddress, &structSize);
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to receive UDP message (errno=%i)\n", errno);
}
if (address) {
if (address)
{
bool isIPv6;
char addrString[INET6_ADDRSTRLEN + 7];
int port;
if (remoteAddress.ss_family == AF_INET) {
if (remoteAddress.ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)&remoteAddress;
port = ntohs(ipv4Addr->sin_port);
inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN);
isIPv6 = false;
}
else if (remoteAddress.ss_family == AF_INET6) {
else if (remoteAddress.ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)&remoteAddress;
port = ntohs(ipv6Addr->sin6_port);
inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN);

@ -1,7 +1,7 @@
/*
* socket_win32.c
*
* Copyright 2013-2021 Michael Zillgith
* Copyright 2013-2024 Michael Zillgith
*
* This file is part of Platform Abstraction Layer (libpal)
* for libiec61850, libmms, and lib60870.
@ -9,6 +9,7 @@
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
@ -17,14 +18,16 @@
#pragma comment(lib, "Ws2_32.lib")
#include "lib_memory.h"
#include "hal_socket.h"
#include "stack_config.h"
#include "lib_memory.h"
#define DEBUG_SOCKET 1
#ifndef DEBUG_SOCKET
#define DEBUG_SOCKET 0
#endif
#ifndef __MINGW64_VERSION_MAJOR
struct tcp_keepalive {
struct tcp_keepalive
{
u_long onoff;
u_long keepalivetime;
u_long keepaliveinterval;
@ -33,22 +36,26 @@ struct tcp_keepalive {
#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR, 4)
struct sSocket {
struct sSocket
{
SOCKET fd;
uint32_t connectTimeout;
};
struct sServerSocket {
struct sServerSocket
{
SOCKET fd;
int backLog;
};
struct sHandleSet {
struct sHandleSet
{
fd_set handles;
SOCKET maxHandle;
};
struct sUdpSocket {
struct sUdpSocket
{
SOCKET fd;
int ns; /* IPv4: AF_INET; IPv6: AF_INET6 */
};
@ -58,7 +65,8 @@ Handleset_new(void)
{
HandleSet result = (HandleSet)GLOBAL_MALLOC(sizeof(struct sHandleSet));
if (result != NULL) {
if (result != NULL)
{
FD_ZERO(&result->handles);
result->maxHandle = INVALID_SOCKET;
}
@ -76,7 +84,8 @@ Handleset_reset(HandleSet self)
void
Handleset_addSocket(HandleSet self, const Socket sock)
{
if (self != NULL && sock != NULL && sock->fd != INVALID_SOCKET) {
if (self != NULL && sock != NULL && sock->fd != INVALID_SOCKET)
{
FD_SET(sock->fd, &self->handles);
@ -88,7 +97,8 @@ Handleset_addSocket(HandleSet self, const Socket sock)
void
Handleset_removeSocket(HandleSet self, const Socket sock)
{
if (self != NULL && sock != NULL && sock->fd != INVALID_SOCKET) {
if (self != NULL && sock != NULL && sock->fd != INVALID_SOCKET)
{
FD_CLR(sock->fd, &self->handles);
}
}
@ -98,7 +108,8 @@ Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
{
int result;
if ((self != NULL) && (self->maxHandle != INVALID_SOCKET)) {
if ((self != NULL) && (self->maxHandle != INVALID_SOCKET))
{
struct timeval timeout;
timeout.tv_sec = timeoutMs / 1000;
@ -109,7 +120,9 @@ Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
memcpy((void*)&handles, &(self->handles), sizeof(fd_set));
result = select(self->maxHandle + 1, &handles, NULL, NULL, &timeout);
} else {
}
else
{
result = -1;
}
@ -137,21 +150,20 @@ Socket_activateTcpKeepAlive(Socket self, int idleTime, int interval, int count)
keepalive.keepalivetime = idleTime * 1000;
keepalive.keepaliveinterval = interval * 1000;
if (WSAIoctl(self->fd, SIO_KEEPALIVE_VALS, &keepalive, sizeof(keepalive),
NULL, 0, &retVal, NULL, NULL) == SOCKET_ERROR)
if (WSAIoctl(self->fd, SIO_KEEPALIVE_VALS, &keepalive, sizeof(keepalive), NULL, 0, &retVal, NULL, NULL) ==
SOCKET_ERROR)
{
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: WSAIotcl(SIO_KEEPALIVE_VALS) failed: %d\n",
WSAGetLastError());
printf("WIN32_SOCKET: WSAIotcl(SIO_KEEPALIVE_VALS) failed: %d\n", WSAGetLastError());
}
}
static void
setSocketNonBlocking(Socket self)
{
unsigned long mode = 1;
if (ioctlsocket(self->fd, FIONBIO, &mode) != 0) {
if (ioctlsocket(self->fd, FIONBIO, &mode) != 0)
{
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: failed to set socket non-blocking!\n");
}
@ -168,7 +180,8 @@ prepareAddress(const char *address, int port, struct sockaddr_in *sockaddr)
{
memset((char*)sockaddr, 0, sizeof(struct sockaddr_in));
if (address != NULL) {
if (address != NULL)
{
struct hostent* server;
server = gethostbyname(address);
@ -189,20 +202,22 @@ prepareAddress(const char *address, int port, struct sockaddr_in *sockaddr)
static bool
wsaStartUp(void)
{
if (wsaStartupCalled == false) {
if (wsaStartupCalled == false)
{
int ec;
WSADATA wsa;
if ((ec = WSAStartup(MAKEWORD(2, 0), &wsa)) != 0) {
if ((ec = WSAStartup(MAKEWORD(2, 0), &wsa)) != 0)
{
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: winsock error: code %i\n", ec);
return false;
}
else {
else
{
wsaStartupCalled = true;
return true;
}
}
else
return true;
@ -211,12 +226,13 @@ wsaStartUp(void)
static void
wsaShutdown(void)
{
if (wsaStartupCalled) {
if (socketCount == 0) {
if (wsaStartupCalled)
{
if (socketCount == 0)
{
WSACleanup();
wsaStartupCalled = false;
}
}
}
@ -237,7 +253,8 @@ TcpServerSocket_create(const char* address, int port)
listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listen_socket == INVALID_SOCKET) {
if (listen_socket == INVALID_SOCKET)
{
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: socket failed with error: %i\n", WSAGetLastError());
@ -251,7 +268,8 @@ TcpServerSocket_create(const char* address, int port)
ec = bind(listen_socket, (struct sockaddr*)&server_addr, sizeof(server_addr));
if (ec == SOCKET_ERROR) {
if (ec == SOCKET_ERROR)
{
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: bind failed with error:%i\n", WSAGetLastError());
closesocket(listen_socket);
@ -263,7 +281,8 @@ TcpServerSocket_create(const char* address, int port)
serverSocket = (ServerSocket)GLOBAL_MALLOC(sizeof(struct sServerSocket));
if (serverSocket) {
if (serverSocket)
{
serverSocket->fd = listen_socket;
serverSocket->backLog = 10;
@ -271,7 +290,8 @@ TcpServerSocket_create(const char* address, int port)
socketCount++;
}
else {
else
{
closesocket(listen_socket);
wsaShutdown();
}
@ -292,7 +312,8 @@ ServerSocket_accept(ServerSocket self)
SOCKET fd = accept(self->fd, NULL, NULL);
if (fd != INVALID_SOCKET) {
if (fd != INVALID_SOCKET)
{
conSocket = (Socket)GLOBAL_CALLOC(1, sizeof(struct sSocket));
conSocket->fd = fd;
@ -303,7 +324,8 @@ ServerSocket_accept(ServerSocket self)
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: connection accepted\n");
}
else {
else
{
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: accept failed\n");
}
@ -320,7 +342,8 @@ ServerSocket_setBacklog(ServerSocket self, int backlog)
void
ServerSocket_destroy(ServerSocket self)
{
if (self->fd != INVALID_SOCKET) {
if (self->fd != INVALID_SOCKET)
{
shutdown(self->fd, 2);
closesocket(self->fd);
socketCount--;
@ -341,25 +364,28 @@ TcpSocket_create()
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock != INVALID_SOCKET) {
if (sock != INVALID_SOCKET)
{
self = (Socket)GLOBAL_MALLOC(sizeof(struct sSocket));
if (self) {
if (self)
{
self->fd = sock;
self->connectTimeout = 5000;
socketCount++;
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to create socket - cannot allocate memory\n");
closesocket(sock);
wsaShutdown();
}
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to create socket (error code=%i)\n", WSAGetLastError());
}
@ -383,7 +409,8 @@ Socket_bind(Socket self, const char* srcAddress, int srcPort)
int result = bind(self->fd, (struct sockaddr*)&localAddress, sizeof(localAddress));
if (result == SOCKET_ERROR) {
if (result == SOCKET_ERROR)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to bind TCP socket (errno=%i)\n", WSAGetLastError());
@ -403,22 +430,19 @@ Socket_connectAsync(Socket self, const char* address, int port)
printf("WIN32_SOCKET: Socket_connect: %s:%i\n", address, port);
struct sockaddr_in serverAddress;
WSADATA wsa;
int ec;
if ((ec = WSAStartup(MAKEWORD(2,0), &wsa)) != 0) {
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: winsock error: code %i\n", ec);
if (wsaStartUp() == false)
return false;
}
if (!prepareAddress(address, port, &serverAddress))
return false;
setSocketNonBlocking(self);
if (connect(self->fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) == SOCKET_ERROR) {
if (WSAGetLastError() != WSAEWOULDBLOCK) {
if (connect(self->fd, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
closesocket(self->fd);
self->fd = INVALID_SOCKET;
return false;
@ -441,19 +465,23 @@ Socket_checkAsyncConnectState(Socket self)
int selectVal = select(self->fd + 1, NULL, &fdSet, NULL, &timeout);
if (selectVal == 1) {
if (selectVal == 1)
{
/* Check if connection is established */
int so_error;
int len = sizeof so_error;
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, (char*) (&so_error), &len) != SOCKET_ERROR) {
if (so_error == 0) {
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, (char*)(&so_error), &len) != SOCKET_ERROR)
{
if (so_error == 0)
{
int recvRes = recv(self->fd, NULL, 0, 0);
if (recvRes == SOCKET_ERROR) {
if (recvRes == SOCKET_ERROR)
{
int wsaError = WSAGetLastError();
if (wsaError == WSAECONNRESET)
@ -463,17 +491,18 @@ Socket_checkAsyncConnectState(Socket self)
return SOCKET_STATE_FAILED;
}
return SOCKET_STATE_CONNECTED;
}
}
return SOCKET_STATE_FAILED;
}
else if (selectVal == 0) {
else if (selectVal == 0)
{
return SOCKET_STATE_CONNECTING;
}
else {
else
{
return SOCKET_STATE_FAILED;
}
}
@ -492,14 +521,16 @@ Socket_connect(Socket self, const char* address, int port)
FD_ZERO(&fdSet);
FD_SET(self->fd, &fdSet);
if (select(self->fd + 1, NULL, &fdSet , NULL, &timeout) == 1) {
if (select(self->fd + 1, NULL, &fdSet, NULL, &timeout) == 1)
{
/* Check if connection is established */
int so_error;
socklen_t len = sizeof so_error;
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, (char*)&so_error, &len) >= 0) {
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, (char*)&so_error, &len) >= 0)
{
if (so_error == 0)
return true;
@ -521,20 +552,22 @@ convertAddressToStr(struct sockaddr_storage* addr)
bool isIPv6;
if (addr->ss_family == AF_INET) {
if (addr->ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)addr;
port = ntohs(ipv4Addr->sin_port);
ipv4Addr->sin_port = 0;
WSAAddressToString((LPSOCKADDR) ipv4Addr, sizeof(struct sockaddr_storage), NULL,
(LPSTR) addrString, (LPDWORD) &addrStringLen);
WSAAddressToString((LPSOCKADDR)ipv4Addr, sizeof(struct sockaddr_storage), NULL, (LPSTR)addrString,
(LPDWORD)&addrStringLen);
isIPv6 = false;
}
else if (addr->ss_family == AF_INET6){
else if (addr->ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)addr;
port = ntohs(ipv6Addr->sin6_port);
ipv6Addr->sin6_port = 0;
WSAAddressToString((LPSOCKADDR) ipv6Addr, sizeof(struct sockaddr_storage), NULL,
(LPSTR) addrString, (LPDWORD) &addrStringLen);
WSAAddressToString((LPSOCKADDR)ipv6Addr, sizeof(struct sockaddr_storage), NULL, (LPSTR)addrString,
(LPDWORD)&addrStringLen);
isIPv6 = true;
}
else
@ -550,14 +583,14 @@ convertAddressToStr(struct sockaddr_storage* addr)
return clientConnection;
}
char*
Socket_getPeerAddress(Socket self)
{
struct sockaddr_storage addr;
socklen_t addrLen = sizeof(addr);
if (getpeername(self->fd, (struct sockaddr*) &addr, &addrLen) == 0) {
if (getpeername(self->fd, (struct sockaddr*)&addr, &addrLen) == 0)
{
return convertAddressToStr(&addr);
}
else
@ -570,7 +603,8 @@ Socket_getLocalAddress(Socket self)
struct sockaddr_storage addr;
socklen_t addrLen = sizeof(addr);
if (getsockname(self->fd, (struct sockaddr*) &addr, &addrLen) == 0) {
if (getsockname(self->fd, (struct sockaddr*)&addr, &addrLen) == 0)
{
return convertAddressToStr(&addr);
}
else
@ -591,20 +625,22 @@ Socket_getPeerAddressStatic(Socket self, char* peerAddressString)
bool isIPv6;
if (addr.ss_family == AF_INET) {
if (addr.ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)&addr;
port = ntohs(ipv4Addr->sin_port);
ipv4Addr->sin_port = 0;
WSAAddressToString((LPSOCKADDR) ipv4Addr, sizeof(struct sockaddr_storage), NULL,
(LPSTR) addrString, (LPDWORD) & addrStringLen);
WSAAddressToString((LPSOCKADDR)ipv4Addr, sizeof(struct sockaddr_storage), NULL, (LPSTR)addrString,
(LPDWORD)&addrStringLen);
isIPv6 = false;
}
else if (addr.ss_family == AF_INET6) {
else if (addr.ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)&addr;
port = ntohs(ipv6Addr->sin6_port);
ipv6Addr->sin6_port = 0;
WSAAddressToString((LPSOCKADDR) ipv6Addr, sizeof(struct sockaddr_storage), NULL,
(LPSTR) addrString, (LPDWORD) & addrStringLen);
WSAAddressToString((LPSOCKADDR)ipv6Addr, sizeof(struct sockaddr_storage), NULL, (LPSTR)addrString,
(LPDWORD)&addrStringLen);
isIPv6 = true;
}
else
@ -626,7 +662,8 @@ Socket_read(Socket self, uint8_t* buf, int size)
if (bytes_read == 0) /* peer has closed socket */
return -1;
if (bytes_read == SOCKET_ERROR) {
if (bytes_read == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
return 0;
else
@ -641,7 +678,8 @@ Socket_write(Socket self, uint8_t* buf, int size)
{
int bytes_sent = send(self->fd, (char*)buf, size, 0);
if (bytes_sent == SOCKET_ERROR) {
if (bytes_sent == SOCKET_ERROR)
{
int errorCode = WSAGetLastError();
if (errorCode == WSAEWOULDBLOCK)
@ -656,7 +694,8 @@ Socket_write(Socket self, uint8_t* buf, int size)
void
Socket_destroy(Socket self)
{
if (self->fd != INVALID_SOCKET) {
if (self->fd != INVALID_SOCKET)
{
shutdown(self->fd, 2);
closesocket(self->fd);
@ -680,21 +719,25 @@ UdpSocket_createUsingNamespace(int ns)
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock != INVALID_SOCKET) {
if (sock != INVALID_SOCKET)
{
self = (UdpSocket)GLOBAL_MALLOC(sizeof(struct sSocket));
if (self) {
if (self)
{
self->fd = sock;
self->ns = ns;
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to allocate memory\n");
closesocket(sock);
}
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to create UDP socket (errno=%i)\n", WSAGetLastError());
}
@ -717,36 +760,42 @@ UdpSocket_createIpV6()
bool
UdpSocket_addGroupMembership(UdpSocket self, const char* multicastAddress)
{
if (self->ns == AF_INET) {
if (self->ns == AF_INET)
{
struct ip_mreq mreq;
if (inet_pton(AF_INET, multicastAddress, &(mreq.imr_multiaddr)) < 1) {
if (inet_pton(AF_INET, multicastAddress, &(mreq.imr_multiaddr)) < 1)
{
printf("SOCKET: Invalid IPv4 multicast address\n");
return false;
}
else {
else
{
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(self->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) == -1) {
if (setsockopt(self->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) == -1)
{
printf("SOCKET: failed to set IPv4 multicast group (errno: %i)\n", WSAGetLastError());
return false;
}
}
return true;
}
else if (self->ns == AF_INET6) {
else if (self->ns == AF_INET6)
{
struct ipv6_mreq mreq;
if (inet_pton(AF_INET6, multicastAddress, &(mreq.ipv6mr_multiaddr)) < 1) {
if (inet_pton(AF_INET6, multicastAddress, &(mreq.ipv6mr_multiaddr)) < 1)
{
printf("SOCKET: failed to set IPv6 multicast group (errno: %i)\n", WSAGetLastError());
return false;
}
mreq.ipv6mr_interface = 0;
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) == -1) {
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) == -1)
{
printf("SOCKET: failed to set IPv6 multicast group (errno: %i)\n", WSAGetLastError());
return false;
}
@ -760,16 +809,20 @@ UdpSocket_addGroupMembership(UdpSocket self, const char* multicastAddress)
bool
UdpSocket_setMulticastTtl(UdpSocket self, int ttl)
{
if (self->ns == AF_INET) {
if (setsockopt(self->fd, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, sizeof(ttl)) == -1) {
if (self->ns == AF_INET)
{
if (setsockopt(self->fd, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, sizeof(ttl)) == -1)
{
printf("SOCKET: failed to set IPv4 multicast TTL (errno: %i)\n", WSAGetLastError());
return false;
}
return true;
}
else if (self->ns == AF_INET6) {
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char*)&ttl, sizeof(ttl)) == -1) {
else if (self->ns == AF_INET6)
{
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char*)&ttl, sizeof(ttl)) == -1)
{
printf("SOCKET: failed to set IPv6 multicast TTL(hops) (errno: %i)\n", WSAGetLastError());
return false;
}
@ -786,7 +839,8 @@ UdpSocket_bind(UdpSocket self, const char* address, int port)
// TODO add support for IPv6
struct sockaddr_in localAddress;
if (!prepareAddress(address, port, &localAddress)) {
if (!prepareAddress(address, port, &localAddress))
{
closesocket(self->fd);
self->fd = 0;
return false;
@ -794,7 +848,8 @@ UdpSocket_bind(UdpSocket self, const char* address, int port)
int result = bind(self->fd, (struct sockaddr*)&localAddress, sizeof(localAddress));
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to bind UDP socket (errno=%i)\n", errno);
@ -813,7 +868,8 @@ UdpSocket_sendTo(UdpSocket self, const char* address, int port, uint8_t* msg, in
// TODO add support for IPv6
struct sockaddr_in remoteAddress;
if (!prepareAddress(address, port, &remoteAddress)) {
if (!prepareAddress(address, port, &remoteAddress))
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to lookup remote address %s\n", address);
@ -821,16 +877,20 @@ UdpSocket_sendTo(UdpSocket self, const char* address, int port, uint8_t* msg, in
return false;
}
int result = sendto(self->fd, (const char*) msg, msgSize, 0, (struct sockaddr*)&remoteAddress, sizeof(remoteAddress));
int result =
sendto(self->fd, (const char*)msg, msgSize, 0, (struct sockaddr*)&remoteAddress, sizeof(remoteAddress));
if (result == msgSize) {
if (result == msgSize)
{
return true;
}
else if (result == -1) {
else if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to send UDP message (errno=%i)\n", errno);
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to send UDP message (insufficient data sent)\n");
}
@ -854,25 +914,29 @@ UdpSocket_receiveFrom(UdpSocket self, char* address, int maxAddrSize, uint8_t* m
if (result == 0) /* peer has closed socket */
return -1;
if (result == SOCKET_ERROR) {
if (result == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
return 0;
else
return -1;
}
if (address) {
if (address)
{
bool isIPv6;
char addrString[INET6_ADDRSTRLEN + 7];
int port;
if (remoteAddress.ss_family == AF_INET) {
if (remoteAddress.ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)&remoteAddress;
port = ntohs(ipv4Addr->sin_port);
inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN);
isIPv6 = false;
}
else if (remoteAddress.ss_family == AF_INET6) {
else if (remoteAddress.ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)&remoteAddress;
port = ntohs(ipv6Addr->sin6_port);
inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN);

@ -1,7 +1,7 @@
/*
* time.c
*
* Copyright 2013-2021 Michael Zillgith
* Copyright 2013-2024 Michael Zillgith
*
* This file is part of Platform Abstraction Layer (libpal)
* for libiec61850, libmms, and lib60870.
@ -62,4 +62,36 @@ Hal_setTimeInNs(nsSinceEpoch nsTime)
return true;
}
msSinceEpoch
Hal_getMonotonicTimeInMs()
{
uint64_t timeVal = 0;
struct timespec ts;
if (clock_gettime (CLOCK_MONOTONIC, &ts) == 0)
{
timeVal = ((uint64_t)ts.tv_sec * 1000LL) + (ts.tv_nsec / 1000000);
}
return timeVal;
}
nsSinceEpoch
Hal_getMonotonicTimeInNs()
{
uint64_t nsTime = 0;
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
{
nsTime = ts.tv_sec * 1000000000UL;
nsTime += ts.tv_nsec;
}
return nsTime;
}
#endif

@ -1,7 +1,7 @@
/*
* time.c
*
* Copyright 2013-2021 Michael Zillgith
* Copyright 2013-2024 Michael Zillgith
*
* This file is part of Platform Abstraction Layer (libpal)
* for libiec61850, libmms, and lib60870.
@ -59,3 +59,14 @@ Hal_setTimeInNs(nsSinceEpoch nsTime)
return SetSystemTime(&st);
}
msSinceEpoch
Hal_getMonotonicTimeInMs()
{
return (msSinceEpoch)GetTickCount64;
}
nsSinceEpoch
Hal_getMonotonicTimeInNs()
{
return (nsSinceEpoch)(GetTickCount64() * 1000000ULL);
}

@ -11,23 +11,21 @@
#include <string.h>
#include "tls_socket.h"
#include "hal_thread.h"
#include "lib_memory.h"
#include "hal_time.h"
#include "lib_memory.h"
#include "linked_list.h"
#include "tls_socket.h"
#include "mbedtls/platform.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
// MIGRATE 2.28->3.x.x: https://github.com/Mbed-TLS/mbedtls/blob/development/docs/3.0-migration-guide.md#remove-the-certs-module-from-the-library
// #include "mbedtls/certs.h" (MIGRATE 2.28->3.x.x)
#include "mbedtls/x509.h"
#include "mbedtls/ssl.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/error.h"
#include "mbedtls/entropy.h"
#include "mbedtls/platform.h"
#include "mbedtls/debug.h"
#include "mbedtls/error.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_cache.h"
#include "mbedtls/x509.h"
#define SEC_EVENT_ALARM 2
#define SEC_EVENT_WARNING 1
@ -40,12 +38,16 @@
#if (CONFIG_DEBUG_TLS == 1)
#define DEBUG_PRINT(appId, fmt, ...) fprintf(stderr, "%s: " fmt, appId, ##__VA_ARGS__)
#else
#define DEBUG_PRINT(fmt, ...) do {} while(0)
#define DEBUG_PRINT(fmt, ...) \
do \
{ \
} while (0)
#endif
static int psaInitCounter = 0;
struct sTLSConfiguration {
struct sTLSConfiguration
{
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
@ -73,11 +75,9 @@ struct sTLSConfiguration {
/* TLS session renegotiation interval in milliseconds */
int renegotiationTimeInMs;
// MIGRATE 2.28->3.x.x: Changed min version to 1.2 to reflect the removal of 1.1 and 1.0
/* TLS minimum version allowed (default: TLS_VERSION_TLS_1_2) */
TLSConfigVersion minVersion;
// MIGRATE 2.28->3.x.x: Kept the max version but changed documentation
/* TLS maximum version allowed (default: TLS_VERSION_NOT_SELECTED) */
TLSConfigVersion maxVersion;
@ -96,7 +96,8 @@ struct sTLSConfiguration {
int maxCiphersuites;
};
struct sTLSSocket {
struct sTLSSocket
{
mbedtls_ssl_context ssl;
Socket socket;
mbedtls_ssl_config conf;
@ -113,9 +114,11 @@ struct sTLSSocket {
};
static void
raiseSecurityEvent(TLSConfiguration config, TLSEventLevel eventCategory, int eventCode, const char* message, TLSSocket socket)
raiseSecurityEvent(TLSConfiguration config, TLSEventLevel eventCategory, int eventCode, const char* message,
TLSSocket socket)
{
if (config->eventHandler)
{
if (config->eventHandler) {
config->eventHandler(config->eventHandlerParameter, eventCategory, eventCode, message, (TLSConnection)socket);
}
}
@ -123,10 +126,9 @@ raiseSecurityEvent(TLSConfiguration config, TLSEventLevel eventCategory, int eve
static bool
compareCertificates(mbedtls_x509_crt* crt1, mbedtls_x509_crt* crt2)
{
// MIGRATE 2.28->3.x.x: https://github.com/Mbed-TLS/mbedtls/blob/development/docs/3.0-migration-guide.md#most-structure-fields-are-now-private
if (crt1 != NULL && crt2 != NULL &&
crt1->raw.len == crt2->raw.len &&
memcmp(crt1->raw.p, crt2->raw.p, crt1->raw.len) == 0) {
if (crt1 != NULL && crt2 != NULL && crt1->raw.len == crt2->raw.len &&
memcmp(crt1->raw.p, crt2->raw.p, crt1->raw.len) == 0)
{
return true;
}
@ -188,7 +190,8 @@ verifyCertificate (void* parameter, mbedtls_x509_crt *crt, int certificate_depth
}
else
{
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_NOT_CONFIGURED, "Alarm: certificate validation: trusted individual certificate not available", self);
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_NOT_CONFIGURED,
"Alarm: certificate validation: trusted individual certificate not available", self);
*flags |= MBEDTLS_X509_BADCERT_OTHER;
return 1;
@ -201,28 +204,32 @@ verifyCertificate (void* parameter, mbedtls_x509_crt *crt, int certificate_depth
{
*flags = *flags - MBEDTLS_X509_BADCERT_EXPIRED;
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_WRN_CERT_EXPIRED, "Warning: certificate validation: using expired certificate", self);
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_WRN_CERT_EXPIRED,
"Warning: certificate validation: using expired certificate", self);
}
if (*flags & MBEDTLS_X509_BADCRL_EXPIRED)
{
*flags = *flags - MBEDTLS_X509_BADCRL_EXPIRED;
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_WRN_CRL_EXPIRED, "Warning: certificate validation: using expired CRL", self);
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_WRN_CRL_EXPIRED,
"Warning: certificate validation: using expired CRL", self);
}
if (*flags & MBEDTLS_X509_BADCERT_FUTURE)
{
*flags = *flags - MBEDTLS_X509_BADCERT_FUTURE;
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_WRN_CERT_NOT_YET_VALID, "Warning: certificate validation: using certificate with validity in future", self);
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_WRN_CERT_NOT_YET_VALID,
"Warning: certificate validation: using certificate with validity in future", self);
}
if (*flags & MBEDTLS_X509_BADCRL_FUTURE)
{
*flags = *flags - MBEDTLS_X509_BADCRL_FUTURE;
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_WRN_CRL_NOT_YET_VALID, "Warning: certificate validation: using CRL with validity in future", self);
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_WRN_CRL_NOT_YET_VALID,
"Warning: certificate validation: using CRL with validity in future", self);
}
}
@ -259,7 +266,8 @@ TLSConfiguration_setupComplete(TLSConfiguration self)
{
int ret = mbedtls_ssl_conf_own_cert(&(self->conf), &(self->ownCertificate), &(self->ownKey));
if (ret != 0) {
if (ret != 0)
{
DEBUG_PRINT("TLS", "mbedtls_ssl_conf_own_cert returned -0x%x\n", -ret);
return false;
}
@ -267,18 +275,16 @@ TLSConfiguration_setupComplete(TLSConfiguration self)
if (self->useSessionResumption)
{
if (mbedtls_ssl_conf_get_endpoint(&(self->conf)) == MBEDTLS_SSL_IS_CLIENT) {
if (mbedtls_ssl_conf_get_endpoint(&(self->conf)) == MBEDTLS_SSL_IS_CLIENT)
{
}
else
{
mbedtls_ssl_cache_init(&(self->cache));
// MIGRATE 2.28->3.x.x: https://github.com/Mbed-TLS/mbedtls/blob/development/docs/3.0-migration-guide.md#most-structure-fields-are-now-private
mbedtls_ssl_cache_set_timeout(&(self->cache), self->sessionResumptionInterval);
mbedtls_ssl_conf_session_cache( &(self->conf), &(self->cache),
mbedtls_ssl_cache_get,
mbedtls_ssl_conf_session_cache(&(self->conf), &(self->cache), mbedtls_ssl_cache_get,
mbedtls_ssl_cache_set);
}
}
@ -351,6 +357,13 @@ TLSConfiguration_create()
/* call to psa_crypto_init required -> see https://github.com/Mbed-TLS/mbedtls/issues/9223 */
psa_status_t psaStatus = psa_crypto_init();
if (psaStatus != PSA_SUCCESS)
{
DEBUG_PRINT("TLS", "psa_crypto_init failed with %i\n", psaStatus);
GLOBAL_FREEMEM(self);
return NULL;
}
psaInitCounter++;
mbedtls_ssl_config_init(&(self->conf));
@ -362,9 +375,7 @@ TLSConfiguration_create()
mbedtls_ctr_drbg_init(&(self->ctr_drbg));
/* WARINING is fixed to server! */
mbedtls_ssl_config_defaults( &(self->conf),
MBEDTLS_SSL_IS_SERVER,
MBEDTLS_SSL_TRANSPORT_STREAM,
mbedtls_ssl_config_defaults(&(self->conf), MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT);
mbedtls_ctr_drbg_seed(&(self->ctr_drbg), mbedtls_entropy_func, &(self->entropy), NULL, 0);
@ -408,13 +419,15 @@ TLSConfiguration_create()
/* mandatory cipher suites by IEC 62351-4:2018 */
self->ciphersuites[cipherIndex++] = MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256;
/* self->ciphersuites[cipherIndex++] = MBEDTLS_TLS_DH_RSA_WITH_AES_128_GCM_SHA256; */ /* weak - not supported? */
/* self->ciphersuites[cipherIndex++] = MBEDTLS_TLS_DH_RSA_WITH_AES_128_GCM_SHA256; */ /* weak - not
supported? */
self->ciphersuites[cipherIndex++] = MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
self->ciphersuites[cipherIndex++] = MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
/* recommended cipher suites by IEC 62351-4:2018 */
/* self->ciphersuites[cipherIndex++] = MBEDTLS_TLS_DH_RSA_WITH_AES_128_CBC_SHA256; */ /* weak - not supported?*/
/* self->ciphersuites[cipherIndex++] = MBEDTLS_TLS_DH_RSA_WITH_AES_128_CBC_SHA256; */ /* weak - not
supported?*/
/* self->ciphersuites[cipherIndex++] = MBEDTLS_TLS_DH_RSA_WITH_AES_256_GCM_SHA384; */ /* not supported?*/
self->ciphersuites[cipherIndex++] = MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
self->ciphersuites[cipherIndex++] = MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
@ -425,11 +438,16 @@ TLSConfiguration_create()
self->ciphersuites[cipherIndex++] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
/* TLS 1.3 cipher suites */
self->ciphersuites[cipherIndex++] = MBEDTLS_TLS1_3_AES_128_GCM_SHA256; /* mandatory according IEC 62351-3:2023 */
self->ciphersuites[cipherIndex++] = MBEDTLS_TLS1_3_AES_256_GCM_SHA384; /* mandatory according IEC 62351-3:2023 */
self->ciphersuites[cipherIndex++] = MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256; /* optional according IEC 62351-3:2023 */
self->ciphersuites[cipherIndex++] = MBEDTLS_TLS1_3_AES_128_CCM_SHA256; /* mandatory according IEC 62351-3:2023 */
self->ciphersuites[cipherIndex++] = MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256 ; /* optional according IEC 62351-3:2023 */
self->ciphersuites[cipherIndex++] =
MBEDTLS_TLS1_3_AES_128_GCM_SHA256; /* mandatory according IEC 62351-3:2023 */
self->ciphersuites[cipherIndex++] =
MBEDTLS_TLS1_3_AES_256_GCM_SHA384; /* mandatory according IEC 62351-3:2023 */
self->ciphersuites[cipherIndex++] =
MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256; /* optional according IEC 62351-3:2023 */
self->ciphersuites[cipherIndex++] =
MBEDTLS_TLS1_3_AES_128_CCM_SHA256; /* mandatory according IEC 62351-3:2023 */
self->ciphersuites[cipherIndex++] =
MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256; /* optional according IEC 62351-3:2023 */
}
}
@ -516,9 +534,9 @@ TLSConfiguration_setOwnCertificateFromFile(TLSConfiguration self, const char* fi
bool
TLSConfiguration_setOwnKey(TLSConfiguration self, uint8_t* key, int keyLen, const char* keyPassword)
{
// MIGRATE 2.28->3.x.x: https://github.com/Mbed-TLS/mbedtls/blob/development/docs/3.0-migration-guide.md#some-functions-gained-an-rng-parameter
// MIGRATE 2.28->3.x.x: drbg needs to be initialized, but it seems to be done in TLSConfiguration_create
int ret = mbedtls_pk_parse_key(&(self->ownKey), key, keyLen, (const uint8_t*) keyPassword, (keyPassword == NULL) ? 0 : strlen(keyPassword), mbedtls_ctr_drbg_random, &(self->ctr_drbg));
int ret = mbedtls_pk_parse_key(&(self->ownKey), key, keyLen, (const uint8_t*)keyPassword,
(keyPassword == NULL) ? 0 : strlen(keyPassword), mbedtls_ctr_drbg_random,
&(self->ctr_drbg));
if (ret != 0)
DEBUG_PRINT("TLS", "mbedtls_pk_parse_key returned -0x%x\n", -ret);
@ -529,9 +547,8 @@ TLSConfiguration_setOwnKey(TLSConfiguration self, uint8_t* key, int keyLen, cons
bool
TLSConfiguration_setOwnKeyFromFile(TLSConfiguration self, const char* filename, const char* keyPassword)
{
// MIGRATE 2.28->3.x.x: https://github.com/Mbed-TLS/mbedtls/blob/development/docs/3.0-migration-guide.md#some-functions-gained-an-rng-parameter
// MIGRATE 2.28->3.x.x: drbg needs to be initialized, but it seems to be done in TLSConfiguration_create
int ret = mbedtls_pk_parse_keyfile(&(self->ownKey), filename, keyPassword, mbedtls_ctr_drbg_random, &(self->ctr_drbg));
int ret =
mbedtls_pk_parse_keyfile(&(self->ownKey), filename, keyPassword, mbedtls_ctr_drbg_random, &(self->ctr_drbg));
if (ret != 0)
DEBUG_PRINT("TLS", "mbedtls_pk_parse_keyfile returned -0x%x\n", -ret);
@ -622,10 +639,12 @@ TLSConfiguration_addCRL(TLSConfiguration self, uint8_t* crl, int crlLen)
{
int ret = mbedtls_x509_crl_parse(&(self->crl), crl, crlLen);
if (ret != 0) {
if (ret != 0)
{
DEBUG_PRINT("TLS", "mbedtls_x509_crl_parse returned -0x%x\n", -ret);
}
else {
else
{
udpatedCRL(self);
}
@ -637,10 +656,12 @@ TLSConfiguration_addCRLFromFile(TLSConfiguration self, const char* filename)
{
int ret = mbedtls_x509_crl_parse_file(&(self->crl), filename);
if (ret != 0) {
if (ret != 0)
{
DEBUG_PRINT("TLS", "mbedtls_x509_crl_parse_file returned %d\n", ret);
}
else {
else
{
udpatedCRL(self);
}
@ -720,111 +741,136 @@ createSecurityEvents(TLSConfiguration config, int ret, uint32_t flags, TLSSocket
if (config->eventHandler == NULL)
return;
switch (ret) {
switch (ret)
{
case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG:
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_NO_CIPHER, "Alarm: Algorithm not supported", socket);
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_NO_CIPHER, "Alarm: Algorithm not supported",
socket);
break;
// MIGRATE 2.28->3.x.x:https://github.com/Mbed-TLS/mbedtls/blob/development/docs/3.0-migration-guide.md#changes-in-the-ssl-error-code-space
// case MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN: (MIGRATE 2.28->3.x.x)
// raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_NO_CIPHER, "Alarm: no matching TLS ciphers", socket);
// break;
// raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_NO_CIPHER, "Alarm: no matching TLS
// ciphers", socket); break;
// case MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE: (MIGRATE 2.28->3.x.x)
// raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_ALGO_NOT_SUPPORTED, "Alarm: Algorithm not supported", socket);
// break;
// raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_ALGO_NOT_SUPPORTED, "Alarm: Algorithm
// not supported", socket); break;
case MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE:
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_ALGO_NOT_SUPPORTED, "Alarm: Handshake failure", socket);
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_ALGO_NOT_SUPPORTED,
"Alarm: Handshake failure", socket);
break;
// case MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION: (MIGRATE 2.28->3.x.x)
// raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_UNSECURE_COMMUNICATION, "Alarm: Unsecure communication", socket);
// break;
// raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_UNSECURE_COMMUNICATION, "Alarm:
// Unsecure communication", socket); break;
case MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_UNAVAILABLE, "Alarm: certificate unavailable", socket);
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_UNAVAILABLE,
"Alarm: certificate unavailable", socket);
break;
// case MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE: (MIGRATE 2.28->3.x.x)
// raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_BAD_CERT, "Alarm: Bad certificate", socket);
// break;
// raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_BAD_CERT, "Alarm: Bad certificate",
// socket); break;
case MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_SIZE_EXCEEDED, "Alarm: TLS certificate size exceeded", socket);
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_SIZE_EXCEEDED,
"Alarm: TLS certificate size exceeded", socket);
break;
// MIGRATE 2.28->3.x.x: the removal of this is undocumented TODO: Verify migration path
// case MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED: (MIGRATE 2.28->3.x.x)
// raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_VALIDATION_FAILED, "Alarm: certificate validation: certificate signature could not be validated", socket);
// break;
// raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_VALIDATION_FAILED, "Alarm:
// certificate validation: certificate signature could not be validated", socket); break;
// MIGRATE 2.28->3.x.x: the removal of this is undocumented. The docs say migrating users are affected but don't provide a migration path TODO: Verify migration path (MIGRATE 2.28->3.x.x)
// case MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED:
// raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_REQUIRED, "Alarm: Certificate required", socket);
// break;
// MIGRATE 2.28->3.x.x: the removal of this is undocumented. The docs say migrating users are affected but don't
// provide a migration path TODO: Verify migration path (MIGRATE 2.28->3.x.x) case
// MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED:
// raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_REQUIRED, "Alarm: Certificate
// required", socket); break;
case MBEDTLS_ERR_SSL_DECODE_ERROR:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON, "Alarm: Decode error", socket);
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON,
"Alarm: Decode error", socket);
break;
case MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON, "Alarm: Illegal parameter", socket);
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON,
"Alarm: Illegal parameter", socket);
break;
case MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON, "Alarm: Bad protocol version", socket);
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON,
"Alarm: Bad protocol version", socket);
break;
case MBEDTLS_ERR_SSL_BAD_CERTIFICATE:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON, "Alarm: Bad certificate", socket);
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON,
"Alarm: Bad certificate", socket);
break;
case MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON, "Alarm: Unrecognized name", socket);
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON,
"Alarm: Unrecognized name", socket);
break;
case MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON, "Alarm: Unsupported extension", socket);
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON,
"Alarm: Unsupported extension", socket);
break;
case MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON, "Alarm: No application protocol", socket);
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON,
"Alarm: No application protocol", socket);
break;
case MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON, "Alarm: Unexpected message", socket);
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON,
"Alarm: Unexpected message", socket);
break;
case MBEDTLS_ERR_SSL_INTERNAL_ERROR:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON, "Alarm: Internal error", socket);
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON,
"Alarm: Internal error", socket);
break;
case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED: {
if (flags & MBEDTLS_X509_BADCERT_EXPIRED)
{
if (flags & MBEDTLS_X509_BADCERT_EXPIRED) {
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_EXPIRED, "Alarm: expired certificate", socket);
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_EXPIRED,
"Alarm: expired certificate", socket);
}
else if (flags & MBEDTLS_X509_BADCERT_REVOKED) {
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_REVOKED, "Alarm: revoked certificate", socket);
else if (flags & MBEDTLS_X509_BADCERT_REVOKED)
{
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_REVOKED,
"Alarm: revoked certificate", socket);
}
else if (flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_NOT_TRUSTED, "Alarm: Certificate validation: CA certificate not available", socket);
else if (flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED)
{
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_NOT_TRUSTED,
"Alarm: Certificate validation: CA certificate not available", socket);
}
else if (flags & MBEDTLS_X509_BADCERT_OTHER) {
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_NOT_CONFIGURED, "Alarm: Certificate not configured", socket);
else if (flags & MBEDTLS_X509_BADCERT_OTHER)
{
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_NOT_CONFIGURED,
"Alarm: Certificate not configured", socket);
}
else if (flags & MBEDTLS_X509_BADCERT_BAD_KEY) {
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_NOT_CONFIGURED, "Alarm: Insufficient key length", socket);
else if (flags & MBEDTLS_X509_BADCERT_BAD_KEY)
{
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_NOT_CONFIGURED,
"Alarm: Insufficient key length", socket);
}
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_VALIDATION_FAILED, "Alarm: Certificate verification failed", socket);
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_CERT_VALIDATION_FAILED,
"Alarm: Certificate verification failed", socket);
}
break;
default:
raiseSecurityEvent(config,TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON, "Alarm: handshake failed for unknown reason", socket);
raiseSecurityEvent(config, TLS_SEC_EVT_INCIDENT, TLS_EVENT_CODE_ALM_HANDSHAKE_FAILED_UNKNOWN_REASON,
"Alarm: handshake failed for unknown reason", socket);
break;
}
}
@ -855,37 +901,11 @@ writeFunction(void* ctx, unsigned char* buf, size_t len)
return ret;
}
static TLSConfigVersion
getTLSVersion(int majorVersion, int minorVersion)
{
if (majorVersion != 3) {
return TLS_VERSION_NOT_SELECTED;
}
else
{
switch (minorVersion) {
/* TODO: Remove from here (MIGRATE 2.28->3.x.x) */
case 0:
return TLS_VERSION_SSL_3_0;
case 1:
return TLS_VERSION_TLS_1_0;
case 2:
return TLS_VERSION_TLS_1_1;
/* Up until here (MIGRATE 2.28->3.x.x) */
case 3:
return TLS_VERSION_TLS_1_2;
case 4:
return TLS_VERSION_TLS_1_3;
default:
return TLS_VERSION_NOT_SELECTED;
}
}
}
static int
getMajorVersion(TLSConfigVersion version)
{
switch(version) {
switch (version)
{
case TLS_VERSION_NOT_SELECTED:
return 0;
/* TODO: Remove from here (MIGRATE 2.28->3.x.x) */
@ -904,7 +924,8 @@ getMajorVersion(TLSConfigVersion version)
static int
getMinorVersion(TLSConfigVersion version)
{
switch(version) {
switch (version)
{
case TLS_VERSION_NOT_SELECTED:
return 0;
/* TODO: Remove from here (MIGRATE 2.28->3.x.x) */
@ -982,8 +1003,8 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
if (ret != 0)
DEBUG_PRINT("TLS", "mbedtls_ssl_setup returned %d\n", ret);
mbedtls_ssl_set_bio(&(self->ssl), socket, (mbedtls_ssl_send_t*) writeFunction,
(mbedtls_ssl_recv_t*) readFunction, NULL);
mbedtls_ssl_set_bio(&(self->ssl), socket, (mbedtls_ssl_send_t*)writeFunction, (mbedtls_ssl_recv_t*)readFunction,
NULL);
if (configuration->useSessionResumption)
{
@ -991,7 +1012,8 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
{
if (configuration->savedSession && configuration->savedSessionTime > 0)
{
if (Hal_getTimeInMs() < (configuration->savedSessionTime + configuration->sessionResumptionInterval * 1000))
if (Hal_getTimeInMs() <
(configuration->savedSessionTime + configuration->sessionResumptionInterval * 1000))
{
ret = mbedtls_ssl_set_session(&(self->ssl), configuration->savedSession);
@ -1026,7 +1048,8 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
mbedtls_ssl_free(&(self->ssl));
if (self->peerCert) {
if (self->peerCert)
{
GLOBAL_FREEMEM(self->peerCert);
}
@ -1066,11 +1089,6 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
self->lastRenegotiationTime = Hal_getTimeInMs();
// MIGRATE 2.28->3.x.x: impossible since mbedtls 3.x.x doesn't support insecure TLS versions
// if (getTLSVersion(self->ssl.major_ver, self->ssl.minor_ver) < TLS_VERSION_TLS_1_2) {
// raiseSecurityEvent(configuration, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_WRN_INSECURE_TLS_VERSION, "Warning: Insecure TLS version", self);
// }
/* create event that TLS session is established */
{
char msg[256];
@ -1103,21 +1121,19 @@ TLSSocket_performHandshake(TLSSocket self)
if (ret == 0 || ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ||
ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS || ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS)
{
// MIGRATE 2.28->3.x.x: impossible since mbedtls 3.x.x doesn't support insecure TLS versions
// if (getTLSVersion(self->ssl.major_ver, self->ssl.minor_ver) < TLS_VERSION_TLS_1_2) {
// raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_WARNING, TLS_EVENT_CODE_WRN_INSECURE_TLS_VERSION, "Warning: Insecure TLS version", self);
// }
return true;
}
else {
else
{
DEBUG_PRINT("TLS", "TLSSocket_performHandshake failed -> ret=%i\n", ret);
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_INFO, TLS_EVENT_CODE_INF_SESSION_RENEGOTIATION, "Alarm: Renegotiation failed", self);
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_INFO, TLS_EVENT_CODE_INF_SESSION_RENEGOTIATION,
"Alarm: Renegotiation failed", self);
/* mbedtls_ssl_renegotiate mandates to reset the ssl session in case of errors */
ret = mbedtls_ssl_session_reset(&(self->ssl));
if (ret != 0) {
if (ret != 0)
{
DEBUG_PRINT("TLS", "mbedtls_ssl_session_reset failed -> ret: -0x%X\n", -ret);
}
@ -1148,10 +1164,21 @@ startRenegotiationIfRequired(TLSSocket self)
if (self->tlsConfig->renegotiationTimeInMs <= 0)
return true;
if (self->lastRenegotiationTime == UINT64_MAX)
return true;
if (TLSConnection_getTLSVersion((TLSConnection)(self)) == TLS_VERSION_TLS_1_3)
{
self->lastRenegotiationTime = UINT64_MAX;
DEBUG_PRINT("TLS", "renegotiation not allowed for TLS 1.3\n");
return true;
}
if (Hal_getTimeInMs() <= self->lastRenegotiationTime + self->tlsConfig->renegotiationTimeInMs)
return true;
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_INFO, TLS_EVENT_CODE_INF_SESSION_RENEGOTIATION, "Info: session renegotiation started", self);
raiseSecurityEvent(self->tlsConfig, TLS_SEC_EVT_INFO, TLS_EVENT_CODE_INF_SESSION_RENEGOTIATION,
"Info: session renegotiation started", self);
if (TLSSocket_performHandshake(self) == false)
{
@ -1170,7 +1197,8 @@ TLSSocket_read(TLSSocket self, uint8_t* buf, int size)
{
checkForCRLUpdate(self);
if (startRenegotiationIfRequired(self) == false) {
if (startRenegotiationIfRequired(self) == false)
{
return -1;
}
@ -1179,8 +1207,8 @@ TLSSocket_read(TLSSocket self, uint8_t* buf, int size)
if ((ret == MBEDTLS_ERR_SSL_WANT_READ) || (ret == MBEDTLS_ERR_SSL_WANT_WRITE))
return 0;
if (ret < 0) {
if (ret < 0)
{
switch (ret)
{
case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
@ -1214,7 +1242,8 @@ TLSSocket_write(TLSSocket self, uint8_t* buf, int size)
checkForCRLUpdate(self);
if (startRenegotiationIfRequired(self) == false) {
if (startRenegotiationIfRequired(self) == false)
{
return -1;
}
@ -1222,14 +1251,17 @@ TLSSocket_write(TLSSocket self, uint8_t* buf, int size)
{
int ret = mbedtls_ssl_write(&(self->ssl), (buf + len), (size - len));
if ((ret == MBEDTLS_ERR_SSL_WANT_READ) || (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ||
(ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) || (ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS)) {
(ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) || (ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS))
{
continue;
}
if (ret < 0) {
if (ret < 0)
{
DEBUG_PRINT("TLS", "mbedtls_ssl_write returned -0x%X\n", -ret);
if (0 != (ret = mbedtls_ssl_session_reset(&(self->ssl)))) {
if (0 != (ret = mbedtls_ssl_session_reset(&(self->ssl))))
{
DEBUG_PRINT("TLS", "mbedtls_ssl_session_reset failed -0x%X\n", -ret);
}
@ -1273,7 +1305,8 @@ TLSConnection_getPeerAddress(TLSConnection self, char* peerAddrBuf)
{
TLSSocket socket = (TLSSocket)self;
if (peerAddrBuf == NULL) {
if (peerAddrBuf == NULL)
{
peerAddrBuf = (char*)GLOBAL_MALLOC(61);
}
@ -1295,10 +1328,11 @@ TLSConfigVersion
TLSConnection_getTLSVersion(TLSConnection self)
{
TLSSocket socket = (TLSSocket)self;
// MIGRATE 2.28->3.x.x: https://github.com/Mbed-TLS/mbedtls/blob/development/docs/3.0-migration-guide.md#most-structure-fields-are-now-private
mbedtls_ssl_protocol_version version = mbedtls_ssl_get_version_number(&(socket->ssl));
switch(version) {
switch (version)
{
case MBEDTLS_SSL_VERSION_TLS1_2:
return TLS_VERSION_TLS_1_2;
case MBEDTLS_SSL_VERSION_TLS1_3:

Loading…
Cancel
Save