static void test_ipv6_masking(void) { struct in6_addr dest; struct in6_addr mask; mask = ipv6_create_mask(0); dest = ipv6_addr_bitand(&in6addr_exact, &mask); assert(ipv6_count_cidr_bits(&dest) == 0); mask = ipv6_create_mask(1); dest = ipv6_addr_bitand(&in6addr_exact, &mask); assert(ipv6_count_cidr_bits(&dest) == 1); mask = ipv6_create_mask(13); dest = ipv6_addr_bitand(&in6addr_exact, &mask); assert(ipv6_count_cidr_bits(&dest) == 13); mask = ipv6_create_mask(127); dest = ipv6_addr_bitand(&in6addr_exact, &mask); assert(ipv6_count_cidr_bits(&dest) == 127); mask = ipv6_create_mask(128); dest = ipv6_addr_bitand(&in6addr_exact, &mask); assert(ipv6_count_cidr_bits(&dest) == 128); }
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)); }
static const char * lex_parse_mask(const char *p, struct lex_token *token) { struct lex_token mask; /* Parse just past the '/' as a second integer. Handle errors. */ p = lex_parse_integer__(p + 1, &mask); if (mask.type == LEX_T_ERROR) { lex_token_swap(&mask, token); lex_token_destroy(&mask); return p; } ovs_assert(mask.type == LEX_T_INTEGER); /* Now convert the value and mask into a masked integer token. * We have a few special cases. */ token->type = LEX_T_MASKED_INTEGER; memset(&token->mask, 0, sizeof token->mask); uint32_t prefix_bits = ntohll(mask.value.integer); if (token->format == mask.format) { /* Same format value and mask is always OK. */ token->mask = mask.value; } else if (token->format == LEX_F_IPV4 && mask.format == LEX_F_DECIMAL && prefix_bits <= 32) { /* IPv4 address with decimal mask is a CIDR prefix. */ token->mask.integer = htonll(ntohl(be32_prefix_mask(prefix_bits))); } else if (token->format == LEX_F_IPV6 && mask.format == LEX_F_DECIMAL && prefix_bits <= 128) { /* IPv6 address with decimal mask is a CIDR prefix. */ token->mask.ipv6 = ipv6_create_mask(prefix_bits); } else if (token->format == LEX_F_DECIMAL && mask.format == LEX_F_HEXADECIMAL && token->value.integer == 0) { /* Special case for e.g. 0/0x1234. */ token->format = LEX_F_HEXADECIMAL; token->mask = mask.value; } else { lex_error(token, "Value and mask have incompatible formats."); return p; } /* Check invariant that a 1-bit in the value corresponds to a 1-bit in the * mask. */ for (int i = 0; i < ARRAY_SIZE(token->mask.be32); i++) { ovs_be32 v = token->value.be32[i]; ovs_be32 m = token->mask.be32[i]; if (v & ~m) { lex_error(token, "Value contains unmasked 1-bits."); break; } } /* Done! */ lex_token_destroy(&mask); return p; }
int str_to_ipv6(const char *str_, struct in6_addr *addrp, struct in6_addr *maskp) { char *str = xstrdup(str_); char *save_ptr = NULL; const char *name, *netmask; struct in6_addr addr, mask; int retval; name = strtok_r(str, "/", &save_ptr); retval = name ? lookup_ipv6(name, &addr) : EINVAL; if (retval) { printf("%s: could not convert to IPv6 address\n", str); return -1; } netmask = strtok_r(NULL, "/", &save_ptr); if (netmask) { int prefix = atoi(netmask); if (prefix <= 0 || prefix > 128) { printf("%s: network prefix bits not between 1 and 128\n", str); return -1; } else { mask = ipv6_create_mask(prefix); } } else { mask = in6addr_zero ; *maskp = mask; *addrp = ipv6_addr_bitand(&addr, &in6addr_exact); return 1; } mask = in6addr_exact ; *addrp = ipv6_addr_bitand(&addr, &mask); if (maskp) { *maskp = mask; } else { if (!ipv6_mask_is_exact(&mask)) { printf("%s: netmask not allowed here", str_); return -1; } } free(str); return 1; }
static void add_ipv6_netaddr(struct lport_addresses *laddrs, struct in6_addr addr, unsigned int plen) { laddrs->n_ipv6_addrs++; laddrs->ipv6_addrs = xrealloc(laddrs->ipv6_addrs, laddrs->n_ipv6_addrs * sizeof *laddrs->ipv6_addrs); struct ipv6_netaddr *na = &laddrs->ipv6_addrs[laddrs->n_ipv6_addrs - 1]; memcpy(&na->addr, &addr, sizeof na->addr); na->mask = ipv6_create_mask(plen); na->network = ipv6_addr_bitand(&addr, &na->mask); na->plen = plen; in6_addr_solicited_node(&na->sn_addr, &addr); inet_ntop(AF_INET6, &addr, na->addr_s, sizeof na->addr_s); inet_ntop(AF_INET6, &na->sn_addr, na->sn_addr_s, sizeof na->sn_addr_s); inet_ntop(AF_INET6, &na->network, na->network_s, sizeof na->network_s); }