s32 cellNetCtlGetInfo(s32 code, vm::ptr<CellNetCtlInfo> info) { cellNetCtl.todo("cellNetCtlGetInfo(code=0x%x (%s), info=*0x%x)", code, InfoCodeToName(code), info); if (code == CELL_NET_CTL_INFO_MTU) { #ifdef _WIN32 ULONG bufLen = sizeof(PIP_ADAPTER_ADDRESSES) + 1; PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)malloc(bufLen); DWORD ret; ret = GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &bufLen); if (ret == ERROR_BUFFER_OVERFLOW) { cellNetCtl.error("cellNetCtlGetInfo(INFO_MTU): GetAdaptersAddresses buffer overflow."); free(pAddresses); pAddresses = (PIP_ADAPTER_ADDRESSES)malloc(bufLen); if (pAddresses == nullptr) { cellNetCtl.error("cellNetCtlGetInfo(INFO_MTU): Unable to allocate memory for pAddresses."); return CELL_NET_CTL_ERROR_NET_CABLE_NOT_CONNECTED; } } ret = GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &bufLen); if (ret == NO_ERROR) { PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddresses; for (int c = 0; c < rpcs3::config.misc.net._interface.value(); c++) { pCurrAddresses = pCurrAddresses->Next; } info->mtu = pCurrAddresses->Mtu; } else { cellNetCtl.error("cellNetCtlGetInfo(INFO_MTU): Call to GetAdaptersAddresses failed. (%d)", ret); info->mtu = 1500; // Seems to be the default value on Windows 10. } free(pAddresses); #else struct ifaddrs *ifaddr, *ifa; s32 family, n; if (getifaddrs(&ifaddr) == -1) { cellNetCtl.error("cellNetCtlGetInfo(INFO_MTU): Call to getifaddrs returned negative."); } for (ifa = ifaddr, n = 0; ifa != nullptr; ifa = ifa->ifa_next, n++) { if (ifa->ifa_addr == nullptr) { continue; } if (n < rpcs3::config.misc.net._interface.value()) { continue; } family = ifa->ifa_addr->sa_family; if (family == AF_INET) { u32 fd = open("/proc/net/dev", O_RDONLY); struct ifreq freq; if (ioctl(fd, SIOCGIFMTU, &freq) == -1) { cellNetCtl.error("cellNetCtlGetInfo(INFO_MTU): Call to ioctl failed."); } else { info->mtu = (u32)freq.ifr_mtu; } close(fd); } } freeifaddrs(ifaddr); #endif } else if (code == CELL_NET_CTL_INFO_LINK) { if (rpcs3::config.misc.net.status.value() == misc_net_status::ip_obtained) { info->link = CELL_NET_CTL_LINK_CONNECTED; } else { info->link = CELL_NET_CTL_LINK_DISCONNECTED; } } else if (code == CELL_NET_CTL_INFO_IP_ADDRESS) { // 0.0.0.0 seems to be the default address when no ethernet cables are connected to the PS3 strcpy_trunc(info->ip_address, "0.0.0.0"); #ifdef _WIN32 ULONG bufLen = sizeof(IP_ADAPTER_INFO); PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO*)malloc(bufLen); DWORD ret; ret = GetAdaptersInfo(pAdapterInfo, &bufLen); if (ret == ERROR_BUFFER_OVERFLOW) { cellNetCtl.error("cellNetCtlGetInfo(IP_ADDRESS): GetAdaptersInfo buffer overflow."); free(pAdapterInfo); pAdapterInfo = (IP_ADAPTER_INFO*)malloc(bufLen); if (pAdapterInfo == nullptr) { cellNetCtl.error("cellNetCtlGetInfo(IP_ADDRESS): Unable to allocate memory for pAddresses."); return CELL_NET_CTL_ERROR_NET_CABLE_NOT_CONNECTED; } } ret = GetAdaptersInfo(pAdapterInfo, &bufLen); if (ret == NO_ERROR) { PIP_ADAPTER_INFO pAdapter = pAdapterInfo; for (int c = 0; c < rpcs3::config.misc.net._interface.value(); c++) { pAdapter = pAdapter->Next; } strcpy_trunc(info->ip_address, pAdapter->IpAddressList.IpAddress.String); } else { cellNetCtl.error("cellNetCtlGetInfo(IP_ADDRESS): Call to GetAdaptersInfo failed. (%d)", ret); } free(pAdapterInfo); #else struct ifaddrs *ifaddr, *ifa; s32 family, n; if (getifaddrs(&ifaddr) == -1) { cellNetCtl.error("cellNetCtlGetInfo(IP_ADDRESS): Call to getifaddrs returned negative."); } for (ifa = ifaddr, n = 0; ifa != nullptr; ifa = ifa->ifa_next, n++) { if (ifa->ifa_addr == nullptr) { continue; } if (n < rpcs3::config.misc.net._interface.value()) { continue; } family = ifa->ifa_addr->sa_family; if (family == AF_INET) { strcpy_trunc(info->ip_address, ifa->ifa_addr->sa_data); } } freeifaddrs(ifaddr); #endif } else if (code == CELL_NET_CTL_INFO_NETMASK) { #ifdef _WIN32 ULONG bufLen = sizeof(IP_ADAPTER_INFO) + 1; PIP_ADAPTER_INFO pAdapterInfo = (PIP_ADAPTER_INFO)malloc(bufLen); DWORD ret; ret = GetAdaptersInfo(pAdapterInfo, &bufLen); if (ret == ERROR_BUFFER_OVERFLOW) { cellNetCtl.error("cellNetCtlGetInfo(INFO_NETMASK): GetAdaptersInfo buffer overflow."); free(pAdapterInfo); pAdapterInfo = (IP_ADAPTER_INFO*)malloc(bufLen); if (pAdapterInfo == nullptr) { cellNetCtl.error("cellNetCtlGetInfo(INFO_NETMASK): Unable to allocate memory for pAddresses."); return CELL_NET_CTL_ERROR_NET_CABLE_NOT_CONNECTED; } } ret = GetAdaptersInfo(pAdapterInfo, &bufLen); if (ret == NO_ERROR) { PIP_ADAPTER_INFO pAdapter = pAdapterInfo; for (int c = 0; c < rpcs3::config.misc.net._interface.value(); c++) { pAdapter = pAdapter->Next; } for (int c = 0; c < 4; c++) { info->netmask[c] = (s8)pAdapter->IpAddressList.IpMask.String; } } else { cellNetCtl.error("cellNetCtlGetInfo(INFO_NETMASK): Call to GetAdaptersInfo failed. (%d)", ret); // TODO: Is this the default netmask? info->netmask[0] = 255; info->netmask[1] = 255; info->netmask[2] = 255; info->netmask[3] = 0; } free(pAdapterInfo); #else struct ifaddrs *ifaddr, *ifa; s32 family, n; if (getifaddrs(&ifaddr) == -1) { cellNetCtl.error("cellNetCtlGetInfo(INFO_NETMASK): Call to getifaddrs returned negative."); } for (ifa = ifaddr, n = 0; ifa != nullptr; ifa = ifa->ifa_next, n++) { if (ifa->ifa_addr == nullptr) { continue; } if (n < rpcs3::config.misc.net._interface.value()) { continue; } family = ifa->ifa_addr->sa_family; if (family == AF_INET) { strcpy_trunc(info->ip_address, ifa->ifa_netmask->sa_data); } } freeifaddrs(ifaddr); #endif } return CELL_OK; }
s32 cellNetCtlGetInfo(s32 code, vm::ptr<CellNetCtlInfo> info) { cellNetCtl.Todo("cellNetCtlGetInfo(code=0x%x (%s), info=*0x%x)", code, InfoCodeToName(code), info); if (code == CELL_NET_CTL_INFO_IP_ADDRESS) { #ifdef _WIN32 PIP_ADAPTER_INFO pAdapterInfo; pAdapterInfo = (IP_ADAPTER_INFO*) malloc(sizeof(IP_ADAPTER_INFO)); ULONG buflen = sizeof(IP_ADAPTER_INFO); if (GetAdaptersInfo(pAdapterInfo, &buflen) == ERROR_BUFFER_OVERFLOW) { free(pAdapterInfo); pAdapterInfo = (IP_ADAPTER_INFO*) malloc(buflen); } if (GetAdaptersInfo(pAdapterInfo, &buflen) == NO_ERROR) { PIP_ADAPTER_INFO pAdapter = pAdapterInfo; for (int c = 0; c < Ini.NETInterface.GetValue(); c++) { pAdapter = pAdapter->Next; } strcpy_trunc(info->ip_address, pAdapter->IpAddressList.IpAddress.String); } else { cellNetCtl.Error("cellNetCtlGetInfo(IP_ADDRESS): Call to GetAdaptersInfo failed."); // 0.0.0.0 seems to be the default address when no ethernet cables are connected to the PS3 strcpy_trunc(info->ip_address, "0.0.0.0"); } #else struct ifaddrs *ifaddr, *ifa; int family, s, n; char host[NI_MAXHOST]; if (getifaddrs(&ifaddr) == -1) { LOG_ERROR(HLE, "Call to getifaddrs returned negative."); } for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) { if (ifa->ifa_addr == NULL) { continue; } if (n < Ini.NETInterface.GetValue()) { continue; } family = ifa->ifa_addr->sa_family; if (family == AF_INET) { strcpy_trunc(info->ip_address, ifa->ifa_addr->sa_data); } } freeifaddrs(ifaddr); #endif } else if (code == CELL_NET_CTL_INFO_NETMASK) { #ifdef _WIN32 PIP_ADAPTER_INFO pAdapterInfo; pAdapterInfo = (IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO)); ULONG buflen = sizeof(IP_ADAPTER_INFO); if (GetAdaptersInfo(pAdapterInfo, &buflen) == ERROR_BUFFER_OVERFLOW) { free(pAdapterInfo); pAdapterInfo = (IP_ADAPTER_INFO*)malloc(buflen); } if (GetAdaptersInfo(pAdapterInfo, &buflen) == NO_ERROR) { PIP_ADAPTER_INFO pAdapter = pAdapterInfo; for (int c = 0; c < Ini.NETInterface.GetValue(); c++) { pAdapter = pAdapter->Next; } strcpy_trunc(info->ip_address, pAdapter->IpAddressList.IpMask.String); } else { cellNetCtl.Error("cellNetCtlGetInfo(INFO_NETMASK): Call to GetAdaptersInfo failed."); // TODO: What would be the default netmask? 255.255.255.0? } #else struct ifaddrs *ifaddr, *ifa; int family, s, n; char host[NI_MAXHOST]; if (getifaddrs(&ifaddr) == -1) { LOG_ERROR(HLE, "Call to getifaddrs returned negative."); } for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) { if (ifa->ifa_addr == NULL) { continue; } if (n < Ini.NETInterface.GetValue()) { continue; } family = ifa->ifa_addr->sa_family; if (family == AF_INET) { strcpy_trunc(info->ip_address, ifa->ifa_netmask->sa_data); } } freeifaddrs(ifaddr); #endif } return CELL_OK; }