/* Given the IPv6 netmask 'netmask', returns the number of bits of the IPv6 * address that it specifies, that is, the number of 1-bits in 'netmask'. * 'netmask' must be a CIDR netmask (see ipv6_is_cidr()). */ int ipv6_count_cidr_bits(const struct in6_addr *netmask) { int i; int count = 0; const uint8_t *netmaskp = &netmask->s6_addr[0]; assert(ipv6_is_cidr(netmask)); for (i=0; i<16; i++) { if (netmaskp[i] == 0xff) { count += 8; } else { uint8_t nm; for(nm = netmaskp[i]; nm; nm <<= 1) { count++; } break; } } return count; }
void print_ipv6_masked(struct ds *s, const struct in6_addr *addr, const struct in6_addr *mask) { print_ipv6_addr(s, addr); if (mask && !ipv6_mask_is_exact(mask)) { if (ipv6_is_cidr(mask)) { int cidr_bits = ipv6_count_cidr_bits(mask); ds_put_format(s, "/%d", cidr_bits); } else { ds_put_char(s, '/'); print_ipv6_addr(s, mask); } } }
static void lex_token_format_masked_integer(const struct lex_token *token, struct ds *s) { enum lex_format format = lex_token_get_format(token); lex_token_format_value(&token->value, format, s); ds_put_char(s, '/'); const union mf_subvalue *mask = &token->mask; if (format == LEX_F_IPV4 && ip_is_cidr(mask->ipv4)) { ds_put_format(s, "%d", ip_count_cidr_bits(mask->ipv4)); } else if (token->format == LEX_F_IPV6 && ipv6_is_cidr(&mask->ipv6)) { ds_put_format(s, "%d", ipv6_count_cidr_bits(&mask->ipv6)); } else { lex_token_format_value(&token->mask, format, s); } }
static void test_ipv6_cidr(void) { struct in6_addr dest; struct in6_addr src = {{{ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, \ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }}}; dest = ipv6_create_mask(0); assert(ipv6_mask_is_any(&dest)); assert(ipv6_count_cidr_bits(&dest) == 0); assert(ipv6_is_cidr(&dest)); dest = ipv6_create_mask(128); assert(ipv6_mask_is_exact(&dest)); assert(ipv6_count_cidr_bits(&dest) == 128); assert(ipv6_is_cidr(&dest)); dest = ipv6_create_mask(1); assert(ipv6_count_cidr_bits(&dest) == 1); assert(ipv6_is_cidr(&dest)); dest = ipv6_create_mask(13); assert(ipv6_count_cidr_bits(&dest) == 13); assert(ipv6_is_cidr(&dest)); dest = ipv6_create_mask(64); assert(ipv6_count_cidr_bits(&dest) == 64); assert(ipv6_is_cidr(&dest)); dest = ipv6_create_mask(95); assert(ipv6_count_cidr_bits(&dest) == 95); assert(ipv6_is_cidr(&dest)); dest = ipv6_create_mask(96); assert(ipv6_count_cidr_bits(&dest) == 96); assert(ipv6_is_cidr(&dest)); dest = ipv6_create_mask(97); assert(ipv6_count_cidr_bits(&dest) == 97); assert(ipv6_is_cidr(&dest)); dest = ipv6_create_mask(127); assert(ipv6_count_cidr_bits(&dest) == 127); assert(ipv6_is_cidr(&dest)); src.s6_addr[8] = 0xf0; assert(ipv6_is_cidr(&src)); assert(ipv6_count_cidr_bits(&src) == 68); src.s6_addr[15] = 0x01; assert(!ipv6_is_cidr(&src)); src.s6_addr[15] = 0x00; assert(ipv6_is_cidr(&src)); src.s6_addr[8] = 0x0f; assert(!ipv6_is_cidr(&src)); }