| 829 | } |
| 830 | |
| 831 | CSubNet LookupSubNet(const std::string& subnet_str) |
| 832 | { |
| 833 | CSubNet subnet; |
| 834 | assert(!subnet.IsValid()); |
| 835 | if (!ContainsNoNUL(subnet_str)) { |
| 836 | return subnet; |
| 837 | } |
| 838 | |
| 839 | const size_t slash_pos{subnet_str.find_last_of('/')}; |
| 840 | const std::string str_addr{subnet_str.substr(0, slash_pos)}; |
| 841 | std::optional<CNetAddr> addr{LookupHost(str_addr, /*fAllowLookup=*/false)}; |
| 842 | |
| 843 | if (addr.has_value()) { |
| 844 | addr = static_cast<CNetAddr>(MaybeFlipIPv6toCJDNS(CService{addr.value(), /*port=*/0})); |
| 845 | if (slash_pos != subnet_str.npos) { |
| 846 | const std::string netmask_str{subnet_str.substr(slash_pos + 1)}; |
| 847 | if (const auto netmask{ToIntegral<uint8_t>(netmask_str)}) { |
| 848 | // Valid number; assume CIDR variable-length subnet masking. |
| 849 | subnet = CSubNet{addr.value(), *netmask}; |
| 850 | } else { |
| 851 | // Invalid number; try full netmask syntax. Never allow lookup for netmask. |
| 852 | const std::optional<CNetAddr> full_netmask{LookupHost(netmask_str, /*fAllowLookup=*/false)}; |
| 853 | if (full_netmask.has_value()) { |
| 854 | subnet = CSubNet{addr.value(), full_netmask.value()}; |
| 855 | } |
| 856 | } |
| 857 | } else { |
| 858 | // Single IP subnet (<ipv4>/32 or <ipv6>/128). |
| 859 | subnet = CSubNet{addr.value()}; |
| 860 | } |
| 861 | } |
| 862 | |
| 863 | return subnet; |
| 864 | } |
| 865 | |
| 866 | bool IsBadPort(uint16_t port) |
| 867 | { |