mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-10 14:12:04 +08:00
142 lines
3.6 KiB
C
142 lines
3.6 KiB
C
/*
|
|
id_posix.c - network device enumeration for unique id generation
|
|
Copyright (C) 2026 Xash3D FWGS contributors
|
|
|
|
This program 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.
|
|
|
|
This program 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.
|
|
*/
|
|
|
|
#include "platform/platform.h"
|
|
|
|
#if XASH_LINUX
|
|
#include <dirent.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
static qboolean Posix_ValidateNetDevice( const char *dev )
|
|
{
|
|
const char *prefix = "/sys/class/net";
|
|
|
|
// These devices are fake, their mac address is generated each boot, while assign_type is 0
|
|
if( !Q_strnicmp( dev, "ccmni", sizeof( "ccmni" ) - 1 ) || !Q_strnicmp( dev, "ifb", sizeof( "ifb" ) - 1 ))
|
|
return false;
|
|
|
|
byte *pfile = FS_LoadDirectFile( va( "%s/%s/addr_assign_type", prefix, dev ), NULL );
|
|
|
|
// if NULL, it may be old kernel
|
|
if( pfile )
|
|
{
|
|
int assignType = Q_atoi( (char*)pfile );
|
|
|
|
Mem_Free( pfile );
|
|
|
|
// check is MAC address is constant
|
|
if( assignType != 0 )
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
int Posix_GetNetDeviceAddresses( uint64_t *addresses, int max )
|
|
{
|
|
const char *prefix = "/sys/class/net";
|
|
DIR *dir = opendir( prefix );
|
|
struct dirent *entry;
|
|
int count = 0;
|
|
|
|
if( !dir )
|
|
return 0;
|
|
|
|
while(( entry = readdir( dir )) && count < max )
|
|
{
|
|
if( !Q_strcmp( entry->d_name, "." ) || !Q_strcmp( entry->d_name, ".." ))
|
|
continue;
|
|
|
|
if( !Posix_ValidateNetDevice( entry->d_name ))
|
|
continue;
|
|
|
|
int fd = open( va( "%s/%s/address", prefix, entry->d_name ), O_RDONLY );
|
|
|
|
if( fd < 0 )
|
|
continue;
|
|
|
|
char buffer[64];
|
|
int ret = read( fd, buffer, sizeof( buffer ) - 1 );
|
|
|
|
close( fd );
|
|
|
|
if( ret <= 0 )
|
|
continue;
|
|
|
|
buffer[ret] = 0;
|
|
|
|
uint mac[6];
|
|
char term = 0;
|
|
|
|
if( sscanf( buffer, "%02x:%02x:%02x:%02x:%02x:%02x%c", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5], &term ) < 6 )
|
|
continue;
|
|
|
|
// skip malformed or long address devices, we only need MAC addresses and they're always 48-bit
|
|
if( term != '\n' && term != '\0' )
|
|
continue;
|
|
|
|
addresses[count] = ((uint64_t)mac[0] << 40) | ((uint64_t)mac[1] << 32) | ((uint64_t)mac[2] << 24) | ((uint64_t)mac[3] << 16) | ((uint64_t)mac[4] << 8) | (uint64_t)mac[5];
|
|
count++;
|
|
}
|
|
|
|
closedir( dir );
|
|
return count;
|
|
}
|
|
#elif XASH_APPLE || XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <ifaddrs.h>
|
|
#include <net/if.h>
|
|
#include <net/if_dl.h>
|
|
|
|
int Posix_GetNetDeviceAddresses( uint64_t *addresses, int max )
|
|
{
|
|
struct ifaddrs *ifaddr;
|
|
int count = 0;
|
|
|
|
if( getifaddrs( &ifaddr ) < 0 )
|
|
return 0;
|
|
|
|
for( struct ifaddrs *ifa = ifaddr; ifa != NULL && count < max; ifa = ifa->ifa_next )
|
|
{
|
|
if( !ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_LINK )
|
|
continue;
|
|
|
|
if( FBitSet( ifa->ifa_flags, IFF_LOOPBACK | IFF_POINTOPOINT ))
|
|
continue;
|
|
|
|
const struct sockaddr_dl *sdl = (const struct sockaddr_dl *)ifa->ifa_addr;
|
|
|
|
if( sdl->sdl_alen != 6 )
|
|
continue;
|
|
|
|
const byte *mac = (const byte *)LLADDR( sdl );
|
|
|
|
addresses[count] = ((uint64_t)mac[0] << 40) | ((uint64_t)mac[1] << 32) | ((uint64_t)mac[2] << 24) | ((uint64_t)mac[3] << 16) | ((uint64_t)mac[4] << 8) | (uint64_t)mac[5];
|
|
count++;
|
|
}
|
|
|
|
freeifaddrs( ifaddr );
|
|
return count;
|
|
}
|
|
#else
|
|
int Posix_GetNetDeviceAddresses( uint64_t *addresses, int max )
|
|
{
|
|
Con_Reportf( S_WARN "%s: implement me!\n", __func__ );
|
|
return 0;
|
|
}
|
|
#endif
|