diff --git a/hal/inc/hal_base.h b/hal/inc/hal_base.h
index b8a3611b..6fe3a417 100644
--- a/hal/inc/hal_base.h
+++ b/hal/inc/hal_base.h
@@ -1,25 +1,10 @@
/*
* hal_base.h
*
- * Copyright 2018 MZ Automation GmbH
+ * Copyright 2013-2021 Michael Zillgith
*
* This file is part of Platform Abstraction Layer (libpal)
- * for libiec61850 and lib60870.
- *
- * libpal 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 3 of the License, or
- * (at your option) any later version.
- *
- * libpal 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 libpal. If not, see .
- *
- * See COPYING file for the complete license text.
+ * for libiec61850, libmms, and lib60870.
*/
#ifndef HAL_INC_HAL_BASE_H_
diff --git a/hal/inc/hal_ethernet.h b/hal/inc/hal_ethernet.h
index c7822407..6cf03f34 100644
--- a/hal/inc/hal_ethernet.h
+++ b/hal/inc/hal_ethernet.h
@@ -1,24 +1,10 @@
/*
* ethernet_hal.h
*
- * Copyright 2013, 2014 Michael Zillgith
+ * Copyright 2013-2021 Michael Zillgith
*
- * This file is part of libIEC61850.
- *
- * libIEC61850 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 3 of the License, or
- * (at your option) any later version.
- *
- * libIEC61850 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 libIEC61850. If not, see .
- *
- * See COPYING file for the complete license text.
+ * This file is part of Platform Abstraction Layer (libpal)
+ * for libiec61850, libmms, and lib60870.
*/
#ifndef ETHERNET_HAL_H_
diff --git a/hal/inc/hal_filesystem.h b/hal/inc/hal_filesystem.h
index d4ff6691..56184117 100644
--- a/hal/inc/hal_filesystem.h
+++ b/hal/inc/hal_filesystem.h
@@ -1,24 +1,10 @@
/*
* filesystem_hal.h
*
- * Copyright 2014 Michael Zillgith
+ * Copyright 2013-2021 Michael Zillgith
*
- * This file is part of libIEC61850.
- *
- * libIEC61850 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 3 of the License, or
- * (at your option) any later version.
- *
- * libIEC61850 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 libIEC61850. If not, see .
- *
- * See COPYING file for the complete license text.
+ * This file is part of Platform Abstraction Layer (libpal)
+ * for libiec61850, libmms, and lib60870.
*/
#ifndef FILESYSTEM_HAL_H_
diff --git a/hal/inc/hal_serial.h b/hal/inc/hal_serial.h
index a56a5fb5..a02a1a1b 100644
--- a/hal/inc/hal_serial.h
+++ b/hal/inc/hal_serial.h
@@ -1,24 +1,10 @@
/*
* hal_serial.h
*
- * Copyright 2017 MZ Automation GmbH
+ * Copyright 2013-2021 Michael Zillgith
*
- * This file is part of lib60870-C
- *
- * lib60870-C 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 3 of the License, or
- * (at your option) any later version.
- *
- * lib60870-C 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 lib60870-C. If not, see .
- *
- * See COPYING file for the complete license text.
+ * This file is part of Platform Abstraction Layer (libpal)
+ * for libiec61850, libmms, and lib60870.
*/
#ifndef SRC_IEC60870_LINK_LAYER_SERIAL_PORT_H_
diff --git a/hal/inc/hal_socket.h b/hal/inc/hal_socket.h
index 414a1a7e..5c594f83 100644
--- a/hal/inc/hal_socket.h
+++ b/hal/inc/hal_socket.h
@@ -1,24 +1,10 @@
/*
* socket_hal.h
*
- * Copyright 2013-2020 Michael Zillgith
+ * Copyright 2013-2021 Michael Zillgith
*
- * This file is part of libIEC61850.
- *
- * libIEC61850 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 3 of the License, or
- * (at your option) any later version.
- *
- * libIEC61850 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 libIEC61850. If not, see .
- *
- * See COPYING file for the complete license text.
+ * This file is part of Platform Abstraction Layer (libpal)
+ * for libiec61850, libmms, and lib60870.
*/
#ifndef SOCKET_HAL_H_
@@ -242,6 +228,20 @@ TcpSocket_create(void);
PAL_API void
Socket_setConnectTimeout(Socket self, uint32_t timeoutInMs);
+/**
+ * \brief bind a socket to a particular IP address and port (for TcpSocket)
+ *
+ * NOTE: Don't use the socket when this functions returns false!
+ *
+ * \param self the client socket instance
+ * \param srcAddress the local IP address or hostname as C string
+ * \param srcPort the local TCP port to use. When < 1 the OS will chose the TCP port to use.
+ *
+ * \return true in case of success, false otherwise
+ */
+PAL_API bool
+Socket_bind(Socket self, const char* srcAddress, int srcPort);
+
/**
* \brief connect to a server
*
diff --git a/hal/inc/hal_thread.h b/hal/inc/hal_thread.h
index 0558f9e4..0a88553e 100644
--- a/hal/inc/hal_thread.h
+++ b/hal/inc/hal_thread.h
@@ -3,24 +3,10 @@
*
* Multi-threading abstraction layer
*
- * Copyright 2013-2018 Michael Zillgith
+ * Copyright 2013-2021 Michael Zillgith
*
- * This file is part of libIEC61850.
- *
- * libIEC61850 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 3 of the License, or
- * (at your option) any later version.
- *
- * libIEC61850 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 libIEC61850. If not, see .
- *
- * See COPYING file for the complete license text.
+ * This file is part of Platform Abstraction Layer (libpal)
+ * for libiec61850, libmms, and lib60870.
*/
#ifndef THREAD_HAL_H_
diff --git a/hal/inc/hal_time.h b/hal/inc/hal_time.h
index 7d5a942c..b19bcd4b 100644
--- a/hal/inc/hal_time.h
+++ b/hal/inc/hal_time.h
@@ -1,24 +1,10 @@
/*
* time.c
*
- * Copyright 2013-2020 Michael Zillgith
+ * Copyright 2013-2021 Michael Zillgith
*
- * This file is part of libIEC61850.
- *
- * libIEC61850 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 3 of the License, or
- * (at your option) any later version.
- *
- * libIEC61850 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 libIEC61850. If not, see .
- *
- * See COPYING file for the complete license text.
+ * This file is part of Platform Abstraction Layer (libpal)
+ * for libiec61850, libmms, and lib60870.
*/
#ifndef HAL_C_
diff --git a/hal/inc/lib_memory.h b/hal/inc/lib_memory.h
index 63463a8e..927a98a7 100644
--- a/hal/inc/lib_memory.h
+++ b/hal/inc/lib_memory.h
@@ -1,24 +1,10 @@
/*
* lib_memory.h
*
- * Copyright 2014 Michael Zillgith
+ * Copyright 2014-2021 Michael Zillgith
*
- * This file is part of libIEC61850.
- *
- * libIEC61850 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 3 of the License, or
- * (at your option) any later version.
- *
- * libIEC61850 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 libIEC61850. If not, see .
- *
- * See COPYING file for the complete license text.
+ * This file is part of Platform Abstraction Layer (libpal)
+ * for libiec61850, libmms, and lib60870.
*/
#ifndef MEMORY_H_
@@ -40,6 +26,8 @@
extern "C" {
#endif
+#include
+
typedef void
(*MemoryExceptionHandler) (void* parameter);
diff --git a/hal/inc/platform_endian.h b/hal/inc/platform_endian.h
index 76c410af..6a6cdd4c 100644
--- a/hal/inc/platform_endian.h
+++ b/hal/inc/platform_endian.h
@@ -1,24 +1,10 @@
/*
* platform_endian.h
*
- * Copyright 2013-2018 Michael Zillgith
+ * Copyright 2013-2021 Michael Zillgith
*
- * This file is part of libIEC61850.
- *
- * libIEC61850 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 3 of the License, or
- * (at your option) any later version.
- *
- * libIEC61850 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 libIEC61850. If not, see .
- *
- * See COPYING file for the complete license text.
+ * This file is part of Platform Abstraction Layer (libpal)
+ * for libiec61850, libmms, and lib60870.
*/
#ifndef ENDIAN_H_
diff --git a/hal/inc/tls_config.h b/hal/inc/tls_config.h
index dea44c43..2accacaa 100644
--- a/hal/inc/tls_config.h
+++ b/hal/inc/tls_config.h
@@ -3,7 +3,7 @@
*
* TLS Configuration API for protocol stacks using TCP/IP
*
- * Copyright 2017-2018 MZ Automation GmbH
+ * Copyright 2017-2021 Michael Zillgith
*
* Abstraction layer for configuration of different TLS implementations
*
@@ -90,21 +90,64 @@ TLSConfiguration_setOwnCertificate(TLSConfiguration self, uint8_t* certificate,
PAL_API bool
TLSConfiguration_setOwnCertificateFromFile(TLSConfiguration self, const char* filename);
+/**
+ * \brief Set the own private key from a byte buffer
+ *
+ * \param key the private key to use
+ * \param keyLen the length of the key
+ * \param password the password of the key or null if the key is not password protected
+ *
+ * \return true, when the key was set, false otherwise (e.g. unknown key format)
+ */
PAL_API bool
TLSConfiguration_setOwnKey(TLSConfiguration self, uint8_t* key, int keyLen, const char* keyPassword);
+/**
+ * \brief Set the own private key from a key file
+ *
+ * \param filename filename/path of the key file
+ * \param password the password of the key or null if the key is not password protected
+ *
+ * \return true, when the key was set, false otherwise (e.g. unknown key format)
+ */
PAL_API bool
TLSConfiguration_setOwnKeyFromFile(TLSConfiguration self, const char* filename, const char* keyPassword);
+/**
+ * Add a certificate to the list of allowed peer certificates from a byte buffer
+ *
+ * \param certificate the certificate buffer
+ * \param certLen the length of the certificate buffer
+ * \return true, when the certificate was set, false otherwise (e.g. unknown certificate format)
+ */
PAL_API bool
-TLSConfiguration_addAllowedCertificate(TLSConfiguration self, uint8_t* certifcate, int certLen);
+TLSConfiguration_addAllowedCertificate(TLSConfiguration self, uint8_t* certificate, int certLen);
+/**
+ * \brief Add a certificate to the list of allowed peer certificates
+ *
+ * \param filename filename of the certificate file
+ * \return true, when the certificate was set, false otherwise (e.g. unknown certificate format)
+ */
PAL_API bool
TLSConfiguration_addAllowedCertificateFromFile(TLSConfiguration self, const char* filename);
+/**
+ * \brief Add a CA certificate used to validate peer certificates from a byte buffer
+ *
+ * \param certificate the certificate buffer
+ * \param certLen the length of the certificate buffer
+ * \return true, when the certificate was set, false otherwise (e.g. unknown certificate format)
+ */
PAL_API bool
-TLSConfiguration_addCACertificate(TLSConfiguration self, uint8_t* certifcate, int certLen);
+TLSConfiguration_addCACertificate(TLSConfiguration self, uint8_t* certificate, int certLen);
+/**
+ * \brief Add a CA certificate used to validate peer certificates from a file
+ *
+ * \param filename filename of the certificate file
+ * \return true, when the certificate was set, false otherwise (e.g. unknown certificate format)
+ */
PAL_API bool
TLSConfiguration_addCACertificateFromFile(TLSConfiguration self, const char* filename);
@@ -118,6 +161,51 @@ TLSConfiguration_addCACertificateFromFile(TLSConfiguration self, const char* fil
PAL_API void
TLSConfiguration_setRenegotiationTime(TLSConfiguration self, int timeInMs);
+typedef enum {
+ TLS_VERSION_NOT_SELECTED = 0,
+ TLS_VERSION_SSL_3_0 = 3,
+ TLS_VERSION_TLS_1_0 = 4,
+ TLS_VERSION_TLS_1_1 = 5,
+ TLS_VERSION_TLS_1_2 = 6,
+ TLS_VERSION_TLS_1_3 = 7
+} TLSConfigVersion;
+
+/**
+ * \brief Set minimal allowed TLS version to use
+ */
+PAL_API void
+TLSConfiguration_setMinTlsVersion(TLSConfiguration self, TLSConfigVersion version);
+
+/**
+ * \brief Set maximal allowed TLS version to use
+ */
+PAL_API void
+TLSConfiguration_setMaxTlsVersion(TLSConfiguration self, TLSConfigVersion version);
+
+/**
+ * \brief Add a CRL (certificate revocation list) from buffer
+ *
+ * \param crl the buffer containing the CRL
+ * \param crlLen the length of the CRL buffer
+ * \return true, when the CRL was imported, false otherwise (e.g. unknown format)
+ */
+PAL_API bool
+TLSConfiguration_addCRL(TLSConfiguration self, uint8_t* crl, int crlLen);
+
+/**
+ * \brief Add a CRL (certificate revocation list) from a file
+ *
+ * \param filename filename of the CRL file
+ * \return true, when the CRL was imported, false otherwise (e.g. unknown format)
+ */
+PAL_API bool
+TLSConfiguration_addCRLFromFile(TLSConfiguration self, const char* filename);
+
+/**
+ * Release all resource allocated by the TLSConfiguration instance
+ *
+ * NOTE: Do not use the object after calling this function!
+ */
PAL_API void
TLSConfiguration_destroy(TLSConfiguration self);
diff --git a/hal/inc/tls_socket.h b/hal/inc/tls_socket.h
index ac5b8c15..fa682f4f 100644
--- a/hal/inc/tls_socket.h
+++ b/hal/inc/tls_socket.h
@@ -3,7 +3,7 @@
*
* TLS socket API for protocol libraries using TCP/IP
*
- * Copyright 2017-2020 Michael Zillgith, MZ Automation GmbH
+ * Copyright 2017-2021 Michael Zillgith, MZ Automation GmbH
*
* Abstraction layer for different TLS implementations
*
diff --git a/hal/memory/lib_memory.c b/hal/memory/lib_memory.c
index 623ba212..adeb105a 100644
--- a/hal/memory/lib_memory.c
+++ b/hal/memory/lib_memory.c
@@ -1,24 +1,10 @@
/*
* lib_memory.c
*
- * Copyright 2014-2018 Michael Zillgith
+ * Copyright 2014-2021 Michael Zillgith
*
- * This file is part of libIEC61850.
- *
- * libIEC61850 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 3 of the License, or
- * (at your option) any later version.
- *
- * libIEC61850 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 libIEC61850. If not, see .
- *
- * See COPYING file for the complete license text.
+ * This file is part of Platform Abstraction Layer (libpal)
+ * for libiec61850, libmms, and lib60870.
*/
#include
diff --git a/hal/serial/linux/serial_port_linux.c b/hal/serial/linux/serial_port_linux.c
index 64acf77d..f976e724 100644
--- a/hal/serial/linux/serial_port_linux.c
+++ b/hal/serial/linux/serial_port_linux.c
@@ -1,24 +1,10 @@
/*
* serial_port_linux.c
*
- * Copyright 2017 MZ Automation GmbH
+ * Copyright 2013-2021 Michael Zillgith
*
- * This file is part of lib60870-C
- *
- * lib60870-C 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 3 of the License, or
- * (at your option) any later version.
- *
- * lib60870-C 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 lib60870-C. If not, see .
- *
- * See COPYING file for the complete license text.
+ * This file is part of Platform Abstraction Layer (libpal)
+ * for libiec61850, libmms, and lib60870.
*/
#include "lib_memory.h"
diff --git a/hal/serial/win32/serial_port_win32.c b/hal/serial/win32/serial_port_win32.c
index 186cd214..b00ec629 100644
--- a/hal/serial/win32/serial_port_win32.c
+++ b/hal/serial/win32/serial_port_win32.c
@@ -1,24 +1,10 @@
/*
* serial_port_win32.c
*
-* Copyright 2017 MZ Automation GmbH
+* Copyright 2013-2021 Michael Zillgith
*
-* This file is part of lib60870-C
-*
-* lib60870-C 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 3 of the License, or
-* (at your option) any later version.
-*
-* lib60870-C 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 lib60870-C. If not, see .
-*
-* See COPYING file for the complete license text.
+* This file is part of Platform Abstraction Layer (libpal)
+* for libiec61850, libmms, and lib60870.
*/
#include
diff --git a/hal/socket/bsd/socket_bsd.c b/hal/socket/bsd/socket_bsd.c
index 2079ba87..198ad227 100644
--- a/hal/socket/bsd/socket_bsd.c
+++ b/hal/socket/bsd/socket_bsd.c
@@ -1,25 +1,10 @@
/*
* socket_bsd.c
*
- * Copyright 2013-2020 Michael Zillgith
- * contributions by Michael Clausen (School of engineering Valais).
+ * Copyright 2013-2021 Michael Zillgith
*
- * This file is part of libIEC61850.
- *
- * libIEC61850 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 3 of the License, or
- * (at your option) any later version.
- *
- * libIEC61850 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 libIEC61850. If not, see .
- *
- * See COPYING file for the complete license text.
+ * This file is part of Platform Abstraction Layer (libpal)
+ * for libiec61850, libmms, and lib60870.
*/
#include "hal_socket.h"
@@ -199,7 +184,7 @@ Socket_activateTcpKeepAlive(Socket self, int idleTime, int interval, int count)
}
static bool
-prepareServerAddress(const char* address, int port, struct sockaddr_in* sockaddr)
+prepareAddress(const char* address, int port, struct sockaddr_in* sockaddr)
{
memset((char *) sockaddr , 0, sizeof(struct sockaddr_in));
@@ -246,7 +231,7 @@ TcpServerSocket_create(const char* address, int port)
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) >= 0) {
struct sockaddr_in serverAddress;
- if (!prepareServerAddress(address, port, &serverAddress)) {
+ if (!prepareAddress(address, port, &serverAddress)) {
close(fd);
return NULL;
}
@@ -257,7 +242,7 @@ TcpServerSocket_create(const char* address, int port)
if (bind(fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) >= 0) {
serverSocket = (ServerSocket) GLOBAL_MALLOC(sizeof(struct sServerSocket));
serverSocket->fd = fd;
- serverSocket->backLog = 0;
+ serverSocket->backLog = 2;
setSocketNonBlocking((Socket) serverSocket);
}
@@ -345,7 +330,7 @@ ServerSocket_destroy(ServerSocket self)
Socket
TcpSocket_create()
{
- Socket self = NULL;
+ Socket self = (Socket)NULL;
int sock = socket(AF_INET, SOCK_STREAM, 0);
@@ -368,7 +353,6 @@ TcpSocket_create()
if (DEBUG_SOCKET)
printf("SOCKET: out of memory\n");
}
-
}
else {
if (DEBUG_SOCKET)
@@ -385,15 +369,24 @@ Socket_setConnectTimeout(Socket self, uint32_t timeoutInMs)
}
bool
-Socket_setLocalAddress(Socket self, const char* address, int port)
+Socket_bind(Socket self, const char* srcAddress, int srcPort)
{
- struct sockaddr_in clientAddress;
+ struct sockaddr_in localAddress;
- if (!prepareServerAddress(address, port, &clientAddress))
+ if (!prepareAddress(srcAddress, srcPort, &localAddress))
return false;
- if (bind(self->fd, (struct sockaddr *) &clientAddress, sizeof(clientAddress)) != 0)
+ int result = bind(self->fd, (struct sockaddr*)&localAddress, sizeof(localAddress));
+
+ if (result == -1) {
+ if (DEBUG_SOCKET)
+ printf("SOCKET: failed to bind TCP socket (errno=%i)\n", errno);
+
+ close(self->fd);
+ self->fd = -1;
+
return false;
+ }
return true;
}
diff --git a/hal/socket/linux/socket_linux.c b/hal/socket/linux/socket_linux.c
index 3c3b284c..33ead6ab 100644
--- a/hal/socket/linux/socket_linux.c
+++ b/hal/socket/linux/socket_linux.c
@@ -1,34 +1,21 @@
/*
* socket_linux.c
*
- * Copyright 2013-2020 Michael Zillgith
+ * Copyright 2013-2021 Michael Zillgith
*
- * This file is part of libIEC61850.
- *
- * libIEC61850 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 3 of the License, or
- * (at your option) any later version.
- *
- * libIEC61850 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 libIEC61850. If not, see .
- *
- * See COPYING file for the complete license text.
+ * This file is part of Platform Abstraction Layer (libpal)
+ * for libiec61850, libmms, and lib60870.
*/
#include "hal_socket.h"
#include
#include
-#include
#include
#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -215,7 +202,7 @@ Socket_activateTcpKeepAlive(Socket self, int idleTime, int interval, int count)
}
static bool
-prepareServerAddress(const char* address, int port, struct sockaddr_in* sockaddr)
+prepareAddress(const char* address, int port, struct sockaddr_in* sockaddr)
{
bool retVal = true;
@@ -231,6 +218,10 @@ prepareServerAddress(const char* address, int port, struct sockaddr_in* sockaddr
result = getaddrinfo(address, NULL, &addressHints, &lookupResult);
if (result != 0) {
+
+ if (DEBUG_SOCKET)
+ printf("SOCKET: getaddrinfo failed (code=%i)\n", result);
+
retVal = false;
goto exit_function;
}
@@ -242,6 +233,10 @@ prepareServerAddress(const char* address, int port, struct sockaddr_in* sockaddr
sockaddr->sin_addr.s_addr = htonl(INADDR_ANY);
sockaddr->sin_family = AF_INET;
+
+ if (port < 0)
+ port = 0;
+
sockaddr->sin_port = htons(port);
exit_function:
@@ -273,7 +268,7 @@ TcpServerSocket_create(const char* address, int port)
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) >= 0) {
struct sockaddr_in serverAddress;
- if (!prepareServerAddress(address, port, &serverAddress)) {
+ if (!prepareAddress(address, port, &serverAddress)) {
close(fd);
return NULL;
}
@@ -327,9 +322,19 @@ ServerSocket_accept(ServerSocket self)
if (fd >= 0) {
conSocket = (Socket) GLOBAL_CALLOC(1, sizeof(struct sSocket));
- conSocket->fd = fd;
- activateTcpNoDelay(conSocket);
+ if (conSocket) {
+ conSocket->fd = fd;
+
+ activateTcpNoDelay(conSocket);
+ }
+ else {
+ /* out of memory */
+ close(fd);
+
+ if (DEBUG_SOCKET)
+ printf("SOCKET: out of memory\n");
+ }
}
return conSocket;
@@ -350,9 +355,19 @@ closeAndShutdownSocket(int socketFd)
printf("SOCKET: call shutdown for %i!\n", socketFd);
/* shutdown is required to unblock read or accept in another thread! */
- shutdown(socketFd, SHUT_RDWR);
+ int result = shutdown(socketFd, SHUT_RDWR);
+
+ if (result == -1) {
+ if (DEBUG_SOCKET)
+ printf("SOCKET: shutdown error: %i\n", errno);
+ }
- close(socketFd);
+ result = close(socketFd);
+
+ if (result == -1) {
+ if (DEBUG_SOCKET)
+ printf("SOCKET: close error: %i\n", errno);
+ }
}
}
@@ -373,26 +388,34 @@ ServerSocket_destroy(ServerSocket self)
Socket
TcpSocket_create()
{
- Socket self = NULL;
+ Socket self = (Socket)NULL;
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock != -1) {
self = (Socket) GLOBAL_MALLOC(sizeof(struct sSocket));
- self->fd = sock;
- self->connectTimeout = 5000;
+ if (self) {
+ self->fd = sock;
+ self->connectTimeout = 5000;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
- int tcpUserTimeout = 10000;
- int result = setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT, &tcpUserTimeout, sizeof(tcpUserTimeout));
+ int tcpUserTimeout = 10000;
+ int result = setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT, &tcpUserTimeout, sizeof(tcpUserTimeout));
- if (result < 0) {
- if (DEBUG_SOCKET)
- printf("SOCKET: failed to set TCP_USER_TIMEOUT\n");
- }
+ if (result == -1) {
+ if (DEBUG_SOCKET)
+ printf("SOCKET: failed to set TCP_USER_TIMEOUT (errno=%i)\n", errno);
+ }
#endif
+ }
+ else {
+ /* out of memory */
+ close(sock);
+ if (DEBUG_SOCKET)
+ printf("SOCKET: out of memory\n");
+ }
}
else {
if (DEBUG_SOCKET)
@@ -402,13 +425,35 @@ TcpSocket_create()
return self;
}
-
void
Socket_setConnectTimeout(Socket self, uint32_t timeoutInMs)
{
self->connectTimeout = timeoutInMs;
}
+bool
+Socket_bind(Socket self, const char* srcAddress, int srcPort)
+{
+ struct sockaddr_in localAddress;
+
+ if (!prepareAddress(srcAddress, srcPort, &localAddress))
+ return false;
+
+ int result = bind(self->fd, (struct sockaddr*)&localAddress, sizeof(localAddress));
+
+ if (result == -1) {
+ if (DEBUG_SOCKET)
+ printf("SOCKET: failed to bind TCP socket (errno=%i)\n", errno);
+
+ close(self->fd);
+ self->fd = -1;
+
+ return false;
+ }
+
+ return true;
+}
+
bool
Socket_connectAsync(Socket self, const char* address, int port)
{
@@ -417,7 +462,7 @@ Socket_connectAsync(Socket self, const char* address, int port)
if (DEBUG_SOCKET)
printf("SOCKET: connect: %s:%i\n", address, port);
- if (!prepareServerAddress(address, port, &serverAddress))
+ if (!prepareAddress(address, port, &serverAddress))
return false;
fd_set fdSet;
@@ -627,6 +672,8 @@ Socket_read(Socket self, uint8_t* buf, int size)
case EAGAIN:
return 0;
+ case EBADF:
+ return -1;
default:
@@ -647,7 +694,7 @@ Socket_write(Socket self, uint8_t* buf, int size)
return -1;
/* MSG_NOSIGNAL - prevent send to signal SIGPIPE when peer unexpectedly closed the socket */
- int retVal = send(self->fd, buf, size, MSG_NOSIGNAL);
+ int retVal = send(self->fd, buf, size, MSG_NOSIGNAL | MSG_DONTWAIT);
if (retVal == -1) {
if (errno == EAGAIN) {
@@ -701,7 +748,7 @@ UdpSocket_bind(UdpSocket self, const char* address, int port)
{
struct sockaddr_in localAddress;
- if (!prepareServerAddress(address, port, &localAddress)) {
+ if (!prepareAddress(address, port, &localAddress)) {
close(self->fd);
self->fd = 0;
return false;
@@ -727,7 +774,7 @@ UdpSocket_sendTo(UdpSocket self, const char* address, int port, uint8_t* msg, in
{
struct sockaddr_in remoteAddress;
- if (!prepareServerAddress(address, port, &remoteAddress)) {
+ if (!prepareAddress(address, port, &remoteAddress)) {
if (DEBUG_SOCKET)
printf("SOCKET: failed to lookup remote address %s\n", address);
diff --git a/hal/socket/win32/socket_win32.c b/hal/socket/win32/socket_win32.c
index 411265d8..2753154a 100644
--- a/hal/socket/win32/socket_win32.c
+++ b/hal/socket/win32/socket_win32.c
@@ -1,26 +1,14 @@
/*
* socket_win32.c
*
- * Copyright 2013-2020 Michael Zillgith
+ * Copyright 2013-2021 Michael Zillgith
*
- * This file is part of libIEC61850.
- *
- * libIEC61850 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 3 of the License, or
- * (at your option) any later version.
- *
- * libIEC61850 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 libIEC61850. If not, see .
- *
- * See COPYING file for the complete license text.
+ * This file is part of Platform Abstraction Layer (libpal)
+ * for libiec61850, libmms, and lib60870.
*/
+#define _WINSOCK_DEPRECATED_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
@@ -65,13 +53,14 @@ struct sUdpSocket {
HandleSet
Handleset_new(void)
{
- HandleSet result = (HandleSet) GLOBAL_MALLOC(sizeof(struct sHandleSet));
+ HandleSet result = (HandleSet) GLOBAL_MALLOC(sizeof(struct sHandleSet));
- if (result != NULL) {
- FD_ZERO(&result->handles);
- result->maxHandle = INVALID_SOCKET;
- }
- return result;
+ if (result != NULL) {
+ FD_ZERO(&result->handles);
+ result->maxHandle = INVALID_SOCKET;
+ }
+
+ return result;
}
void
@@ -97,37 +86,40 @@ void
Handleset_removeSocket(HandleSet self, const Socket sock)
{
if (self != NULL && sock != NULL && sock->fd != INVALID_SOCKET) {
- FD_CLR(sock->fd, &self->handles);
+ FD_SET(sock->fd, &self->handles);
+
+ if ((sock->fd > self->maxHandle) || (self->maxHandle == INVALID_SOCKET))
+ self->maxHandle = sock->fd;
}
}
int
Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
{
- int result;
+ int result;
- if ((self != NULL) && (self->maxHandle != INVALID_SOCKET)) {
- struct timeval timeout;
+ if ((self != NULL) && (self->maxHandle != INVALID_SOCKET)) {
+ struct timeval timeout;
- timeout.tv_sec = timeoutMs / 1000;
- timeout.tv_usec = (timeoutMs % 1000) * 1000;
+ timeout.tv_sec = timeoutMs / 1000;
+ timeout.tv_usec = (timeoutMs % 1000) * 1000;
- fd_set handles;
+ fd_set handles;
- memcpy((void*)&handles, &(self->handles), sizeof(fd_set));
+ memcpy((void*)&handles, &(self->handles), sizeof(fd_set));
- result = select(self->maxHandle + 1, &handles, NULL, NULL, &timeout);
- } else {
- result = -1;
- }
+ result = select(self->maxHandle + 1, &handles, NULL, NULL, &timeout);
+ } else {
+ result = -1;
+ }
- return result;
+ return result;
}
void
Handleset_destroy(HandleSet self)
{
- GLOBAL_FREEMEM(self);
+ GLOBAL_FREEMEM(self);
}
static bool wsaStartupCalled = false;
@@ -172,18 +164,18 @@ setSocketNonBlocking(Socket self)
}
static bool
-prepareServerAddress(const char* address, int port, struct sockaddr_in* sockaddr)
+prepareAddress(const char *address, int port, struct sockaddr_in *sockaddr)
{
-
- memset((char *) sockaddr , 0, sizeof(struct sockaddr_in));
+ memset((char *)sockaddr, 0, sizeof(struct sockaddr_in));
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);
+ memcpy((char *)&sockaddr->sin_addr.s_addr, (char *)server->h_addr, server->h_length);
}
else
sockaddr->sin_addr.s_addr = htonl(INADDR_ANY);
@@ -240,7 +232,7 @@ TcpServerSocket_create(const char* address, int port)
struct sockaddr_in server_addr;
- if (!prepareServerAddress(address, port, &server_addr))
+ if (!prepareAddress(address, port, &server_addr))
return NULL;
listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
@@ -269,14 +261,20 @@ TcpServerSocket_create(const char* address, int port)
return NULL;
}
- serverSocket = (ServerSocket) GLOBAL_MALLOC(sizeof(struct sServerSocket));
+ serverSocket = (ServerSocket)GLOBAL_MALLOC(sizeof(struct sServerSocket));
- serverSocket->fd = listen_socket;
- serverSocket->backLog = 10;
+ if (serverSocket) {
+ serverSocket->fd = listen_socket;
+ serverSocket->backLog = 10;
- setSocketNonBlocking((Socket) serverSocket);
+ setSocketNonBlocking((Socket)serverSocket);
- socketCount++;
+ socketCount++;
+ }
+ else {
+ closesocket(listen_socket);
+ wsaShutdown();
+ }
return serverSocket;
}
@@ -346,14 +344,24 @@ TcpSocket_create()
if (sock != INVALID_SOCKET) {
self = (Socket) GLOBAL_MALLOC(sizeof(struct sSocket));
- self->fd = sock;
- self->connectTimeout = 5000;
+ if (self) {
+ self->fd = sock;
+ self->connectTimeout = 5000;
+
+ socketCount++;
+ }
+ else {
+ if (DEBUG_SOCKET)
+ printf("SOCKET: failed to create socket - cannot allocate memory\n");
+
+ closesocket(sock);
+ wsaShutdown();
+ }
- socketCount++;
}
else {
if (DEBUG_SOCKET)
- printf("WIN32_SOCKET: failed to create socket (error code=%i)\n", WSAGetLastError());
+ printf("SOCKET: failed to create socket (error code=%i)\n", WSAGetLastError());
}
return self;
@@ -365,6 +373,29 @@ Socket_setConnectTimeout(Socket self, uint32_t timeoutInMs)
self->connectTimeout = timeoutInMs;
}
+bool
+Socket_bind(Socket self, const char* srcAddress, int srcPort)
+{
+ struct sockaddr_in localAddress;
+
+ if (!prepareAddress(srcAddress, srcPort, &localAddress))
+ return false;
+
+ int result = bind(self->fd, (struct sockaddr*)&localAddress, sizeof(localAddress));
+
+ if (result == SOCKET_ERROR) {
+ if (DEBUG_SOCKET)
+ printf("SOCKET: failed to bind TCP socket (errno=%i)\n", WSAGetLastError());
+
+ closesocket(self->fd);
+ self->fd = -1;
+
+ return false;
+ ]
+
+ return true;
+}
+
bool
Socket_connectAsync(Socket self, const char* address, int port)
{
@@ -381,7 +412,7 @@ Socket_connectAsync(Socket self, const char* address, int port)
return false;
}
- if (!prepareServerAddress(address, port, &serverAddress))
+ if (!prepareAddress(address, port, &serverAddress))
return false;
setSocketNonBlocking(self);
@@ -438,7 +469,7 @@ Socket_connect(Socket self, const char* address, int port)
{
struct sockaddr_in serverAddress;
- if (!prepareServerAddress(address, port, &serverAddress))
+ if (!prepareAddress(address, port, &serverAddress))
return false;
setSocketNonBlocking(self);
@@ -456,7 +487,7 @@ Socket_connect(Socket self, const char* address, int port)
timeout.tv_sec = self->connectTimeout / 1000;
timeout.tv_usec = (self->connectTimeout % 1000) * 1000;
- if (select(self->fd + 1, NULL, &fdSet, NULL, &timeout) <= 0)
+ if (select((int)self->fd + 1, NULL, &fdSet, NULL, &timeout) <= 0)
return false;
else
return true;
@@ -647,7 +678,7 @@ UdpSocket_bind(UdpSocket self, const char* address, int port)
{
struct sockaddr_in localAddress;
- if (!prepareServerAddress(address, port, &localAddress)) {
+ if (!prepareAddress(address, port, &localAddress)) {
closesocket(self->fd);
self->fd = 0;
return false;
@@ -673,7 +704,7 @@ UdpSocket_sendTo(UdpSocket self, const char* address, int port, uint8_t* msg, in
{
struct sockaddr_in remoteAddress;
- if (!prepareServerAddress(address, port, &remoteAddress)) {
+ if (!prepareAddress(address, port, &remoteAddress)) {
if (DEBUG_SOCKET)
printf("SOCKET: failed to lookup remote address %s\n", address);
diff --git a/hal/thread/bsd/thread_bsd.c b/hal/thread/bsd/thread_bsd.c
index 23ed9512..ef501a9e 100644
--- a/hal/thread/bsd/thread_bsd.c
+++ b/hal/thread/bsd/thread_bsd.c
@@ -1,39 +1,24 @@
/**
* thread_bsd.c
*
- * Copyright 2016 Michael Zillgith
+ * Copyright 2013-2021 Michael Zillgith
*
- * This file is part of libIEC61850.
- *
- * libIEC61850 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 3 of the License, or
- * (at your option) any later version.
- *
- * libIEC61850 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 libIEC61850. If not, see .
- *
- * See COPYING file for the complete license text.
+ * This file is part of Platform Abstraction Layer (libpal)
+ * for libiec61850, libmms, and lib60870.
*/
#include
#include
#include
#include "hal_thread.h"
-
#include "lib_memory.h"
struct sThread {
- ThreadExecutionFunction function;
- void* parameter;
- pthread_t pthread;
- int state;
- bool autodestroy;
+ ThreadExecutionFunction function;
+ void* parameter;
+ pthread_t pthread;
+ int state;
+ bool autodestroy;
};
Semaphore
@@ -62,7 +47,8 @@ Semaphore_post(Semaphore self)
void
Semaphore_destroy(Semaphore self)
{
- sem_close(self);
+ sem_destroy((sem_t*) self);
+ GLOBAL_FREEMEM(self);
}
Thread
@@ -85,38 +71,39 @@ destroyAutomaticThread(void* parameter)
{
Thread thread = (Thread) parameter;
- thread->function(thread->parameter);
+ thread->function(thread->parameter);
- GLOBAL_FREEMEM(thread);
+ GLOBAL_FREEMEM(thread);
- pthread_exit(NULL);
+ pthread_exit(NULL);
}
void
Thread_start(Thread thread)
{
- if (thread->autodestroy == true) {
- pthread_create(&thread->pthread, NULL, destroyAutomaticThread, thread);
- pthread_detach(thread->pthread);
- }
- else
- pthread_create(&thread->pthread, NULL, thread->function, thread->parameter);
-
- thread->state = 1;
+ if (thread->autodestroy == true) {
+ pthread_create(&thread->pthread, NULL, destroyAutomaticThread, thread);
+ pthread_detach(thread->pthread);
+ }
+ else
+ pthread_create(&thread->pthread, NULL, thread->function, thread->parameter);
+
+ thread->state = 1;
}
void
Thread_destroy(Thread thread)
{
- if (thread->state == 1) {
- pthread_join(thread->pthread, NULL);
- }
+ if (thread->state == 1) {
+ pthread_join(thread->pthread, NULL);
+ }
- GLOBAL_FREEMEM(thread);
+ GLOBAL_FREEMEM(thread);
}
void
Thread_sleep(int millies)
{
- usleep(millies * 1000);
+ usleep(millies * 1000);
}
+
diff --git a/hal/thread/linux/thread_linux.c b/hal/thread/linux/thread_linux.c
index 488b7339..3c36d157 100644
--- a/hal/thread/linux/thread_linux.c
+++ b/hal/thread/linux/thread_linux.c
@@ -1,40 +1,24 @@
/*
* thread_linux.c
*
- * Copyright 2013 Michael Zillgith
+ * Copyright 2013-2021 Michael Zillgith
*
- * This file is part of libIEC61850.
- *
- * libIEC61850 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 3 of the License, or
- * (at your option) any later version.
- *
- * libIEC61850 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 libIEC61850. If not, see .
- *
- * See COPYING file for the complete license text.
+ * This file is part of Platform Abstraction Layer (libpal)
+ * for libiec61850, libmms, and lib60870.
*/
-
#include
#include
#include
#include "hal_thread.h"
-
#include "lib_memory.h"
struct sThread {
- ThreadExecutionFunction function;
- void* parameter;
- pthread_t pthread;
- int state;
- bool autodestroy;
+ ThreadExecutionFunction function;
+ void* parameter;
+ pthread_t pthread;
+ int state;
+ bool autodestroy;
};
Semaphore
@@ -70,16 +54,16 @@ Semaphore_destroy(Semaphore self)
Thread
Thread_create(ThreadExecutionFunction function, void* parameter, bool autodestroy)
{
- Thread thread = (Thread) GLOBAL_MALLOC(sizeof(struct sThread));
+ Thread thread = (Thread) GLOBAL_MALLOC(sizeof(struct sThread));
- if (thread != NULL) {
+ if (thread != NULL) {
thread->parameter = parameter;
thread->function = function;
thread->state = 0;
thread->autodestroy = autodestroy;
- }
+ }
- return thread;
+ return thread;
}
static void*
@@ -87,39 +71,39 @@ destroyAutomaticThread(void* parameter)
{
Thread thread = (Thread) parameter;
- thread->function(thread->parameter);
+ thread->function(thread->parameter);
- GLOBAL_FREEMEM(thread);
+ GLOBAL_FREEMEM(thread);
- pthread_exit(NULL);
+ pthread_exit(NULL);
}
void
Thread_start(Thread thread)
{
- if (thread->autodestroy == true) {
- pthread_create(&thread->pthread, NULL, destroyAutomaticThread, thread);
- pthread_detach(thread->pthread);
- }
- else
- pthread_create(&thread->pthread, NULL, thread->function, thread->parameter);
-
- thread->state = 1;
+ if (thread->autodestroy == true) {
+ pthread_create(&thread->pthread, NULL, destroyAutomaticThread, thread);
+ pthread_detach(thread->pthread);
+ }
+ else
+ pthread_create(&thread->pthread, NULL, thread->function, thread->parameter);
+
+ thread->state = 1;
}
void
Thread_destroy(Thread thread)
{
- if (thread->state == 1) {
- pthread_join(thread->pthread, NULL);
- }
+ if (thread->state == 1) {
+ pthread_join(thread->pthread, NULL);
+ }
- GLOBAL_FREEMEM(thread);
+ GLOBAL_FREEMEM(thread);
}
void
Thread_sleep(int millies)
{
- usleep(millies * 1000);
+ usleep(millies * 1000);
}
diff --git a/hal/thread/macos/thread_macos.c b/hal/thread/macos/thread_macos.c
index 64d9a6dd..2ba58b06 100644
--- a/hal/thread/macos/thread_macos.c
+++ b/hal/thread/macos/thread_macos.c
@@ -1,7 +1,7 @@
/**
* thread_macos.c
*
- * Copyright 2013-2019 MZ Automation GmbH
+ * Copyright 2013-2021 Michael Zillgith
*
* This file is part of Platform Abstraction Layer (libpal)
* for libiec61850, libmms, and lib60870.
diff --git a/hal/thread/win32/thread_win32.c b/hal/thread/win32/thread_win32.c
index aa72e613..7b17401d 100644
--- a/hal/thread/win32/thread_win32.c
+++ b/hal/thread/win32/thread_win32.c
@@ -1,24 +1,10 @@
/*
* thread_win32.c
*
- * Copyright 2013, 2014 Michael Zillgith
+ * Copyright 2013-2021 Michael Zillgith
*
- * This file is part of libIEC61850.
- *
- * libIEC61850 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 3 of the License, or
- * (at your option) any later version.
- *
- * libIEC61850 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 libIEC61850. If not, see .
- *
- * See COPYING file for the complete license text.
+ * This file is part of Platform Abstraction Layer (libpal)
+ * for libiec61850, libmms, and lib60870.
*/
#include
diff --git a/hal/time/unix/time.c b/hal/time/unix/time.c
index 5c1bffe7..44094038 100644
--- a/hal/time/unix/time.c
+++ b/hal/time/unix/time.c
@@ -3,26 +3,11 @@
*
* Copyright 2013-2021 Michael Zillgith
*
- * This file is part of libIEC61850.
- *
- * libIEC61850 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 3 of the License, or
- * (at your option) any later version.
- *
- * libIEC61850 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 libIEC61850. If not, see .
- *
- * See COPYING file for the complete license text.
+ * This file is part of Platform Abstraction Layer (libpal)
+ * for libiec61850, libmms, and lib60870.
*/
#include "hal_time.h"
-
#include
#ifdef CONFIG_SYSTEM_HAS_CLOCK_GETTIME
diff --git a/hal/time/win32/time.c b/hal/time/win32/time.c
index 1e7adfe3..25faf710 100644
--- a/hal/time/win32/time.c
+++ b/hal/time/win32/time.c
@@ -1,61 +1,45 @@
/*
* time.c
*
- * Copyright 2013, 2014 Michael Zillgith
+ * Copyright 2013-2021 Michael Zillgith
*
- * This file is part of libIEC61850.
- *
- * libIEC61850 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 3 of the License, or
- * (at your option) any later version.
- *
- * libIEC61850 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 libIEC61850. If not, see .
- *
- * See COPYING file for the complete license text.
+ * This file is part of Platform Abstraction Layer (libpal)
+ * for libiec61850, libmms, and lib60870.
*/
#include "hal_time.h"
-
#include
-
#include
uint64_t
Hal_getTimeInMs()
{
- FILETIME ft;
- uint64_t now;
+ FILETIME ft;
+ uint64_t now;
+
+ static const uint64_t DIFF_TO_UNIXTIME = 11644473600000ULL;
- static const uint64_t DIFF_TO_UNIXTIME = 11644473600000ULL;
-
- GetSystemTimeAsFileTime(&ft);
+ GetSystemTimeAsFileTime(&ft);
- now = (LONGLONG)ft.dwLowDateTime + ((LONGLONG)(ft.dwHighDateTime) << 32LL);
+ now = (LONGLONG)ft.dwLowDateTime + ((LONGLONG)(ft.dwHighDateTime) << 32LL);
- return (now / 10000LL) - DIFF_TO_UNIXTIME;
+ return (now / 10000LL) - DIFF_TO_UNIXTIME;
}
nsSinceEpoch
Hal_getTimeInNs()
{
- FILETIME ft;
+ FILETIME ft;
- static const uint64_t DIFF_TO_UNIXTIME = 11644473600000000000ULL;
+ static const uint64_t DIFF_TO_UNIXTIME = 11644473600000000000ULL;
- GetSystemTimeAsFileTime(&ft);
+ GetSystemTimeAsFileTime(&ft);
- nsSinceEpoch nsTime = (LONGLONG)ft.dwLowDateTime + ((LONGLONG)(ft.dwHighDateTime) << 32LL);
+ nsSinceEpoch nsTime = (LONGLONG)ft.dwLowDateTime + ((LONGLONG)(ft.dwHighDateTime) << 32LL);
- nsTime = nsTime * 100LL - DIFF_TO_UNIXTIME;
+ nsTime = nsTime * 100LL - DIFF_TO_UNIXTIME;
- return nsTime;
+ return nsTime;
}
bool
@@ -65,8 +49,8 @@ Hal_setTimeInNs(nsSinceEpoch nsTime)
FILETIME ft;
- ft.dwLowDateTime = (uint32_t)(t & 0xffffffff);
- ft.dwHighDateTime = (uint32_t)(t >> 32);
+ ft.dwLowDateTime = (uint32_t)(t & 0xffffffff);
+ ft.dwHighDateTime = (uint32_t)(t >> 32);
SYSTEMTIME st;
diff --git a/hal/tls/mbedtls/mbedtls_config.h b/hal/tls/mbedtls/mbedtls_config.h
index 27d2aa83..e8414377 100644
--- a/hal/tls/mbedtls/mbedtls_config.h
+++ b/hal/tls/mbedtls/mbedtls_config.h
@@ -40,6 +40,7 @@
#define MBEDTLS_SSL_SRV_C
#define MBEDTLS_SSL_TLS_C
#define MBEDTLS_X509_CRT_PARSE_C
+#define MBEDTLS_X509_CRL_PARSE_C
#define MBEDTLS_X509_USE_C
#define MBEDTLS_SSL_CACHE_C
diff --git a/hal/tls/mbedtls/tls_mbedtls.c b/hal/tls/mbedtls/tls_mbedtls.c
index 6f651769..4e3af470 100644
--- a/hal/tls/mbedtls/tls_mbedtls.c
+++ b/hal/tls/mbedtls/tls_mbedtls.c
@@ -3,7 +3,7 @@
*
* TLS API for TCP/IP protocol stacks
*
- * Copyright 2017 MZ Automation GmbH
+ * Copyright 2017-2021 Michael Zillgith, MZ Automation GmbH
*
* Implementation of the TLS abstraction layer for mbedtls
*
@@ -14,6 +14,7 @@
#include "tls_socket.h"
#include "hal_thread.h"
#include "lib_memory.h"
+#include "hal_time.h"
#include "linked_list.h"
#include "mbedtls/platform.h"
@@ -27,9 +28,7 @@
#include "mbedtls/debug.h"
#if (CONFIG_DEBUG_TLS == 1)
-#define DEBUG_PRINT(appId, fmt, ...) fprintf(stderr, "%s: " fmt, \
- appId, \
- __VA_ARGS__)
+#define DEBUG_PRINT(appId, fmt, ...) fprintf(stderr, "%s: " fmt, appId, ## __VA_ARGS__);
#else
#define DEBUG_PRINT(fmt, ...) {do {} while(0);}
#endif
@@ -44,15 +43,23 @@ struct sTLSConfiguration {
mbedtls_x509_crt cacerts;
+ mbedtls_x509_crl crl;
+
mbedtls_ssl_config conf;
LinkedList /* */ allowedCertificates;
bool chainValidation;
bool allowOnlyKnownCertificates;
- /* TLS session renegotioation time in milliseconds */
+ /* TLS session renegotiation interval in milliseconds */
int renegotiationTimeInMs;
+ /* TLS minimum version allowed (default: TLS_VERSION_TLS_1_0) */
+ TLSConfigVersion minVersion;
+
+ /* TLS minimum version allowed (default: TLS_VERSION_TLS_1_2) */
+ TLSConfigVersion maxVersion;
+
bool setupComplete;
};
@@ -64,6 +71,9 @@ struct sTLSSocket {
bool storePeerCert;
uint8_t* peerCert;
int peerCertLength;
+
+ /* time of last session renegotiation (used to calculate next renegotiation time) */
+ uint64_t lastRenegotiationTime;
};
static bool
@@ -147,7 +157,27 @@ verifyCertificate (void* parameter, mbedtls_x509_crt *crt, int certificate_depth
return 0;
}
+/*
+ * Finish configuration when used the first time.
+ */
+static bool
+TLSConfiguration_setupComplete(TLSConfiguration self)
+{
+ if (self->setupComplete == false) {
+ mbedtls_ssl_conf_ca_chain( &(self->conf), &(self->cacerts), NULL );
+
+ int ret = mbedtls_ssl_conf_own_cert( &(self->conf), &(self->ownCertificate), &(self->ownKey));
+
+ if (ret != 0) {
+ DEBUG_PRINT("TLS", "mbedtls_ssl_conf_own_cert returned %d\n", ret);
+ return false;
+ }
+ self->setupComplete = true;
+ }
+
+ return true;
+}
TLSConfiguration
TLSConfiguration_create()
@@ -157,7 +187,8 @@ TLSConfiguration_create()
if (self != NULL) {
mbedtls_ssl_config_init( &(self->conf) );
mbedtls_x509_crt_init( &(self->ownCertificate) );
- mbedtls_x509_crt_init( &(self->cacerts));
+ mbedtls_x509_crt_init( &(self->cacerts) );
+ mbedtls_x509_crl_init( &(self->crl) );
mbedtls_pk_init( &(self->ownKey) );
mbedtls_entropy_init( &(self->entropy) );
mbedtls_ctr_drbg_init( &(self->ctr_drbg) );
@@ -173,11 +204,16 @@ TLSConfiguration_create()
mbedtls_ssl_conf_authmode(&(self->conf), MBEDTLS_SSL_VERIFY_REQUIRED);
- mbedtls_ssl_conf_renegotiation(&(self->conf), MBEDTLS_SSL_RENEGOTIATION_DISABLED);
+ mbedtls_ssl_conf_renegotiation(&(self->conf), MBEDTLS_SSL_RENEGOTIATION_ENABLED);
/* static int hashes[] = {3,4,5,6,7,8,0}; */
/* mbedtls_ssl_conf_sig_hashes(&(self->conf), hashes); */
+ self->minVersion = TLS_VERSION_TLS_1_0;
+ self->maxVersion = TLS_VERSION_NOT_SELECTED;
+
+ self->renegotiationTimeInMs = -1; /* no automatic renegotiation */
+
self->allowedCertificates = LinkedList_create();
/* default behavior is to allow all certificates that are signed by the CA */
@@ -195,6 +231,18 @@ TLSConfiguration_setClientMode(TLSConfiguration self)
self->conf.endpoint = MBEDTLS_SSL_IS_CLIENT;
}
+void
+TLSConfiguration_setMinTlsVersion(TLSConfiguration self, TLSConfigVersion version)
+{
+ self->minVersion = version;
+}
+
+void
+TLSConfiguration_setMaxTlsVersion(TLSConfiguration self, TLSConfigVersion version)
+{
+ self->maxVersion = version;
+}
+
void
TLSConfiguration_setChainValidation(TLSConfiguration self, bool value)
{
@@ -213,7 +261,7 @@ TLSConfiguration_setOwnCertificate(TLSConfiguration self, uint8_t* certificate,
int ret = mbedtls_x509_crt_parse(&(self->ownCertificate), certificate, certLen);
if (ret != 0)
- DEBUG_PRINT("mbedtls_x509_crt_parse returned %d\n", ret);
+ DEBUG_PRINT("TLS", "mbedtls_x509_crt_parse returned %d\n", ret);
return (ret == 0);
}
@@ -309,6 +357,29 @@ TLSConfiguration_addCACertificateFromFile(TLSConfiguration self, const char* fil
return (ret == 0);
}
+bool
+TLSConfiguration_addCRL(TLSConfiguration self, uint8_t* crl, int crlLen)
+{
+ int ret = mbedtls_x509_crl_parse(&(self->crl), crl, crlLen);
+
+ if (ret != 0) {
+ DEBUG_PRINT("TLS", "mbedtls_x509_crl_parse returned %d\n", ret);
+ }
+
+ return (ret == 0);
+}
+
+bool
+TLSConfiguration_addCRLFromFile(TLSConfiguration self, const char* filename)
+{
+ int ret = mbedtls_x509_crl_parse_file(&(self->crl), filename);
+
+ if (ret != 0)
+ DEBUG_PRINT("TLS", "mbedtls_x509_crl_parse_file returned %d\n", ret);
+
+ return (ret == 0);
+}
+
void
TLSConfiguration_setRenegotiationTime(TLSConfiguration self, int timeInMs)
{
@@ -320,6 +391,7 @@ TLSConfiguration_destroy(TLSConfiguration self)
{
mbedtls_x509_crt_free(&(self->ownCertificate));
mbedtls_x509_crt_free(&(self->cacerts));
+ mbedtls_x509_crl_free(&(self->crl));
mbedtls_pk_free(&(self->ownKey));
mbedtls_ssl_config_free(&(self->conf));
@@ -351,26 +423,42 @@ readFunction(void* ctx, unsigned char* buf, size_t len)
return ret;
}
-/*
- * Finish configuration when used the first time.
- */
-static bool
-TLSConfiguration_setupComplete(TLSConfiguration self)
+static int
+getMajorVersion(TLSConfigVersion version)
{
- if (self->setupComplete == false) {
- mbedtls_ssl_conf_ca_chain( &(self->conf), &(self->cacerts), NULL );
-
- int ret = mbedtls_ssl_conf_own_cert( &(self->conf), &(self->ownCertificate), &(self->ownKey));
-
- if (ret != 0) {
- DEBUG_PRINT("TLS", "mbedtls_ssl_conf_own_cert returned %d\n", ret);
- return false;
- }
-
- self->setupComplete = true;
+ switch(version) {
+ case TLS_VERSION_NOT_SELECTED:
+ return 0;
+ case TLS_VERSION_SSL_3_0:
+ case TLS_VERSION_TLS_1_0:
+ case TLS_VERSION_TLS_1_1:
+ case TLS_VERSION_TLS_1_2:
+ case TLS_VERSION_TLS_1_3:
+ return 3;
+ default:
+ return 0;
}
+}
- return true;
+static int
+getMinorVersion(TLSConfigVersion version)
+{
+ switch(version) {
+ case TLS_VERSION_NOT_SELECTED:
+ return 0;
+ case TLS_VERSION_SSL_3_0:
+ return 0;
+ case TLS_VERSION_TLS_1_0:
+ return 1;
+ case TLS_VERSION_TLS_1_1:
+ return 2;
+ case TLS_VERSION_TLS_1_2:
+ return 3;
+ case TLS_VERSION_TLS_1_3:
+ return 4;
+ default:
+ return 0;
+ }
}
TLSSocket
@@ -392,7 +480,34 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
mbedtls_ssl_conf_verify(&(self->conf), verifyCertificate, (void*) self);
- int ret = mbedtls_ssl_setup( &(self->ssl), &(self->conf) );
+ int ret;
+
+ mbedtls_ssl_conf_ca_chain( &(self->conf), &(configuration->cacerts), NULL );
+
+ if (configuration->minVersion != TLS_VERSION_NOT_SELECTED) {
+ /* set minimum TLS version */
+
+ int majorVer = getMajorVersion(configuration->minVersion);
+ int minorVer = getMinorVersion(configuration->minVersion);
+
+ mbedtls_ssl_conf_min_version( &(self->conf), majorVer, minorVer);
+ }
+
+ if (configuration->maxVersion != TLS_VERSION_NOT_SELECTED) {
+ /* set maximum TLS version */
+
+ int majorVer = getMajorVersion(configuration->maxVersion);
+ int minorVer = getMinorVersion(configuration->maxVersion);
+
+ mbedtls_ssl_conf_max_version( &(self->conf), majorVer, minorVer);
+ }
+
+ ret = mbedtls_ssl_conf_own_cert( &(self->conf), &(configuration->ownCertificate), &(configuration->ownKey));
+
+ if (ret != 0)
+ DEBUG_PRINT("TLS", "mbedtls_ssl_conf_own_cert returned %d\n", ret);
+
+ ret = mbedtls_ssl_setup( &(self->ssl), &(self->conf) );
if (ret != 0)
DEBUG_PRINT("TLS", "mbedtls_ssl_setup returned %d\n", ret);
@@ -404,15 +519,24 @@ TLSSocket_create(Socket socket, TLSConfiguration configuration, bool storeClient
{
if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
{
- DEBUG_PRINT("TLS", "mbedtls_ssl_handshake returned %d\n\n", ret );
+ DEBUG_PRINT("TLS", "handshake failed - mbedtls_ssl_handshake --> %d\n\n", ret );
mbedtls_ssl_free(&(self->ssl));
+ if (self->peerCert) {
+ GLOBAL_FREEMEM(self->peerCert);
+ }
+
GLOBAL_FREEMEM(self);
return NULL;
}
}
+
+ self->lastRenegotiationTime = Hal_getTimeInMs();
+
+ /* TODO check for TLS version warning or alarm condition */
+ /* printf("TLS %i.%i\n", self->ssl.major_ver, self->ssl.minor_ver); */
}
return self;
@@ -439,6 +563,19 @@ TLSSocket_performHandshake(TLSSocket self)
int
TLSSocket_read(TLSSocket self, uint8_t* buf, int size)
{
+ if (self->tlsConfig->renegotiationTimeInMs > 0) {
+ if (Hal_getTimeInMs() > self->lastRenegotiationTime + self->tlsConfig->renegotiationTimeInMs) {
+ if (TLSSocket_performHandshake(self) == false) {
+ DEBUG_PRINT("TLS", " renegotiation failed\n");
+ return -1;
+ }
+ else {
+ DEBUG_PRINT("TLS", " started renegotiation\n");
+ self->lastRenegotiationTime = Hal_getTimeInMs();
+ }
+ }
+ }
+
int ret = mbedtls_ssl_read(&(self->ssl), buf, size);
if ((ret == MBEDTLS_ERR_SSL_WANT_READ) || (ret == MBEDTLS_ERR_SSL_WANT_WRITE))