9 Star 31 Fork 22

10km/common_source_cpp

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
if_utilits.cpp 14.91 KB
一键复制 编辑 原始数据 按行查看 历史
#include "if_utilits.h"
#include <sample_log.h>
#include <common_utilits.h>
#include <algorithm>
#ifdef _WIN32
#include <iostream>
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windef.h>
#include <iphlpapi.h>
#include <vector>
#include <errno.h>
#pragma comment(lib,"iphlpapi.lib")
#else
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <vector>
#include <regex>
#endif
//************************************
// 归一化MAC地址字符串转大写并去除分隔符
// @param const std::string & input [in] MAC地址字符串
// @param std::string & mac [out] 成功保存归一化后的MAC地址字符串
// @param bool debugLog 是否输出调试信息
// @return bool 成功返回true,否则返回false
//************************************
static bool normalize_nic(const std::string &input, std::string &mac,bool debugLog)
{
try
{
std::regex pattern("[^\\w\\d]+");
mac = gdface::toupper(std::regex_replace(input, pattern, ""));
return true;
}
catch (const std::regex_error & e)
{
auto errmsg = std::string(typeid(e).name()) + ":" + e.what();
SAMPLE_LOG_IF(debugLog, "REGEX error:{}", errmsg);
return false;
}
}
#if __linux__
/**
* 获取网卡设备MAC/IP地址
* @param required_name 指定网卡名,未指定则获取第一个非loopback网卡
* @param addrtype 请求的地址类型:0:MAC地址,1:IP地址
* @param fmt 返回的数据是否格式化为可见字符串,为true时将MAC地址格式化为16进制MAC地址字符串,IP地址格式化为.分割的十进制IP地址
* @param addr [out] 返回的MAC/IP地址
* @param debugLog 是否输出调试信息
* @return 调用成功返回true,否则返回false
*/
static bool get_if_address(const std::string &required_name, int addrtype, bool fmt, std::string &addr, bool debugLog)
{
int fd, nic;
struct ifreq buf[8];
struct ifconf ifc;
bool nameMatchRequired = !required_name.empty();
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0)
{
gdface::raii fd_guard([=]() { close(fd); });/** 自动关闭fd */
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = (caddr_t)buf;
if (!ioctl(fd, SIOCGIFCONF, (char *)&ifc))
{
nic = ifc.ifc_len / sizeof(struct ifreq);
for (int i = 0; i < nic; ++i)
{
if (nameMatchRequired && strcmp(required_name.c_str(), buf[i].ifr_name))
{
continue;
}
if (ioctl(fd, SIOCGIFFLAGS, (char *)&buf[i]) == 0) {
if ((buf[i].ifr_flags & IFF_LOOPBACK)) { // don't count loopback
continue;
}
switch (addrtype)
{
case 0:
{
if (!(ioctl(fd, SIOCGIFHWADDR, (char *)&buf[i])))
{
if (!fmt)
{
addr = std::string((char*)buf[i].ifr_hwaddr.sa_data, 6);
}
else {
addr = gdface::bytes_to_hex_string(buf[i].ifr_hwaddr.sa_data, 6);
}
SAMPLE_LOG_IF(debugLog, "found network interface {} MAC: {}", buf[i].ifr_name, addr);
return true;
}
break;
}
case 1:
default:
{
if (!(ioctl(fd, SIOCGIFADDR, (char *)&buf[i])))
{
auto ipstr = std::string(inet_ntoa(((struct sockaddr_in *)&(buf[i].ifr_addr))->sin_addr));
if (fmt)
{
addr = ipstr;
}
else {
addr = gdface::parse_ip(ipstr);
}
SAMPLE_LOG_IF(debugLog, "found network interface {} IP: {}", buf[i].ifr_name, addr);
return true;
}
break;
}
}
}
}
SAMPLE_LOG_IF(nameMatchRequired && debugLog, "Not found adapter named: {}", required_name);
}
}
return false;
}
/**
* 获取网卡设备MAC地址
* @param mac [out] 返回16进制MAC地址字符串
* @param required_name 指定网卡名,未指定则获取第一个非loopback网卡
* @param fmt 返回的数据是否格式化为可见字符串,为true时将IP地址格式化为.分割的十进制IP地址
* @param debugLog 是否输出调试信息
* @return 调用成功返回true,否则返回false
*/
static bool get_mac(std::string &mac,const std::string &required_name, bool fmt, bool debugLog)
{
return get_if_address(required_name, 0, fmt,mac,debugLog);
}
/**
* 获取网卡设备IP地址
* @param ipaddr [out] 返回.分割十进制IP地址字符串
* @param required_name 指定网卡名,未指定则获取第一个非loopback网卡
* @param fmt 返回的数据是否格式化为可见字符串,为true时将IP地址格式化为.分割的十进制IP地址
* @param debugLog 是否输出调试信息
* @return 调用成功返回true,否则返回false
*/
static bool get_ipaddr(std::string &ipaddr, const std::string &required_name, bool fmt, bool debugLog)
{
return get_if_address(required_name, 1, fmt,ipaddr, debugLog);
}
//************************************
// 执行command指定的控制台命令,返回结果保存在output,返回执行命令的状态码
// @param const std::string & command
// @param bool debugLog 是否输出调试信息
// @param std::string & output
// @return int 命令执行成功 执行命令返回的状态码,失败则返回错误代码
//************************************
static int shell_command(const std::string &command, bool debugLog,std::string &output)
{
if(command.empty())
{
SAMPLE_LOG_IF(debugLog, "command is empty");
return -1;
}
FILE *stream;
SAMPLE_LOG_IF(debugLog, "command [{}]",command);
stream = popen(command.c_str(),"r");
if(!stream)
{
SAMPLE_LOG_IF(debugLog, "fail to open pipe");
return -1;
}
/* 输出缓冲区 */
std::vector<char> buf(1024,0);
auto readsize = fread(buf.data(), sizeof(char), buf.capacity(), stream); //将刚刚FILE* stream的数据流读取到buf中
auto msg = std::string(buf.data(), readsize);
auto code = pclose(stream);
SAMPLE_LOG_IF(debugLog, "{} exitcode={}",msg,code);
output = msg;
return code;
}
//************************************
// 通过执行shell命令("cat /sys/class/net/$ifname/address")获取MAC地址
// @param const std::string & ifname 网卡名
// @param bool debugLog 是否输出调试信息
// @param std::string & mac 返回16进制MAC地址字符串
// @return bool 调用成功返回true,否则返回false
//************************************
static bool get_mac_by_cat_sys_class_net(const std::string &ifname, bool debugLog, std::string &mac)
{
std::string output;
auto cmd = std::string("cat /sys/class/net/").append(ifname).append("/address 2>/dev/null");
if (shell_command(cmd, debugLog, output))
{
return false;
}
if (normalize_nic(output, mac, debugLog))
{
SAMPLE_LOG_IF(debugLog, "found network interface {} {}", ifname, mac);
return true;
}
return false;
}
/**
* 通过执行shell命令获取MAC地址
* @param mac [out] 返回16进制MAC地址字符串
* @param required_name 指定网卡名,未指定则获取第一个非loopback网卡
* @return 调用成功返回true,否则返回false
*/
static bool get_mac_by_pipe(const std::string required_name, bool debugLog, std::string &mac)
{
std::string output;
if (!required_name.empty())
{
return get_mac_by_cat_sys_class_net(required_name, debugLog, mac);
}
/* 列出所有网卡设备名 */
if (shell_command("ls /sys/class/net 2>/dev/null", debugLog, output))
{
return false;
}
/* 排除 lo 的所有网卡设备名称 */
auto ifnames = std::regex_replace(output, std::regex("lo"), "");
auto vifnames = gdface::split(ifnames, "\\s+");
if (vifnames.empty())
{
SAMPLE_LOG_IF(debugLog, "NOT FOUND NET INTERFACE");
return false;
}
size_t pos = ifnames.find("eth0");
if (pos != std::string::npos) {
return get_mac_by_cat_sys_class_net("eth0", debugLog, mac);
}
pos = ifnames.find("wlan0");
if (pos != std::string::npos) {
return get_mac_by_cat_sys_class_net("wlan0", debugLog, mac);
}
return get_mac_by_cat_sys_class_net(vifnames[0], debugLog, mac);
}
#endif
bool ifu::get_ip_address(const std::string& ifname, std::string &ip_address, bool debugLog)
{
SAMPLE_LOG_IF(debugLog, "ifname [{}]", ifname);
#ifdef _WIN32
/*ULONG bufsize = 0;
if (ERROR_BUFFER_OVERFLOW != GetAdaptersInfo(nullptr, &bufsize))
{
SAMPLE_LOG_IF(debugLog,"GetAdaptersInfo Failed! ErrorCode: {}", GetLastError());
return false;
}*/
std::vector<IP_ADAPTER_INFO> adapterInfo(16);
ULONG bufsize = adapterInfo.size()*sizeof(IP_ADAPTER_INFO);
auto status = GetAdaptersInfo(adapterInfo.data(), &bufsize);
if (ERROR_SUCCESS == status)
{
if (ifname.empty())
{
ip_address = std::string((char*)adapterInfo[0].IpAddressList.IpAddress.String);
SAMPLE_LOG_IF(debugLog,"found network interface {} IP:{}", adapterInfo[0].AdapterName, ip_address);
return true;
}
else
{
/** 遍历所有网卡,查找指定名字的网卡并返回 */
PIP_ADAPTER_INFO pAdapterInfo = &adapterInfo[0];
while (pAdapterInfo)
{
SAMPLE_LOG_IF(debugLog, "---- network interface {}", pAdapterInfo->AdapterName);
if (0 == std::strncmp(pAdapterInfo->AdapterName, ifname.c_str(), sizeof(pAdapterInfo->AdapterName)))
{
ip_address = std::string((char*)pAdapterInfo->IpAddressList.IpAddress.String);
SAMPLE_LOG_IF(debugLog, "found network interface {} IP:{}", pAdapterInfo->AdapterName,ip_address);
return true;
}
pAdapterInfo = pAdapterInfo->Next;
}
SAMPLE_LOG_IF(debugLog, "Not found adapter named: {}", ifname);
}
}
else {
SAMPLE_LOG_IF(debugLog,"GetAdaptersInfo Failed! ErrorCode: {}", GetLastError());
}
return false;
#elif __linux__
if (!ifname.empty())
{
return get_ipaddr(ip_address, ifname, true, debugLog);
}
if (get_ipaddr(ip_address,"eth0", true, debugLog))
{
return true;
}
if (get_ipaddr(ip_address,"wlan0", true, debugLog))
{
return true;
}
return get_ipaddr(ip_address, ifname, true, debugLog);
#else
SAMPLE_LOG_IF(debugLog, "UNIMPLEMENTED");
return false;
#endif
}
bool ifu::get_mac_address(const std::string& ifname, std::string &mac_address, bool debugLog)
{
SAMPLE_LOG_IF(debugLog, "ifname [{}]", ifname);
#ifdef _WIN32
/*ULONG bufsize = 0;
if (ERROR_BUFFER_OVERFLOW != GetAdaptersInfo(nullptr, &bufsize))
{
SAMPLE_LOG_IF(debugLog, "GetAdaptersInfo Failed! ErrorCode: {}", GetLastError());
return false;
}*/
std::vector<IP_ADAPTER_INFO> adapterInfo(16);
ULONG bufsize = adapterInfo.size()*sizeof(IP_ADAPTER_INFO);
auto status = GetAdaptersInfo(adapterInfo.data(), &bufsize);
if (ERROR_SUCCESS == status)
{
if (ifname.empty())
{
auto buf = gdface::bytes_to_hex_string(adapterInfo[0].Address, 6);
SAMPLE_LOG_IF(debugLog, "found network interface {} MAC:{} ", adapterInfo[0].AdapterName, buf);
mac_address = buf;
return true;
}
else
{
// 遍历所有网卡,查找指定名字的网卡并返回
PIP_ADAPTER_INFO pAdapterInfo = &adapterInfo[0];
while (pAdapterInfo)
{
SAMPLE_LOG_IF(debugLog, "---- network interface {}", pAdapterInfo->AdapterName);
if (0 == std::strncmp(pAdapterInfo->AdapterName, ifname.c_str(), sizeof(pAdapterInfo->AdapterName)))
{
auto buf = gdface::bytes_to_hex_string(pAdapterInfo->Address,6);
SAMPLE_LOG_IF(debugLog, "found network interface {} MAC:{}", pAdapterInfo->AdapterName, buf);
mac_address = buf;
return true;
}
pAdapterInfo = pAdapterInfo->Next;
}
SAMPLE_LOG_IF(debugLog, "Not found adapter named: {}", ifname);
}
}
else {
SAMPLE_LOG_IF(debugLog, "GetAdaptersInfo Failed! ErrorCode: {}", GetLastError());
}
return false;
#else
if (!ifname.empty())
{
if (!get_mac_by_pipe(ifname, debugLog, mac_address))
{
return get_mac(mac_address,ifname, true, debugLog);
}
return true;
}
if (get_mac_by_pipe("eth0", debugLog, mac_address))
{
return true;
}
if (get_mac(mac_address,"eth0", true,debugLog))
{
return true;
}
if (get_mac_by_pipe("wlan0", debugLog, mac_address))
{
return true;
}
if (get_mac(mac_address,"wlan0", true,debugLog))
{
return true;
}
return get_mac(mac_address,"", true,debugLog);
#endif
}
bool ifu::find_nic_by_mac(const std::string &input_mac, std::string& ifname, std::string &foundnics, bool debugLog)
{
if (input_mac.empty())
{
SAMPLE_LOG_IF(debugLog, "input_mac is empty");
return false;
}
std::string mac_address;
if (!normalize_nic(input_mac, mac_address, debugLog))
{
return false;
}
SAMPLE_LOG_IF(debugLog, "mac_address [{}]", mac_address);
ifname = "";
foundnics = "";
#ifdef _WIN32
/*ULONG bufsize = 0;
if (ERROR_BUFFER_OVERFLOW != GetAdaptersInfo(nullptr, &bufsize))
{
SAMPLE_LOG_IF(debugLog, "GetAdaptersInfo Failed! ErrorCode: {}", GetLastError());
return false;
}*/
std::vector<IP_ADAPTER_INFO> adapterInfo(16);
ULONG bufsize = adapterInfo.size()*sizeof(IP_ADAPTER_INFO);
auto status = GetAdaptersInfo(adapterInfo.data(), &bufsize);
if (ERROR_SUCCESS == status)
{
// 遍历所有网卡,查找指定MAC地址的网卡并返回
PIP_ADAPTER_INFO pAdapterInfo = &adapterInfo[0];
while (pAdapterInfo)
{
auto buf = gdface::bytes_to_hex_string(pAdapterInfo->Address, 6);
foundnics.append(pAdapterInfo->AdapterName).append("/").append(buf);
SAMPLE_LOG_IF(debugLog, "found network interface {} {}", pAdapterInfo->AdapterName, buf);
std::string m = buf;
if (m == mac_address)
{
ifname = pAdapterInfo->AdapterName;
}
pAdapterInfo = pAdapterInfo->Next;
if (pAdapterInfo)
{
foundnics.append(",");
}
}
SAMPLE_LOG_IF(debugLog && ifname.empty(), "Not found adapter mac: {},found nic:{}", mac_address,foundnics);
return !ifname.empty();
}
else {
SAMPLE_LOG_IF(debugLog, "GetAdaptersInfo Failed! ErrorCode: {}", GetLastError());
}
return false;
#else
std::string output;
/* 列出所有网卡设备名 */
if (shell_command("ls /sys/class/net 2>/dev/null", debugLog, output))
{
return false;
}
/* 排除 lo 的所有网卡设备名称 */
auto ifnames = std::regex_replace(output, std::regex("lo"), "");
auto vifnames = gdface::split(ifnames, "\\s+");
if (vifnames.empty())
{
SAMPLE_LOG_IF(debugLog, "NOT FOUND NET INTERFACE");
return false;
}
SAMPLE_LOG_IF(debugLog, "FOUND NET INTERFACE:{}", ifnames);
for ( int i=0; i<vifnames.size(); ++i)
{
auto name = vifnames[i];
std::string m;
if (!get_mac_by_cat_sys_class_net(name, debugLog, m))
{
continue;
}
foundnics.append(ifname).append("/").append(m);
if (i < vifnames.size() - 1)
{
foundnics.append(",");
}
if (m == mac_address)
{
ifname = name;
}
}
SAMPLE_LOG_IF(debugLog && ifname.empty(), "Not found adapter named: {},found nic:", ifname, foundnics);
return !ifname.empty();
#endif
}
bool ifu::check_mac_matched(const std::string &mac, bool debugFlag, std::string &errmsg)
{
std::string ifname;
std::string foundnics;
/* 检查指定MAC地址是否为本机的MAC地址 */
if (!find_nic_by_mac(mac, ifname, foundnics, debugFlag))
{
errmsg = gdface::log::sample_format("device MAC {} of license file mismatch with current device,found nics:{}", mac, foundnics);
SAMPLE_LOG_IF(debugFlag,"error {}", errmsg);
return false;
}
SAMPLE_LOG_IF(debugFlag,"net interface device with mac {} named {}", mac, ifname);
return true;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/l0km/common_source_cpp.git
git@gitee.com:l0km/common_source_cpp.git
l0km
common_source_cpp
common_source_cpp
master

搜索帮助

D67c1975 1850385 1daf7b77 1850385