2011-10-07 106 views
1

我需要驗證某個IPv6前綴。我瞭解到inet_pton()可用於驗證IPv6地址本身,但它不接受前綴長度以及地址(fec1 :: 9/96)。驗證IPv6網絡掩碼前綴

IPv6前綴如何在C/C++中驗證?

謝謝!

+0

「驗證」 假設一個客觀的標準。你想要什麼?僅僅是語法檢查?檢查網絡是否真的在線?或者介於兩者之間? – MSalters

回答

1
// @param[in] cidr_ - contains an IPv6 network address (as a string) and a routing prefix 
bool valid_ipv6_cidr(std::pair<std::string, uint16_t> const& cidr_) { 
    if(cidr_.first.find(':') != std::string::npos) { 
     _error_msg = "IPv6 address does not contain a ':'"; 
     return false; 
    } 
    struct in6_addr addr6; 
    if(!inet_pton(AF_INET6, cidr_.first.c_str(), &(addr6.s6_addr))) { 
     _error_msg = "invalid IPv6 address"; 
     return false; 
    } 
    uint16_t routing_prefix = cidr_.second; 
    if(routing_prefix > MAX_IPV6_CIDR_MASK) { // MAX_IPV6_CIDR_MASK = 128 
     _error_msg = "invalid IPv6 CIDR mask"; 
     return false; 
    } 
    for(size_t i=0; i<16; i++) { 
     uint8_t byte_netmask = 0xff; 
     if(routing_prefix >= 8) { 
      routing_prefix -= 8; 
     } else if(routing_prefix == 0) { 
      byte_netmask = 0; 
     } else { // routing_prefix is between 1 and 7, inclusive 
      byte_netmask <<= (8 - routing_prefix); 
      routing_prefix = 0; 
     } 
     //std::cout << "DEBUG: mask=" << std::hex 
     // << static_cast<unsigned>(byte_netmask) << std::dec << std::endl; 
     if((addr6.s6_addr[i] & byte_netmask) != addr6.s6_addr[i]) { 
      std::ostringstream oss; 
      oss << "invalid CIDR: " << cidr_.first  << '/' 
       << cidr_.second  << " - mask ("  << std::hex 
       << static_cast<unsigned>(byte_netmask) << std::dec 
       << ") failed at byte " 
       << i << " (" << std::hex 
       << static_cast<unsigned>(addr6.s6_addr[i]) << std::dec << ')'; 
      _error_msg = oss.str(); 
      return false; 
     } 
    } 
    // check for special case ..../0 
    if((cidr_.second == 0) && (cidr_.first != "::")) { 
     _error_msg = "invalid CIDR - /0 found with something other than ::"; 
     return false; 
    } 
    return true; 
}