static inline bool is_left_child(const struct lrtr_ip_addr *addr, unsigned int lvl) { /* A node must be inserted as left child if bit <lvl> of the IP address * is 0 otherwise as right child */ return lrtr_ip_addr_is_zero(lrtr_ip_addr_get_bits(addr, lvl, 1)); }
/* * @brief Test IPv4 address bit operations required by trie */ static void get_bits_testv4(void) { struct lrtr_ip_addr addr; struct lrtr_ip_addr result; addr.ver = LRTR_IPV4; addr.u.addr4.addr = 0xAABBCC22; result = lrtr_ip_addr_get_bits(&addr, 0, 32); assert(result.u.addr4.addr == 0xAABBCC22); result = lrtr_ip_addr_get_bits(&addr, 0, 1); assert(result.u.addr4.addr == 0x80000000); result = lrtr_ip_addr_get_bits(&addr, 1, 1); assert(result.u.addr4.addr == 0); result = lrtr_ip_addr_get_bits(&addr, 2, 1); assert(result.u.addr4.addr == 0x20000000); result = lrtr_ip_addr_get_bits(&addr, 0, 8); assert(result.u.addr4.addr == 0xAA000000); result = lrtr_ip_addr_get_bits(&addr, 8, 8); assert(result.u.addr4.addr == 0x00BB0000); lrtr_ip_str_to_addr("10.10.10.0", &addr); result = lrtr_ip_addr_get_bits(&addr, 0, 8); assert(lrtr_ip_str_cmp(&result, "10.0.0.0")); result = lrtr_ip_addr_get_bits(&addr, 0, 16); assert(lrtr_ip_str_cmp(&result, "10.10.0.0")); result = lrtr_ip_addr_get_bits(&addr, 8, 8); assert(lrtr_ip_str_cmp(&result, "0.10.0.0")); result = lrtr_ip_addr_get_bits(&addr, 8, 24); assert(lrtr_ip_str_cmp(&result, "0.10.10.0")); result = lrtr_ip_addr_get_bits(&addr, 31, 1); assert(result.u.addr4.addr == 0); result = lrtr_ip_addr_get_bits(&addr, 0, 1); assert(result.u.addr4.addr == 0); result = lrtr_ip_addr_get_bits(&addr, 3, 3); assert(lrtr_ip_str_cmp(&result, "8.0.0.0")); assert(lrtr_ip_str_to_addr("132.200.0.0", &addr) == 0); result = lrtr_ip_addr_get_bits(&addr, 0, 1); assert(result.u.addr4.addr == 0x80000000); assert(lrtr_ip_str_to_addr("101.200.0.0", &addr) == 0); result = lrtr_ip_addr_get_bits(&addr, 0, 1); assert(result.u.addr4.addr == 0); addr.u.addr4.addr = 0x6D698000; result = lrtr_ip_addr_get_bits(&addr, 0, 19); assert(result.u.addr4.addr == 0x6D698000); /* ip_str_to_addr("109.105.128.0", &addr); * result = ip_addr_get_bits(&addr, 0, 8); * printf("%u\n", result.u.addr4.addr); */ char buf[INET_ADDRSTRLEN]; assert(lrtr_ip_str_to_addr("10.10.10.5", &addr) == 0); assert(lrtr_ip_addr_to_str(&addr, buf, sizeof(buf)) == 0); assert(strcmp("10.10.10.5", buf) == 0); }
/* * @brief Test IPv6 address bit operations required by trie */ static void get_bits_testv6(void) { struct lrtr_ip_addr addr; struct lrtr_ip_addr result; addr.ver = LRTR_IPV6; addr.u.addr6.addr[0] = 0x22AABBCC; addr.u.addr6.addr[1] = 0xDDEEFF99; addr.u.addr6.addr[2] = 0x33001122; addr.u.addr6.addr[3] = 0x33445566; result = lrtr_ip_addr_get_bits(&addr, 0, 128); assert(result.u.addr6.addr[0] == addr.u.addr6.addr[0] && result.u.addr6.addr[1] == addr.u.addr6.addr[1] && result.u.addr6.addr[2] == addr.u.addr6.addr[2] && result.u.addr6.addr[3] == addr.u.addr6.addr[3]); result = lrtr_ip_addr_get_bits(&addr, 0, 64); assert(result.u.addr6.addr[0] == addr.u.addr6.addr[0] && result.u.addr6.addr[1] == addr.u.addr6.addr[1] && result.u.addr6.addr[2] == 0 && result.u.addr6.addr[3] == 0); bzero(&result, sizeof(result)); result = lrtr_ip_addr_get_bits(&addr, 64, 64); assert(result.u.addr6.addr[0] == 0); assert(result.u.addr6.addr[1] == 0); assert(result.u.addr6.addr[2] == addr.u.addr6.addr[2]); assert(result.u.addr6.addr[3] == addr.u.addr6.addr[3]); result = lrtr_ip_addr_get_bits(&addr, 0, 8); assert(result.u.addr6.addr[0] == 0x22000000 && result.u.addr6.addr[1] == 0); result = lrtr_ip_addr_get_bits(&addr, 64, 8); assert(result.u.addr6.addr[1] == 0 && result.u.addr6.addr[2] == 0x33000000); result = lrtr_ip_addr_get_bits(&addr, 7, 8); assert(result.u.addr6.addr[0] == 0xAA0000 && result.u.addr6.addr[1] == 0); result = lrtr_ip_addr_get_bits(&addr, 68, 7); assert(result.u.addr6.addr[0] == 0 && result.u.addr6.addr[2] == 0x03000000); char buf[INET6_ADDRSTRLEN]; lrtr_ip_str_to_addr("fe80::862b:2bff:fe9a:f50f", &addr); addr.ver = LRTR_IPV6; assert(addr.u.addr6.addr[0] == 0xfe800000); assert(addr.u.addr6.addr[1] == 0); assert(addr.u.addr6.addr[2] == 0x862b2bff); assert(addr.u.addr6.addr[3] == 0xfe9af50f); assert(lrtr_ip_str_to_addr("2001::", &addr) == 0); assert(addr.u.addr6.addr[0] == 0x20010000); assert(addr.u.addr6.addr[1] == 0); assert(addr.u.addr6.addr[2] == 0); assert(addr.u.addr6.addr[3] == 0); assert(lrtr_ip_addr_to_str(&addr, buf, sizeof(buf)) == 0); assert(strcmp("2001::", buf) == 0); lrtr_ip_str_to_addr("2001:0db8:85a3:08d3:1319:8a2e:0370:7344", &addr); assert(lrtr_ip_addr_to_str(&addr, buf, sizeof(buf)) == 0); assert(strcmp("2001:db8:85a3:8d3:1319:8a2e:370:7344", buf) == 0); result = lrtr_ip_addr_get_bits(&addr, 0, 16); assert(lrtr_ip_addr_to_str(&result, buf, sizeof(buf)) == 0); assert(lrtr_ip_str_cmp(&result, "2001::")); result = lrtr_ip_addr_get_bits(&addr, 16, 16); assert(lrtr_ip_addr_to_str(&result, buf, sizeof(buf)) == 0); assert(lrtr_ip_str_cmp(&result, "0:db8::")); result = lrtr_ip_addr_get_bits(&addr, 0, 1); assert(lrtr_ip_str_cmp(&result, "::")); result = lrtr_ip_addr_get_bits(&addr, 126, 1); assert(lrtr_ip_addr_to_str(&result, buf, sizeof(buf)) == 0); assert(lrtr_ip_str_cmp(&result, "::")); }
int pfx_table_validate_r(struct pfx_table *pfx_table, struct pfx_record **reason, unsigned int *reason_len, const uint32_t asn, const struct lrtr_ip_addr *prefix, const uint8_t prefix_len, enum pfxv_state *result) { //assert(reason_len == NULL || *reason_len == 0); //assert(reason == NULL || *reason == NULL); pthread_rwlock_rdlock(&(pfx_table->lock)); struct lpfst_node *root = pfx_table_get_root(pfx_table, prefix->ver); if(root == NULL) { pthread_rwlock_unlock(&pfx_table->lock); *result = BGP_PFXV_STATE_NOT_FOUND; pfx_table_free_reason(reason, reason_len); return PFX_SUCCESS; } unsigned int lvl = 0; struct lpfst_node *node = lpfst_lookup(root, prefix, prefix_len, &lvl); if(node == NULL) { pthread_rwlock_unlock(&pfx_table->lock); *result = BGP_PFXV_STATE_NOT_FOUND; pfx_table_free_reason(reason, reason_len); return PFX_SUCCESS; } if(reason_len != NULL && reason != NULL) { *reason_len = ((struct node_data *) node->data)->len; *reason = realloc(*reason, *reason_len * sizeof(struct pfx_record)); if(*reason == NULL) { pthread_rwlock_unlock(&pfx_table->lock); pfx_table_free_reason(reason, reason_len); return PFX_ERROR; } if(pfx_table_node2pfx_record(node, *reason, *reason_len) == PFX_ERROR) { pthread_rwlock_unlock(&pfx_table->lock); pfx_table_free_reason(reason, reason_len); return PFX_ERROR; } } while(!pfx_table_elem_matches(node->data, asn, prefix_len)) { if(lrtr_ip_addr_is_zero(lrtr_ip_addr_get_bits(prefix, lvl++, 1))) //post-incr lvl, lpfst_lookup is performed on child_nodes => parent lvl + 1 node = lpfst_lookup(node->lchild, prefix, prefix_len, &lvl); else node = lpfst_lookup(node->rchild, prefix, prefix_len, &lvl); if(node == NULL) { pthread_rwlock_unlock(&pfx_table->lock); *result = BGP_PFXV_STATE_INVALID; return PFX_SUCCESS; } if(reason_len != NULL && reason != NULL) { unsigned int r_len_old = *reason_len; *reason_len += ((struct node_data *) node->data)->len; *reason = realloc(*reason, *reason_len * sizeof(struct pfx_record)); struct pfx_record *start = *reason + r_len_old; if(*reason == NULL) { pthread_rwlock_unlock(&pfx_table->lock); pfx_table_free_reason(reason, reason_len); return PFX_ERROR; } if(pfx_table_node2pfx_record(node, start, ((struct node_data *) node->data)->len) == PFX_ERROR) { pthread_rwlock_unlock(&pfx_table->lock); pfx_table_free_reason(reason, reason_len); return PFX_ERROR; } } } pthread_rwlock_unlock(&pfx_table->lock); *result = BGP_PFXV_STATE_VALID; return PFX_SUCCESS; }