From ac9cef1c3ef1efb34e7bbbc2e2bdb122a6e725a7 Mon Sep 17 00:00:00 2001 From: Vasiliy Kiryanov Date: Sun, 17 Nov 2024 13:25:28 -0500 Subject: [PATCH] RFC5424 origin structure added --- include/stumpless/log.h | 18 +++++ src/log.c | 169 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+) diff --git a/include/stumpless/log.h b/include/stumpless/log.h index b7bba3c99..2885ef4b5 100644 --- a/include/stumpless/log.h +++ b/include/stumpless/log.h @@ -689,4 +689,22 @@ vstumplog_trace( int priority, } /* extern "C" */ # endif +/* + * Returns RFC 5424 origin structured data element that provides information about the originator of the log message. + * see: https://datatracker.ietf.org/doc/html/rfc5424#section-7.2 + * + * It used by stumpless' syslog and vsyslogs replacement - stumplog, and vstumplog. + * + * @return stumpless_element with origin structure + * ip - Origin IP address (for now just first address used ipv4 or ipv6) + * enterpriseId - Enterprise ID (skipped for now) + * software - Software name (stumpless) + * swVersion Software version (current version of stumpless) + * + * @since 2.1.1 +*/ +STUMPLESS_PUBLIC_FUNCTION +struct stumpless_element* +get_origin_struct_instance( void ); + #endif /* __STUMPLESS_LOG_H */ diff --git a/src/log.c b/src/log.c index a02292115..cd7347946 100644 --- a/src/log.c +++ b/src/log.c @@ -17,10 +17,26 @@ */ #include +#include +#include + #include +#include "private/memory.h" #include +#include + #include "private/target.h" +#ifdef _WIN32 +#include +#include +#include +#else +#include +#include +#include +#endif + int stump( const char *message, ... ) { int result; @@ -199,3 +215,156 @@ vstumplog_trace( int priority, vstumpless_trace_log( target, priority, file, line, func, message, subs ); } + + +char** get_ip_addresses() { + char **ip_addresses = NULL; + int ip_addresses_counter = 0; + char ip[INET6_ADDRSTRLEN]; + + #ifdef _WIN32 + WSADATA wsaData; + if ( WSAStartup( MAKEWORD(2, 2), &wsaData ) != 0 ) { + perror( "WSAStartup failed" ); + return NULL; + } + + // Get the list of network interfaces + ULONG size = 0; + GetAdaptersAddresses( AF_UNSPEC, 0, NULL, NULL, &size ); + IP_ADAPTER_ADDRESSES *adapterAddresses = (IP_ADAPTER_ADDRESSES *)malloc( size ); + if ( !adapterAddresses ) { + WSACleanup(); // Cleanup before returning + return NULL; + } + if ( GetAdaptersAddresses( AF_UNSPEC, 0, NULL, adapterAddresses, &size ) == NO_ERROR ) { + IP_ADAPTER_ADDRESSES *adapter = adapterAddresses; + while ( adapter ) { + IP_ADAPTER_UNICAST_ADDRESS *unicast = adapter->FirstUnicastAddress; + while ( unicast ) { + if ( unicast->Address.lpSockaddr->sa_family == AF_INET ) { + struct sockaddr_in *sockaddr_in = (struct sockaddr_in *)unicast->Address.lpSockaddr; + inet_ntop(AF_INET, &sockaddr_in->sin_addr, ip, sizeof(ip)); + + char **temp = realloc( ip_addresses, ( ip_addresses_counter + 1 ) * sizeof(char*) ); + if (!temp) { + // Reallocation failed, cleanup + free( adapterAddresses ); + WSACleanup(); + for ( int i = 0; i < ip_addresses_counter; i++ ) { + free(ip_addresses[i]); + } + free(ip_addresses); + return NULL; + } + ip_addresses = temp; + ip_addresses[ip_addresses_counter++] = strdup( ip ); + + } else if ( unicast->Address.lpSockaddr->sa_family == AF_INET6 ) { + struct sockaddr_in6 *sockaddr_in6 = (struct sockaddr_in6 *)unicast->Address.lpSockaddr; + inet_ntop( AF_INET6, &sockaddr_in6->sin6_addr, ip, sizeof( ip ) ); + + char **temp = realloc( ip_addresses, ( ip_addresses_counter + 1 ) * sizeof(char*) ); + if ( !temp ) { + // Reallocation failed, cleanup + free( adapterAddresses ); + WSACleanup(); + for ( int i = 0; i < ip_addresses_counter; i++ ) { + free( ip_addresses[i] ); + } + free( ip_addresses ); + return NULL; + } + ip_addresses = temp; + ip_addresses[ip_addresses_counter++] = strdup(ip); + } + unicast = unicast->Next; + } + adapter = adapter->Next; + } + } + free( adapterAddresses ); + WSACleanup(); + #else + struct ifaddrs *ifaddr, *ifa; + + // Get the list of network interfaces + if ( getifaddrs( &ifaddr ) == -1 ) { + perror( "getifaddrs" ); + return NULL; + } + + // Loop through all the interfaces + for ( ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next ) { + if ( ifa->ifa_addr == NULL ) + continue; + + if ( ifa->ifa_addr->sa_family == AF_INET ) { // IPv4 + struct sockaddr_in *addr = (struct sockaddr_in *)ifa->ifa_addr; + inet_ntop( AF_INET, &addr->sin_addr, ip, sizeof( ip ) ); + char **temp = realloc( ip_addresses, ( ip_addresses_counter + 1 ) * sizeof(char*) ); + if (!temp) { + perror("realloc failed"); + freeifaddrs(ifaddr); + for ( int i = 0; i < ip_addresses_counter; i++ ) { + free( ip_addresses[i] ); + } + free( ip_addresses ); + return NULL; + } + ip_addresses = temp; + ip_addresses[ip_addresses_counter++] = strdup( ip ); + + } else if ( ifa->ifa_addr->sa_family == AF_INET6 ) { // IPv6 + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)ifa->ifa_addr; + inet_ntop( AF_INET6, &addr->sin6_addr, ip, sizeof( ip ) ); + char **temp = realloc( ip_addresses, ( ip_addresses_counter + 1 ) * sizeof( char* ) ); + if ( !temp ) { + perror( "realloc failed" ); + freeifaddrs( ifaddr ); + for ( int i = 0; i < ip_addresses_counter; i++ ) { + free( ip_addresses[i] ); + } + free( ip_addresses ); + return NULL; + } + ip_addresses = temp; + ip_addresses[ip_addresses_counter++] = strdup( ip ); + } + } + + // Free the memory allocated by getifaddrs + freeifaddrs(ifaddr); + #endif + + // Add a NULL terminator to mark the end of the array + ip_addresses = realloc( ip_addresses, ( ip_addresses_counter + 1 ) * sizeof( char* ) ); + if ( ip_addresses ) { + ip_addresses[ip_addresses_counter] = NULL; + } + + return ip_addresses; +} + + +struct stumpless_element* get_origin_struct_instance( void ) { + char** ip_addressess = get_ip_addresses(); + int ip_addresses_counter = 0; + + struct stumpless_version* version = stumpless_get_version(); + + struct stumpless_element *origin_element = alloc_mem( sizeof( *origin_element ) ); + stumpless_set_element_name( origin_element, "origin structure" ); + stumpless_add_new_param( origin_element, "software", "stumpless" ); + stumpless_add_new_param( origin_element, "swVersion", stumpless_version_to_string( version ) ) ; + + if ( ip_addressess[ ip_addresses_counter ] != NULL ) { + stumpless_add_new_param( origin_element, "ip", ip_addressess[ ip_addresses_counter ] ); + + while ( ip_addressess[ ip_addresses_counter ] != NULL ) { + free( ip_addressess[ ip_addresses_counter ] ); + ip_addresses_counter++; + } + free( ip_addressess ); + } +}