| 677 | } |
| 678 | |
| 679 | bool LookupSubNet(const std::string& subnet_str, CSubNet& subnet_out) |
| 680 | { |
| 681 | if (!ValidAsCString(subnet_str)) { |
| 682 | return false; |
| 683 | } |
| 684 | |
| 685 | const size_t slash_pos{subnet_str.find_last_of('/')}; |
| 686 | const std::string str_addr{subnet_str.substr(0, slash_pos)}; |
| 687 | CNetAddr addr; |
| 688 | |
| 689 | if (LookupHost(str_addr, addr, /*fAllowLookup=*/false)) { |
| 690 | if (slash_pos != subnet_str.npos) { |
| 691 | const std::string netmask_str{subnet_str.substr(slash_pos + 1)}; |
| 692 | uint8_t netmask; |
| 693 | if (ParseUInt8(netmask_str, &netmask)) { |
| 694 | // Valid number; assume CIDR variable-length subnet masking. |
| 695 | subnet_out = CSubNet{addr, netmask}; |
| 696 | return subnet_out.IsValid(); |
| 697 | } else { |
| 698 | // Invalid number; try full netmask syntax. Never allow lookup for netmask. |
| 699 | CNetAddr full_netmask; |
| 700 | if (LookupHost(netmask_str, full_netmask, /*fAllowLookup=*/false)) { |
| 701 | subnet_out = CSubNet{addr, full_netmask}; |
| 702 | return subnet_out.IsValid(); |
| 703 | } |
| 704 | } |
| 705 | } else { |
| 706 | // Single IP subnet (<ipv4>/32 or <ipv6>/128). |
| 707 | subnet_out = CSubNet{addr}; |
| 708 | return subnet_out.IsValid(); |
| 709 | } |
| 710 | } |
| 711 | return false; |
| 712 | } |
| 713 | |
| 714 | bool SetSocketNonBlocking(const SOCKET& hSocket, bool fNonBlocking) |
| 715 | { |