/* Returns true if 'wc' is exact-match, false if 'wc' wildcards any bits or * fields. */ bool flow_wildcards_is_exact(const struct flow_wildcards *wc) { int i; BUILD_ASSERT_DECL(FLOW_WC_SEQ == 8); if (wc->wildcards || wc->tun_id_mask != htonll(UINT64_MAX) || wc->nw_src_mask != htonl(UINT32_MAX) || wc->nw_dst_mask != htonl(UINT32_MAX) || wc->tp_src_mask != htons(UINT16_MAX) || wc->tp_dst_mask != htons(UINT16_MAX) || wc->vlan_tci_mask != htons(UINT16_MAX) || !ipv6_mask_is_exact(&wc->ipv6_src_mask) || !ipv6_mask_is_exact(&wc->ipv6_dst_mask) || wc->nw_frag_mask != UINT8_MAX) { return false; } for (i = 0; i < FLOW_N_REGS; i++) { if (wc->reg_masks[i] != UINT32_MAX) { return false; } } return true; }
static void test_ipv6_static_masks(void) { /* The 'exact' and 'any' addresses should be identical to * 'in6addr_exact' and 'in6addr_any' definitions, but we redefine * them here since the pre-defined ones are used in the functions * we're testing. */ struct in6_addr exact = {{{ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, \ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }}}; struct in6_addr any = {{{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, \ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }}}; struct in6_addr neither = {{{ 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, \ 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef }}}; assert(ipv6_mask_is_exact(&exact)); assert(!ipv6_mask_is_exact(&any)); assert(!ipv6_mask_is_exact(&neither)); assert(!ipv6_mask_is_any(&exact)); assert(ipv6_mask_is_any(&any)); assert(!ipv6_mask_is_any(&neither)); }
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 void nxm_put_ipv6(struct ofpbuf *b, uint32_t header, const struct in6_addr *value, const struct in6_addr *mask) { if (ipv6_mask_is_any(mask)) { return; } else if (ipv6_mask_is_exact(mask)) { nxm_put_header(b, header); ofpbuf_put(b, value, sizeof *value); } else { nxm_put_header(b, NXM_MAKE_WILD_HEADER(header)); ofpbuf_put(b, value, sizeof *value); ofpbuf_put(b, mask, sizeof *mask); } }
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); } } }
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; }