static bool init(void) { int i; if (!str_to_addr4(ipv4_addr_str, &ipv4_addr)) { log_warning("Could not convert '%s' to a IPv4 address. Failing...", ipv4_addr_str); return false; } for (i = 0; i < 6; i++) { if (!str_to_addr6(ipv6_addr_str[i], &ipv6_addr[i])) { log_warning("Could not convert '%s' to a IPv6 address. Failing...", ipv6_addr_str[i]); return false; } } for (i = 0; i < 6; i++) { if (!str_to_addr6(prefixes_str[i], &prefixes[i].address)) { log_warning("Could not convert '%s' to a IPv6 address. Failing...", prefixes_str[i]); return false; } prefixes[i].len = prefixes_mask[i]; } return true; }
static bool test_compare_full6(void) { struct bib_entry *bib; struct ipv6_transport_addr taddr6; bool success = true; bib = bib_create_str("1::1", 1111, "1.1.1.1", 1111, L4PROTO_TCP); if (!bib) return false; if (str_to_addr6("2::2", &taddr6.l3) != 0) goto fail; taddr6.l4 = 1111; success &= assert_true(compare_full6(bib, &taddr6) < 0, "<< 0"); if (str_to_addr6("1::1", &taddr6.l3) != 0) goto fail; taddr6.l4 = 1112; success &= assert_true(compare_full6(bib, &taddr6) < 0, "< 0"); taddr6.l4 = 1111; success &= assert_true(compare_full6(bib, &taddr6) == 0, "= 0"); taddr6.l4 = 1110; success &= assert_true(compare_full6(bib, &taddr6) > 0, "> 0"); if (str_to_addr6("0::0", &taddr6.l3) != 0) goto fail; taddr6.l4 = 1111; success &= assert_true(compare_full6(bib, &taddr6) > 0, ">> 0"); bib_kfree(bib); return success; fail: bib_kfree(bib); return false; }
bool test_append_ipv4(char* expected_as_string, char* prefix_as_string, int prefix_len) { char ipv4_as_string[INET_ADDRSTRLEN] = "192.0.2.33"; struct in_addr ipv4; struct in6_addr prefix, actual, expected; if (!str_to_addr4(ipv4_as_string, &ipv4)) { log_warning("Can't parse IPv4 address '%s'. Failing test.", ipv4_as_string); return false; } if (!str_to_addr6(prefix_as_string, &prefix)) { log_warning("Can't parse prefix '%s'. Failing test.", prefix_as_string); return false; } if (!str_to_addr6(expected_as_string, &expected)) { log_warning("Can't parse expected address '%s'. Failing test.", expected_as_string); return false; } actual = nat64_append_ipv4(&prefix, &ipv4, prefix_len); if (!ipv6_addr_equals(&expected, &actual)) { log_warning("Test failed: %s Expected: %pI6c. Actual: %pI6c.", "Append IPv4.", &expected, &actual); return false; } return true; }
static bool test_compare_addr6(void) { struct bib_entry *bib; struct in6_addr addr6; bool success = true; bib = bib_create_str("1::1", 1111, "1.1.1.1", 1111, L4PROTO_TCP); if (!bib) return false; if (str_to_addr6("2::2", &addr6) != 0) goto fail; success &= assert_true(compare_addr6(bib, &addr6) < 0, "< 0"); if (str_to_addr6("1::1", &addr6) != 0) goto fail; success &= assert_true(compare_addr6(bib, &addr6) == 0, "= 0"); if (str_to_addr6("0::0", &addr6) != 0) goto fail; success &= assert_true(compare_addr6(bib, &addr6) > 0, "> 0"); bib_kfree(bib); return success; fail: bib_kfree(bib); return false; }
static bool remove_entry(char *addr4, __u8 len4, char *addr6, __u8 len6, int expected_error) { struct ipv4_prefix prefix4; struct ipv6_prefix prefix6; bool success; int error; log_debug("----------------"); log_debug("Removing entry %s/%u %s/%u", addr6, len6, addr4, len4); if (!addr4 && !addr6) { log_err("Both addr4 and addr6 are NULL."); return false; } if (addr4) { if (is_error(str_to_addr4(addr4, &prefix4.address))) return false; prefix4.len = len4; } if (addr6) { if (is_error(str_to_addr6(addr6, &prefix6.address))) return false; prefix6.len = len6; } error = eamt_rm(addr6 ? &prefix6 : NULL, addr4 ? &prefix4 : NULL); success = ASSERT_INT(expected_error, error, "removing EAM entry"); /* rtrie_print(eamt.tree6); */ return success; }
bool str_to_addr6_port(const char *str, struct ipv6_tuple_address *addr_out) { const char *FORMAT = "<IPv6 address>#<port> (eg. 64:ff9b::#96)"; const int STR_MAX_LEN = INET6_ADDRSTRLEN + 1 + 5; // [addr + null chara] + # + port char str_copy[STR_MAX_LEN]; // strtok corrupts the string, so we'll be using this copy instead. char *token; if (strlen(str) + 1 > STR_MAX_LEN) { printf("Error: '%s' is too long for this poor, limited parser...\n", str); return false; } strcpy(str_copy, str); token = strtok(str_copy, "#"); if (!token || !str_to_addr6(token, &addr_out->address)) { printf("Error: Cannot parse '%s' as a %s.\n", str, FORMAT); return false; } token = strtok(NULL, "#"); if (!token) { printf("Error: '%s' does not seem to contain a port (format: %s).\n", str, FORMAT); return false; } if (!str_to_u16(token, &addr_out->l4_id, 0, MAX_PORT)) return false; // Error msg already printed. return true; }
static int __add_entry(char *addr4, __u8 len4, char *addr6, __u8 len6) { struct ipv4_prefix prefix4; struct ipv6_prefix prefix6; int error; if (str_to_addr4(addr4, &prefix4.address)) return false; prefix4.len = len4; if (str_to_addr6(addr6, &prefix6.address)) return false; prefix6.len = len6; log_debug("\nInserting %s/%u | %s/%u", addr6, len6, addr4, len4); error = eamt_add(&prefix6, &prefix4, true); /* if (error) { log_err("Errcode %d; I'm not going to print the tree.", error); } else { rtrie_print(eamt.tree6); } */ return error; }
bool init(void) { int error; int i; for (i = 0; i < ARRAY_SIZE(IPV4_ADDRS); i++) { error = str_to_addr4(IPV4_ADDRS[i], &addr4[i].address); if (error) return false; addr4[i].l4_id = IPV4_PORTS[i]; } for (i = 0; i < ARRAY_SIZE(IPV4_ADDRS); i++) { error = str_to_addr6(IPV6_ADDRS[i], &addr6[i].address); if (error) return false; addr6[i].l4_id = IPV6_PORTS[i]; } error = bib_init(); if (error) return false; error = session_init(session_always_dies); if (error) { bib_destroy(); return false; } return true; }
/* strtok corrupts the string, so we'll be using this copy instead. */ char str_copy[STR_MAX_LEN]; char *token; int error; if (strlen(str) + 1 > STR_MAX_LEN) { log_err("'%s' is too long for this poor, limited parser...", str); return -EINVAL; } strcpy(str_copy, str); token = strtok(str_copy, "#"); if (!token) { log_err("Cannot parse '%s' as a %s.", str, FORMAT); return -EINVAL; } error = str_to_addr4(token, &addr_out->l3); if (error) return error; token = strtok(NULL, "#"); if (!token) { log_err("'%s' does not seem to contain a port (format: %s).", str, FORMAT); return -EINVAL; } return str_to_u16(token, &addr_out->l4, 0, MAX_PORT); /* Error msg already printed. */ } #undef STR_MAX_LEN #define STR_MAX_LEN (INET6_ADDRSTRLEN + 1 + 5) /* [addr + null chara] + # + port */ int str_to_addr6_port(const char *str, struct ipv6_transport_addr *addr_out) { const char *FORMAT = "<IPv6 address>#<port> (eg. 2001:db8::1#96)"; /* strtok corrupts the string, so we'll be using this copy instead. */ char str_copy[STR_MAX_LEN]; char *token; int error; if (strlen(str) + 1 > STR_MAX_LEN) { log_err("'%s' is too long for this poor, limited parser...", str); return -EINVAL; } strcpy(str_copy, str); token = strtok(str_copy, "#"); if (!token) { log_err("Cannot parse '%s' as a %s.", str, FORMAT); return -EINVAL; } error = str_to_addr6(token, &addr_out->l3); if (error) return error; token = strtok(NULL, "#"); if (!token) { log_err("'%s' does not seem to contain a port (format: %s).", str, FORMAT); return -EINVAL; } return str_to_u16(token, &addr_out->l4, 0, MAX_PORT); /* Error msg already printed. */ }
static bool init(void) { char *pool4_addrs[] = { "1.1.1.1", "2.2.2.2" }; int i; for (i = 0; i < ARRAY_SIZE(IPV4_ADDRS); i++) { if (is_error(str_to_addr4(IPV4_ADDRS[i], &addr4[i].l3))) return false; addr4[i].l4 = IPV4_PORTS[i]; } for (i = 0; i < ARRAY_SIZE(IPV4_ADDRS); i++) { if (is_error(str_to_addr6(IPV6_ADDRS[i], &addr6[i].l3))) return false; addr6[i].l4 = IPV6_PORTS[i]; } if (is_error(config_init(false))) return false; if (is_error(pool4_init(pool4_addrs, ARRAY_SIZE(pool4_addrs)))) { config_destroy(); return false; } if (is_error(bibdb_init())) { pool4_destroy(); config_destroy(); return false; } return true; }
/* strtok corrupts the string, so we'll be using this copy instead. */ char str_copy[STR_MAX_LEN]; char *token; int error; if (strlen(str) + 1 > STR_MAX_LEN) { log_err("'%s' is too long for this poor, limited parser...", str); return -EINVAL; } strcpy(str_copy, str); token = strtok(str_copy, "/"); if (!token) { log_err("Cannot parse '%s' as a %s.", str, FORMAT); return -EINVAL; } error = str_to_addr4(token, &prefix_out->addr); if (error) return error; token = strtok(NULL, "/"); if (!token) { prefix_out->len = IPV4_MAX_PREFIX; return 0; } return str_to_u8(token, &prefix_out->len, 0, 32); /* Error msg already printed. */ } #undef STR_MAX_LEN #define STR_MAX_LEN (INET6_ADDRSTRLEN + 1 + 3) /* [addr + null chara] + / + pref len */ int str_to_prefix6(const char *str, struct ipv6_prefix *prefix_out) { const char *FORMAT = "<IPv6 address>[/<length>] (eg. 64:ff9b::/96)"; /* strtok corrupts the string, so we'll be using this copy instead. */ char str_copy[STR_MAX_LEN]; char *token; int error; if (strlen(str) + 1 > STR_MAX_LEN) { log_err("'%s' is too long for this poor, limited parser...", str); return -EINVAL; } strcpy(str_copy, str); token = strtok(str_copy, "/"); if (!token) { log_err("Cannot parse '%s' as a %s.", str, FORMAT); return -EINVAL; } error = str_to_addr6(token, &prefix_out->addr); if (error) return error; token = strtok(NULL, "/"); if (!token) { prefix_out->len = IPV6_MAX_PREFIX; return 0; } return str_to_u8(token, &prefix_out->len, 0, 128); /* Error msg already printed. */ }
/** * Prepares the environment for the tests. * * @return whether the initialization was successful or not. An error message has been printed to * the kernel ring buffer. */ static bool init(void) { u_int8_t protocols[] = { IPPROTO_UDP, IPPROTO_TCP, IPPROTO_ICMP }; int i; struct ipv6_prefix prefix; // Init test addresses if (str_to_addr6(remote_ipv6_str, &remote_ipv6) != 0) { log_warning("Can't parse address '%s'. Failing test...", remote_ipv6_str); return false; } if (str_to_addr6(local_ipv6_str, &local_ipv6) != 0) { log_warning("Can't parse address '%s'. Failing test...", local_ipv6_str); return false; } if (str_to_addr4(local_ipv4_str, &local_ipv4) != 0) { log_warning("Can't parse address '%s'. Failing test...", local_ipv4_str); return false; } if (str_to_addr4(remote_ipv4_str, &remote_ipv4) != 0) { log_warning("Can't parse address '%s'. Failing test...", remote_ipv4_str); return false; } // Init the IPv6 pool module if (!pool6_init()) return false; if (str_to_addr6("64:ff9b::", &prefix.address) != 0) { log_warning("Cannot parse the IPv6 prefix. Failing..."); return false; } prefix.len = 96; if (pool6_register(&prefix) != 0) { log_warning("Could not add the IPv6 prefix. Failing..."); return false; } // Init the BIB module if (!bib_init()) return false; for (i = 0; i < ARRAY_SIZE(protocols); i++) if (!add_bib(&local_ipv4, 80, &remote_ipv6, 1500, protocols[i])) return false; return true; }
struct ipv6_tuple_address create_tuple_addr_6(int index) { struct ipv6_tuple_address result; if (!str_to_addr6(IPV6_ADDRS[index], &result.address)) log_warning("Can't convert '%s' to a in6_addr. Test is going to fail.", IPV6_ADDRS[index]); result.l4_id = IPV6_PORTS[index]; return result; }
bool str_to_addr6_verbose(const char *str, struct in6_addr *addr) { if (str_to_addr6(str, addr) != 0) { log_warning("Cannot parse '%s' as a valid IPv6 address", str); return false; } return true; }
/** * Prepares the environment for the tests. * * @return whether the initialization was successful or not. An error message has been printed to * the kernel ring buffer. */ static bool init(void) { l4_protocol l4_protos[] = { L4PROTO_UDP, L4PROTO_TCP, L4PROTO_ICMP }; int i; struct ipv6_prefix prefix; /* Init test addresses */ if (str_to_addr6(remote_ipv6_str, &remote_ipv6) != 0) { log_warning("Can't parse address '%s'. Failing test...", remote_ipv6_str); return false; } if (str_to_addr6(local_ipv6_str, &local_ipv6) != 0) { log_warning("Can't parse address '%s'. Failing test...", local_ipv6_str); return false; } if (str_to_addr4(local_ipv4_str, &local_ipv4) != 0) { log_warning("Can't parse address '%s'. Failing test...", local_ipv4_str); return false; } if (str_to_addr4(remote_ipv4_str, &remote_ipv4) != 0) { log_warning("Can't parse address '%s'. Failing test...", remote_ipv4_str); return false; } /* Init the IPv6 pool module */ if (is_error(pool6_init(NULL, 0))) /* we'll use the defaults. */ return false; if (str_to_addr6("64:ff9b::", &prefix.address) != 0) { log_warning("Cannot parse the IPv6 prefix. Failing..."); return false; } prefix.len = 96; /* Init the BIB module */ if (is_error(bib_init())) return false; for (i = 0; i < ARRAY_SIZE(l4_protos); i++) if (!add_bib(&local_ipv4, 80, &remote_ipv6, 1500, l4_protos[i])) return false; return true; }
int init_ipv6_tuple(struct tuple *tuple6, unsigned char *src_addr, u16 src_port, unsigned char *dst_addr, u16 dst_port, l4_protocol l4_proto) { int error; error = str_to_addr6(src_addr, &tuple6->src.addr6.l3); if (error) return error; tuple6->src.addr6.l4 = src_port; error = str_to_addr6(dst_addr, &tuple6->dst.addr6.l3); if (error) return error; tuple6->dst.addr6.l4 = (l4_proto != L4PROTO_ICMP) ? dst_port : src_port; tuple6->l3_proto = L3PROTO_IPV6; tuple6->l4_proto = l4_proto; return 0; }
int init_module(void) { START_TESTS("Packet"); if (str_to_addr6("1::1", &dummies6[0]) != 0) return -EINVAL; if (str_to_addr6("2::2", &dummies6[1]) != 0) return -EINVAL; if (str_to_addr4("1.1.1.1", &dummies4[0]) != 0) return -EINVAL; if (str_to_addr4("2.2.2.2", &dummies4[1]) != 0) return -EINVAL; CALL_TEST(test_function_is_dont_fragment_set(), "Dont fragment getter"); CALL_TEST(test_function_is_more_fragments_set(), "More fragments getter"); CALL_TEST(test_function_build_ipv4_frag_off_field(), "Generate frag offset + flags function"); CALL_TEST(test_inner_packet_validation4(), "Inner packet IPv4 Validation"); CALL_TEST(test_inner_packet_validation6(), "Inner packet IPv6 Validation"); END_TESTS; }
bool ASSERT_ADDR6(char const *expected_str, struct in6_addr const *actual, char const *test_name) { struct in6_addr expected; if (!expected_str) return __ASSERT_ADDR6(NULL, actual, test_name); return str_to_addr6(expected_str, &expected) ? false : __ASSERT_ADDR6(&expected, actual, test_name); }
static bool assert_session_exists(char *src6_addr, u16 src6_port, char *dst6_addr, u16 dst6_port, char *src4_addr, u16 src4_port, char *dst4_addr, u16 dst4_port, l4_protocol proto, u_int8_t state, session_timer_type timer_type, unsigned long timeout) { struct session_entry expected; int result; if (str_to_addr6(src6_addr, &expected.src6.l3)) return false; if (str_to_addr6(dst6_addr, &expected.dst6.l3)) return false; if (str_to_addr4(src4_addr, &expected.src4.l3)) return false; if (str_to_addr4(dst4_addr, &expected.dst4.l3)) return false; expected.src6.l4 = src6_port; expected.dst6.l4 = dst6_port; expected.src4.l4 = src4_port; expected.dst4.l4 = dst4_port; expected.proto = proto; expected.state = state; expected.timer_type = timer_type; expected.update_time = 0; expected.timeout = msecs_to_jiffies(timeout * 1000); expected.has_stored = false; result = session_exists(&expected); if (result > 0) return true; else if (result < 0) return false; return ASSERT_BOOL(1, 0, "session search"); }
static int init(void) { struct config_prefix6 pool6; struct pool4_entry_usr entry; int error; pool6.set = true; pool6.prefix.len = 96; error = str_to_addr6("3::", &pool6.prefix.addr); if (error) return error; error = xlator_add(FW_NETFILTER, INAME_DEFAULT, &pool6, &jool); if (error) return error; entry.mark = 0; entry.iterations = 0; entry.flags = ITERATIONS_SET | ITERATIONS_INFINITE; error = str_to_addr4("192.0.2.128", &entry.range.prefix.addr); if (error) goto fail; entry.range.prefix.len = 32; entry.range.ports.min = 1024; entry.range.ports.max = 1024; entry.proto = L4PROTO_TCP; error = pool4db_add(jool.nat64.pool4, &entry); if (error) goto fail; entry.proto = L4PROTO_UDP; error = pool4db_add(jool.nat64.pool4, &entry); if (error) goto fail; entry.proto = L4PROTO_ICMP; error = pool4db_add(jool.nat64.pool4, &entry); if (error) goto fail; return 0; fail: xlator_put(&jool); xlator_rm(INAME_DEFAULT); return error; }
int str_to_prefix(const char *str, struct ipv6_prefix *prefix_out) { const char *FORMAT = "<IPv6 address>/<length> (eg. 64:ff9b::/96)"; /* [addr + null chara] + / + pref len */ const unsigned int STR_MAX_LEN = INET6_ADDRSTRLEN + 1 + 3; /* strtok corrupts the string, so we'll be using this copy instead. */ char str_copy[STR_MAX_LEN]; char *token; __u8 valid_lengths[] = POOL6_PREFIX_LENGTHS; int valid_lengths_size = sizeof(valid_lengths) / sizeof(valid_lengths[0]); int i; int error; if (strlen(str) + 1 > STR_MAX_LEN) { log_err(ERR_PARSE_PREFIX, "'%s' is too long for this poor, limited parser...", str); return -EINVAL; } strcpy(str_copy, str); token = strtok(str_copy, "/"); if (!token) { log_err(ERR_PARSE_PREFIX, "Cannot parse '%s' as a %s.", str, FORMAT); return -EINVAL; } error = str_to_addr6(token, &prefix_out->address); if (error) return error; token = strtok(NULL, "/"); if (!token) { log_err(ERR_PARSE_PREFIX, "'%s' does not seem to contain a mask (format: %s).", str, FORMAT); return -EINVAL; } error = str_to_u8(token, &prefix_out->len, 0, 0xFF); if (error) return error; /* Error msg already printed. */ for (i = 0; i < valid_lengths_size; i++) if (prefix_out->len == valid_lengths[i]) return 0; log_err(ERR_PREF_LEN_RANGE, "%u is not a valid prefix length.", prefix_out->len); return -EINVAL; }
static bool init(void) { int i; for (i = 0; i < ARRAY_SIZE(IPV4_ADDRS); i++) { if (is_error(str_to_addr4(IPV4_ADDRS[i], &addr4[i].l3))) return false; addr4[i].l4 = IPV4_PORTS[i]; } for (i = 0; i < ARRAY_SIZE(IPV4_ADDRS); i++) { if (is_error(str_to_addr6(IPV6_ADDRS[i], &addr6[i].l3))) return false; addr6[i].l4 = IPV6_PORTS[i]; } if (is_error(config_init(false))) goto config_fail; if (is_error(pktqueue_init())) goto pktqueue_fail; if (is_error(pool4_init(NULL, 0))) goto pool4_fail; if (is_error(pool6_init(NULL, 0))) goto pool6_fail; if (is_error(bibdb_init())) goto bib_fail; if (is_error(sessiondb_init())) goto session_fail; return true; session_fail: bibdb_destroy(); bib_fail: pool6_destroy(); pool6_fail: pool4_destroy(); pool4_fail: pktqueue_destroy(); pktqueue_fail: config_destroy(); config_fail: return false; }
static bool test_6to4(char *addr6_str, char *addr4_str) { struct in6_addr addr6; struct in_addr addr4; bool success = true; log_debug("Testing %s -> %s...", addr6_str, addr4_str); if (str_to_addr6(addr6_str, &addr6)) return false; if (addr4_str) { success &= ASSERT_INT(0, eamt_xlat_6to4(&addr6, &addr4), "errcode"); success &= ASSERT_ADDR4(addr4_str, &addr4, "resulting address"); } else { success &= ASSERT_INT(-ESRCH, eamt_xlat_6to4(&addr6, &addr4), "errcode"); } return success; }
bool test_extract_ipv4(char* ipv6_as_string, int prefix_len) { const char expected_as_string[INET_ADDRSTRLEN] = "192.0.2.33"; struct in_addr expected; struct in_addr actual; struct in6_addr ipv6; if (!str_to_addr4(expected_as_string, &expected)) { log_warning("Can't parse expected IPv4 address '%s'. Failing test.", expected_as_string); return false; } if (!str_to_addr6(ipv6_as_string, &ipv6)) { log_warning("Can't parse IPv6 address being tested '%s'. Failing test.", ipv6_as_string); return false; } actual = nat64_extract_ipv4(&ipv6, prefix_len); ASSERT_EQUALS_IPV4(expected, actual, "Extract IPv4.") return true; }
/** Convert the network mask in CIDR format ('/n') to address format. * * @param[in] af Address Family: AF_INET[6]. * @param[in] bits Network mask bits, integer value from: /n. * @param[out] net Network mask in address format. * @return true if OK, otherwise false. */ int convert_bits_to_netmask(int af, unsigned char bits, void *net) { unsigned char ii = 0; switch(af) { case AF_INET: str_to_addr4("0.0.0.0", net); (*(struct in_addr *)net).s_addr = \ BROADCAST_ADDR >>(IPV4_NETMASK_BITS_MAX - bits); break; case AF_INET6: str_to_addr6("::0", net); for (ii = 0; ii < IPV6_SIZE_UINT32; ii++) { if (bits <= ii * IPV6_SIZE_UINT32_BITS ) { if (bits == ii * IPV6_SIZE_UINT32_BITS ) (*(struct in6_addr *)net).s6_addr32[ii] = \ DONT_CARE; else (*(struct in6_addr *)net).s6_addr32[ii] = \ htonl( BROADCAST_ADDR <<(IPV6_NETMASK_BITS_MAX - bits ) ); } else { (*(struct in6_addr *)net).s6_addr32[ii] = BROADCAST_ADDR; } } break; default: /* log_warning("%s. Error, bad address family.", "convert_bits_to_netmask"); */ return false; } return true; }
static bool init(void) { int i; for (i = 0; i < ARRAY_SIZE(IPV4_ADDRS); i++) { if (is_error(str_to_addr4(IPV4_ADDRS[i], &addr4[i].l3))) return false; addr4[i].l4 = IPV4_PORTS[i]; } for (i = 0; i < ARRAY_SIZE(IPV4_ADDRS); i++) { if (is_error(str_to_addr6(IPV6_ADDRS[i], &addr6[i].l3))) return false; addr6[i].l4 = IPV6_PORTS[i]; } if (is_error(sessiondb_init())) return false; if (is_error(pktqueue_init())) return false; return true; }
static bool assert_bib_exists(char *addr6, u16 port6, char *addr4, u16 port4, l4_protocol proto, unsigned int session_count) { struct bib_entry bib; struct ipv6_transport_addr tuple_addr; bool success = true; if (str_to_addr6(addr6, &tuple_addr.l3)) return false; tuple_addr.l4 = port6; success &= ASSERT_INT(0, bib_find6(jool.nat64.bib, proto, &tuple_addr, &bib), "BIB exists"); if (!success) return false; success &= ASSERT_ADDR6(addr6, &bib.ipv6.l3, "IPv6 address"); success &= ASSERT_UINT(port6, bib.ipv6.l4, "IPv6 port"); success &= ASSERT_ADDR4(addr4, &bib.ipv4.l3, "IPv4 address"); /* The IPv4 port is unpredictable. */ success &= ASSERT_BOOL(proto, bib.l4_proto, "BIB proto"); return success; }
int str_to_addr6_port(const char *str, struct ipv6_tuple_address *addr_out) { const char *FORMAT = "<IPv6 address>#<port> (eg. 64:ff9b::#96)"; const unsigned int STR_MAX_LEN = INET6_ADDRSTRLEN + 1 + 5; /* [addr + null chara] + # + port */ /* strtok corrupts the string, so we'll be using this copy instead. */ char str_copy[STR_MAX_LEN]; char *token; int error; if (strlen(str) + 1 > STR_MAX_LEN) { log_err(ERR_PARSE_ADDR6_PORT, "'%s' is too long for this poor, limited parser...", str); return -EINVAL; } strcpy(str_copy, str); token = strtok(str_copy, "#"); if (!token) { log_err(ERR_PARSE_ADDR6_PORT, "Cannot parse '%s' as a %s.", str, FORMAT); return -EINVAL; } error = str_to_addr6(token, &addr_out->address); if (error) return error; token = strtok(NULL, "#"); if (!token) { log_err(ERR_PARSE_ADDR6_PORT, "'%s' does not seem to contain a port (format: %s).", str, FORMAT); return -EINVAL; } error = str_to_u16(token, &addr_out->l4_id, 0, MAX_PORT); if (error) return error; /* Error msg already printed. */ return 0; }
bool str_to_prefix(const char *str, struct ipv6_prefix *prefix_out) { const char *FORMAT = "<IPv6 address>/<length> (eg. 64:ff9b::/96)"; const int STR_MAX_LEN = INET6_ADDRSTRLEN + 1 + 3; // [addr + null chara] + / + prefix len char str_copy[STR_MAX_LEN]; // strtok corrupts the string, so we'll be using this copy instead. char *token; __u8 valid_lengths[] = POOL6_PREFIX_LENGTHS; int valid_lengths_size = sizeof(valid_lengths) / sizeof((valid_lengths)[0]); int i; if (strlen(str) + 1 > STR_MAX_LEN) { printf("Error: '%s' is too long for this poor, limited parser...\n", str); return false; } strcpy(str_copy, str); token = strtok(str_copy, "/"); if (!token || !str_to_addr6(token, &prefix_out->address)) { printf("Error: Cannot parse '%s' as a %s.\n", str, FORMAT); return false; } token = strtok(NULL, "/"); if (!token) { printf("Error: '%s' does not seem to contain a mask (format: %s).\n", str, FORMAT); return false; } if (!str_to_u8(token, &prefix_out->len, 0, 0xFF)) return false; // Error msg already printed. for (i = 0; i < valid_lengths_size; i++) if (prefix_out->len == valid_lengths[i]) return true; printf("Error: %u is not a valid prefix length.\n", prefix_out->len); return false; }