/* * Copyright (c) 2021, The OpenThread Authors. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /** * @file * @brief * This file includes the implementation of OTBR firewall. */ #include "firewall.hpp" #include #include #include #include "common/code_utils.hpp" #include "posix/platform/utils.hpp" namespace ot { namespace Posix { #if defined(__linux__) && OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE #if !OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || !OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE #error Configurations 'OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE' and 'OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE' are required. #endif static const char kIpsetCommand[] = OPENTHREAD_POSIX_CONFIG_IPSET_BINARY; static const char kIngressDenySrcIpSet[] = "otbr-ingress-deny-src"; static const char kIngressDenySrcSwapIpSet[] = "otbr-ingress-deny-src-swap"; static const char kIngressAllowDstIpSet[] = "otbr-ingress-allow-dst"; static const char kIngressAllowDstSwapIpSet[] = "otbr-ingress-allow-dst-swap"; class IpSetManager { public: otError FlushIpSet(const char *aName); otError AddToIpSet(const char *aSetName, const char *aAddress); otError SwapIpSets(const char *aSetName1, const char *aSetName2); }; inline otError IpSetManager::FlushIpSet(const char *aName) { return ExecuteCommand("%s flush %s", kIpsetCommand, aName); } inline otError IpSetManager::AddToIpSet(const char *aSetName, const char *aAddress) { return ExecuteCommand("%s add %s %s -exist", kIpsetCommand, aSetName, aAddress); } inline otError IpSetManager::SwapIpSets(const char *aSetName1, const char *aSetName2) { return ExecuteCommand("%s swap %s %s", kIpsetCommand, aSetName1, aSetName2); } void UpdateIpSets(otInstance *aInstance) { otError error = OT_ERROR_NONE; otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT; otBorderRouterConfig config; otIp6Prefix prefix; char prefixBuf[OT_IP6_PREFIX_STRING_SIZE]; IpSetManager ipSetManager; // 1. Flush the '*-swap' ipsets SuccessOrExit(error = ipSetManager.FlushIpSet(kIngressAllowDstSwapIpSet)); SuccessOrExit(error = ipSetManager.FlushIpSet(kIngressDenySrcSwapIpSet)); // 2. Update otbr-deny-src-swap while (otNetDataGetNextOnMeshPrefix(aInstance, &iterator, &config) == OT_ERROR_NONE) { if (config.mDp) { continue; } otIp6PrefixToString(&config.mPrefix, prefixBuf, sizeof(prefixBuf)); SuccessOrExit(error = ipSetManager.AddToIpSet(kIngressDenySrcSwapIpSet, prefixBuf)); } memcpy(prefix.mPrefix.mFields.m8, otThreadGetMeshLocalPrefix(aInstance)->m8, sizeof(otThreadGetMeshLocalPrefix(aInstance)->m8)); prefix.mLength = OT_IP6_PREFIX_BITSIZE; otIp6PrefixToString(&prefix, prefixBuf, sizeof(prefixBuf)); SuccessOrExit(error = ipSetManager.AddToIpSet(kIngressDenySrcSwapIpSet, prefixBuf)); // 3. Update otbr-allow-dst-swap iterator = OT_NETWORK_DATA_ITERATOR_INIT; while (otNetDataGetNextOnMeshPrefix(aInstance, &iterator, &config) == OT_ERROR_NONE) { otIp6PrefixToString(&config.mPrefix, prefixBuf, sizeof(prefixBuf)); SuccessOrExit(error = ipSetManager.AddToIpSet(kIngressAllowDstSwapIpSet, prefixBuf)); } // 4. Swap ipsets to let them take effect SuccessOrExit(error = ipSetManager.SwapIpSets(kIngressDenySrcSwapIpSet, kIngressDenySrcIpSet)); SuccessOrExit(error = ipSetManager.SwapIpSets(kIngressAllowDstSwapIpSet, kIngressAllowDstIpSet)); exit: if (error != OT_ERROR_NONE) { otLogWarnPlat("Firewall - failed to update ipsets: %s", otThreadErrorToString(error)); } } #endif // defined(__linux__) && OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE } // namespace Posix } // namespace ot