NetworkInfo.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #include "StdAfx.h"
  2. #include "NetConfigCommon.h"
  3. #include "NetConfig.h"
  4. #include "NetworkInfo.h"
  5. #include <stdio.h>
  6. #include <ws2tcpip.h>
  7. using namespace std;
  8. #pragma comment(lib,"Iphlpapi.lib") //需要添加Iphlpapi.lib库
  9. NetCardInfo::NetCardInfo()
  10. {
  11. }
  12. std::vector<std::shared_ptr<NetCardInfo>> NetCardInfo::GetNetworkInfo() {
  13. std::vector<std::shared_ptr<NetCardInfo>> info_list;
  14. {
  15. /*****************获取网卡名、mac地址、ip地址、子网掩码、默认网关**********************/
  16. //PIP_ADAPTER_INFO结构体指针存储本机网卡信息
  17. PIP_ADAPTER_INFO adapter_info = new IP_ADAPTER_INFO();
  18. PIP_ADAPTER_INFO adapter = nullptr;
  19. unsigned long stSize = sizeof(IP_ADAPTER_INFO);
  20. memset(adapter_info, 0, stSize);
  21. //调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量;其中stSize参数既是一个输入量也是一个输出量
  22. auto ret = GetAdaptersInfo(adapter_info, &stSize);
  23. if (ERROR_BUFFER_OVERFLOW == ret) {
  24. delete adapter_info;
  25. adapter_info = (PIP_ADAPTER_INFO)new BYTE[stSize];
  26. ret = GetAdaptersInfo(adapter_info, &stSize);
  27. }
  28. if (ERROR_SUCCESS == ret) { // 可能有多网卡,因此通过循环去判断
  29. adapter = adapter_info; // 保存链表头,等下需要释放空间
  30. while (adapter) {
  31. NetCardInfo info;
  32. if (info.ParseInfo(adapter)) {
  33. info_list.push_back(std::make_shared<NetCardInfo>(info)); // 转换成功才添加
  34. }
  35. adapter = adapter->Next;
  36. }
  37. }
  38. //释放内存空间
  39. if (adapter_info) {
  40. delete adapter_info;
  41. }
  42. }
  43. {
  44. /******************获取连接名和dns地址************************/
  45. PIP_ADAPTER_ADDRESSES addresses = nullptr, cur_addresses = nullptr;
  46. ULONG outBufLen = 15000; // Allocate a 15 KB buffer to start with.
  47. ULONG Iterations = 0, ret = 0;
  48. do {
  49. addresses = (IP_ADAPTER_ADDRESSES*)new BYTE[outBufLen];
  50. if (addresses != nullptr) {
  51. // 0x07,Skip_UNICAST、Skip_ANYCAST、Skip_MULTICAST
  52. ret = GetAdaptersAddresses(AF_UNSPEC, 0x07, nullptr, addresses, &outBufLen);
  53. if (ret == NO_ERROR) break;
  54. if (ret == ERROR_BUFFER_OVERFLOW) {
  55. delete addresses;
  56. addresses = nullptr;
  57. }
  58. }
  59. Iterations++;
  60. } while ((ret == ERROR_BUFFER_OVERFLOW) && (Iterations < 3));
  61. if (ret == NO_ERROR) {
  62. // If successful, output some information from the data we received
  63. cur_addresses = addresses;
  64. while (cur_addresses) {
  65. std::vector<std::shared_ptr<NetCardInfo>>::iterator it;
  66. for (it = info_list.begin(); it != info_list.end(); ++it) {
  67. if ((*it)->info_.adapter_name == cur_addresses->AdapterName)
  68. {
  69. break;
  70. }
  71. }
  72. /*auto it = std::find_if(info_list.begin(), info_list.end(), [&](auto& info)
  73. { // 根据适配器的GUID找到相应的对象,添加信息
  74. return info->info_.adapter_name == cur_addresses->AdapterName;
  75. });
  76. */
  77. if (it != info_list.end()) {
  78. (*it)->ParseInfo(cur_addresses);
  79. }
  80. else { // 没找到的只会是Loopback型的,因为环回地址不需要
  81. #if _DEBUG
  82. std::cout << "Not found:" << cur_addresses->AdapterName << std::endl;
  83. #endif
  84. }
  85. cur_addresses = cur_addresses->Next;
  86. }
  87. }
  88. if (addresses) delete addresses;
  89. }
  90. return std::move(info_list);
  91. }
  92. const NetCardInfo::Info& NetCardInfo::GetNetCardInfo()
  93. {
  94. return info_;
  95. }
  96. void NetCardInfo::show() {
  97. std::cout << "网卡名:" << info_.adapter_name << std::endl;
  98. std::cout << "连接名:" << info_.friendly_name << std::endl;
  99. std::cout << "Mac地址:" << info_.physical_addr << std::endl;
  100. std::cout << "Ip地址:" << info_.ip << std::endl;
  101. std::cout << "子网掩码:" << info_.ip_mask << std::endl;
  102. std::cout << "默认网关:" << info_.gateway << std::endl;
  103. std::cout << "默认Dns:" << info_.default_dns << std::endl;
  104. std::cout << "备选Dns:" << info_.backup_dns << std::endl;
  105. std::cout << std::endl;
  106. }
  107. void NetCardInfo::show(char *buffer, int len) {
  108. _snprintf(buffer, len,
  109. "网卡名:%s, 连接名:%s, Mac地址:%s, Ip地址:%s, 子网掩码:%s, 默认网关:%s, 默认Dns:%s, 备选Dns:%s.",
  110. info_.adapter_name.c_str(), info_.friendly_name.c_str(), info_.physical_addr.c_str(), info_.ip.c_str(),
  111. info_.ip_mask.c_str(), info_.gateway.c_str(), info_.default_dns.c_str(), info_.backup_dns.c_str());
  112. }
  113. bool NetCardInfo::SetDns(const std::string& default_dns, const std::string& backup_dns) {
  114. if (config_ && config_->set_dns(default_dns, backup_dns)) {
  115. info_.default_dns = default_dns; // 更新信息
  116. info_.backup_dns = backup_dns;
  117. return true;
  118. }
  119. return false;
  120. }
  121. bool NetCardInfo::SetAutoDns() { // 设置autodns之后需要更新信息,目前未在设置里自动更新
  122. return config_ && config_->set_auto_dns();
  123. }
  124. bool NetCardInfo::SetIpConfig(const std::string& ip, const std::string& ip_mask)
  125. {
  126. //设置静态ip之前要调用下enable_dhcp, 可以把以前设置的ip和网关都清空, 否则注册表会有多个ip信息
  127. if (!config_) return false;
  128. config_->enable_dhcp();
  129. if (config_->set_ip_config(ip, ip_mask)) {
  130. info_.ip = ip; // 设置成功就更新信息
  131. info_.ip_mask = ip_mask;
  132. return true;
  133. }
  134. return false;
  135. }
  136. bool NetCardInfo::SetGateway(const std::string& gateway) {
  137. if (!config_) return false; // 设置默认网关需要在静态ip的模式下才能成功,静态模式依靠SetIpConfig,
  138. bool flag = true;
  139. if (gateway != "0.0.0.0")
  140. flag = config_ && config_->set_gateway(gateway); // 如果要设置的gateway不为"0.0.0.0",那就直接设置
  141. else if (info_.gateway != gateway)
  142. flag = config_->set_gateway(info_.ip); // 设置当前正在使用的ip为网关,就能清空网关
  143. if (flag) info_.gateway = gateway; // 不论是清空还是设置网关,只要成功了,就需要更新当前的信息
  144. return flag;
  145. }
  146. bool NetCardInfo::ParseInfo(PIP_ADAPTER_INFO adapter_info) {
  147. if (!adapter_info) return false;
  148. if (adapter_info->Type == MIB_IF_TYPE_LOOPBACK) return false; // 忽略环回地址
  149. info_.adapter_name = adapter_info->AdapterName;
  150. char mac[128] = { 0 };
  151. for (DWORD i = 0; i < adapter_info->AddressLength; i++)
  152. sprintf(mac + strlen(mac)
  153. , (i < adapter_info->AddressLength - 1 ? "%02X-" : "%02X")
  154. , adapter_info->Address[i]);
  155. info_.physical_addr = mac;
  156. info_.ip = adapter_info->IpAddressList.IpAddress.String; // 虽然一个网卡可能有多个ip和子网掩码,但是这里只需要第一个即可
  157. info_.ip_mask = adapter_info->IpAddressList.IpMask.String;
  158. info_.gateway = adapter_info->GatewayList.IpAddress.String;
  159. config_.reset(new NetConfig(info_.adapter_name)); // 根据网卡的GUID创建一个config对象,提供网卡属性的修改
  160. return true;
  161. }
  162. // get sockaddr, IPv4 or IPv6:
  163. static void* get_in_addr(struct sockaddr* sa)
  164. {
  165. if (sa->sa_family == AF_INET)
  166. return &(((struct sockaddr_in*)sa)->sin_addr);
  167. return &(((struct sockaddr_in6*)sa)->sin6_addr);
  168. }
  169. // 主要获取dns和适配器的名称,其余的由重载的另一个函数获取
  170. bool NetCardInfo::ParseInfo(PIP_ADAPTER_ADDRESSES adapter_addresses) {
  171. auto dns_server = adapter_addresses->FirstDnsServerAddress;
  172. if (dns_server) {
  173. for (int count = 0; dns_server != nullptr; count++) {
  174. struct addrinfo* p;
  175. char s[INET6_ADDRSTRLEN];
  176. inet_ntop(dns_server->Address.lpSockaddr->sa_family, get_in_addr((struct sockaddr*)dns_server->Address.lpSockaddr), s, sizeof s);
  177. std::string dns = s;
  178. /*unsigned char* addr = (unsigned char*)(dns_server->Address.lpSockaddr->sa_data);
  179. std::string dns = "";
  180. for (int i = 2; i < 6; ++i) { // 将addr[2]-addr[5]转为字符串表示,每一个字节就是dns的一段
  181. dns += std::to_string(addr[i]);
  182. if (i != 5) dns += ".";
  183. }
  184. */
  185. if (!count) {
  186. info_.default_dns = dns;
  187. }
  188. else {
  189. info_.backup_dns = dns;
  190. break;
  191. }
  192. dns_server = dns_server->Next;
  193. }
  194. }
  195. info_.friendly_name = CW2A(adapter_addresses->FriendlyName); // 获取名称
  196. return true;
  197. }