These are added to provide wrappers to gethostbyaddr() and gethostbyname().
Update the unit tests.
}
#endif // _di_f_network_from_host_short_
+#ifndef _di_f_network_from_ip_address_
+ f_status_t f_network_from_ip_address(const f_network_family_ip_t from, struct hostent * const to) {
+ #ifndef _di_level_0_parameter_checking_
+ if (!to) return F_status_set_error(F_parameter);
+ #endif // _di_level_0_parameter_checking_
+
+ if (!(from.type == f_network_family_ip_4_e || from.type == f_network_family_ip_6_e)) return F_data_not;
+
+ h_errno = 0;
+
+ struct hostent * const result = from.type == f_network_family_ip_4_e
+ ? gethostbyaddr((void *) &from.address.v4, INET_ADDRSTRLEN, AF_INET)
+ : gethostbyaddr((void *) &from.address.v6, INET6_ADDRSTRLEN, AF_INET6);
+
+ if (!result) {
+ if (h_errno == HOST_NOT_FOUND) return F_status_set_error(F_found_not);
+ if (h_errno == NO_DATA || h_errno == NO_ADDRESS) return F_status_set_error(F_data_not);
+ if (h_errno == NO_RECOVERY) return F_status_set_error(F_recover_not);
+ if (h_errno == TRY_AGAIN) return F_status_set_error(F_again);
+
+ return F_status_set_error(F_failure);
+ }
+
+ memcpy((void *) to, (void *) result, sizeof(struct hostent));
+
+ return F_none;
+ }
+#endif // _di_f_network_from_ip_address_
+
+#ifndef _di_f_network_from_ip_name_
+ f_status_t f_network_from_ip_name(const f_string_static_t from, struct hostent * const to) {
+ #ifndef _di_level_0_parameter_checking_
+ if (!to) return F_status_set_error(F_parameter);
+ #endif // _di_level_0_parameter_checking_
+
+ if (!from.used) return F_data_not;
+
+ h_errno = 0;
+
+ struct hostent * const result = gethostbyname(from.string);
+
+ if (!result) {
+ if (h_errno == HOST_NOT_FOUND) return F_status_set_error(F_found_not);
+ if (h_errno == NO_DATA || h_errno == NO_ADDRESS) return F_status_set_error(F_data_not);
+ if (h_errno == NO_RECOVERY) return F_status_set_error(F_recover_not);
+ if (h_errno == TRY_AGAIN) return F_status_set_error(F_again);
+
+ return F_status_set_error(F_failure);
+ }
+
+ memcpy((void *) to, (void *) result, sizeof(struct hostent));
+
+ return F_none;
+ }
+#endif // _di_f_network_from_ip_name_
+
#ifndef _di_f_network_from_ip_string_
f_status_t f_network_from_ip_string(const f_string_static_t from, f_network_family_ip_t * const to) {
#ifndef _di_level_0_parameter_checking_
// Libc includes.
#include <arpa/inet.h>
+#include <netdb.h>
+#include <string.h>
+#include <sys/socket.h>
// FLL-0 includes.
#include <fll/level_0/type.h>
#endif // _di_f_network_from_host_short_
/**
- * Convert from a human-friendly string into a network IP address digit.
+ * Convert from a IP version 4 or version 6 family integer into a network IP address host entity.
*
- * This is for the ip address and is not for the domain name.
+ * This is for the Domain Name and is not for the IP address digit itself.
*
* @param from
- * The human-friendly ip address string.
+ * The IP version 4 or version 6 family integer.
+ * @param to
+ * The converted IP host entity.
+ *
+ * @return
+ * F_none on success.
+ * F_data_not on success but there is nothing to convert (to.type is f_network_family_none_e).
+ *
+ * F_again (with error bit) Resolver temporarily failed, try again.
+ * F_data_not (with error bit) The requested name is valid, but does not have an IP address.
+ * F_found_not (with error bit) Resolver did not know host.
+ * F_recover_not (with error bit) Resolver failed and cannot recover from the failure, do not try again.
+ * F_failure (with error bit) on any other error.
+ *
+ * @see gethostbyaddr()
+ */
+#ifndef _di_f_network_from_ip_address_
+ extern f_status_t f_network_from_ip_address(const f_network_family_ip_t from, struct hostent * const to);
+#endif // _di_f_network_from_ip_address_
+
+/**
+ * Convert from a Domain Name into a network IP address host entity.
+ *
+ * This is for the Domain Name and is not for the IP address digit itself.
+ *
+ * @param from
+ * The human-friendly IP Domain Name.
+ * @param to
+ * The converted IP host entity.
+ *
+ * @return
+ * F_none on success.
+ * F_data_not on success but there is nothing to convert (from.used is 0).
+ *
+ * F_again (with error bit) Resolver temporarily failed, try again.
+ * F_data_not (with error bit) The requested name is valid, but does not have an IP address.
+ * F_found_not (with error bit) Resolver did not know host.
+ * F_recover_not (with error bit) Resolver failed and cannot recover from the failure, do not try again.
+ * F_failure (with error bit) on any other error.
+ *
+ * @see gethostbyname()
+ */
+#ifndef _di_f_network_from_ip_name_
+ extern f_status_t f_network_from_ip_name(const f_string_static_t from, struct hostent * const to);
+#endif // _di_f_network_from_ip_name_
+
+/**
+ * Convert from a human-friendly string representing the IP address digit into a network IP address digit.
+ *
+ * This is for the IP address and is not for the Domain Name.
+ *
+ * @param from
+ * The human-friendly IP address string.
* @param to
* The converted IP version 4 or version 6 family integer.
*
#endif // _di_f_network_to_host_short_
/**
- * Convert from a network IP address digit into a human-friendly string.
+ * Convert from a network IP address digit into a human-friendly string representing the IP address digit.
*
- * This is for the ip address and is not for the domain name.
+ * This is for the IP address and is not for the Domain Name.
*
* @param from
* The IP version 4 or version 6 family integer.
* @param to
- * The converted human-friendly ip address string.
+ * The converted human-friendly IP address string.
*
* @return
* F_none on success.
flags_library -fPIC
# Inject mocks.
+flags -Wl,--wrap=gethostbyaddr
+flags -Wl,--wrap=gethostbyname
flags -Wl,--wrap=htonl
flags -Wl,--wrap=htons
flags -Wl,--wrap=inet_ntop
build_libraries -lc -lcmocka
build_libraries-individual -lf_memory -lf_string -lf_network
-build_sources_program test-network-from_host_long.c test-network-from_host_short.c test-network-from_ip_string.c test-network-to_host_long.c test-network-to_host_short.c test-network-to_ip_string.c
+build_sources_program test-network-from_host_long.c test-network-from_host_short.c test-network-from_ip_address.c test-network-from_ip_name.c test-network-from_ip_string.c test-network-to_host_long.c test-network-to_host_short.c test-network-to_ip_string.c
build_sources_program test-network.c
build_script no
extern "C" {
#endif
+struct hostent *__wrap_gethostbyaddr(const void *addr, socklen_t len, int type) {
+
+ const bool failure = mock_type(bool);
+
+ if (failure) {
+ errno = mock_type(int);
+
+ return 0;
+ }
+
+ return mock_type(struct hostent *);
+}
+
+struct hostent *__wrap_gethostbyname(const char *name) {
+
+ const bool failure = mock_type(bool);
+
+ if (failure) {
+ errno = mock_type(int);
+
+ return 0;
+ }
+
+ return mock_type(struct hostent *);
+}
+
uint32_t __wrap_htonl(uint32_t hostlong) {
return mock_type(uint32_t);
const static int mock_errno_generic = 32767;
+extern struct hostent *__wrap_gethostbyaddr(const void *addr, socklen_t len, int type);
+extern struct hostent *__wrap_gethostbyname(const char *name);
extern uint32_t __wrap_htonl(uint32_t hostlong);
extern uint16_t __wrap_htons(uint16_t hostshort);
const char *__wrap_inet_ntop(int af, const void *src, char *dst, socklen_t size);
--- /dev/null
+#include "test-network.h"
+#include "test-network-from_ip_address.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_network_from_ip_address__fails(void **state) {
+
+ f_network_family_ip_t family = f_network_family_ip_t_initialize;
+
+ int errnos[] = {
+ HOST_NOT_FOUND,
+ NO_DATA,
+ NO_ADDRESS,
+ NO_RECOVERY,
+ TRY_AGAIN,
+ mock_errno_generic,
+ };
+
+ f_status_t statuss[] = {
+ F_found_not,
+ F_data_not,
+ F_data_not,
+ F_recover_not,
+ F_again,
+ F_failure,
+ };
+
+ for (uint8_t i = 0; i < 6; ++i) {
+
+ struct hostent host;
+
+ will_return(__wrap_gethostbyaddr, true);
+ will_return(__wrap_gethostbyaddr, errnos[i]);
+
+ const f_status_t status = f_network_from_ip_address(family, &host);
+
+ assert_int_equal(status, F_status_set_error(statuss[i]));
+ } // for
+}
+
+void test__f_network_from_ip_address__parameter_checking(void **state) {
+
+ f_network_family_ip_t family = f_network_family_ip_t_initialize;
+
+ {
+ const f_status_t status = f_network_from_ip_address(family, 0);
+
+ assert_int_equal(status, F_status_set_error(F_parameter));
+ }
+}
+
+void test__f_network_from_ip_address__returns_data_not(void **state) {
+
+ f_network_family_ip_t family = f_network_family_ip_t_initialize;
+
+ struct hostent host;
+
+ {
+ const f_status_t status = f_network_from_ip_address(family, &host);
+
+ assert_int_equal(status, F_data_not);
+ }
+}
+
+void test__f_network_from_ip_address__works(void **state) {
+
+ f_network_family_ip_t family = f_network_family_ip_t_initialize;
+
+ struct hostent host;
+ struct hostent mocked;
+
+ char *mocked_strings[] = {
+ "localhost",
+ 0,
+ };
+
+ char *mocked_ips[] = {
+ "127.0.0.1",
+ "::1",
+ 0,
+ };
+
+ memset(&mocked, 0, sizeof(struct hostent));
+
+ mocked.h_name = mocked_strings[0];
+ mocked.h_aliases = mocked_strings;
+ mocked.h_addrtype = 1;
+ mocked.h_length = 2;
+ mocked.h_addr_list = mocked_ips;
+
+ family.type = f_network_family_ip_4_e;
+
+ {
+ will_return(__wrap_gethostbyaddr, false);
+ will_return(__wrap_gethostbyaddr, &mocked);
+
+ const f_status_t status = f_network_from_ip_address(family, &host);
+
+ assert_int_equal(status, F_none);
+ assert_string_equal(host.h_name, mocked.h_name);
+ assert_int_equal(host.h_aliases, mocked.h_aliases);
+ assert_int_equal(host.h_length, mocked.h_length);
+ assert_int_equal(host.h_aliases, mocked.h_aliases);
+ assert_int_equal(host.h_aliases[0], mocked.h_aliases[0]);
+ assert_int_equal(host.h_addr_list, mocked.h_addr_list);
+ assert_int_equal(host.h_addr_list[0], mocked.h_addr_list[0]);
+ assert_int_equal(host.h_addr_list[1], mocked.h_addr_list[1]);
+ }
+
+ family.type = f_network_family_ip_6_e;
+
+ {
+ will_return(__wrap_gethostbyaddr, false);
+ will_return(__wrap_gethostbyaddr, &mocked);
+
+ const f_status_t status = f_network_from_ip_address(family, &host);
+
+ assert_int_equal(status, F_none);
+ assert_string_equal(host.h_name, mocked.h_name);
+ assert_int_equal(host.h_aliases, mocked.h_aliases);
+ assert_int_equal(host.h_length, mocked.h_length);
+ assert_int_equal(host.h_aliases, mocked.h_aliases);
+ assert_int_equal(host.h_aliases[0], mocked.h_aliases[0]);
+ assert_int_equal(host.h_addr_list, mocked.h_addr_list);
+ assert_int_equal(host.h_addr_list[0], mocked.h_addr_list[0]);
+ assert_int_equal(host.h_addr_list[1], mocked.h_addr_list[1]);
+ }
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * FLL - Level 0
+ *
+ * Project: Network
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the network project.
+ */
+#ifndef _TEST__F_network_from_ip_address_h
+#define _TEST__F_network_from_ip_address_h
+
+/**
+ * Test that function fails.
+ *
+ * @see f_network_from_ip_address()
+ */
+extern void test__f_network_from_ip_address__fails(void **state);
+
+/**
+ * Test that parameter checking works as expected.
+ *
+ * @see f_network_from_ip_address()
+ */
+extern void test__f_network_from_ip_address__parameter_checking(void **state);
+
+/**
+ * Test that function works but the string is empty or the address.type is 0.
+ *
+ * @see f_network_from_ip_address()
+ */
+extern void test__f_network_from_ip_address__returns_data_not(void **state);
+
+/**
+ * Test that function works.
+ *
+ * @see f_network_from_ip_address()
+ */
+extern void test__f_network_from_ip_address__works(void **state);
+
+#endif // _TEST__F_network_from_ip_address_h
--- /dev/null
+#include "test-network.h"
+#include "test-network-from_ip_name.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_network_from_ip_name__fails(void **state) {
+
+ int errnos[] = {
+ HOST_NOT_FOUND,
+ NO_DATA,
+ NO_ADDRESS,
+ NO_RECOVERY,
+ TRY_AGAIN,
+ mock_errno_generic,
+ };
+
+ f_status_t statuss[] = {
+ F_found_not,
+ F_data_not,
+ F_data_not,
+ F_recover_not,
+ F_again,
+ F_failure,
+ };
+
+ for (uint8_t i = 0; i < 6; ++i) {
+
+ struct hostent host;
+
+ will_return(__wrap_gethostbyname, true);
+ will_return(__wrap_gethostbyname, errnos[i]);
+
+ const f_status_t status = f_network_from_ip_name(f_string_empty_s, &host);
+
+ assert_int_equal(status, F_status_set_error(statuss[i]));
+ } // for
+}
+
+void test__f_network_from_ip_name__parameter_checking(void **state) {
+
+ {
+ const f_status_t status = f_network_from_ip_name(f_string_empty_s, 0);
+
+ assert_int_equal(status, F_status_set_error(F_parameter));
+ }
+}
+
+void test__f_network_from_ip_name__returns_data_not(void **state) {
+
+ struct hostent host;
+
+ {
+ const f_status_t status = f_network_from_ip_name(f_string_empty_s, &host);
+
+ assert_int_equal(status, F_data_not);
+ }
+}
+
+void test__f_network_from_ip_name__works(void **state) {
+
+ const f_string_static_t ip = macro_f_string_static_t_initialize_1("localhost", 0, 9);
+
+ struct hostent host;
+ struct hostent mocked;
+
+ char *mocked_strings[] = {
+ ip.string,
+ 0,
+ };
+
+ char *mocked_ips[] = {
+ "127.0.0.1",
+ "::1",
+ 0,
+ };
+
+ memset(&mocked, 0, sizeof(struct hostent));
+
+ mocked.h_name = ip.string;
+ mocked.h_aliases = mocked_strings;
+ mocked.h_addrtype = 1;
+ mocked.h_length = 2;
+ mocked.h_addr_list = mocked_ips;
+
+ {
+ will_return(__wrap_gethostbyname, false);
+ will_return(__wrap_gethostbyname, &mocked);
+
+ const f_status_t status = f_network_from_ip_name(ip, &host);
+
+ assert_int_equal(status, F_none);
+ assert_string_equal(host.h_name, mocked.h_name);
+ assert_int_equal(host.h_aliases, mocked.h_aliases);
+ assert_int_equal(host.h_length, mocked.h_length);
+ assert_int_equal(host.h_aliases, mocked.h_aliases);
+ assert_int_equal(host.h_aliases[0], mocked.h_aliases[0]);
+ assert_int_equal(host.h_addr_list, mocked.h_addr_list);
+ assert_int_equal(host.h_addr_list[0], mocked.h_addr_list[0]);
+ assert_int_equal(host.h_addr_list[1], mocked.h_addr_list[1]);
+ }
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * FLL - Level 0
+ *
+ * Project: Network
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the network project.
+ */
+#ifndef _TEST__F_network_from_ip_name_h
+#define _TEST__F_network_from_ip_name_h
+
+/**
+ * Test that function fails.
+ *
+ * @see f_network_from_ip_name()
+ */
+extern void test__f_network_from_ip_name__fails(void **state);
+
+/**
+ * Test that parameter checking works as expected.
+ *
+ * @see f_network_from_ip_name()
+ */
+extern void test__f_network_from_ip_name__parameter_checking(void **state);
+
+/**
+ * Test that function works but the string is empty or the address.type is 0.
+ *
+ * @see f_network_from_ip_name()
+ */
+extern void test__f_network_from_ip_name__returns_data_not(void **state);
+
+/**
+ * Test that function works.
+ *
+ * @see f_network_from_ip_name()
+ */
+extern void test__f_network_from_ip_name__works(void **state);
+
+#endif // _TEST__F_network_from_ip_name_h
assert_int_equal(status, F_data_not);
}
+
+ family.type = f_network_family_ip_6_e;
+
+ {
+ const f_status_t status = f_network_from_ip_string(f_string_empty_s, &family);
+
+ assert_int_equal(status, F_data_not);
+ }
}
void test__f_network_from_ip_string__works(void **state) {
f_network_family_ip_t family = f_network_family_ip_t_initialize;
- family.type = f_network_family_ip_4_e;
const f_string_static_t ip = macro_f_string_static_t_initialize_1("127.0.0.1", 0, 9);
+ family.type = f_network_family_ip_4_e;
+
+ {
+ will_return(__wrap_inet_pton, false);
+
+ const f_status_t status = f_network_from_ip_string(ip, &family);
+
+ assert_int_equal(status, F_none);
+ }
+
+ family.type = f_network_family_ip_6_e;
+
{
will_return(__wrap_inet_pton, false);
void test__f_network_to_ip_string__works(void **state) {
f_network_family_ip_t family = f_network_family_ip_t_initialize;
- family.type = f_network_family_ip_4_e;
f_string_dynamic_t ip = f_string_dynamic_t_initialize;
const f_string_static_t expect = macro_f_string_static_t_initialize_1("127.0.0.1", 0, 9);
+ family.type = f_network_family_ip_4_e;
+
+ {
+ will_return(__wrap_inet_ntop, false);
+ will_return(__wrap_inet_ntop, expect.string);
+ will_return(__wrap_inet_ntop, expect.used);
+
+ const f_status_t status = f_network_to_ip_string(family, &ip);
+
+ assert_int_equal(status, F_none);
+ assert_int_equal(ip.used, expect.used);
+ assert_string_equal(ip.string, expect.string);
+ }
+
+ free(ip.string);
+
+ family.type = f_network_family_ip_6_e;
+ ip.used = 0;
+
{
will_return(__wrap_inet_ntop, false);
will_return(__wrap_inet_ntop, expect.string);
int main(void) {
const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test__f_network_from_ip_address__returns_data_not),
+ cmocka_unit_test(test__f_network_from_ip_name__returns_data_not),
cmocka_unit_test(test__f_network_from_ip_string__returns_data_not),
+
cmocka_unit_test(test__f_network_to_ip_string__returns_data_not),
cmocka_unit_test(test__f_network_from_host_long__works),
cmocka_unit_test(test__f_network_from_host_short__works),
+ cmocka_unit_test(test__f_network_from_ip_address__works),
+ cmocka_unit_test(test__f_network_from_ip_name__works),
cmocka_unit_test(test__f_network_from_ip_string__works),
+
cmocka_unit_test(test__f_network_to_host_long__works),
cmocka_unit_test(test__f_network_to_host_short__works),
cmocka_unit_test(test__f_network_to_ip_string__works),
#ifndef _di_level_0_parameter_checking_
cmocka_unit_test(test__f_network_from_host_long__parameter_checking),
cmocka_unit_test(test__f_network_from_host_short__parameter_checking),
+ cmocka_unit_test(test__f_network_from_ip_address__parameter_checking),
+ cmocka_unit_test(test__f_network_from_ip_name__parameter_checking),
cmocka_unit_test(test__f_network_from_ip_string__parameter_checking),
cmocka_unit_test(test__f_network_to_host_long__parameter_checking),
cmocka_unit_test(test__f_network_to_host_short__parameter_checking),
// Test includes.
#include "test-network-from_host_long.h"
#include "test-network-from_host_short.h"
+#include "test-network-from_ip_address.h"
+#include "test-network-from_ip_name.h"
#include "test-network-from_ip_string.h"
#include "test-network-to_host_long.h"
#include "test-network-to_host_short.h"