120 lines
2.7 KiB
C
120 lines
2.7 KiB
C
/**
|
|
* Copyright (c) 2026 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#include "networklinux.h"
|
|
#include "util/memory.h"
|
|
#include "util/string.h"
|
|
#include "assert/assert.h"
|
|
|
|
errorret_t networkLinuxInit() {
|
|
errorOk();
|
|
}
|
|
|
|
errorret_t networkLinuxUpdate() {
|
|
errorOk();
|
|
}
|
|
|
|
bool_t networkLinuxIsConnected() {
|
|
// Call the OS network stack to check for connectivity.
|
|
struct ifaddrs *ifaddr, *ifa;
|
|
if(getifaddrs(&ifaddr) == -1) {
|
|
return false;
|
|
}
|
|
|
|
// Check if any non loopback interfaces have running flag set.
|
|
bool_t connected = false;
|
|
for(ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
|
|
if(!ifa->ifa_name || !ifa->ifa_flags) continue;
|
|
|
|
// Skip loopback (localhost)
|
|
if(ifa->ifa_flags & IFF_LOOPBACK) continue;
|
|
|
|
// Is interface up and running?
|
|
if(!(ifa->ifa_flags & IFF_UP)) continue;
|
|
if(!(ifa->ifa_flags & IFF_RUNNING)) continue;
|
|
|
|
connected = true;
|
|
break;
|
|
}
|
|
|
|
// Free the linked list of interfaces
|
|
freeifaddrs(ifaddr);
|
|
|
|
return connected;
|
|
}
|
|
|
|
errorret_t networkLinuxDispose() {
|
|
errorOk();
|
|
}
|
|
|
|
networkinfo_t networkLinuxGetInfo() {
|
|
networkinfo_t info;
|
|
memoryZero(&info, sizeof(networkinfo_t));
|
|
|
|
bool_t found = false;
|
|
|
|
struct ifaddrs *ifaddr, *ifa;
|
|
if(getifaddrs(&ifaddr) == -1) {
|
|
assertUnreachable("getifaddrs failed");
|
|
}
|
|
|
|
// Find the first non-loopback interface with an IP address
|
|
for(ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
|
|
if(!ifa->ifa_name || !ifa->ifa_flags) continue;
|
|
|
|
// Skip loopback (localhost)
|
|
if(ifa->ifa_flags & IFF_LOOPBACK) continue;
|
|
|
|
// Is interface up and running?
|
|
if(!(ifa->ifa_flags & IFF_UP)) continue;
|
|
if(!(ifa->ifa_flags & IFF_RUNNING)) continue;
|
|
if(ifa->ifa_addr == NULL) continue;
|
|
|
|
// Check for IPv4 address
|
|
if(ifa->ifa_addr->sa_family == AF_INET) {
|
|
info.type = NETWORK_TYPE_IPV4;
|
|
|
|
struct sockaddr_in *sa = (struct sockaddr_in *)ifa->ifa_addr;
|
|
memoryCopy(
|
|
info.ipv4.ip,
|
|
&sa->sin_addr,
|
|
NETWORK_INFO_IPV4_OCTET_COUNT
|
|
);
|
|
|
|
found = true;
|
|
|
|
// sa = (struct sockaddr_in *)ifa->ifa_netmask;
|
|
// memoryCopy(
|
|
// info.ipv4.subnet,
|
|
// &sa->sin_addr,
|
|
// NETWORK_INFO_IPV4_OCTET_COUNT
|
|
// );
|
|
break;
|
|
}
|
|
|
|
// Check for IPv6 address
|
|
#ifdef DUSK_NETWORK_IPV6
|
|
if(ifa->ifa_addr->sa_family == AF_INET6) {
|
|
info.type = NETWORK_TYPE_IPV6;
|
|
|
|
struct sockaddr_in6 *sa = (struct sockaddr_in6 *)ifa->ifa_addr;
|
|
memoryCopy(
|
|
info.ipv6.ip,
|
|
&sa->sin6_addr,
|
|
NETWORK_INFO_IPV6_OCTET_COUNT
|
|
);
|
|
found = true;
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
freeifaddrs(ifaddr);
|
|
|
|
assertTrue(found, "No active network interface found?");
|
|
return info;
|
|
} |