diff --git a/hal/inc/hal_socket.h b/hal/inc/hal_socket.h index 0f8bb1dc..f4101e17 100644 --- a/hal/inc/hal_socket.h +++ b/hal/inc/hal_socket.h @@ -269,6 +269,9 @@ Socket_read(Socket self, uint8_t* buf, int size); PAL_API int Socket_write(Socket self, uint8_t* buf, int size); +PAL_API char* +Socket_getLocalAddress(Socket self); + /** * \brief Get the address of the peer application (IP address and port number) * diff --git a/hal/socket/bsd/socket_bsd.c b/hal/socket/bsd/socket_bsd.c index c1dd339e..84128d1d 100644 --- a/hal/socket/bsd/socket_bsd.c +++ b/hal/socket/bsd/socket_bsd.c @@ -332,27 +332,22 @@ Socket_connect(Socket self, const char* address, int port) return true; } -char* -Socket_getPeerAddress(Socket self) +static char* +convertAddressToStr(struct sockaddr_storage* addr) { - struct sockaddr_storage addr; - socklen_t addrLen = sizeof(addr); - - getpeername(self->fd, (struct sockaddr*) &addr, &addrLen); - char addrString[INET6_ADDRSTRLEN + 7]; int port; bool isIPv6; - if (addr.ss_family == AF_INET) { - struct sockaddr_in* ipv4Addr = (struct sockaddr_in*) &addr; + 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) { - struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*) &addr; + 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); isIPv6 = true; @@ -360,8 +355,7 @@ Socket_getPeerAddress(Socket self) else return NULL ; - char* clientConnection = GLOBAL_MALLOC(strlen(addrString) + 9); - + char* clientConnection = (char*) GLOBAL_MALLOC(strlen(addrString) + 9); if (isIPv6) sprintf(clientConnection, "[%s]:%i", addrString, port); @@ -371,6 +365,32 @@ Socket_getPeerAddress(Socket self) 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) { + return convertAddressToStr(&addr); + } + else + return NULL; +} + +char* +Socket_getLocalAddress(Socket self) +{ + struct sockaddr_storage addr; + socklen_t addrLen = sizeof(addr); + + if (getsockname(self->fd, (struct sockaddr*) &addr, &addrLen) == 0) { + return convertAddressToStr(&addr); + } + else + return NULL; +} + char* Socket_getPeerAddressStatic(Socket self, char* peerAddressString) { diff --git a/hal/socket/linux/socket_linux.c b/hal/socket/linux/socket_linux.c index 01c497cc..3dffb576 100644 --- a/hal/socket/linux/socket_linux.c +++ b/hal/socket/linux/socket_linux.c @@ -236,7 +236,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) @@ -421,27 +420,22 @@ Socket_connect(Socket self, const char* address, int port) } -char* -Socket_getPeerAddress(Socket self) +static char* +convertAddressToStr(struct sockaddr_storage* addr) { - struct sockaddr_storage addr; - socklen_t addrLen = sizeof(addr); - - getpeername(self->fd, (struct sockaddr*) &addr, &addrLen); - char addrString[INET6_ADDRSTRLEN + 7]; int port; bool isIPv6; - if (addr.ss_family == AF_INET) { - struct sockaddr_in* ipv4Addr = (struct sockaddr_in*) &addr; + 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) { - struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*) &addr; + 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); isIPv6 = true; @@ -451,7 +445,6 @@ Socket_getPeerAddress(Socket self) char* clientConnection = (char*) GLOBAL_MALLOC(strlen(addrString) + 9); - if (isIPv6) sprintf(clientConnection, "[%s]:%i", addrString, port); else @@ -460,6 +453,32 @@ Socket_getPeerAddress(Socket self) 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) { + return convertAddressToStr(&addr); + } + else + return NULL; +} + +char* +Socket_getLocalAddress(Socket self) +{ + struct sockaddr_storage addr; + socklen_t addrLen = sizeof(addr); + + if (getsockname(self->fd, (struct sockaddr*) &addr, &addrLen) == 0) { + return convertAddressToStr(&addr); + } + else + return NULL; +} + char* Socket_getPeerAddressStatic(Socket self, char* peerAddressString) { diff --git a/hal/socket/win32/socket_win32.c b/hal/socket/win32/socket_win32.c index a75eaccc..276b8d83 100644 --- a/hal/socket/win32/socket_win32.c +++ b/hal/socket/win32/socket_win32.c @@ -434,47 +434,69 @@ Socket_connect(Socket self, const char* address, int port) return true; } -char* -Socket_getPeerAddress(Socket self) +static char* +convertAddressToStr(struct sockaddr_storage* addr) { - struct sockaddr_storage addr; - int addrLen = sizeof(addr); - - getpeername(self->fd, (struct sockaddr*) &addr, &addrLen); - - char addrString[INET6_ADDRSTRLEN + 7]; - int addrStringLen = INET6_ADDRSTRLEN + 7; - int port; + char addrString[INET6_ADDRSTRLEN + 7]; + int addrStringLen = INET6_ADDRSTRLEN + 7; + int port; - bool isIPv6; + bool isIPv6; - 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); - isIPv6 = false; - } - 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); - isIPv6 = true; - } - else - return NULL; + 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); + isIPv6 = false; + } + 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); + isIPv6 = true; + } + else + return NULL; - char* clientConnection = (char*) GLOBAL_MALLOC(strlen(addrString) + 9); + char* clientConnection = (char*) GLOBAL_MALLOC(strlen(addrString) + 9); if (isIPv6) sprintf(clientConnection, "[%s]:%i", addrString, port); else sprintf(clientConnection, "%s:%i", addrString, port); - return clientConnection; + 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) { + return convertAddressToStr(&addr); + } + else + return NULL; +} + +char* +Socket_getLocalAddress(Socket self) +{ + struct sockaddr_storage addr; + socklen_t addrLen = sizeof(addr); + + if (getsockname(self->fd, (struct sockaddr*) &addr, &addrLen) == 0) { + return convertAddressToStr(&addr); + } + else + return NULL; } char* diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h index 63c668f1..6bf9b4f5 100644 --- a/src/iec61850/inc/iec61850_server.h +++ b/src/iec61850/inc/iec61850_server.h @@ -525,6 +525,18 @@ IedServer_setAuthenticator(IedServer self, AcseAuthenticator authenticator, void LIB61850_API const char* ClientConnection_getPeerAddress(ClientConnection self); +/** + * \brief get the local address of this connection as string + * + * Note: the returned string is only valid as long as the client connection exists. It is save to use + * the string inside of the connection indication callback function. + * + * \param self the ClientConnection instance + * \return local address as C string. + */ +LIB61850_API const char* +ClientConnection_getLocalAddress(ClientConnection self); + /** * \brief Get the security token associated with this connection * diff --git a/src/iec61850/server/impl/client_connection.c b/src/iec61850/server/impl/client_connection.c index bea9f136..111a8a3a 100644 --- a/src/iec61850/server/impl/client_connection.c +++ b/src/iec61850/server/impl/client_connection.c @@ -128,6 +128,14 @@ ClientConnection_getPeerAddress(ClientConnection self) return MmsServerConnection_getClientAddress(mmsConnection); } +const char* +ClientConnection_getLocalAddress(ClientConnection self) +{ + MmsServerConnection mmsConnection = (MmsServerConnection) self->serverConnectionHandle; + + return MmsServerConnection_getLocalAddress(mmsConnection); +} + void* ClientConnection_getSecurityToken(ClientConnection self) diff --git a/src/mms/inc/mms_server.h b/src/mms/inc/mms_server.h index 9b946b6c..7f827f7b 100644 --- a/src/mms/inc/mms_server.h +++ b/src/mms/inc/mms_server.h @@ -507,6 +507,9 @@ MmsServer_setStatusRequestListener(MmsServer self, MmsStatusRequestListener list LIB61850_INTERNAL char* MmsServerConnection_getClientAddress(MmsServerConnection self); +LIB61850_INTERNAL char* +MmsServerConnection_getLocalAddress(MmsServerConnection self); + LIB61850_INTERNAL void* MmsServerConnection_getSecurityToken(MmsServerConnection self); diff --git a/src/mms/inc_private/iso_server.h b/src/mms/inc_private/iso_server.h index b6707a58..c5991693 100644 --- a/src/mms/inc_private/iso_server.h +++ b/src/mms/inc_private/iso_server.h @@ -69,6 +69,9 @@ typedef void LIB61850_INTERNAL char* IsoConnection_getPeerAddress(IsoConnection self); +LIB61850_INTERNAL char* +IsoConnection_getLocalAddress(IsoConnection self); + LIB61850_INTERNAL void IsoConnection_close(IsoConnection self); diff --git a/src/mms/iso_mms/server/mms_server_connection.c b/src/mms/iso_mms/server/mms_server_connection.c index 448d9a98..a7aa7621 100644 --- a/src/mms/iso_mms/server/mms_server_connection.c +++ b/src/mms/iso_mms/server/mms_server_connection.c @@ -787,6 +787,12 @@ MmsServerConnection_getClientAddress(MmsServerConnection self) return IsoConnection_getPeerAddress(self->isoConnection); } +char* +MmsServerConnection_getLocalAddress(MmsServerConnection self) +{ + return IsoConnection_getLocalAddress(self->isoConnection); +} + void* MmsServerConnection_getSecurityToken(MmsServerConnection self) { diff --git a/src/mms/iso_server/iso_connection.c b/src/mms/iso_server/iso_connection.c index beb8330d..777bc72b 100644 --- a/src/mms/iso_server/iso_connection.c +++ b/src/mms/iso_server/iso_connection.c @@ -82,6 +82,7 @@ struct sIsoConnection AcseConnection* acseConnection; char* clientAddress; + char* localAddress; #if (CONFIG_MMS_THREADLESS_STACK != 1) Thread thread; @@ -122,6 +123,7 @@ finalizeIsoConnection(IsoConnection self) GLOBAL_FREEMEM(self->receiveBuffer); GLOBAL_FREEMEM(self->sendBuffer); GLOBAL_FREEMEM(self->clientAddress); + GLOBAL_FREEMEM(self->localAddress); IsoServer isoServer = self->isoServer; GLOBAL_FREEMEM(self); if (DEBUG_ISO_SERVER) @@ -472,6 +474,7 @@ IsoConnection_create(Socket socket, IsoServer isoServer) self->isoServer = isoServer; self->state = ISO_CON_STATE_RUNNING; self->clientAddress = Socket_getPeerAddress(self->socket); + self->localAddress = Socket_getLocalAddress(self->socket); #if (CONFIG_MMS_THREADLESS_STACK != 1) self->conMutex = Semaphore_create(1); @@ -546,6 +549,12 @@ IsoConnection_getPeerAddress(IsoConnection self) return self->clientAddress; } +char* +IsoConnection_getLocalAddress(IsoConnection self) +{ + return self->localAddress; +} + void IsoConnection_sendMessage(IsoConnection self, ByteBuffer* message, bool handlerMode) {