/* * Copyright (c) 2008-2023 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in * the packaging of this file. * * Alternatively, it may be distributed under the terms of the GNU General * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" #import "OFSystemInfo.h" #import "OFSystemInfo+NetworkInterfaces.h" #import "OFData.h" #import "OFDictionary.h" #import "OFLocale.h" #import "OFSocket.h" #import "OFString.h" #include #define interface struct #include #undef interface @implementation OFSystemInfo (NetworkInterfaces) + (OFDictionary OF_GENERIC(OFString *, OFNetworkInterface) *)networkInterfaces { void *pool = objc_autoreleasePoolPush(); OFMutableDictionary *ret = [OFMutableDictionary dictionary]; OFStringEncoding encoding = [OFLocale encoding]; ULONG adapterInfoSize; PIP_ADAPTER_INFO adapterInfo; OFEnumerator *enumerator; OFMutableDictionary *interface; adapterInfoSize = sizeof(IP_ADAPTER_INFO); if ((adapterInfo = malloc(adapterInfoSize)) == NULL) { objc_autoreleasePoolPop(pool); return nil; } @try { ULONG error = GetAdaptersInfo(adapterInfo, &adapterInfoSize); if (error == ERROR_BUFFER_OVERFLOW) { PIP_ADAPTER_INFO newAdapterInfo = realloc( adapterInfo, adapterInfoSize); if (newAdapterInfo == NULL) { objc_autoreleasePoolPop(pool); return nil; } adapterInfo = newAdapterInfo; error = GetAdaptersInfo(adapterInfo, &adapterInfoSize); } if (error != ERROR_SUCCESS) { objc_autoreleasePoolPop(pool); return nil; } for (PIP_ADAPTER_INFO iter = adapterInfo; iter != NULL; iter = iter->Next) { OFString *name, *IPString; OFMutableData *addresses; OFSocketAddress address; name = [OFString stringWithCString: iter->AdapterName encoding: encoding]; if ((interface = [ret objectForKey: name]) == nil) { interface = [OFMutableDictionary dictionary]; [ret setObject: interface forKey: name]; } IPString = [OFString stringWithCString: iter->IpAddressList.IpAddress .String encoding: encoding]; if ([IPString isEqual: @"0.0.0.0"]) continue; if ((addresses = [interface objectForKey: OFNetworkInterfaceIPv4Addresses]) == nil) { addresses = [OFMutableData dataWithItemSize: sizeof(OFSocketAddress)]; [interface setObject: addresses forKey: OFNetworkInterfaceIPv4Addresses]; } address = OFSocketAddressParseIPv4(IPString, 0); [addresses addItem: &address]; } } @finally { free(adapterInfo); } enumerator = [ret objectEnumerator]; while ((interface = [enumerator nextObject]) != nil) [interface makeImmutable]; [ret makeImmutable]; [ret retain]; objc_autoreleasePoolPop(pool); return [ret autorelease]; } @end