/* getifaddrs.c * * Copyright (c) 2024 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file contains unit tests for ioloop_map_interface_addresses(). */ #include "srp.h" #include #include #include "srp-test-runner.h" #include "srp-api.h" #include "dns-msg.h" #include "ioloop.h" #include "srp-mdns-proxy.h" #include "test-api.h" #include "srp-proxy.h" #include "srp-mdns-proxy.h" #include "test-dnssd.h" #include "test.h" #include "dnssd-proxy.h" #define DNSMessageHeader dns_wire_t #include "dso.h" #include "dso-utils.h" #define SUBSCRIBE_LIMIT 4 // SOA + SRV + A + AAAA || PTR + SRV + A + AAAA typedef struct ifaddr_test_state ifaddr_test_state_t; struct ifaddr_test_state { test_state_t *test_state; struct ifaddrs *real_ifaddrs; bool lladdr_removed, lladdr_added; interface_address_state_t *ifaddr_state; }; static void test_ifaddrs_changed_l2addr(srp_server_t UNUSED *server_state, void *context, const char UNUSED *name, const addr_t *address, const addr_t UNUSED *netmask, uint32_t UNUSED flags, enum interface_address_change event_type) { ifaddr_test_state_t *its = context; if (address->sa.sa_family == AF_LINK) { if (event_type == interface_address_deleted) { its->lladdr_removed = true; } else if (event_type == interface_address_added) { its->lladdr_added = true; } } } static void test_ifaddrs_ignore(srp_server_t UNUSED *server_state, void UNUSED *context, const char UNUSED *name, const addr_t UNUSED *address, const addr_t UNUSED *netmask, uint32_t UNUSED flags, enum interface_address_change UNUSED event_type) { } static int test_ifaddrs_get(srp_server_t UNUSED *server_state, struct ifaddrs **ifaddrs, void *context) { ifaddr_test_state_t *its = context; *ifaddrs = its->real_ifaddrs; return 0; } static void test_ifaddrs_free(srp_server_t UNUSED *server_state, struct ifaddrs UNUSED *ifaddrs, void UNUSED *context) { } void test_ifaddrs_start(test_state_t *next_test) { extern srp_server_t *srp_servers; test_state_t *state = NULL; const char *summary = " The goal of this test is to exercise the various behaviors of ioloop_map_interface_addresses when\n" " used to track the coming and going of interfaces and addresses on interfaces.\n"; state = test_state_create(srp_servers, "ioloop_map_interface_addresses test", NULL, summary, NULL); state->next = next_test; state->getifaddrs = test_ifaddrs_get; state->freeifaddrs = test_ifaddrs_free; ifaddr_test_state_t *its = calloc(1, sizeof (*its)); TEST_FAIL_CHECK(state, its != NULL, "no memory for test-specific state."); its->test_state = state; srp_proxy_init("local"); TEST_FAIL_CHECK_STATUS(state, getifaddrs(&its->real_ifaddrs) == 0, "getifaddrs failed: %s", strerror(errno)); TEST_FAIL_CHECK(state, ioloop_map_interface_addresses_here(srp_servers, &its->ifaddr_state, NULL, its, test_ifaddrs_ignore), "initial map call failed"); for (struct ifaddrs *ifp = its->real_ifaddrs; ifp != NULL; ifp = ifp->ifa_next) { if (ifp->ifa_addr != NULL && ifp->ifa_addr->sa_family == AF_LINK) { struct sockaddr_dl *sdl = (struct sockaddr_dl *)ifp->ifa_addr; LLADDR(sdl)[0] = ~LLADDR(sdl)[0]; } } TEST_FAIL_CHECK(state, ioloop_map_interface_addresses_here(srp_servers, &its->ifaddr_state, NULL, its, test_ifaddrs_changed_l2addr), "changed_l2addr map call failed"); TEST_FAIL_CHECK(state, its->lladdr_removed && its->lladdr_added, "link local address wasn't updated"); TEST_PASSED(state); } // Local Variables: // mode: C // tab-width: 4 // c-file-style: "bsd" // c-basic-offset: 4 // fill-column: 108 // indent-tabs-mode: nil // End: