diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-11-17 15:57:34 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-11-17 15:57:34 +0000 |
commit | 0e51148c671f95feeb82cabfd3473cd992fcb1ef (patch) | |
tree | 93542243872ff4cf171611b22f9be42368b04f7d | |
parent | 2b0b5676f8a4b4c3ec5b8f8334a31c63ae170291 (diff) | |
parent | 5b43e4c161826a36024d3f0420b9d15baef7a6ee (diff) | |
download | goldfish-android12-mainline-art-release.tar.gz |
Snap for 7924065 from 5b43e4c161826a36024d3f0420b9d15baef7a6ee to mainline-art-releaseandroid-mainline-12.0.0_r42android12-mainline-art-release
Change-Id: I49d6d954ef7a9f033f86d8d7a591eb5e58add8b0
82 files changed, 16 insertions, 6211 deletions
diff --git a/64bitonly/product/arm64-vendor.mk b/64bitonly/product/arm64-vendor.mk index c676559a..87876ece 100644 --- a/64bitonly/product/arm64-vendor.mk +++ b/64bitonly/product/arm64-vendor.mk @@ -3,9 +3,6 @@ include device/generic/goldfish/arm64-kernel.mk PRODUCT_PROPERTY_OVERRIDES += \ vendor.rild.libpath=/vendor/lib64/libgoldfish-ril.so -PRODUCT_PACKAGES += \ - emulatorip - PRODUCT_PROPERTY_OVERRIDES += \ ro.crypto.dm_default_key.options_format.version=2 diff --git a/64bitonly/product/vendor.mk b/64bitonly/product/vendor.mk index 7c8b3cf7..b38526af 100644 --- a/64bitonly/product/vendor.mk +++ b/64bitonly/product/vendor.mk @@ -59,8 +59,6 @@ PRODUCT_PACKAGES += \ libcodec2_goldfish_vp9dec \ libcodec2_goldfish_avcdec \ sh_vendor \ - ip_vendor \ - iw_vendor \ local_time.default \ SdkSetup \ EmulatorRadioConfig \ @@ -195,13 +193,8 @@ PRODUCT_PACKAGES += \ # WiFi: vendor side PRODUCT_PACKAGES += \ mac80211_create_radios \ - createns \ dhcpclient \ - execns \ hostapd \ - hostapd_nohidl \ - netmgr \ - wifi_forwarder \ wpa_supplicant \ PRODUCT_PACKAGES += \ @@ -274,7 +267,6 @@ PRODUCT_COPY_FILES += \ device/generic/goldfish/init.qemu-adb-keys.sh:$(TARGET_COPY_OUT_SYSTEM_EXT)/bin/init.qemu-adb-keys.sh \ device/generic/goldfish/init.ranchu-core.sh:$(TARGET_COPY_OUT_VENDOR)/bin/init.ranchu-core.sh \ device/generic/goldfish/init.ranchu-net.sh:$(TARGET_COPY_OUT_VENDOR)/bin/init.ranchu-net.sh \ - device/generic/goldfish/wifi/init.wifi.sh:$(TARGET_COPY_OUT_VENDOR)/bin/init.wifi.sh \ device/generic/goldfish/init.ranchu.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.ranchu.rc \ device/generic/goldfish/init.system_ext.rc:$(TARGET_COPY_OUT_SYSTEM_EXT)/etc/init/init.system_ext.rc \ device/generic/goldfish/fstab.ranchu:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.ranchu \ diff --git a/64bitonly/product/x86_64-vendor.mk b/64bitonly/product/x86_64-vendor.mk index f130b0ad..bbfeb7c4 100644 --- a/64bitonly/product/x86_64-vendor.mk +++ b/64bitonly/product/x86_64-vendor.mk @@ -22,9 +22,6 @@ PRODUCT_SDK_ADDON_COPY_FILES += \ PRODUCT_COPY_FILES += \ device/generic/goldfish/data/etc/configs/gpu.config:data/misc/gceconfigs/gpu.config -PRODUCT_PACKAGES += \ - emulatorip - PRODUCT_PROPERTY_OVERRIDES += \ ro.crypto.dm_default_key.options_format.version=2 diff --git a/arm64-vendor.mk b/arm64-vendor.mk index c45cc6da..7cbc19f2 100644 --- a/arm64-vendor.mk +++ b/arm64-vendor.mk @@ -3,9 +3,6 @@ include device/generic/goldfish/arm64-kernel.mk PRODUCT_PROPERTY_OVERRIDES += \ vendor.rild.libpath=/vendor/lib64/libgoldfish-ril.so -PRODUCT_PACKAGES += \ - emulatorip - PRODUCT_PROPERTY_OVERRIDES += \ ro.crypto.dm_default_key.options_format.version=2 diff --git a/audio/device_port_source.cpp b/audio/device_port_source.cpp index 3bdb766a..058654b8 100644 --- a/audio/device_port_source.cpp +++ b/audio/device_port_source.cpp @@ -263,18 +263,18 @@ template <class G> struct GeneratedSource : public DevicePortSource { const unsigned nFrames = std::min(requestedFrames, availableFrames); mGenerator(samples, nFrames); - const size_t sizeBytes = nFrames * nChannels * sizeof(*samples); + const size_t nSamples = nFrames * nChannels; if (nChannels > 1) { adjust_channels(samples, 1, samples, nChannels, - sizeof(*samples), sizeBytes); + sizeof(*samples), nFrames * sizeof(*samples)); } mSentFrames += nFrames; aops::multiplyByVolume(volume, mWriteBuffer.data(), - sizeBytes / sizeof(int16_t)); + nSamples); - writer(mWriteBuffer.data(), sizeBytes); + writer(mWriteBuffer.data(), nSamples * sizeof(*samples)); return 0; } diff --git a/data/etc/Android.bp b/data/etc/Android.bp deleted file mode 100644 index d87c1c9f..00000000 --- a/data/etc/Android.bp +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (C) 2020 The Android Open Source Project -// -// 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 -// -// http://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. - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "device_generic_goldfish_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["device_generic_goldfish_license"], -} - -cc_prebuilt_binary { - name: "emulatorip", - arch: { - arm64: { - srcs: ["arm64/emulatorip"], - }, - x86: { - srcs: ["x86/emulatorip"], - }, - x86_64: { - srcs: ["x86_64/emulatorip"], - }, - }, - stem: "ip", - shared_libs: [ - "libc", - "libc++", - "libdl", - "libm", - ], - vendor: true, - strip: { - none: true, - }, -} diff --git a/init.ranchu-net.sh b/init.ranchu-net.sh index fa468a68..588f2104 100755 --- a/init.ranchu-net.sh +++ b/init.ranchu-net.sh @@ -12,17 +12,6 @@ case "$wifi_virtio" in ;; esac -# Check if WiFi with mac80211_hwsim is enabled. If so, run the WiFi init script. If not we just -# have to run the DHCP client in the default namespace and that will set up -# all the networking. -wifi_hwsim=`getprop ro.boot.qemu.wifi` -case "$wifi_hwsim" in - 1) /vendor/bin/init.wifi.sh - ;; - *) setprop ctl.start dhcpclient_def - ;; -esac - # set up the second interface (for inter-emulator connections) # if required my_ip=`getprop vendor.net.shared_net_ip` diff --git a/init.ranchu.rc b/init.ranchu.rc index d62215dd..7846703e 100644 --- a/init.ranchu.rc +++ b/init.ranchu.rc @@ -68,7 +68,6 @@ on post-fs-data mkdir /data/vendor/devicestate 0755 root root mkdir /data/vendor/var 0755 root root mkdir /data/vendor/var/run 0755 root root - mkdir /data/vendor/var/run/netns 0755 root root start qemu-adb-keys start qemu-device-state @@ -129,15 +128,9 @@ on property:dev.bootcomplete=1 setprop vendor.qemu.dev.bootcomplete 1 start ranchu-setup -on post-fs-data && property:ro.boot.qemu.wifi=1 - start create_router_ns - on post-fs-data && property:ro.boot.qemu.virtiowifi=1 start ranchu-net -on property:vendor.qemu.networknamespace=ready - start ranchu-net - service ranchu-net /vendor/bin/init.ranchu-net.sh class late_start user root @@ -145,40 +138,11 @@ service ranchu-net /vendor/bin/init.ranchu-net.sh oneshot disabled # Started on post-fs-data -service emu_hostapd /vendor/bin/execns router /vendor/bin/hostapd_nohidl /data/vendor/wifi/hostapd/hostapd.conf - user root - group root wifi net_raw net_admin - disabled - -service netmgr /vendor/bin/execns router /vendor/bin/netmgr --if-prefix wlan1 --bridge eth0,radio0-peer - user root - group root wifi - disabled - -service create_router_ns /vendor/bin/createns router - user root - group root - disabled - oneshot - -service wifi_forwarder /vendor/bin/wifi_forwarder - user root - group root wifi - disabled - -service dhcpclient_rtr /vendor/bin/dhcpclient -i radio0 --no-gateway - user root - group root - disabled - service dhcpclient_wifi /vendor/bin/dhcpclient -i wlan0 --no-gateway user root group root disabled -on property:vendor.network.bridged=1 - start dhcpclient_rtr - service dhcpclient_def /vendor/bin/dhcpclient -i eth0 --no-gateway user root group root diff --git a/network/netmgr/Android.bp b/network/netmgr/Android.bp deleted file mode 100644 index e5d95140..00000000 --- a/network/netmgr/Android.bp +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright (C) 2018 The Android Open Source Project -// -// 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 -// -// http://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. -// - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "device_generic_goldfish_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["device_generic_goldfish_license"], -} - -cc_binary { - name: "netmgr", - vendor: true, - cflags: [ - "-Wall", - "-Werror", - ], - srcs: [ - "bridge.cpp", - "bridge_builder.cpp", - "commander.cpp", - "interface_state.cpp", - "log.cpp", - "main.cpp", - "monitor.cpp", - "poller.cpp", - "utils.cpp", - "wifi_forwarder.cpp", - "commands/wifi_command.cpp", - ], - shared_libs: [ - "libcutils", - "liblog", - "libpcap", - ], - static_libs: [ - "libqemupipe.ranchu", - ], -} diff --git a/network/netmgr/bridge.cpp b/network/netmgr/bridge.cpp deleted file mode 100644 index adbe21e6..00000000 --- a/network/netmgr/bridge.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "bridge.h" - -#include "log.h" - -#include <errno.h> -#include <net/if.h> -#include <string.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <unistd.h> - -Bridge::Bridge(const std::string& bridgeName) : mBridgeName(bridgeName) { -} - -Bridge::~Bridge() { - if (mSocketFd != -1) { - ::close(mSocketFd); - mSocketFd = -1; - } -} - -Result Bridge::init() { - Result res = createSocket(); - if (!res) { - return res; - } - res = createBridge(); - if (!res) { - return res; - } - return Result::success(); -} - -Result Bridge::addInterface(const std::string& interfaceName) { - return doInterfaceOperation(interfaceName, SIOCBRADDIF, "add"); -} - -Result Bridge::removeInterface(const std::string& interfaceName) { - return doInterfaceOperation(interfaceName, SIOCBRDELIF, "remove"); -} - -Result Bridge::createSocket() { - if (mSocketFd != -1) { - return Result::error("Bridge already initialized"); - } - mSocketFd = ::socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); - if (mSocketFd < 0) { - return Result::error("Unable to create socket for bridge: %s", - strerror(errno)); - } - return Result::success(); -} - -Result Bridge::createBridge() { - int res = ::ioctl(mSocketFd, SIOCBRADDBR, mBridgeName.c_str()); - if (res < 0) { - // If the bridge already exists we just keep going, that's fine. - // Otherwise something went wrong. - if (errno != EEXIST) { - return Result::error("Cannot create bridge %s: %s", - mBridgeName.c_str(), strerror(errno)); - } - } - - struct ifreq request; - memset(&request, 0, sizeof(request)); - // Determine interface index of bridge - request.ifr_ifindex = if_nametoindex(mBridgeName.c_str()); - if (request.ifr_ifindex == 0) { - return Result::error("Unable to get bridge %s interface index", - mBridgeName.c_str()); - } - // Get bridge interface flags - strlcpy(request.ifr_name, mBridgeName.c_str(), sizeof(request.ifr_name)); - res = ::ioctl(mSocketFd, SIOCGIFFLAGS, &request); - if (res != 0) { - return Result::error("Unable to get interface flags for bridge %s: %s", - mBridgeName.c_str(), strerror(errno)); - } - - if ((request.ifr_flags & IFF_UP) != 0) { - // Bridge is already up, it's ready to go - return Result::success(); - } - - // Bridge is not up, it needs to be up to work - request.ifr_flags |= IFF_UP; - res = ::ioctl(mSocketFd, SIOCSIFFLAGS, &request); - if (res != 0) { - return Result::error("Unable to set interface flags for bridge %s: %s", - strerror(errno)); - } - - return Result::success(); -} - -Result Bridge::doInterfaceOperation(const std::string& interfaceName, - unsigned long operation, - const char* operationName) { - struct ifreq request; - memset(&request, 0, sizeof(request)); - - request.ifr_ifindex = if_nametoindex(interfaceName.c_str()); - if (request.ifr_ifindex == 0) { - return Result::error("Bridge unable to %s interface '%s', no such " - "interface", operationName, interfaceName.c_str()); - } - strlcpy(request.ifr_name, mBridgeName.c_str(), sizeof(request.ifr_name)); - int res = ::ioctl(mSocketFd, operation, &request); - // An errno of EBUSY most likely indicates that the interface is already - // part of the bridge. Ignore this. - if (res < 0 && errno != EBUSY) { - return Result::error("Bridge unable to %s interface '%s': %s", - operationName, interfaceName.c_str(), - strerror(errno)); - } - return Result::success(); -} diff --git a/network/netmgr/bridge.h b/network/netmgr/bridge.h deleted file mode 100644 index fc7ff519..00000000 --- a/network/netmgr/bridge.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include "result.h" - -#include <string> - -class Bridge { -public: - explicit Bridge(const std::string& bridgeName); - ~Bridge(); - - Result init(); - - Result addInterface(const std::string& interfaceName); - Result removeInterface(const std::string& interfaceName); -private: - Result createSocket(); - Result createBridge(); - Result doInterfaceOperation(const std::string& interfaceName, - unsigned long operation, - const char* operationName); - - std::string mBridgeName; - int mSocketFd = -1; -}; diff --git a/network/netmgr/bridge_builder.cpp b/network/netmgr/bridge_builder.cpp deleted file mode 100644 index d772eaef..00000000 --- a/network/netmgr/bridge_builder.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "bridge_builder.h" - -#include "bridge.h" -#include "log.h" -#include "result.h" - -BridgeBuilder::BridgeBuilder(Bridge& bridge, const char* interfacePrefix) : - mBridge(bridge), - mInterfacePrefix(interfacePrefix), - mPrefixLength(strlen(interfacePrefix)) { -} - -void BridgeBuilder::onInterfaceState(unsigned int /*index*/, - const char* name, - InterfaceState state) { - if (strncmp(name, mInterfacePrefix, mPrefixLength) != 0) { - // Does not match our prefix, ignore it - return; - } - - if (state == InterfaceState::Up) { - Result res = mBridge.addInterface(name); - if (!res) { - LOGE("%s", res.c_str()); - } - } -} diff --git a/network/netmgr/bridge_builder.h b/network/netmgr/bridge_builder.h deleted file mode 100644 index e3d95805..00000000 --- a/network/netmgr/bridge_builder.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include "interface_state.h" - -#include <stddef.h> - -class Bridge; - -class BridgeBuilder { -public: - // Construct a bridge builder that will add any interface that comes up to - // |bridge| if the interface name begins with |interfacePrefix|. - BridgeBuilder(Bridge& bridge, const char* interfacePrefix); - - void onInterfaceState(unsigned int index, - const char* name, - InterfaceState state); - -private: - Bridge& mBridge; - const char* mInterfacePrefix; - size_t mPrefixLength; -}; diff --git a/network/netmgr/commander.cpp b/network/netmgr/commander.cpp deleted file mode 100644 index e7775d2d..00000000 --- a/network/netmgr/commander.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "commander.h" - -#include "commands/command.h" -#include "log.h" - -#include <errno.h> -#include <qemu_pipe_bp.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/types.h> - -static const char kQemuPipeName[] = "qemud:network"; - -// How much space to use for each command received -static const size_t kReceiveSpace = 1024; -// The maximum amount of bytes to keep in the receive buffer for a single -// command before dropping data. -static const size_t kMaxReceiveBufferSize = 65536; - -Commander::Commander() : mPipeFd(-1) { -} - -Commander::~Commander() { - closePipe(); -} - -Result Commander::init() { - if (mPipeFd != -1) { - return Result::error("Commander already initialized"); - } - - openPipe(); - - return Result::success(); -} - -void Commander::registerCommand(const char* commandStr, Command* command) { - mCommands[commandStr] = command; -} - -void Commander::getPollData(std::vector<pollfd>* fds) const { - if (mPipeFd != -1) { - fds->push_back(pollfd{mPipeFd, POLLIN, 0}); - } -} - -Pollable::Timestamp Commander::getTimeout() const { - return mDeadline; -} - -bool Commander::onReadAvailable(int /*fd*/, int* /*status*/) { - size_t offset = mReceiveBuffer.size(); - mReceiveBuffer.resize(offset + kReceiveSpace); - if (mReceiveBuffer.size() > kMaxReceiveBufferSize) { - // We have buffered too much data, this should never happen but as a - // seurity measure let's just drop everything we have and keep - // receiving. Maybe the situation will improve. - mReceiveBuffer.resize(kReceiveSpace); - offset = 0; - } - while (true) { - int status = qemu_pipe_read(mPipeFd, &mReceiveBuffer[offset], kReceiveSpace); - - if (status < 0) { - if (errno == EINTR) { - // We got an interrupt, try again - continue; - } - LOGE("Commander failed to receive on pipe: %s", strerror(errno)); - // Don't exit the looper because of this, keep trying - return true; - } - size_t length = static_cast<size_t>(status); - mReceiveBuffer.resize(offset + length); - - while (true) { - auto endline = std::find(mReceiveBuffer.begin(), - mReceiveBuffer.end(), - '\n'); - if (endline == mReceiveBuffer.end()) { - // No endline in sight, keep waiting and buffering - return true; - } - - *endline = '\0'; - - char* args = ::strchr(mReceiveBuffer.data(), ' '); - if (args) { - *args++ = '\0'; - } - auto command = mCommands.find(mReceiveBuffer.data()); - - if (command != mCommands.end()) { - command->second->onCommand(mReceiveBuffer.data(), args); - } - // Now that we have processed this line let's remove it from the - // receive buffer - ++endline; - if (endline == mReceiveBuffer.end()) { - mReceiveBuffer.clear(); - // There can be nothing left, just return - return true; - } else { - mReceiveBuffer.erase(mReceiveBuffer.begin(), endline + 1); - // There may be another line in there so keep looping and look - // for more - } - } - return true; - } -} - -bool Commander::onClose(int /*fd*/, int* /*status*/) { - // Pipe was closed from the other end, close it on our side and re-open - closePipe(); - openPipe(); - return true; -} - -bool Commander::onTimeout(int* /*status*/) { - if (mPipeFd == -1) { - openPipe(); - } - return true; -} - -void Commander::openPipe() { - mPipeFd = qemu_pipe_open_ns(NULL, kQemuPipeName, O_RDWR); - if (mPipeFd == -1) { - LOGE("Failed to open QEMU pipe '%s': %s", - kQemuPipeName, - strerror(errno)); - // Try again in the future - mDeadline = Pollable::Clock::now() + std::chrono::minutes(1); - } else { - mDeadline = Pollable::Timestamp::max(); - } -} - -void Commander::closePipe() { - if (qemu_pipe_valid(mPipeFd)) { - qemu_pipe_close(mPipeFd); - mPipeFd = QEMU_PIPE_INVALID_HANDLE; - } -} diff --git a/network/netmgr/commander.h b/network/netmgr/commander.h deleted file mode 100644 index 7f7fc7e8..00000000 --- a/network/netmgr/commander.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include "pollable.h" -#include "result.h" - -#include <unordered_map> -#include <vector> - -class Command; - -class Commander : public Pollable { -public: - Commander(); - ~Commander(); - - Result init(); - - void registerCommand(const char* commandStr, Command* command); - - void getPollData(std::vector<pollfd>* fds) const override; - Timestamp getTimeout() const override; - bool onReadAvailable(int fd, int* status) override; - bool onClose(int fd, int* status) override; - bool onTimeout(int* status) override; -private: - void openPipe(); - void closePipe(); - - int mPipeFd; - Pollable::Timestamp mDeadline; - std::vector<char> mReceiveBuffer; - std::unordered_map<std::string, Command*> mCommands; -}; diff --git a/network/netmgr/commands/command.h b/network/netmgr/commands/command.h deleted file mode 100644 index 0612cefa..00000000 --- a/network/netmgr/commands/command.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include "../result.h" - -// An interface for commands coming through the pipe. Note that each instance -// can handle any number of commands, all it has to do is differentiate based -// on the incoming command string or arguments. It will have to be registered -// multiple times, once for each command though. -class Command { -public: - virtual ~Command() = default; - - // Work to perform when a command is received. The result will be used to - // report the result to the user. If the result indicates success the user - // will see an "OK" response, on failure the error message in the result - // will be presented to the user. This means that the result error string - // should be fairly user-friendly. - virtual Result onCommand(const char* command, const char* args) = 0; - -}; - diff --git a/network/netmgr/commands/wifi_command.cpp b/network/netmgr/commands/wifi_command.cpp deleted file mode 100644 index 27bf95a8..00000000 --- a/network/netmgr/commands/wifi_command.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "wifi_command.h" - -#include "../bridge.h" -#include "../utils.h" - -#include <cutils/properties.h> -#include <errno.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -static const char kHostApdStubFile[] = "/vendor/etc/simulated_hostapd.conf"; -static const char kHostApdConfFile[] = "/data/vendor/wifi/hostapd/hostapd.conf"; - -static const char kControlRestartProperty[] = "ctl.restart"; -static const char kHostApdServiceName[] = "emu_hostapd"; - -static const char kIfNamePrefix[] = "wlan1_"; - -class File { -public: - explicit File(FILE* file) : mFile(file) {} - ~File() { - if (mFile) { - fclose(mFile); - } - } - - FILE* get() { return mFile; } - - bool operator!() const { return mFile == nullptr; } -private: - FILE* mFile; -}; - -class Fd { -public: - explicit Fd(int fd) : mFd(fd) {} - ~Fd() { - if (mFd != -1) { - ::close(mFd); - mFd = -1; - } - } - - int get() const { return mFd; } - -private: - int mFd; -}; - -WifiCommand::WifiCommand(Bridge& bridge) - : mBridge(bridge) - , mLowestInterfaceNumber(1) { - readConfig(); -} - -Result WifiCommand::onCommand(const char* /*command*/, const char* args) { - const char* divider = ::strchr(args, ' '); - if (divider == nullptr) { - // Unknown command, every command needs an argument - return Result::error("Invalid wifi command '%s'", args); - } - - std::string subCommand(args, divider); - if (subCommand.empty()) { - return Result::error("Empty wifi command"); - } - - std::vector<std::string> subArgs = explode(divider + 1, ' '); - if (subArgs.empty()) { - // All of these commands require sub arguments - return Result::error("Missing argument to command '%s'", - subCommand.c_str()); - } - - if (subCommand == "add") { - return onAdd(subArgs); - } else if (subCommand == "block") { - return onBlock(subArgs); - } else if (subCommand == "unblock") { - return onUnblock(subArgs); - } else { - return Result::error("Unknown wifi command '%s'", subCommand.c_str()); - } -} - -void WifiCommand::readConfig() { -} - -Result WifiCommand::writeConfig() { - File in(fopen(kHostApdStubFile, "r")); - if (!in) { - return Result::error("Config failure: could not open template: %s", - strerror(errno)); - } - - File out(fopen(kHostApdConfFile, "w")); - if (!out) { - return Result::error("Config failure: could not open target: %s", - strerror(errno)); - } - - char buffer[32768]; - while (!feof(in.get())) { - size_t bytesRead = fread(buffer, 1, sizeof(buffer), in.get()); - if (bytesRead != sizeof(buffer) && ferror(in.get())) { - return Result::error("Config failure: Error reading template: %s", - strerror(errno)); - } - - size_t bytesWritten = fwrite(buffer, 1, bytesRead, out.get()); - if (bytesWritten != bytesRead) { - return Result::error("Config failure: Error writing target: %s", - strerror(errno)); - } - } - fprintf(out.get(), "\n\n"); - - for (const auto& ap : mAccessPoints) { - fprintf(out.get(), "bss=%s\n", ap.second.ifName.c_str()); - fprintf(out.get(), "ssid=%s\n", ap.second.ssid.c_str()); - if (!ap.second.password.empty()) { - fprintf(out.get(), "wpa=2\n"); - fprintf(out.get(), "wpa_key_mgmt=WPA-PSK\n"); - fprintf(out.get(), "rsn_pairwise=CCMP\n"); - fprintf(out.get(), "wpa_passphrase=%s\n", ap.second.password.c_str()); - } - fprintf(out.get(), "\n"); - } - return Result::success(); -} - -Result WifiCommand::triggerHostApd() { - property_set(kControlRestartProperty, kHostApdServiceName); - return Result::success(); -} - -Result WifiCommand::onAdd(const std::vector<std::string>& arguments) { - AccessPoint& ap = mAccessPoints[arguments[0]]; - ap.ssid = arguments[0]; - if (arguments.size() > 1) { - ap.password = arguments[1]; - } else { - ap.password.clear(); - } - if (ap.ifName.empty()) { - char buffer[sizeof(kIfNamePrefix) + 10]; - while (true) { - snprintf(buffer, sizeof(buffer), "%s%d", - kIfNamePrefix, mLowestInterfaceNumber); - ap.ifName = buffer; - auto usedInterface = mUsedInterfaces.find(ap.ifName); - if (usedInterface == mUsedInterfaces.end()) { - // This interface is available, use it - ++mLowestInterfaceNumber; - mUsedInterfaces.insert(ap.ifName); - break; - } - // The interface name was alread in use, try the next one - ++mLowestInterfaceNumber; - } - } - Result res = writeConfig(); - if (!res) { - return res; - } - return triggerHostApd(); -} - -Result WifiCommand::onBlock(const std::vector<std::string>& arguments) { - auto interface = mAccessPoints.find(arguments[0]); - if (interface == mAccessPoints.end()) { - return Result::error("Unknown SSID '%s'", arguments[0].c_str()); - } - interface->second.blocked = true; - return mBridge.removeInterface(interface->second.ifName.c_str()); -} - -Result WifiCommand::onUnblock(const std::vector<std::string>& arguments) { - auto interface = mAccessPoints.find(arguments[0]); - if (interface == mAccessPoints.end()) { - return Result::error("Unknown SSID '%s'", arguments[0].c_str()); - } - interface->second.blocked = false; - return mBridge.addInterface(interface->second.ifName.c_str()); -} - diff --git a/network/netmgr/commands/wifi_command.h b/network/netmgr/commands/wifi_command.h deleted file mode 100644 index b47edb89..00000000 --- a/network/netmgr/commands/wifi_command.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include "command.h" -#include "result.h" - -#include <string> -#include <unordered_map> -#include <unordered_set> -#include <vector> - -class Bridge; - -class WifiCommand : public Command { -public: - explicit WifiCommand(Bridge& bridge); - virtual ~WifiCommand() = default; - - Result onCommand(const char* command, const char* args) override; -private: - void readConfig(); - Result writeConfig(); - Result triggerHostApd(); - - Result onAdd(const std::vector<std::string>& args); - Result onBlock(const std::vector<std::string>& args); - Result onUnblock(const std::vector<std::string>& args); - - struct AccessPoint { - AccessPoint() : blocked(false) {} - std::string ifName; - std::string ssid; - std::string password; - bool blocked; - }; - - Bridge& mBridge; - std::unordered_map<std::string, AccessPoint> mAccessPoints; - std::unordered_set<std::string> mUsedInterfaces; - int mLowestInterfaceNumber; -}; - diff --git a/network/netmgr/fork.cpp b/network/netmgr/fork.cpp deleted file mode 100644 index 49c4c614..00000000 --- a/network/netmgr/fork.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "fork.h" - -#include "log.h" - -#include <errno.h> -#include <string.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> - -bool forkAndExec(const char* argv[]) { - pid_t pid = ::fork(); - if (pid < 0) { - // Failed to fork - LOGE("fork() failed: %s", strerror(errno)); - return false; - } else if (pid == 0) { - // Child - char buffer[32768]; - size_t offset = 0; - for (size_t i = 0; argv[i]; ++i) { - offset += snprintf(buffer + offset, sizeof(buffer) - offset, - "%s ", argv[i]); - } - LOGE("Running '%s'", buffer); - execvp(argv[0], const_cast<char* const*>(argv)); - LOGE("Failed to run '%s': %s", argv[0], strerror(errno)); - _exit(1); - } else { - // Parent - int status = 0; - do { - ::waitpid(pid, &status, 0); - if (WIFEXITED(status)) { - int exitStatus = WEXITSTATUS(status); - if (exitStatus == 0) { - return true; - } - LOGE("Error: '%s' exited with code: %d", argv[0], exitStatus); - } else if (WIFSIGNALED(status)) { - LOGE("Error: '%s' terminated with signal: %d", - argv[0], WTERMSIG(status)); - } - // Other possibilities include being stopped and continued as part - // of a trace but we don't really care about that. The important - // part is that unless the process explicitly exited or was killed - // by a signal we have to keep waiting. - } while (!WIFEXITED(status) && !WIFSIGNALED(status)); - return false; - } -} diff --git a/network/netmgr/fork.h b/network/netmgr/fork.h deleted file mode 100644 index a7cfd48e..00000000 --- a/network/netmgr/fork.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -// Fork and run the provided program with arguments and wait until the program -// exits. The list of arguments in |argv| has to be terminated by a NULL -// pointer (e.g. { "ls", "-l", "/", nullptr } to run 'ls -l /' -// Returns true if the process exits normally with a return code of 0. Returns -// false if the process is terminated by a signal or if it exits with a return -// code that is not 0. -bool forkAndExec(const char* argv[]); - diff --git a/network/netmgr/interface_state.cpp b/network/netmgr/interface_state.cpp deleted file mode 100644 index 57e169c2..00000000 --- a/network/netmgr/interface_state.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "interface_state.h" - -const char* interfaceStateToStr(InterfaceState state) { - switch (state) { - case InterfaceState::Up: - return "Up"; - case InterfaceState::Down: - return "Down"; - } -} - diff --git a/network/netmgr/interface_state.h b/network/netmgr/interface_state.h deleted file mode 100644 index 6d56aba1..00000000 --- a/network/netmgr/interface_state.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -enum class InterfaceState { - Up, - Down, -}; - -const char* interfaceStateToStr(InterfaceState state); diff --git a/network/netmgr/log.cpp b/network/netmgr/log.cpp deleted file mode 100644 index 7256a3f9..00000000 --- a/network/netmgr/log.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "log.h" - -#include <stdio.h> -#include <unistd.h> - -bool isTerminal; - -void initIsTerminal() { - isTerminal = isatty(STDOUT_FILENO) != 0; -} - diff --git a/network/netmgr/log.h b/network/netmgr/log.h deleted file mode 100644 index 1efe72a2..00000000 --- a/network/netmgr/log.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#define LOG_TAG "netmgr" -#include <log/log.h> -#include <stdio.h> - -extern bool isTerminal; -void initIsTerminal(); - -// Print errors to stderr if running from a terminal, otherwise print to logcat -// This is useful for debugging from a terminal -#define LOGE(...) do { \ - if (isTerminal) { \ - fprintf(stderr, __VA_ARGS__); \ - fprintf(stderr, "\n"); \ - } else { \ - ALOGE(__VA_ARGS__); \ - } \ -} while (0) - -#define LOGW(...) do { \ - if (isTerminal) { \ - fprintf(stderr, __VA_ARGS__); \ - fprintf(stderr, "\n"); \ - } else { \ - ALOGW(__VA_ARGS__); \ - } \ -} while (0) - diff --git a/network/netmgr/macaddress.h b/network/netmgr/macaddress.h deleted file mode 100644 index 9363859c..00000000 --- a/network/netmgr/macaddress.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * 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 - * - * http://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. - * 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. - */ - -#pragma once - -#include <functional> - -#include <linux/if_ether.h> -#include <stdint.h> -#include <string.h> - -struct MacAddress { - uint8_t addr[ETH_ALEN]; - bool isBroadcast() const { - return memcmp(addr, "\xFF\xFF\xFF\xFF\xFF\xFF", ETH_ALEN) == 0; - } -} __attribute__((__packed__)); - -template<class T> -inline void hash_combine(size_t& seed, const T& value) { - std::hash<T> hasher; - seed ^= hasher(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2); -} - -namespace std { -template<> struct hash<MacAddress> { - size_t operator()(const MacAddress& addr) const { - size_t seed = 0; - // Treat the first 4 bytes as an uint32_t to save some computation - hash_combine(seed, *reinterpret_cast<const uint32_t*>(addr.addr)); - // And the remaining 2 bytes as an uint16_t - hash_combine(seed, *reinterpret_cast<const uint16_t*>(addr.addr + 4)); - return seed; - } -}; -} - diff --git a/network/netmgr/main.cpp b/network/netmgr/main.cpp deleted file mode 100644 index d83de399..00000000 --- a/network/netmgr/main.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "bridge.h" -#include "bridge_builder.h" -#include "commander.h" -#include "commands/wifi_command.h" -#include "log.h" -#include "monitor.h" -#include "poller.h" -#include "utils.h" -#include "wifi_forwarder.h" - -#include <arpa/inet.h> -#include <netinet/in.h> - -#include <cutils/properties.h> - -#include <functional> - -static const char kBridgeName[] = "br0"; -static const char kNetworkBridgedProperty[] = "vendor.network.bridged"; - -static void usage(const char* name) { - LOGE("Usage: %s --if-prefix <prefix> --bridge <if1,if2,...>", name); - LOGE(" <prefix> indicates the name of network interfaces to configure."); - LOGE(" <ip/mask> is the base IP address to assign to the first interface"); - LOGE(" and mask indicates the netmask and broadcast to set."); - LOGE(" Additionally mask is used to determine the address"); - LOGE(" for the second interface by skipping ahead one subnet"); - LOGE(" and the size of the subnet is indicated by <mask>"); -} - -static Result addBridgeInterfaces(Bridge& bridge, const char* interfaces) { - std::vector<std::string> ifNames = explode(interfaces, ','); - - for (const auto& ifName : ifNames) { - Result res = bridge.addInterface(ifName); - if (!res) { - return res; - } - } - return Result::success(); -} - -int main(int argc, char* argv[]) { - const char* interfacePrefix = nullptr; - const char* bridgeInterfaces = nullptr; - - for (int i = 1; i < argc; ++i) { - if (strcmp(argv[i], "--if-prefix") == 0 && i + 1 < argc) { - interfacePrefix = argv[++i]; - } else if (strcmp(argv[i], "--bridge") == 0 && i + 1 < argc) { - bridgeInterfaces = argv[++i]; - } else { - LOGE("Unknown parameter '%s'", argv[i]); - usage(argv[0]); - return 1; - } - } - - if (interfacePrefix == nullptr) { - LOGE("Missing parameter --if-prefix"); - } - if (bridgeInterfaces == nullptr) { - LOGE("Missing parameter --bridge"); - } - if (interfacePrefix == nullptr || bridgeInterfaces == nullptr) { - usage(argv[0]); - return 1; - } - - Bridge bridge(kBridgeName); - Result res = bridge.init(); - if (!res) { - LOGE("%s", res.c_str()); - return 1; - } - res = addBridgeInterfaces(bridge, bridgeInterfaces); - if (!res) { - LOGE("%s", res.c_str()); - return 1; - } - - BridgeBuilder bridgeBuilder(bridge, interfacePrefix); - - property_set(kNetworkBridgedProperty, "1"); - - Monitor monitor; - - monitor.setOnInterfaceState(std::bind(&BridgeBuilder::onInterfaceState, - &bridgeBuilder, - std::placeholders::_1, - std::placeholders::_2, - std::placeholders::_3)); - - res = monitor.init(); - if (!res) { - LOGE("%s", res.c_str()); - return 1; - } - - Commander commander; - res = commander.init(); - if (!res) { - LOGE("%s", res.c_str()); - return 1; - } - - WifiCommand wifiCommand(bridge); - commander.registerCommand("wifi", &wifiCommand); - - Poller poller; - poller.addPollable(&monitor); - poller.addPollable(&commander); - - return poller.run(); -} - diff --git a/network/netmgr/monitor.cpp b/network/netmgr/monitor.cpp deleted file mode 100644 index a9d248ae..00000000 --- a/network/netmgr/monitor.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "monitor.h" - -#include "log.h" - -#include <arpa/inet.h> -#include <errno.h> -#include <linux/rtnetlink.h> -#include <net/if.h> -#include <stdio.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <unistd.h> - -Monitor::Monitor() : mSocketFd(-1) { - -} - -Monitor::~Monitor() { - closeSocket(); -} - -Result Monitor::init() { - Result res = openSocket(); - if (!res) { - return res; - } - return requestInterfaces(); -} - -void Monitor::setOnInterfaceState(OnInterfaceStateCallback callback) { - mOnInterfaceStateCallback = callback; -} - -bool Monitor::onReadAvailable(int /*fd*/, int* /*status*/) { - char buffer[32768]; - struct sockaddr_storage storage; - - while (true) { - socklen_t addrSize = sizeof(storage); - int status = ::recvfrom(mSocketFd, - buffer, - sizeof(buffer), - MSG_DONTWAIT, - reinterpret_cast<struct sockaddr*>(&storage), - &addrSize); - if (status < 0) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - // Nothing to receive, everything is fine - return true; - } else if (errno == EINTR) { - continue; - } - LOGE("Monitor receive failed: %s", strerror(errno)); - // An error occurred but let's keep trying - return true; - } else if (addrSize < 0 || - static_cast<size_t>(addrSize) != sizeof(struct sockaddr_nl)) { - LOGE("Monitor received invalid address size"); - // It's an error but no need to exit, let's keep polling - return true; - } - - size_t length = static_cast<size_t>(status); - - auto hdr = reinterpret_cast<struct nlmsghdr*>(buffer); - while (NLMSG_OK(hdr, length) && hdr->nlmsg_type != NLMSG_DONE) { - switch (hdr->nlmsg_type) { - case RTM_NEWLINK: - handleNewLink(hdr); - break; - default: - break; - } - hdr = NLMSG_NEXT(hdr, length); - } - } -} - -bool Monitor::onClose(int /*fd*/, int* status) { - // Socket was closed from the other end, close it from our end and re-open - closeSocket(); - Result res = openSocket(); - if (!res) { - LOGE("%s", res.c_str()); - *status = 1; - return false; - } - return true; -} - -bool Monitor::onTimeout(int* /*status*/) { - return true; -} - -void Monitor::getPollData(std::vector<pollfd>* fds) const { - if (mSocketFd != -1) { - fds->push_back(pollfd{mSocketFd, POLLIN, 0}); - } -} - -Pollable::Timestamp Monitor::getTimeout() const { - return Pollable::Timestamp::max(); -} - -Result Monitor::openSocket() { - if (mSocketFd != -1) { - return Result::error("Monitor already initialized"); - } - - mSocketFd = ::socket(AF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_ROUTE); - if (mSocketFd == -1) { - return Result::error("Monitor failed to open socket: %s", - strerror(errno)); - } - - struct sockaddr_nl addr; - memset(&addr, 0, sizeof(addr)); - addr.nl_family = AF_NETLINK; - addr.nl_groups = RTNLGRP_LINK | RTNLGRP_IPV4_IFADDR | RTNLGRP_IPV6_IFADDR; - - struct sockaddr* sa = reinterpret_cast<struct sockaddr*>(&addr); - if (::bind(mSocketFd, sa, sizeof(addr)) != 0) { - return Result::error("Monitor failed to bind socket: %s", - strerror(errno)); - } - - return Result::success(); -} - -Result Monitor::requestInterfaces() { - if (mSocketFd == -1) { - return Result::error("Monitor not initialized yet"); - } - - struct { - struct nlmsghdr hdr; - struct rtgenmsg gen; - } request; - - memset(&request, 0, sizeof(request)); - - request.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(request.gen)); - request.hdr.nlmsg_type = RTM_GETLINK; - request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; - request.hdr.nlmsg_seq = 1; - request.hdr.nlmsg_pid = getpid(); - request.gen.rtgen_family = AF_PACKET; - - ssize_t result = TEMP_FAILURE_RETRY(::send(mSocketFd, - &request, - request.hdr.nlmsg_len, - 0)); - if (result < 0) { - return Result::error("Failed to request interfaces: %s", - strerror(errno)); - } - return Result::success(); -} - -void Monitor::closeSocket() { - if (mSocketFd != -1) { - ::close(mSocketFd); - mSocketFd = -1; - } -} - -void Monitor::handleNewLink(const struct nlmsghdr* hdr) { - if (!mOnInterfaceStateCallback) { - return; - } - - auto msg = reinterpret_cast<const struct ifinfomsg*>(NLMSG_DATA(hdr)); - - char name[IF_NAMESIZE + 1] = { 0 }; - const unsigned int ifIndex = msg->ifi_index; - if (if_indextoname(ifIndex, name) == nullptr) { - LOGE("Unable to get interface name for interface index %u", ifIndex); - } - - bool isUp = !!(msg->ifi_flags & IFF_UP); - auto iterator = mUpInterfaces.find(ifIndex); - - if (iterator == mUpInterfaces.end() && isUp) { - // The interface was not known to be up but is up, known state changed - mUpInterfaces.insert(ifIndex); - mOnInterfaceStateCallback(ifIndex, name, InterfaceState::Up); - } else if (iterator != mUpInterfaces.end() && !isUp) { - // The interface was known to be up, now it's not, known state changed - mUpInterfaces.erase(iterator); - mOnInterfaceStateCallback(ifIndex, name, InterfaceState::Down); - } -} - diff --git a/network/netmgr/monitor.h b/network/netmgr/monitor.h deleted file mode 100644 index 00f525ee..00000000 --- a/network/netmgr/monitor.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include "interface_state.h" -#include "pollable.h" -#include "result.h" - -#include <unordered_set> - -/** Monitor network interfaces and provide notifications of changes to those - * interfaces. - */ -class Monitor : public Pollable { -public: - using OnInterfaceStateCallback = std::function<void (unsigned int index, - const char* name, - InterfaceState state)>; - Monitor(); - ~Monitor(); - - Result init(); - - void setOnInterfaceState(OnInterfaceStateCallback callback); - - // Pollable interface - void getPollData(std::vector<pollfd>* fds) const override; - Timestamp getTimeout() const override; - bool onReadAvailable(int fd, int* status) override; - bool onClose(int fd, int* status) override; - bool onTimeout(int* status) override; - -private: - Result openSocket(); - Result requestInterfaces(); - void closeSocket(); - void handleNewLink(const struct nlmsghdr* hdr); - - int mSocketFd; - OnInterfaceStateCallback mOnInterfaceStateCallback; - std::unordered_set<unsigned int> mUpInterfaces; -}; - diff --git a/network/netmgr/pollable.h b/network/netmgr/pollable.h deleted file mode 100644 index fbf4baf7..00000000 --- a/network/netmgr/pollable.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include <chrono> -#include <vector> - -#include <poll.h> - -/* An interface for pollable classes. - */ -class Pollable { -public: - using Clock = std::chrono::steady_clock; - using Timestamp = Clock::time_point; - virtual ~Pollable() = default; - - /* Get the poll data for the next poll loop. The implementation can place - * as many fds as needed in |fds|. - */ - virtual void getPollData(std::vector<pollfd>* fds) const = 0; - /* Get the timeout for the next poll loop. This should be a timestamp - * indicating when the timeout should be triggered. Note that this may - * be called at any time and any number of times for a poll loop so the - * deadline should not be adjusted in this call, a set deadline should - * just be returned. Note specifically that if a call to onReadAvailable - * modifies the deadline the timeout for the previous timestamp might not - * fire as the poller will check the timestamp AFTER onReadAvailable is - * called. - */ - virtual Timestamp getTimeout() const = 0; - /* Called when there is data available to read on an fd associated with - * the pollable. |fd| indicates which fd to read from. If the call returns - * false the poller will exit its poll loop with a return code of |status|. - */ - virtual bool onReadAvailable(int fd, int* status) = 0; - /* Called when an fd associated with the pollable is closed. |fd| indicates - * which fd was closed. If the call returns false the poller will exit its - * poll loop with a return code of |status|. - */ - virtual bool onClose(int fd, int* status) = 0; - /* Called when the timeout returned by getPollData has been reached. If - * the call returns false the poller will exit its poll loop with a return - * code of |status|. - */ - virtual bool onTimeout(int* status) = 0; -}; - diff --git a/network/netmgr/poller.cpp b/network/netmgr/poller.cpp deleted file mode 100644 index 8dcbcabf..00000000 --- a/network/netmgr/poller.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "poller.h" - -#include "log.h" - -#include <errno.h> -#include <poll.h> -#include <signal.h> -#include <stdio.h> -#include <string.h> - -#include <unordered_map> -#include <vector> - -using std::chrono::duration_cast; - -static struct timespec* calculateTimeout(Pollable::Timestamp deadline, - struct timespec* ts) { - Pollable::Timestamp now = Pollable::Clock::now(); - if (deadline < Pollable::Timestamp::max()) { - if (deadline <= now) { - LOGE("Poller found past due deadline, setting to zero"); - ts->tv_sec = 0; - ts->tv_nsec = 0; - return ts; - } - - auto timeout = deadline - now; - // Convert and round down to seconds - auto seconds = duration_cast<std::chrono::seconds>(timeout); - // Then subtract the seconds from the timeout and convert the remainder - auto nanos = duration_cast<std::chrono::nanoseconds>(timeout - seconds); - - ts->tv_sec = seconds.count(); - ts->tv_nsec = nanos.count(); - - return ts; - } - return nullptr; -} - -Poller::Poller() { -} - -void Poller::addPollable(Pollable* pollable) { - mPollables.push_back(pollable); -} - -int Poller::run() { - // Block all signals while we're running. This way we don't have to deal - // with things like EINTR. We then uses ppoll to set the original mask while - // polling. This way polling can be interrupted but socket writing, reading - // and ioctl remain interrupt free. If a signal arrives while we're blocking - // it it will be placed in the signal queue and handled once ppoll sets the - // original mask. This way no signals are lost. - sigset_t blockMask, mask; - int status = ::sigfillset(&blockMask); - if (status != 0) { - LOGE("Unable to fill signal set: %s", strerror(errno)); - return errno; - } - status = ::sigprocmask(SIG_SETMASK, &blockMask, &mask); - if (status != 0) { - LOGE("Unable to set signal mask: %s", strerror(errno)); - return errno; - } - - std::vector<struct pollfd> fds; - std::unordered_map<int, Pollable*> pollables; - while (true) { - fds.clear(); - pollables.clear(); - Pollable::Timestamp deadline = Pollable::Timestamp::max(); - for (auto& pollable : mPollables) { - size_t start = fds.size(); - pollable->getPollData(&fds); - Pollable::Timestamp pollableDeadline = pollable->getTimeout(); - // Create a map from each fd to the pollable - for (size_t i = start; i < fds.size(); ++i) { - pollables[fds[i].fd] = pollable; - } - if (pollableDeadline < deadline) { - deadline = pollableDeadline; - } - } - - struct timespec ts = { 0, 0 }; - struct timespec* tsPtr = calculateTimeout(deadline, &ts); - status = ::ppoll(fds.data(), fds.size(), tsPtr, &mask); - if (status < 0) { - if (errno == EINTR) { - // Interrupted, just keep going - continue; - } - // Actual error, time to quit - LOGE("Polling failed: %s", strerror(errno)); - return errno; - } else if (status > 0) { - // Check for read or close events - for (const auto& fd : fds) { - if ((fd.revents & (POLLIN | POLLHUP)) == 0) { - // Neither POLLIN nor POLLHUP, not interested - continue; - } - auto pollable = pollables.find(fd.fd); - if (pollable == pollables.end()) { - // No matching fd, weird and unexpected - LOGE("Poller could not find fd matching %d", fd.fd); - continue; - } - if (fd.revents & POLLIN) { - // This pollable has data available for reading - int status = 0; - if (!pollable->second->onReadAvailable(fd.fd, &status)) { - // The onReadAvailable handler signaled an exit - return status; - } - } - if (fd.revents & POLLHUP) { - // The fd was closed from the other end - int status = 0; - if (!pollable->second->onClose(fd.fd, &status)) { - // The onClose handler signaled an exit - return status; - } - } - } - } - // Check for timeouts - Pollable::Timestamp now = Pollable::Clock::now(); - for (const auto& pollable : mPollables) { - if (pollable->getTimeout() <= now) { - int status = 0; - if (!pollable->onTimeout(&status)) { - // The onTimeout handler signaled an exit - return status; - } - } - } - } - - return 0; -} diff --git a/network/netmgr/poller.h b/network/netmgr/poller.h deleted file mode 100644 index 9794f4da..00000000 --- a/network/netmgr/poller.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include <vector> - -#include "pollable.h" - -class Poller { -public: - Poller(); - - void addPollable(Pollable* pollable); - - int run(); - -private: - std::vector<Pollable*> mPollables; -}; - diff --git a/network/netmgr/result.h b/network/netmgr/result.h deleted file mode 100644 index 5087e146..00000000 --- a/network/netmgr/result.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * 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 - * - * http://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. - */ -#pragma once - -#include <stdio.h> -#include <stdarg.h> - -#include <string> - -class Result { -public: - static Result success() { - return Result(true); - } - // Construct a result indicating an error. - static Result error(std::string message) { - return Result(message); - } - static Result error(const char* format, ...) { - char buffer[1024]; - va_list args; - va_start(args, format); - vsnprintf(buffer, sizeof(buffer), format, args); - va_end(args); - buffer[sizeof(buffer) - 1] = '\0'; - return Result(std::string(buffer)); - } - - bool isSuccess() const { return mSuccess; } - bool operator!() const { return !mSuccess; } - - const char* c_str() const { return mMessage.c_str(); } -private: - explicit Result(bool success) : mSuccess(success) { } - explicit Result(std::string message) - : mMessage(message), mSuccess(false) { - } - std::string mMessage; - bool mSuccess; -}; - diff --git a/network/netmgr/utils.cpp b/network/netmgr/utils.cpp deleted file mode 100644 index fa71c1e1..00000000 --- a/network/netmgr/utils.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "utils.h" - -#include <string.h> - -std::vector<std::string> explode(const char* str, char divider) { - const char* cur = str; - const char* space = nullptr; - std::vector<std::string> result; - do { - space = ::strchr(cur, divider); - if (space) { - result.emplace_back(cur, space); - cur = space + 1; - } else { - result.emplace_back(cur); - } - } while (space); - - return result; -} - diff --git a/network/netmgr/utils.h b/network/netmgr/utils.h deleted file mode 100644 index 7c05882c..00000000 --- a/network/netmgr/utils.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include <string> -#include <vector> - -std::vector<std::string> explode(const char* str, char divider); diff --git a/network/netmgr/wifi_forwarder.cpp b/network/netmgr/wifi_forwarder.cpp deleted file mode 100644 index 077dd30c..00000000 --- a/network/netmgr/wifi_forwarder.cpp +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "wifi_forwarder.h" - -#include "log.h" - -#include <inttypes.h> -#include <arpa/inet.h> -#include <errno.h> -#include <linux/if_packet.h> -#include <linux/kernel.h> -#include <qemu_pipe_bp.h> -#include <string.h> -#include <net/ethernet.h> -#include <net/if.h> -#include <pcap/pcap.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <unistd.h> - -static const char kQemuPipeName[] = "qemud:wififorward"; - -// The largest packet size to capture with pcap on the monitor interface -static const int kPcapSnapLength = 65536; - -static const size_t kForwardBufferIncrement = 32768; -static const size_t kForwardBufferMaxSize = 1 << 20; - -static const uint32_t kWifiForwardMagic = 0xD5C4B3A2; - -struct WifiForwardHeader { - WifiForwardHeader(uint32_t dataLength, uint32_t radioLength) - : magic(__cpu_to_le32(kWifiForwardMagic)) - , fullLength(__cpu_to_le32(dataLength + sizeof(WifiForwardHeader))) - , radioLength(__cpu_to_le32(radioLength)) { } - - uint32_t magic; - uint32_t fullLength; - uint32_t radioLength; -} __attribute__((__packed__)); - -struct RadioTapHeader { - uint8_t it_version; - uint8_t it_pad; - uint16_t it_len; - uint32_t it_present; -} __attribute__((__packed__)); - -enum class FrameType { - Management, - Control, - Data, - Extension -}; - -enum class ManagementType { - AssociationRequest, - AssociationResponse, - ReassociationRequest, - ReassociationResponse, - ProbeRequest, - ProbeResponse, - TimingAdvertisement, - Beacon, - Atim, - Disassociation, - Authentication, - Deauthentication, - Action, - ActionNoAck, -}; - -enum class ControlType { - BeamFormingReportPoll, - VhtNdpAnnouncement, - ControlFrameExtension, - ControlWrapper, - BlockAckReq, - BlockAck, - PsPoll, - Rts, - Cts, - Ack, - CfEnd, - CfEndCfAck -}; - -// Since the IEEE 802.11 header can vary in size depending on content we have -// to establish a minimum size that we need to be able to inspect and forward -// the frame. Every frame need to contain at least frame_control, duration_id, -// and addr1. -static const uint32_t kMinimumIeee80211Size = sizeof(uint16_t) + - sizeof(uint16_t) + - sizeof(MacAddress); - -WifiForwarder::WifiForwarder(const char* monitorInterfaceName) - : mInterfaceName(monitorInterfaceName), - mDeadline(Pollable::Timestamp::max()), - mMonitorPcap(nullptr), - mPipeFd(-1) { -} - -WifiForwarder::~WifiForwarder() { - cleanup(); -} - -Result WifiForwarder::init() { - if (mMonitorPcap || mPipeFd != -1) { - return Result::error("WifiForwarder already initialized"); - } - - mPipeFd = qemu_pipe_open_ns(NULL, kQemuPipeName, O_RDWR); - if (mPipeFd == -1) { - // It's OK if this fails, the emulator might not have been started with - // this feature enabled. If it's not enabled we'll try again later, in - // the meantime there is no point in opening the monitor socket either. - LOGE("WifiForwarder unable to open QEMU pipe: %s", strerror(errno)); - mDeadline = Pollable::Clock::now() + std::chrono::minutes(1); - return Result::success(); - } - - char errorMsg[PCAP_ERRBUF_SIZE]; - memset(errorMsg, 0, sizeof(errorMsg)); - mMonitorPcap = pcap_create(mInterfaceName.c_str(), errorMsg); - if (mMonitorPcap == nullptr) { - return Result::error("WifiForwarder cannot create pcap handle: %s", - errorMsg); - } - int result = pcap_set_snaplen(mMonitorPcap, kPcapSnapLength); - if (result != 0) { - return Result::error("WifiForwader cannot set pcap snap length: %s", - pcap_statustostr(result)); - } - - result = pcap_set_promisc(mMonitorPcap, 1); - if (result != 0) { - return Result::error("WifiForwader cannot set pcap promisc mode: %s", - pcap_statustostr(result)); - } - - result = pcap_set_immediate_mode(mMonitorPcap, 1); - if (result != 0) { - return Result::error("WifiForwader cannot set pcap immediate mode: %s", - pcap_statustostr(result)); - } - - result = pcap_activate(mMonitorPcap); - if (result > 0) { - // A warning, log it but keep going - LOGW("WifiForwader received warnings when activating pcap: %s", - pcap_statustostr(result)); - } else if (result < 0) { - // An error, return - return Result::error("WifiForwader unable to activate pcap: %s", - pcap_statustostr(result)); - } - - int datalinkType = pcap_datalink(mMonitorPcap); - if (datalinkType != DLT_IEEE802_11_RADIO) { - // Unexpected data link encapsulation, we don't support this - return Result::error("WifiForwarder detected incompatible data link " - "encapsulation: %d", datalinkType); - } - // All done - return Result::success(); -} - - -void WifiForwarder::getPollData(std::vector<pollfd>* fds) const { - if (mPipeFd == -1) { - return; - } - int pcapFd = pcap_get_selectable_fd(mMonitorPcap); - if (pcapFd != -1) { - fds->push_back(pollfd{pcapFd, POLLIN, 0}); - } else { - LOGE("WifiForwarder unable to get pcap fd"); - } - if (mPipeFd != -1) { - fds->push_back(pollfd{mPipeFd, POLLIN, 0}); - } -} - -Pollable::Timestamp WifiForwarder::getTimeout() const { - // If there is no pipe return the deadline, we're going to retry, otherwise - // use an infinite timeout. - return mPipeFd == -1 ? mDeadline : Pollable::Timestamp::max(); -} - -bool WifiForwarder::onReadAvailable(int fd, int* /*status*/) { - if (fd == mPipeFd) { - injectFromPipe(); - } else { - forwardFromPcap(); - } - return true; -} - -void WifiForwarder::forwardFromPcap() { - struct pcap_pkthdr* header = nullptr; - const u_char* data = nullptr; - int result = pcap_next_ex(mMonitorPcap, &header, &data); - if (result == 0) { - // Timeout, nothing to do - return; - } else if (result < 0) { - LOGE("WifiForwarder failed to read from pcap: %s", - pcap_geterr(mMonitorPcap)); - return; - } - if (header->caplen < header->len) { - LOGE("WifiForwarder received packet exceeding capture length: %u < %u", - header->caplen, header->len); - return; - } - - if (mPipeFd == -1) { - LOGE("WifiForwarder unable to forward data, pipe not open"); - return; - } - - if (header->caplen < sizeof(RadioTapHeader)) { - // This packet is too small to be a valid radiotap packet, drop it - LOGE("WifiForwarder captured packet that is too small: %u", - header->caplen); - return; - } - - auto radiotap = reinterpret_cast<const RadioTapHeader*>(data); - uint32_t radioLen = __le16_to_cpu(radiotap->it_len); - if (header->caplen < radioLen + kMinimumIeee80211Size) { - // This packet is too small to contain a valid IEEE 802.11 frame - LOGE("WifiForwarder captured packet that is too small: %u < %u", - header->caplen, radioLen + kMinimumIeee80211Size); - return; - } - - WifiForwardHeader forwardHeader(header->caplen, radioLen); - - if (qemu_pipe_write_fully(mPipeFd, &forwardHeader, sizeof(forwardHeader))) { - LOGE("WifiForwarder failed to write to pipe: %s", strerror(errno)); - return; - } - - if (qemu_pipe_write_fully(mPipeFd, data, header->caplen)) { - LOGE("WifiForwarder failed to write to pipe: %s", strerror(errno)); - return; - } -} - -void WifiForwarder::injectFromPipe() { - size_t start = mMonitorBuffer.size(); - size_t newSize = start + kForwardBufferIncrement; - if (newSize > kForwardBufferMaxSize) { - // We've exceeded the maximum allowed size, drop everything we have so - // far and start over. This is most likely caused by some delay in - // injection or the injection failing in which case keeping old data - // around isn't going to be very useful. - LOGE("WifiForwarder ran out of buffer space"); - newSize = kForwardBufferIncrement; - start = 0; - } - mMonitorBuffer.resize(newSize); - - while (true) { - int result = ::read(mPipeFd, - mMonitorBuffer.data() + start, - mMonitorBuffer.size() - start); - if (result < 0) { - if (errno == EINTR) { - continue; - } - LOGE("WifiForwarder failed to read to forward buffer: %s", - strerror(errno)); - // Return the buffer to its previous size - mMonitorBuffer.resize(start); - return; - } else if (result == 0) { - // Nothing received, nothing to write - // Return the buffer to its previous size - mMonitorBuffer.resize(start); - LOGE("WifiForwarder did not receive anything to inject"); - return; - } - // Adjust the buffer size to match everything we recieved - mMonitorBuffer.resize(start + static_cast<size_t>(result)); - break; - } - - while (mMonitorBuffer.size() >= - sizeof(WifiForwardHeader) + sizeof(RadioTapHeader)) { - auto fwd = reinterpret_cast<WifiForwardHeader*>(mMonitorBuffer.data()); - if (__le32_to_cpu(fwd->magic) != kWifiForwardMagic) { - // We are not properly aligned, this can happen for the first read - // if the client or server happens to send something that's in the - // middle of a stream. Attempt to find the next packet boundary. - LOGE("WifiForwarder found incorrect magic, finding next magic"); - uint32_t le32magic = __cpu_to_le32(kWifiForwardMagic); - auto next = reinterpret_cast<unsigned char*>( - ::memmem(mMonitorBuffer.data(), mMonitorBuffer.size(), - &le32magic, sizeof(le32magic))); - if (next) { - // We've found a possible candidate, erase everything before - size_t length = next - mMonitorBuffer.data(); - mMonitorBuffer.erase(mMonitorBuffer.begin(), - mMonitorBuffer.begin() + length); - continue; - } else { - // There is no possible candidate, drop everything except the - // last three bytes. The last three bytes could possibly be the - // start of the next magic without actually triggering the - // search above. - if (mMonitorBuffer.size() > 3) { - mMonitorBuffer.erase(mMonitorBuffer.begin(), - mMonitorBuffer.end() - 3); - } - // In this case there is nothing left to parse so just return - // right away. - return; - } - } - // The length according to the wifi forward header - const size_t fullLength = __le32_to_cpu(fwd->fullLength); - const size_t payloadLength = fullLength - sizeof(WifiForwardHeader); - const size_t radioLength = __le32_to_cpu(fwd->radioLength); - // Get the radio tap header, right after the wifi forward header - unsigned char* radioTapLocation = mMonitorBuffer.data() + sizeof(*fwd); - auto hdr = reinterpret_cast<RadioTapHeader*>(radioTapLocation); - const size_t radioHdrLength = __le16_to_cpu(hdr->it_len); - - if (radioLength != radioHdrLength) { - LOGE("WifiForwarder radiotap (%u), forwarder (%u) length mismatch", - (unsigned)(radioHdrLength), (unsigned)radioLength); - // The wifi forward header radio length does not match up with the - // radiotap header length. Either this was not an actual packet - // boundary or the packet is malformed. Remove a single byte from - // the buffer to trigger a new magic marker search. - mMonitorBuffer.erase(mMonitorBuffer.begin(), - mMonitorBuffer.begin() + 1); - continue; - } - // At this point we have verified that the magic marker is present and - // that the length in the wifi forward header matches the radiotap - // header length. We're now reasonably sure this is actually a valid - // packet that we can process. - - if (fullLength > mMonitorBuffer.size()) { - // We have not received enough data yet, wait for more to arrive. - return; - } - - if (hdr->it_version != 0) { - // Unknown header version, skip this packet because we don't know - // how to handle it. - LOGE("WifiForwarder encountered unknown radiotap version %u", - static_cast<unsigned>(hdr->it_version)); - mMonitorBuffer.erase(mMonitorBuffer.begin(), - mMonitorBuffer.begin() + fullLength); - continue; - } - - if (mMonitorPcap) { - // A sufficient amount of data has arrived, forward it. - int result = pcap_inject(mMonitorPcap, hdr, payloadLength); - if (result < 0) { - LOGE("WifiForwarder failed to inject %" PRIu64 " bytes: %s", - static_cast<uint64_t>(payloadLength), - pcap_geterr(mMonitorPcap)); - } else if (static_cast<size_t>(result) < payloadLength) { - LOGE("WifiForwarder only injected %d out of %" PRIu64 " bytes", - result, static_cast<uint64_t>(payloadLength)); - } - } else { - LOGE("WifiForwarder could not forward to monitor, pcap not set up"); - } - mMonitorBuffer.erase(mMonitorBuffer.begin(), - mMonitorBuffer.begin() + fullLength); - } - -} - -void WifiForwarder::cleanup() { - if (mMonitorPcap) { - pcap_close(mMonitorPcap); - mMonitorPcap = nullptr; - } - if (mPipeFd != -1) { - ::close(mPipeFd); - mPipeFd = -1; - } -} - -bool WifiForwarder::onClose(int /*fd*/, int* status) { - // Don't care which fd, just start all over again for simplicity - cleanup(); - Result res = init(); - if (!res) { - *status = 1; - return false; - } - return true; -} - -bool WifiForwarder::onTimeout(int* status) { - if (mPipeFd == -1 && mMonitorPcap == nullptr) { - Result res = init(); - if (!res) { - *status = 1; - return false; - } - } - return true; -} - diff --git a/network/netmgr/wifi_forwarder.h b/network/netmgr/wifi_forwarder.h deleted file mode 100644 index 5e9939e0..00000000 --- a/network/netmgr/wifi_forwarder.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include "macaddress.h" -#include "pollable.h" -#include "result.h" - -#include <string> -#include <unordered_set> - -struct Ieee80211Header; -struct pcap; -typedef struct pcap pcap_t; - -class WifiForwarder : public Pollable { -public: - explicit WifiForwarder(const char* monitorInterfaceName); - ~WifiForwarder(); - - Result init(); - - // Pollable interface - void getPollData(std::vector<pollfd>* fds) const override; - Timestamp getTimeout() const override; - bool onReadAvailable(int fd, int* status) override; - bool onClose(int fd, int* status) override; - bool onTimeout(int* status) override; -private: - void forwardFromPcap(); - void injectFromPipe(); - void cleanup(); - - std::string mInterfaceName; - Pollable::Timestamp mDeadline; - std::vector<unsigned char> mMonitorBuffer; - pcap_t* mMonitorPcap; - int mPipeFd; -}; diff --git a/network/wifi_forwarder/Android.bp b/network/wifi_forwarder/Android.bp deleted file mode 100644 index 26fd018c..00000000 --- a/network/wifi_forwarder/Android.bp +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright (C) 2019 The Android Open Source Project -// -// 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 -// -// http://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. -// - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "device_generic_goldfish_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["device_generic_goldfish_license"], -} - -cc_binary { - name: "wifi_forwarder", - vendor: true, - cppflags: [ - "-Wall", - "-Werror", - "--std=c++17", - ], - srcs: [ - "frame.cpp", - "local_connection.cpp", - "main.cpp", - "netlink_message.cpp", - "netlink_socket.cpp", - "poller.cpp", - "remote_connection.cpp", - "wifi_forwarder.cpp", - ], - shared_libs: [ - "libcutils", - "liblog", - "libnl", - "libpcap", - "libutils", - "libutilscallstack", - ], - static_libs: [ - "libqemupipe.ranchu", - ], -} diff --git a/network/wifi_forwarder/cache.h b/network/wifi_forwarder/cache.h deleted file mode 100644 index bd64f1a4..00000000 --- a/network/wifi_forwarder/cache.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include <inttypes.h> -#include "log.h" - -#include <chrono> -#include <unordered_map> - -// Default amount of time until a cache entry expires -static constexpr auto kDefaultCacheTimeout = std::chrono::seconds(30); - -template<typename Key, - typename Value, - typename Timestamp = std::chrono::steady_clock::time_point> -class Cache { -public: - using TimedValue = std::pair<Timestamp, Value>; - - using MapType = std::unordered_map<Key, TimedValue>; - using key_type = typename MapType::key_type; - using mapped_type = Value; - - class ConstIterator { - public: - class IterPair { - public: - IterPair(const Key& key, const Value& value) - : first(key), second(value) { - } - - const IterPair* operator->() const { return this; } - const Key& first; - const Value& second; - private: - }; - - ConstIterator(typename MapType::const_iterator current) - : mCurrent(current) { } - - IterPair operator->() const { - return IterPair(mCurrent->first, mCurrent->second.second); - } - - IterPair operator*() const { - return IterPair(mCurrent->first, mCurrent->second.second); - } - - bool operator==(const ConstIterator& other) const { - return mCurrent == other.mCurrent; - } - - bool operator!=(const ConstIterator& other) const { - return mCurrent != other.mCurrent; - } - - typename MapType::const_iterator internal() const { return mCurrent; } - - private: - typename MapType::const_iterator mCurrent; - }; - class Iterator { - public: - class IterPair { - public: - IterPair(const Key& key, Value& value) : first(key), second(value) { } - - IterPair* operator->() { return this; } - const Key& first; - Value& second; - private: - }; - - Iterator(typename MapType::iterator current) : mCurrent(current) { } - - IterPair operator->() { - return IterPair(mCurrent->first, mCurrent->second.second); - } - - IterPair operator*() { - return IterPair(mCurrent->first, mCurrent->second.second); - } - - bool operator==(const Iterator& other) const { - return mCurrent == other.mCurrent; - } - - bool operator!=(const Iterator& other) const { - return mCurrent != other.mCurrent; - } - - typename MapType::iterator internal() { return mCurrent; } - - private: - typename MapType::iterator mCurrent; - }; - - using iterator = Iterator; - using const_iterator = ConstIterator; - using insert_return_type = std::pair<const_iterator, bool>; - - Cache(std::chrono::milliseconds timeout = kDefaultCacheTimeout) - : mTimeout(timeout) { - } - - template<typename M> - insert_return_type insert_or_assign(const key_type& key, M&& value) { - std::pair<typename MapType::iterator,bool> inserted = - mMap.insert_or_assign(key, TimedValue(mCurrentTime, - std::move(value))); - return insert_return_type(inserted.first, inserted.second); - } - - mapped_type& operator[](const key_type& key) { - TimedValue& v = mMap[key]; - v.first = mCurrentTime; - return v.second; - } - - iterator find(const key_type& key) { - return iterator(mMap.find(key)); - } - - const_iterator find(const key_type& key) const { - return const_iterator(mMap.find(key)); - } - - iterator erase(const_iterator pos) { - return iterator(mMap.erase(pos.internal())); - } - - iterator erase(iterator pos) { - return iterator(mMap.erase(pos.internal())); - } - - size_t erase(const key_type& key) { - return mMap.erase(key); - } - - iterator begin() { - return iterator(mMap.begin()); - } - - iterator end() { - return iterator(mMap.end()); - } - - const_iterator begin() const { - return const_iterator(mMap.begin()); - } - - const_iterator end() const { - return const_iterator(mMap.end()); - } - - void setCurrentTime(Timestamp currentTime) { - mCurrentTime = currentTime; - } - - void expireEntries() { - for (auto it = mMap.begin(); it != mMap.end(); ) { - const Timestamp timestamp = it->second.first; - if (mCurrentTime > timestamp && - (mCurrentTime - timestamp) > mTimeout) { - // This entry has expired, remove it - it = mMap.erase(it); - } else { - ++it; - } - } - } -private: - const std::chrono::milliseconds mTimeout; - Timestamp mCurrentTime; - MapType mMap; -}; - diff --git a/network/wifi_forwarder/frame.cpp b/network/wifi_forwarder/frame.cpp deleted file mode 100644 index 3b20b4e1..00000000 --- a/network/wifi_forwarder/frame.cpp +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "frame.h" - -#include "hwsim.h" -#include "ieee80211.h" - -#include <asm/byteorder.h> - -#include <sstream> - -static constexpr uint64_t kSlotTime = 9; - -static const AccessCategory kPriorityToAc[8] = { - AccessCategory::BestEffort, - AccessCategory::Background, - AccessCategory::Background, - AccessCategory::BestEffort, - AccessCategory::Video, - AccessCategory::Video, - AccessCategory::Voice, - AccessCategory::Voice, -}; - -static uint32_t calcContentionWindowMin(AccessCategory ac) { - switch (ac) { - case AccessCategory::Voice: - return 3; - case AccessCategory::Video: - return 7; - case AccessCategory::BestEffort: - return 15; - case AccessCategory::Background: - return 15; - } -} - -static uint32_t calcContentionWindowMax(AccessCategory ac) { - switch (ac) { - case AccessCategory::Voice: - return 7; - case AccessCategory::Video: - return 15; - case AccessCategory::BestEffort: - return 1023; - case AccessCategory::Background: - return 1023; - } -} - -FrameType frameTypeFromByte(uint8_t byte) { - if (byte == static_cast<uint8_t>(FrameType::Ack)) { - return FrameType::Ack; - } else if (byte == static_cast<uint8_t>(FrameType::Data)) { - return FrameType::Data; - } - return FrameType::Unknown; -} - -FrameInfo::FrameInfo(const MacAddress& transmitter, - uint64_t cookie, - uint32_t flags, - uint32_t channel, - const hwsim_tx_rate* rates, - size_t numRates) - : mTransmitter(transmitter) - , mCookie(cookie) - , mFlags(flags) - , mChannel(channel) { - size_t i = 0; - for (; i < numRates; ++i) { - mTxRates[i].count = 0; - mTxRates[i].idx = rates[i].idx; - } - for (; i < mTxRates.size(); ++i) { - mTxRates[i].count = 0; - mTxRates[i].idx = -1; - } -} - -bool FrameInfo::shouldAck() const { - return !!(mFlags & HWSIM_TX_CTL_REQ_TX_STATUS); -} - -Frame::Frame(const uint8_t* data, size_t size) : mData(data, data + size) { -} - -Frame::Frame(const uint8_t* data, size_t size, const MacAddress& transmitter, - uint64_t cookie, uint32_t flags, uint32_t channel, - const hwsim_tx_rate* rates, size_t numRates) - : mData(data, data + size) - , mInfo(transmitter, cookie, flags, channel, rates, numRates) - , mContentionWindow(calcContentionWindowMin(getAc())) - , mContentionWindowMax(calcContentionWindowMax(getAc())) { - memcpy(mInitialTxRates.data(), rates, numRates * sizeof(*rates)); -} - -bool Frame::incrementAttempts() { - Rates& rates = mInfo.rates(); - for (size_t i = 0; i < rates.size(); ++i) { - if (mInitialTxRates[i].idx == -1) { - // We've run out of attempts - break; - } - if (rates[i].count < mInitialTxRates[i].count) { - ++rates[i].count; - return true; - } - } - return false; -} - -bool Frame::hasRemainingAttempts() { - Rates& rates = mInfo.rates(); - for (size_t i = 0; i < rates.size(); ++i) { - if (mInitialTxRates[i].idx == -1) { - break; - } - if (rates[i].count < mInitialTxRates[i].count) { - return true; - } - } - return false; -} - -const MacAddress& Frame::source() const { - auto hdr = reinterpret_cast<const struct ieee80211_hdr*>(mData.data()); - return *reinterpret_cast<const MacAddress*>(hdr->addr2); -} - -const MacAddress& Frame::destination() const { - auto hdr = reinterpret_cast<const struct ieee80211_hdr*>(mData.data()); - return *reinterpret_cast<const MacAddress*>(hdr->addr1); -} - -std::string Frame::str() const { - uint8_t type = (mData[0] >> 2) & 0x3; - uint8_t subType = (mData[0] >> 4) & 0x0F; - - std::stringstream ss; - ss << "[ Ck: " << cookie() << " Ch: " << channel() << " ] "; - switch (type) { - case 0: - // Management - ss << "Management ("; - switch (subType) { - case 0: - ss << "Association Request"; - break; - case 1: - ss << "Association Response"; - break; - case 2: - ss << "Reassociation Request"; - break; - case 3: - ss << "Reassociation Response"; - break; - case 4: - ss << "Probe Request"; - break; - case 5: - ss << "Probe Response"; - break; - case 6: - ss << "Timing Advertisement"; - break; - case 8: - ss << "Beacon"; - break; - case 9: - ss << "ATIM"; - break; - case 10: - ss << "Disassociation"; - break; - case 11: - ss << "Authentication"; - break; - case 12: - ss << "Deauthentication"; - break; - case 13: - ss << "Action"; - break; - case 14: - ss << "Action No Ack"; - break; - default: - ss << subType; - break; - } - ss << ')'; - break; - case 1: - // Control - ss << "Control ("; - switch (subType) { - case 4: - ss << "Beamforming Report Poll"; - break; - case 5: - ss << "VHT NDP Announcement"; - break; - case 6: - ss << "Control Frame Extension"; - break; - case 7: - ss << "Control Wrapper"; - break; - case 8: - ss << "Block Ack Request"; - break; - case 9: - ss << "Block Ack"; - break; - case 10: - ss << "PS-Poll"; - break; - case 11: - ss << "RTS"; - break; - case 12: - ss << "CTS"; - break; - case 13: - ss << "Ack"; - break; - case 14: - ss << "CF-End"; - break; - case 15: - ss << "CF-End+CF-Ack"; - break; - default: - ss << subType; - break; - } - ss << ')'; - break; - case 2: - // Data - ss << "Data ("; - switch (subType) { - case 0: - ss << "Data"; - break; - case 1: - ss << "Data+CF-Ack"; - break; - case 2: - ss << "Data+CF-Poll"; - break; - case 3: - ss << "Data+CF-Ack+CF-Poll"; - break; - case 4: - ss << "Null"; - break; - case 5: - ss << "CF-Ack"; - break; - case 6: - ss << "CF-Poll"; - break; - case 7: - ss << "CF-Ack+CF-Poll"; - break; - case 8: - ss << "QoS Data"; - break; - case 9: - ss << "QoS Data+CF-Ack"; - break; - case 10: - ss << "QoS Data+CF-Poll"; - break; - case 11: - ss << "QoS Data+CF-Ack+CF-Poll"; - break; - case 12: - ss << "QoS Null"; - break; - case 14: - ss << "QoS CF-Poll"; - break; - case 15: - ss << "QoS CF-Poll+CF-Ack"; - break; - default: - ss << subType; - break; - } - ss << ')'; - break; - case 3: - // Extension - ss << "Extension ("; - switch (subType) { - case 0: - ss << "DMG Beacon"; - break; - default: - ss << subType; - break; - } - ss << ')'; - break; - default: - ss << type << " (" << subType << ')'; - break; - } - return ss.str(); -} - -bool Frame::isBeacon() const { - uint8_t totalType = mData[0] & 0xFC; - return totalType == 0x80; -} - -bool Frame::isData() const { - uint8_t totalType = mData[0] & 0x0C; - return totalType == 0x08; -} - -bool Frame::isDataQoS() const { - uint8_t totalType = mData[0] & 0xFC; - return totalType == 0x88; -} - -uint16_t Frame::getQoSControl() const { - // Some frames have 4 address fields instead of 3 which pushes QoS control - // forward 6 bytes. - bool uses4Addresses = !!(mData[1] & 0x03); - const uint8_t* addr = &mData[uses4Addresses ? 30 : 24]; - - return __le16_to_cpu(*reinterpret_cast<const uint16_t*>(addr)); -} - -uint64_t Frame::calcNextTimeout() { - mNextTimeout = (mContentionWindow * kSlotTime) / 2; - mContentionWindow = std::min((mContentionWindow * 2) + 1, - mContentionWindowMax); - return mNextTimeout; -} - -AccessCategory Frame::getAc() const { - if (!isData()) { - return AccessCategory::Voice; - } - if (!isDataQoS()) { - return AccessCategory::BestEffort; - } - uint16_t priority = getQoSControl() & 0x07; - return kPriorityToAc[priority]; -} diff --git a/network/wifi_forwarder/frame.h b/network/wifi_forwarder/frame.h deleted file mode 100644 index ac76f827..00000000 --- a/network/wifi_forwarder/frame.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include "macaddress.h" - -#include <stdint.h> - -#include <array> -#include <vector> - -#define IEEE80211_TX_MAX_RATES 4 - -struct hwsim_tx_rate { - signed char idx; - unsigned char count; -} __attribute__((__packed__)); - -enum class FrameType : uint8_t { - Unknown, - Ack, - Data, -}; - -enum class AccessCategory { - Voice, - Video, - BestEffort, - Background, -}; - -FrameType frameTypeFromByte(uint8_t byte); - -using Rates = std::array<hwsim_tx_rate, IEEE80211_TX_MAX_RATES>; - -class FrameInfo { -public: - FrameInfo() = default; - FrameInfo(const FrameInfo&) = default; - FrameInfo(FrameInfo&&) = default; - FrameInfo(const MacAddress& transmitter, - uint64_t cookie, - uint32_t flags, - uint32_t channel, - const hwsim_tx_rate* rates, - size_t numRates); - - FrameInfo& operator=(const FrameInfo&) = default; - FrameInfo& operator=(FrameInfo&&) = default; - - const Rates& rates() const { return mTxRates; } - Rates& rates() { return mTxRates; } - - const MacAddress& transmitter() const { return mTransmitter; } - uint64_t cookie() const { return mCookie; } - uint32_t flags() const { return mFlags; } - uint32_t channel() const { return mChannel; } - - bool shouldAck() const; - -private: - Rates mTxRates; - MacAddress mTransmitter; - uint64_t mCookie = 0; - uint32_t mFlags = 0; - uint32_t mChannel = 0; -}; - -class Frame { -public: - Frame() = default; - Frame(const uint8_t* data, size_t size); - Frame(const uint8_t* data, - size_t size, - const MacAddress& transmitter, - uint64_t cookie, - uint32_t flags, - uint32_t channel, - const hwsim_tx_rate* rates, - size_t numRates); - Frame(Frame&& other) = default; - - Frame& operator=(Frame&& other) = default; - - size_t size() const { return mData.size(); } - const uint8_t* data() const { return mData.data(); } - uint8_t* data() { return mData.data(); } - uint64_t cookie() const { return mInfo.cookie(); } - uint32_t flags() const { return mInfo.flags(); } - uint32_t channel() const { return mInfo.channel(); } - - Rates& rates() { return mInfo.rates(); } - const Rates& rates() const { return mInfo.rates(); } - - const Rates& initialRates() const { return mInitialTxRates; } - - // Increment the number of attempts made in the tx rates - bool incrementAttempts(); - bool hasRemainingAttempts(); - - // The transmitter as indicated by hwsim - const MacAddress& transmitter() const { return mInfo.transmitter(); } - // The source as indicated by the 802.11 frame - const MacAddress& source() const; - // The destination as indicated by the 802.11 frame - const MacAddress& destination() const; - - std::string str() const; - - const FrameInfo& info() const { return mInfo; } - FrameInfo& info() { return mInfo; } - - bool isBeacon() const; - bool isData() const; - bool isDataQoS() const; - - uint16_t getQoSControl() const; - - bool shouldAck() const { return mInfo.shouldAck(); } - - uint64_t calcNextTimeout(); - - void setRadioDestination(const MacAddress& destination) { - mRadioDestination = destination; - } - const MacAddress& radioDestination() const { return mRadioDestination; } -private: - Frame(const Frame&) = delete; - Frame& operator=(const Frame&) = delete; - - AccessCategory getAc() const; - - std::vector<uint8_t> mData; - FrameInfo mInfo; - MacAddress mRadioDestination; - Rates mInitialTxRates; - uint64_t mNextTimeout = 0; - // The contention winow determines how much time to back off on each retry. - // The contention window initial value and max value are determined by the - // access category of the frame. - uint32_t mContentionWindow = 0; - uint32_t mContentionWindowMax = 0; -}; - diff --git a/network/wifi_forwarder/frame_id.h b/network/wifi_forwarder/frame_id.h deleted file mode 100644 index 545693a2..00000000 --- a/network/wifi_forwarder/frame_id.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include "macaddress.h" - -#include <string.h> - -struct FrameId { - FrameId() {} - FrameId(uint64_t cookie, const MacAddress& transmitter) - : cookie(cookie), transmitter(transmitter) { - } - FrameId(const FrameId&) = default; - FrameId(FrameId&&) = default; - - FrameId& operator=(const FrameId&) = default; - FrameId& operator=(FrameId&&) = default; - - uint64_t cookie; - MacAddress transmitter; -}; - -namespace std { -template<> struct hash<FrameId> { - size_t operator()(const FrameId& id) const { - size_t seed = 0; - hash_combine(seed, id.cookie); - hash_combine(seed, id.transmitter); - return seed; - } -}; -} - -inline bool operator==(const FrameId& left, const FrameId& right) { - return left.cookie == right.cookie && left.transmitter == right.transmitter; -} - -inline bool operator<(const FrameId& left, const FrameId& right) { - if (left.cookie < right.cookie) { - return true; - } - if (left.cookie > right.cookie) { - return false; - } - return memcmp(left.transmitter.addr, - right.transmitter.addr, - sizeof(left.transmitter.addr)) < 0; -} diff --git a/network/wifi_forwarder/hash.h b/network/wifi_forwarder/hash.h deleted file mode 100644 index ecd8c23a..00000000 --- a/network/wifi_forwarder/hash.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include <functional> - -template<class T> -inline void hash_combine(size_t& seed, const T& value) { - std::hash<T> hasher; - seed ^= hasher(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2); -} - diff --git a/network/wifi_forwarder/hwsim.h b/network/wifi_forwarder/hwsim.h deleted file mode 100644 index 1a7b09b3..00000000 --- a/network/wifi_forwarder/hwsim.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -// mac80211_hwsim flags, from kernel drivers/net/wireless/mac80211_hwsim.h -#define BIT(num) (1UL << (num)) -enum hwsim_tx_control_flags { - HWSIM_TX_CTL_REQ_TX_STATUS = BIT(0), - HWSIM_TX_CTL_NO_ACK = BIT(1), - HWSIM_TX_STAT_ACK = BIT(2), -}; - -// mac80211_hwsim commands, from kernel drivers/net/wireless/mac80211_hwsim.h -enum HwSimCommand { - HWSIM_CMD_UNSPEC, - HWSIM_CMD_REGISTER, - HWSIM_CMD_FRAME, - HWSIM_CMD_TX_INFO_FRAME, - HWSIM_CMD_NEW_RADIO, - HWSIM_CMD_DEL_RADIO, - HWSIM_CMD_GET_RADIO, - __HWSIM_CMD_MAX, -}; - -// mac80211_hwsim attributes, from kernel drivers/net/wireless/mac80211_hwsim.h -enum HwSimAttribute { - HWSIM_ATTR_UNSPEC, - HWSIM_ATTR_ADDR_RECEIVER, - HWSIM_ATTR_ADDR_TRANSMITTER, - HWSIM_ATTR_FRAME, - HWSIM_ATTR_FLAGS, - HWSIM_ATTR_RX_RATE, - HWSIM_ATTR_SIGNAL, - HWSIM_ATTR_TX_INFO, - HWSIM_ATTR_COOKIE, - HWSIM_ATTR_CHANNELS, - HWSIM_ATTR_RADIO_ID, - HWSIM_ATTR_REG_HINT_ALPHA2, - HWSIM_ATTR_REG_CUSTOM_REG, - HWSIM_ATTR_REG_STRICT_REG, - HWSIM_ATTR_SUPPORT_P2P_DEVICE, - HWSIM_ATTR_USE_CHANCTX, - HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE, - HWSIM_ATTR_RADIO_NAME, - HWSIM_ATTR_NO_VIF, - HWSIM_ATTR_FREQ, - __HWSIM_ATTR_MAX, -}; -#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) - diff --git a/network/wifi_forwarder/ieee80211.h b/network/wifi_forwarder/ieee80211.h deleted file mode 100644 index 6bcf2326..00000000 --- a/network/wifi_forwarder/ieee80211.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include <net/ethernet.h> -#include <stdint.h> - -struct ieee80211_hdr { - uint16_t frame_control; - uint16_t duration_id; - uint8_t addr1[ETH_ALEN]; - uint8_t addr2[ETH_ALEN]; - uint8_t addr3[ETH_ALEN]; - uint16_t seq_ctrl; - uint8_t addr4[ETH_ALEN]; -} __attribute__((__packed__)); - diff --git a/network/wifi_forwarder/local_connection.cpp b/network/wifi_forwarder/local_connection.cpp deleted file mode 100644 index 1cebc17e..00000000 --- a/network/wifi_forwarder/local_connection.cpp +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "local_connection.h" - -#include "hwsim.h" -#include "log.h" -#include "macaddress.h" -#include "netlink_message.h" - -#include <net/ethernet.h> -#include <netlink/netlink.h> -#include <netlink/genl/ctrl.h> -#include <netlink/genl/genl.h> - -#include <utils/CallStack.h> - -#include <inttypes.h> -#include <stdlib.h> - -static const char kHwSimFamilyName[] = "MAC80211_HWSIM"; -static const int kHwSimVersion = 1; -static const unsigned int kDefaultSignalStrength = -50; -static const int kDefaultSocketBufferSize = 8 * (1 << 20); - -static uint32_t getSeqNum(struct nl_msg* msg) { - return nlmsg_hdr(msg)->nlmsg_seq; -} - -static int onSent(struct nl_msg* , void*) { - return NL_OK; -} - -static int onSeqCheck(struct nl_msg* msg, void*) { - uint32_t seq = getSeqNum(msg); - return seq == 0 ? NL_SKIP : NL_OK; -} - -LocalConnection::LocalConnection(OnFrameCallback onFrameCallback, - OnAckCallback onAckCallback, - OnErrorCallback onErrorCallback) - : mOnFrameCallback(onFrameCallback) - , mOnAckCallback(onAckCallback) - , mOnErrorCallback(onErrorCallback) { - -} - -Result LocalConnection::init(std::chrono::steady_clock::time_point now) { - Result res = mNetlinkSocket.init(); - if (!res) { return res; } - res = mNetlinkSocket.setOnMsgInCallback(staticOnMessage, this); - if (!res) { return res; } - res = mNetlinkSocket.setOnMsgOutCallback(onSent, this); - if (!res) { return res; } - res = mNetlinkSocket.setOnSeqCheckCallback(onSeqCheck, this); - if (!res) { return res; } - res = mNetlinkSocket.setOnAckCallback(staticOnAck, this); - if (!res) { return res; } - res = mNetlinkSocket.setOnErrorCallback(staticOnError, this); - if (!res) { return res; } - res = mNetlinkSocket.connectGeneric(); - if (!res) { return res; } - res = mNetlinkSocket.setBufferSizes(kDefaultSocketBufferSize, - kDefaultSocketBufferSize); - if (!res) { return res; } - - mNetlinkFamily = mNetlinkSocket.resolveNetlinkFamily(kHwSimFamilyName); - if (mNetlinkFamily < 0) { - return Result::error("Failed to resolve netlink family name: %s", - nl_geterror(mNetlinkFamily)); - } - - mPendingFrames.setCurrentTime(now); - mSequenceNumberCookies.setCurrentTime(now); - - mLastCacheTimeUpdate = now; - mLastCacheExpiration = now; - - return registerReceiver(); -} - -int LocalConnection::getFd() const { - return mNetlinkSocket.getFd(); -} - -bool LocalConnection::receive() { - return mNetlinkSocket.receive(); -} - -uint32_t LocalConnection::transferFrame(std::unique_ptr<Frame> frame, - const MacAddress& dest) { - NetlinkMessage msg; - - if (!msg.initGeneric(mNetlinkFamily, HWSIM_CMD_FRAME, kHwSimVersion)) { - ALOGE("LocalConnection transferFrame failed to init msg"); - return 0; - } - - frame->incrementAttempts(); - - if (!msg.addAttribute(HWSIM_ATTR_ADDR_RECEIVER, dest.addr, ETH_ALEN) || - !msg.addAttribute(HWSIM_ATTR_FRAME, frame->data(), frame->size()) || - !msg.addAttribute(HWSIM_ATTR_RX_RATE, 1u) || - !msg.addAttribute(HWSIM_ATTR_SIGNAL, kDefaultSignalStrength) || - !msg.addAttribute(HWSIM_ATTR_FREQ, frame->channel())) { - - ALOGE("LocalConnection transferFrame failed to set attrs"); - return 0; - } - - if (!mNetlinkSocket.send(msg)) { - return 0; - } - - // Store the radio destination for potential retransmissions. - frame->setRadioDestination(dest); - - uint32_t seqNum = msg.getSeqNum(); - uint64_t cookie = frame->cookie(); - FrameId id(cookie, frame->transmitter()); - mSequenceNumberCookies[seqNum] = id; - mPendingFrames[id] = std::move(frame); - - return seqNum; -} - -uint32_t LocalConnection::cloneFrame(const Frame& frame, - const MacAddress& dest) { - auto copy = std::make_unique<Frame>(frame.data(), - frame.size(), - frame.transmitter(), - frame.cookie(), - frame.flags(), - frame.channel(), - frame.rates().data(), - frame.rates().size()); - return transferFrame(std::move(copy), dest); -} - -bool LocalConnection::ackFrame(FrameInfo& info, bool success) { - NetlinkMessage msg; - - if (!msg.initGeneric(mNetlinkFamily, - HWSIM_CMD_TX_INFO_FRAME, - kHwSimVersion)) { - ALOGE("LocalConnection ackFrame failed to create msg"); - return false; - } - - uint32_t flags = info.flags(); - if (success) { - flags |= HWSIM_TX_STAT_ACK; - } - - const uint8_t* transmitter = info.transmitter().addr; - const Rates& rates = info.rates(); - if (!msg.addAttribute(HWSIM_ATTR_ADDR_TRANSMITTER, transmitter, ETH_ALEN) || - !msg.addAttribute(HWSIM_ATTR_TX_INFO, rates.data(), rates.size()) || - !msg.addAttribute(HWSIM_ATTR_FLAGS, flags) || - !msg.addAttribute(HWSIM_ATTR_SIGNAL, kDefaultSignalStrength) || - !msg.addAttribute(HWSIM_ATTR_COOKIE, info.cookie())) { - - ALOGE("LocalConnection ackFrame failed to set attributes"); - return false; - } - - if (!mNetlinkSocket.send(msg)) { - return false; - } - mPendingFrames.erase(FrameId(info.cookie(), info.transmitter())); - return true; -} - -std::chrono::steady_clock::time_point LocalConnection::getTimeout() const { - if (mRetryQueue.empty()) { - return std::chrono::steady_clock::time_point::max(); - } - return mRetryQueue.top().first; -} - -void LocalConnection::onTimeout(std::chrono::steady_clock::time_point now) { - - if (now - mLastCacheTimeUpdate > std::chrono::seconds(1)) { - // Only update the time once per second, there's no need for a super - // high resolution here. We just want to make sure these caches don't - // fill up over a long period of time. - mPendingFrames.setCurrentTime(now); - mSequenceNumberCookies.setCurrentTime(now); - mLastCacheTimeUpdate = now; - } - if (now - mLastCacheExpiration > std::chrono::seconds(10)) { - // Only expire entries every 10 seconds, this is an operation that has - // some cost to it and doesn't have to happen very often. - mPendingFrames.expireEntries(); - mSequenceNumberCookies.expireEntries(); - mLastCacheExpiration = now; - } - - while (!mRetryQueue.empty() && now >= mRetryQueue.top().first) { - FrameId id = mRetryQueue.top().second; - auto frameIt = mPendingFrames.find(id); - if (frameIt != mPendingFrames.end()) { - // Frame is still available, retry it - std::unique_ptr<Frame> frame = std::move(frameIt->second); - mPendingFrames.erase(frameIt); - MacAddress dest = frame->radioDestination(); - transferFrame(std::move(frame), dest); - } - mRetryQueue.pop(); - } -} - -Result LocalConnection::registerReceiver() { - NetlinkMessage msg; - - if (!msg.initGeneric(mNetlinkFamily, HWSIM_CMD_REGISTER, kHwSimVersion)) { - return Result::error("Failed to create register receiver message"); - } - - if (!mNetlinkSocket.send(msg)) { - return Result::error("Failed to send register receiver message"); - } - return Result::success(); -} - -int LocalConnection::staticOnMessage(struct nl_msg* msg, void* context) { - if (!context) { - return NL_SKIP; - } - auto connection = static_cast<LocalConnection*>(context); - return connection->onMessage(msg); -} - -int LocalConnection::staticOnAck(struct nl_msg* msg, void* context) { - if (!context) { - return NL_SKIP; - } - auto connection = static_cast<LocalConnection*>(context); - return connection->onAck(msg); -} - -int LocalConnection::staticOnError(struct sockaddr_nl* addr, - struct nlmsgerr* error, - void* context) { - if (!context) { - return NL_SKIP; - } - auto connection = static_cast<LocalConnection*>(context); - return connection->onError(addr, error); -} - -int LocalConnection::onMessage(struct nl_msg* msg) { - struct nlmsghdr* hdr = nlmsg_hdr(msg); - auto generic = reinterpret_cast<const struct genlmsghdr*>(nlmsg_data(hdr)); - - switch (generic->cmd) { - case HWSIM_CMD_FRAME: - return onFrame(msg); - } - return NL_OK; -} - -int LocalConnection::onFrame(struct nl_msg* msg) { - - struct nlmsghdr* hdr = nlmsg_hdr(msg); - std::unique_ptr<Frame> frame = parseFrame(hdr); - if (!frame) { - return NL_SKIP; - } - - mOnFrameCallback(std::move(frame)); - return NL_OK; -} - -std::unique_ptr<Frame> LocalConnection::parseFrame(struct nlmsghdr* hdr) { - struct nlattr* attrs[HWSIM_ATTR_MAX + 1]; - genlmsg_parse(hdr, 0, attrs, HWSIM_ATTR_MAX, nullptr); - if (!attrs[HWSIM_ATTR_ADDR_TRANSMITTER]) { - ALOGE("Received cmd frame without transmitter address"); - return nullptr; - } - if (!attrs[HWSIM_ATTR_TX_INFO]) { - ALOGE("Received cmd frame without tx rates"); - return nullptr; - } - if (!attrs[HWSIM_ATTR_FREQ]) { - ALOGE("Recieved cmd frame without channel frequency"); - return nullptr; - } - - uint64_t cookie = nla_get_u64(attrs[HWSIM_ATTR_COOKIE]); - - const auto& source = *reinterpret_cast<const MacAddress*>( - nla_data(attrs[HWSIM_ATTR_ADDR_TRANSMITTER])); - - auto rates = reinterpret_cast<const hwsim_tx_rate*>( - nla_data(attrs[HWSIM_ATTR_TX_INFO])); - int rateLength = nla_len(attrs[HWSIM_ATTR_TX_INFO]); - // Make sure the length is valid, must be multiple of hwsim_tx_rate - if (rateLength <= 0 || (rateLength % sizeof(hwsim_tx_rate)) != 0) { - ALOGE("Invalid tx rate length %d", rateLength); - } - size_t numRates = static_cast<size_t>(rateLength) / sizeof(hwsim_tx_rate); - - int length = nla_len(attrs[HWSIM_ATTR_FRAME]); - auto data = reinterpret_cast<uint8_t*>(nla_data(attrs[HWSIM_ATTR_FRAME])); - - uint32_t flags = nla_get_u32(attrs[HWSIM_ATTR_FLAGS]); - - uint32_t channel = nla_get_u32(attrs[HWSIM_ATTR_FREQ]); - - return std::make_unique<Frame>(data, length, source, cookie, - flags, channel, rates, numRates); -} - -int LocalConnection::onAck(struct nl_msg* msg) { - struct nlmsghdr* hdr = nlmsg_hdr(msg); - uint32_t seqNum = hdr->nlmsg_seq; - auto cookie = mSequenceNumberCookies.find(seqNum); - if (cookie == mSequenceNumberCookies.end()) { - // This is not a frame we sent. This is fairly common for libnl's - // internal use so don't log this. - return NL_SKIP; - } - auto pendingFrame = mPendingFrames.find(cookie->second); - // We don't need to keep this around anymore, erase it. - mSequenceNumberCookies.erase(seqNum); - if (pendingFrame == mPendingFrames.end()) { - // We have no cookie associated with this sequence number. This might - // happen if the remote connection already acked the frame and removed - // the frame info. Consider this resolved. - return NL_SKIP; - } - - Frame* frame = pendingFrame->second.get(); - mOnAckCallback(frame->info()); - // Make sure to erase using the cookie instead of the iterator. The callback - // might have already erased this entry so the iterator could be invalid at - // this point. Instead of a fancy scheme of checking this just play it safe - // to allow the callback more freedom. - mPendingFrames.erase(cookie->second); - - return NL_OK; -} - -int LocalConnection::onError(struct sockaddr_nl*, struct nlmsgerr* error) { - struct nlmsghdr* hdr = &error->msg; - uint32_t seqNum = hdr->nlmsg_seq; - - auto idIt = mSequenceNumberCookies.find(seqNum); - if (idIt == mSequenceNumberCookies.end()) { - return NL_SKIP; - } - FrameId id = idIt->second; - // No need to keep the sequence number around anymore, it's expired and is - // no longer useful. - mSequenceNumberCookies.erase(idIt); - - auto frameIt = mPendingFrames.find(id); - if (frameIt == mPendingFrames.end()) { - return NL_SKIP; - } - Frame* frame = frameIt->second.get(); - - if (!frame->hasRemainingAttempts()) { - // This frame has used up all its attempts, there's nothing we can do - mOnErrorCallback(frame->info()); - mPendingFrames.erase(id); - return NL_SKIP; - } - // Store the frame in the retry queue - uint64_t timeout = frame->calcNextTimeout(); - auto deadline = std::chrono::steady_clock::now() + - std::chrono::microseconds(timeout); - mRetryQueue.emplace(deadline, id); - - return NL_SKIP; -} - diff --git a/network/wifi_forwarder/local_connection.h b/network/wifi_forwarder/local_connection.h deleted file mode 100644 index 9f3969a0..00000000 --- a/network/wifi_forwarder/local_connection.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include "cache.h" -#include "frame.h" -#include "frame_id.h" -#include "macaddress.h" -#include "netlink_socket.h" -#include "result.h" - -#include <chrono> -#include <functional> -#include <memory> -#include <queue> - -struct MacAddress; - -class LocalConnection { -public: - using OnFrameCallback = std::function<void (std::unique_ptr<Frame>)>; - using OnAckCallback = std::function<void (FrameInfo&)>; - using OnErrorCallback = OnAckCallback; - - LocalConnection(OnFrameCallback onFrameCallback, - OnAckCallback onAckCallback, - OnErrorCallback onErrorCallback); - Result init(std::chrono::steady_clock::time_point now); - - int getFd() const; - bool receive(); - uint32_t cloneFrame(const Frame& frame, const MacAddress& destination); - uint32_t transferFrame(std::unique_ptr<Frame> frame, - const MacAddress& destination); - bool ackFrame(FrameInfo& info, bool success); - - std::chrono::steady_clock::time_point getTimeout() const; - void onTimeout(std::chrono::steady_clock::time_point now); - -private: - using Timestamp = std::chrono::steady_clock::time_point; - - Result registerReceiver(); - static int staticOnMessage(struct nl_msg* msg, void* context); - static int staticOnAck(struct nl_msg* msg, void* context); - static int staticOnError(struct sockaddr_nl* addr, - struct nlmsgerr* error, - void* context); - int onMessage(struct nl_msg* msg); - int onFrame(struct nl_msg* msg); - std::unique_ptr<Frame> parseFrame(struct nlmsghdr* hdr); - - int onAck(struct nl_msg* msg); - int onError(struct sockaddr_nl* addr, struct nlmsgerr* error); - bool sendFrameOnNetlink(const Frame& frame, const MacAddress& dest); - - OnFrameCallback mOnFrameCallback; - OnAckCallback mOnAckCallback; - OnErrorCallback mOnErrorCallback; - - NetlinkSocket mNetlinkSocket; - int mNetlinkFamily = -1; - - // [cookie,transmitter] -> frame. - Cache<FrameId, std::unique_ptr<Frame>> mPendingFrames; - // sequence number -> [cookie,transmitter] - Cache<uint32_t, FrameId> mSequenceNumberCookies; - - Timestamp mLastCacheTimeUpdate; - Timestamp mLastCacheExpiration; - - // A queue (using an ordered map) with the next timeout mapping to the - // cookie and transmitter of the frame to retry. This way we can easily - // determine when the next deadline is by looking at the first entry and we - // can quickly determine which frames to retry by starting at the beginning. - std::priority_queue<std::pair<Timestamp, FrameId>> mRetryQueue; -}; - diff --git a/network/wifi_forwarder/log.h b/network/wifi_forwarder/log.h deleted file mode 100644 index edadc43b..00000000 --- a/network/wifi_forwarder/log.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#define LOG_TAG "wifi_forwarder" -#include <log/log.h> diff --git a/network/wifi_forwarder/macaddress.h b/network/wifi_forwarder/macaddress.h deleted file mode 100644 index a9bcb660..00000000 --- a/network/wifi_forwarder/macaddress.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include "hash.h" - -#include <linux/if_ether.h> -#include <stdint.h> -#include <string.h> - -// Format macros for printf, e.g. printf("MAC address: " PRIMAC, MACARG(mac)) -#define PRIMAC "%02x:%02x:%02x:%02x:%02x:%02x" -#define MACARG(x) (x)[0], (x)[1], (x)[2], (x)[3],(x)[4], (x)[5] - -struct MacAddress { - MacAddress() { - memset(addr, 0, sizeof(addr)); - } - MacAddress(uint8_t b1, uint8_t b2, uint8_t b3, - uint8_t b4, uint8_t b5, uint8_t b6) { - addr[0] = b1; addr[1] = b2; addr[2] = b3; - addr[3] = b4; addr[4] = b5; addr[5] = b6; - } - uint8_t addr[ETH_ALEN]; - bool isBroadcast() const { - return memcmp(addr, "\xFF\xFF\xFF\xFF\xFF\xFF", ETH_ALEN) == 0; - } - bool isMulticast() const { - return addr[0] & 0x01; - } - bool empty() const { - return memcmp(addr, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0; - } - uint8_t operator[](size_t index) const { - return addr[index]; - } -} __attribute__((__packed__)); - -namespace std { -template<> struct hash<MacAddress> { - size_t operator()(const MacAddress& addr) const { - size_t seed = 0; - // Treat the first 4 bytes as an uint32_t to save some computation - hash_combine(seed, *reinterpret_cast<const uint32_t*>(addr.addr)); - // And the remaining 2 bytes as an uint16_t - hash_combine(seed, *reinterpret_cast<const uint16_t*>(addr.addr + 4)); - return seed; - } -}; -} - -inline bool operator==(const MacAddress& left, const MacAddress& right) { - return memcmp(left.addr, right.addr, ETH_ALEN) == 0; -} - -inline bool operator!=(const MacAddress& left, const MacAddress& right) { - return memcmp(left.addr, right.addr, ETH_ALEN) != 0; -} - diff --git a/network/wifi_forwarder/main.cpp b/network/wifi_forwarder/main.cpp deleted file mode 100644 index 57127a94..00000000 --- a/network/wifi_forwarder/main.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "log.h" -#include "poller.h" -#include "wifi_forwarder.h" - -int main(int /*argc*/, char* /*argv*/[]) { - WifiForwarder forwarder; - Result res = forwarder.init(); - if (!res) { - ALOGE("%s", res.c_str()); - return 1; - } - - Poller poller; - poller.addPollable(&forwarder); - return poller.run(); -} - diff --git a/network/wifi_forwarder/netlink_message.cpp b/network/wifi_forwarder/netlink_message.cpp deleted file mode 100644 index 265c2968..00000000 --- a/network/wifi_forwarder/netlink_message.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "netlink_message.h" - -#include <netlink/genl/genl.h> -#include <netlink/msg.h> - -NetlinkMessage::NetlinkMessage() { -} - -NetlinkMessage::NetlinkMessage(NetlinkMessage&& other) { - std::swap(mMessage, other.mMessage); -} - -NetlinkMessage::~NetlinkMessage() { - if (mMessage) { - nlmsg_free(mMessage); - mMessage = nullptr; - } -} - -NetlinkMessage& NetlinkMessage::operator=(NetlinkMessage&& other) { - if (mMessage) { - nlmsg_free(mMessage); - mMessage = nullptr; - } - std::swap(mMessage, other.mMessage); - return *this; -} - -bool NetlinkMessage::initGeneric(int family, uint8_t command, int version) { - if (mMessage) { - return false; - } - - mMessage = nlmsg_alloc(); - if (!mMessage) { - return false; - } - - return genlmsg_put(mMessage, NL_AUTO_PORT, NL_AUTO_SEQ, family, 0, - NLM_F_REQUEST, command, version) != nullptr; -} - -uint32_t NetlinkMessage::getSeqNum() const { - return nlmsg_hdr(mMessage)->nlmsg_seq; -} diff --git a/network/wifi_forwarder/netlink_message.h b/network/wifi_forwarder/netlink_message.h deleted file mode 100644 index 53d97a96..00000000 --- a/network/wifi_forwarder/netlink_message.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include "result.h" - -#include <netlink/netlink.h> - -#include <type_traits> - -class NetlinkMessage { -public: - NetlinkMessage(); - NetlinkMessage(NetlinkMessage&& other); - ~NetlinkMessage(); - - NetlinkMessage& operator=(NetlinkMessage&& other); - - bool initGeneric(int family, uint8_t command, int version); - - template<typename T, - typename = typename std::enable_if<!std::is_pointer<T>::value>::type> - bool addAttribute(int attribute, const T& value) { - return nla_put(mMessage, attribute, sizeof(T), &value) == 0; - } - template<typename T, - typename = typename std::enable_if<std::is_pointer<T>::value>::type> - bool addAttribute(int attribute, T data, size_t numElements) { - return nla_put(mMessage, - attribute, - sizeof(*data) * numElements, - data) == 0; - } - - uint32_t getSeqNum() const; - - struct nl_msg* get() { return mMessage; } - -private: - NetlinkMessage(const NetlinkMessage&) = delete; - NetlinkMessage& operator=(const NetlinkMessage&) = delete; - - struct nl_msg* mMessage = nullptr; -}; - diff --git a/network/wifi_forwarder/netlink_socket.cpp b/network/wifi_forwarder/netlink_socket.cpp deleted file mode 100644 index 5af66a56..00000000 --- a/network/wifi_forwarder/netlink_socket.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "netlink_socket.h" - -#include "log.h" -#include "netlink_message.h" - -#include <netlink/genl/ctrl.h> -#include <netlink/genl/genl.h> -#include <netlink/netlink.h> - -NetlinkSocket::NetlinkSocket() { -} - -NetlinkSocket::~NetlinkSocket() { - if (mSocket) { - nl_socket_free(mSocket); - mSocket = nullptr; - mCallback = nullptr; - } -} - -Result NetlinkSocket::init() { - if (mSocket || mCallback) { - return Result::error("Netlink socket already initialized"); - } - mCallback = nl_cb_alloc(NL_CB_CUSTOM); - if (!mCallback) { - return Result::error("Netlink socket failed to allocate callbacks"); - } - mSocket = nl_socket_alloc_cb(mCallback); - if (!mSocket) { - return Result::error("Failed to allocate netlink socket"); - } - return Result::success(); -} - -Result NetlinkSocket::setBufferSizes(int rxBufferSize, int txBufferSize) { - int res = nl_socket_set_buffer_size(mSocket, rxBufferSize, txBufferSize); - if (res != 0) { - return Result::error("Failed to set buffer sizes: %s", - nl_geterror(res)); - } - return Result::success(); -} - -Result NetlinkSocket::setOnMsgInCallback(int (*callback)(struct nl_msg*, void*), - void* context) { - if (nl_cb_set(mCallback, NL_CB_MSG_IN, NL_CB_CUSTOM, callback, context)) { - return Result::error("Failed to set OnMsgIn callback"); - } - return Result::success(); -} - -Result NetlinkSocket::setOnMsgOutCallback(int (*callback)(struct nl_msg*, - void*), - void* context) { - if (nl_cb_set(mCallback, NL_CB_MSG_OUT, NL_CB_CUSTOM, callback, context)) { - return Result::error("Failed to set OnMsgOut callback"); - } - return Result::success(); -} - -Result NetlinkSocket::setOnSeqCheckCallback(int (*callback)(struct nl_msg*, - void*), - void* context) { - if (nl_cb_set(mCallback, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, - callback, context)) { - return Result::error("Failed to set OnSeqCheck callback"); - } - return Result::success(); -} - -Result NetlinkSocket::setOnAckCallback(int (*callback)(struct nl_msg*, void*), - void* context) { - if (nl_cb_set(mCallback, NL_CB_ACK, NL_CB_CUSTOM, callback, context)) { - return Result::error("Failed to set OnAck callback"); - } - return Result::success(); -} - -Result NetlinkSocket::setOnErrorCallback(int (*callback)(struct sockaddr_nl*, - struct nlmsgerr*, - void*), - void* context) { - if (nl_cb_err(mCallback, NL_CB_CUSTOM, callback, context)) { - return Result::error("Failed to set OnError callback"); - } - return Result::success(); -} - -Result NetlinkSocket::connectGeneric() { - int status = genl_connect(mSocket); - if (status < 0) { - return Result::error("WifiNetlinkForwarder socket connect failed: %d", - status); - } - return Result::success(); -} - -int NetlinkSocket::resolveNetlinkFamily(const char* familyName) { - return genl_ctrl_resolve(mSocket, familyName); -} - -bool NetlinkSocket::send(NetlinkMessage& message) { - int status = nl_send_auto(mSocket, message.get()) >= 0; - if (status < 0) { - ALOGE("Failed to send on netlink socket: %s", nl_geterror(status)); - return false; - } - return true; -} - -bool NetlinkSocket::receive() { - int res = nl_recvmsgs_default(mSocket); - if (res != 0) { - ALOGE("Failed to receive messages on netlink socket: %s", - nl_geterror(res)); - return false; - } - return true; -} - -int NetlinkSocket::getFd() const { - if (!mSocket) { - return -1; - } - return nl_socket_get_fd(mSocket); -} diff --git a/network/wifi_forwarder/netlink_socket.h b/network/wifi_forwarder/netlink_socket.h deleted file mode 100644 index 9ff392c5..00000000 --- a/network/wifi_forwarder/netlink_socket.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include "result.h" - -struct nl_cb; -struct nl_msg; -struct nl_sock; -struct nlmsgerr; -struct sockaddr_nl; - -class NetlinkMessage; - -class NetlinkSocket { -public: - NetlinkSocket(); - ~NetlinkSocket(); - - Result init(); - - /* Set the size of the receive buffer to |rxBufferSize| bytes and the - * transmit buffer to |txBufferSize| bytes. - */ - Result setBufferSizes(int rxBufferSize, int txBufferSize); - - Result setOnMsgInCallback(int (*callback)(struct nl_msg*, void*), - void* context); - Result setOnMsgOutCallback(int (*callback)(struct nl_msg*, void*), - void* context); - Result setOnSeqCheckCallback(int (*callback)(struct nl_msg*, void*), - void* context); - Result setOnAckCallback(int (*callback)(struct nl_msg*, void*), - void* context); - Result setOnErrorCallback(int (*callback)(struct sockaddr_nl*, - struct nlmsgerr*, - void*), - void* context); - - /* Connect socket to generic netlink. This needs to be done before generic - * netlink messages can be sent. After this is done the caller should use - * @resolveGenericNetlinkFamily to determine the generic family id to use. - * Then create NetlinkMessage's with that family id. - */ - Result connectGeneric(); - - /* Resolve a generic family name to a family identifier. This is used when - * sending generic netlink messages to indicate where the message should go. - * Examples of family names are "mac80211_hwsim" or "nl80211". - */ - int resolveNetlinkFamily(const char* familyName); - - /* Send a netlink message on this socket. */ - bool send(NetlinkMessage& message); - - /* Receive all pending message. This method does not return any messages, - * instead they will be provided through the callback set with - * setOnMsgInCallback. This callback will be called on the same thread as - * this method while this method is running. */ - bool receive(); - - int getFd() const; - -private: - struct nl_cb* mCallback = nullptr; - struct nl_sock* mSocket = nullptr; -}; - diff --git a/network/wifi_forwarder/pollable.h b/network/wifi_forwarder/pollable.h deleted file mode 100644 index 51724c05..00000000 --- a/network/wifi_forwarder/pollable.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include <chrono> -#include <vector> - -#include <poll.h> - -/* An interface for pollable classes. - */ -class Pollable { -public: - using Clock = std::chrono::steady_clock; - using Timestamp = Clock::time_point; - virtual ~Pollable() = default; - - /* Get the poll data for the next poll loop. The implementation can place - * as many fds as needed in |fds|. - */ - virtual void getPollData(std::vector<pollfd>* fds) const = 0; - /* Get the timeout for the next poll loop. This should be a timestamp - * indicating when the timeout should be triggered. Note that this may - * be called at any time and any number of times for a poll loop so the - * deadline should not be adjusted in this call, a set deadline should - * just be returned. Note specifically that if a call to onReadAvailable - * modifies the deadline the timeout for the previous timestamp might not - * fire as the poller will check the timestamp AFTER onReadAvailable is - * called. - */ - virtual Timestamp getTimeout() const = 0; - /* Called when there is data available to read on an fd associated with - * the pollable. |fd| indicates which fd to read from. If the call returns - * false the poller will exit its poll loop with a return code of |status|. - */ - virtual bool onReadAvailable(int fd, int* status) = 0; - /* Called when an fd associated with the pollable is closed. |fd| indicates - * which fd was closed. If the call returns false the poller will exit its - * poll loop with a return code of |status|. - */ - virtual bool onClose(int fd, int* status) = 0; - /* Called when the timeout returned by getPollData has been reached. If - * the call returns false the poller will exit its poll loop with a return - * code of |status|. - */ - virtual bool onTimeout(Timestamp now, int* status) = 0; -}; - diff --git a/network/wifi_forwarder/poller.cpp b/network/wifi_forwarder/poller.cpp deleted file mode 100644 index 319dff4f..00000000 --- a/network/wifi_forwarder/poller.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "poller.h" - -#include "log.h" - -#include <errno.h> -#include <poll.h> -#include <signal.h> -#include <stdio.h> -#include <string.h> - -#include <unordered_map> -#include <vector> - -using std::chrono::duration_cast; - -static struct timespec* calculateTimeout(Pollable::Timestamp deadline, - struct timespec* ts) { - Pollable::Timestamp now = Pollable::Clock::now(); - if (deadline < Pollable::Timestamp::max()) { - if (deadline <= now) { - ts->tv_sec = 0; - ts->tv_nsec = 0; - return ts; - } - - auto timeout = deadline - now; - // Convert and round down to seconds - auto seconds = duration_cast<std::chrono::seconds>(timeout); - // Then subtract the seconds from the timeout and convert the remainder - auto nanos = duration_cast<std::chrono::nanoseconds>(timeout - seconds); - - ts->tv_sec = seconds.count(); - ts->tv_nsec = nanos.count(); - - return ts; - } - return nullptr; -} - -Poller::Poller() { -} - -void Poller::addPollable(Pollable* pollable) { - mPollables.push_back(pollable); -} - -int Poller::run() { - // Block all signals while we're running. This way we don't have to deal - // with things like EINTR. We then uses ppoll to set the original mask while - // polling. This way polling can be interrupted but socket writing, reading - // and ioctl remain interrupt free. If a signal arrives while we're blocking - // it it will be placed in the signal queue and handled once ppoll sets the - // original mask. This way no signals are lost. - sigset_t blockMask, mask; - int status = ::sigfillset(&blockMask); - if (status != 0) { - ALOGE("Unable to fill signal set: %s", strerror(errno)); - return errno; - } - status = ::sigprocmask(SIG_SETMASK, &blockMask, &mask); - if (status != 0) { - ALOGE("Unable to set signal mask: %s", strerror(errno)); - return errno; - } - - std::vector<struct pollfd> fds; - std::unordered_map<int, Pollable*> pollables; - while (true) { - fds.clear(); - pollables.clear(); - Pollable::Timestamp deadline = Pollable::Timestamp::max(); - for (auto& pollable : mPollables) { - size_t start = fds.size(); - pollable->getPollData(&fds); - Pollable::Timestamp pollableDeadline = pollable->getTimeout(); - // Create a map from each fd to the pollable - for (size_t i = start; i < fds.size(); ++i) { - pollables[fds[i].fd] = pollable; - } - if (pollableDeadline < deadline) { - deadline = pollableDeadline; - } - } - - struct timespec ts = { 0, 0 }; - struct timespec* tsPtr = calculateTimeout(deadline, &ts); - status = ::ppoll(fds.data(), fds.size(), tsPtr, &mask); - if (status < 0) { - if (errno == EINTR) { - // Interrupted, just keep going - continue; - } - // Actual error, time to quit - ALOGE("Polling failed: %s", strerror(errno)); - return errno; - } else if (status > 0) { - // Check for read or close events - for (const auto& fd : fds) { - if ((fd.revents & (POLLIN | POLLHUP)) == 0) { - // Neither POLLIN nor POLLHUP, not interested - continue; - } - auto pollable = pollables.find(fd.fd); - if (pollable == pollables.end()) { - // No matching fd, weird and unexpected - ALOGE("Poller could not find fd matching %d", fd.fd); - continue; - } - if (fd.revents & POLLIN) { - // This pollable has data available for reading - int status = 0; - if (!pollable->second->onReadAvailable(fd.fd, &status)) { - // The onReadAvailable handler signaled an exit - return status; - } - } - if (fd.revents & POLLHUP) { - // The fd was closed from the other end - int status = 0; - if (!pollable->second->onClose(fd.fd, &status)) { - // The onClose handler signaled an exit - return status; - } - } - } - } - // Check for timeouts - Pollable::Timestamp now = Pollable::Clock::now(); - for (const auto& pollable : mPollables) { - if (pollable->getTimeout() <= now) { - int status = 0; - if (!pollable->onTimeout(now, &status)) { - // The onTimeout handler signaled an exit - return status; - } - } - } - } - - return 0; -} diff --git a/network/wifi_forwarder/poller.h b/network/wifi_forwarder/poller.h deleted file mode 100644 index 9794f4da..00000000 --- a/network/wifi_forwarder/poller.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include <vector> - -#include "pollable.h" - -class Poller { -public: - Poller(); - - void addPollable(Pollable* pollable); - - int run(); - -private: - std::vector<Pollable*> mPollables; -}; - diff --git a/network/wifi_forwarder/remote_connection.cpp b/network/wifi_forwarder/remote_connection.cpp deleted file mode 100644 index 69e7b87c..00000000 --- a/network/wifi_forwarder/remote_connection.cpp +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "remote_connection.h" - -#include "hwsim.h" -#include "frame.h" -#include "log.h" - -#include <errno.h> -#include <linux/kernel.h> -#include <netinet/in.h> -#include <qemu_pipe_bp.h> -#include <sys/uio.h> -#include <unistd.h> - -static const char kQemuPipeName[] = "qemud:wififorward"; -static const size_t kReceiveBufferIncrement = 32768; -static const size_t kReceiveBufferMaxSize = 1 << 20; - -static const uint8_t kWifiForwardVersion = 0x01; -static const uint32_t kWifiForwardMagic = 0xD6C4B3A2; - -// This matches with the kernel constant IEEE80211_TX_MAX_RATES in -// include/net/mac80211.h in the kernel tree. -static const uint32_t kMaxNumRates = 4; - -struct WifiForwardHeader { - WifiForwardHeader(FrameType type, const MacAddress& transmitter, - uint32_t fullLength, uint64_t cookie, - uint32_t flags, uint32_t channel, uint32_t numRates, - const hwsim_tx_rate* txRates) - : magic(__cpu_to_le32(kWifiForwardMagic)) - , version(kWifiForwardVersion) - , type(static_cast<uint16_t>(type)) - , transmitter(transmitter) - , dataOffset(sizeof(WifiForwardHeader)) - , fullLength(__cpu_to_le32(fullLength)) - , cookie(__cpu_to_le64(cookie)) - , flags(__cpu_to_le32(flags)) - , channel(__cpu_to_le32(channel)) - , numRates(__cpu_to_le32(numRates)) { - memcpy(rates, txRates, std::min(numRates, kMaxNumRates)); - if (numRates < kMaxNumRates) { - memset(&rates[numRates], - 0, - sizeof(rates[0]) * (kMaxNumRates - numRates)); - } - } - - uint32_t magic; - uint8_t version; - uint8_t type; - MacAddress transmitter; - uint16_t dataOffset; - uint32_t fullLength; - uint64_t cookie; - uint32_t flags; - uint32_t channel; - uint32_t numRates; - hwsim_tx_rate rates[kMaxNumRates]; -} __attribute__((__packed__)); - -RemoteConnection::RemoteConnection(OnFrameCallback onFrameCallback, - OnAckCallback onAckCallback, - OnErrorCallback onErrorCallback) - : mOnFrameCallback(onFrameCallback) - , mOnAckCallback(onAckCallback) - , mOnErrorCallback(onErrorCallback) { - -} - -RemoteConnection::~RemoteConnection() { - if (mPipeFd != -1) { - ::close(mPipeFd); - mPipeFd = -1; - } -} - -Result RemoteConnection::init() { - if (mPipeFd != -1) { - return Result::error("RemoteConnetion already initialized"); - } - - mPipeFd = qemu_pipe_open_ns(NULL, kQemuPipeName, O_RDWR); - if (mPipeFd == -1) { - return Result::error("RemoteConnection failed to open pipe"); - } - return Result::success(); -} - -Pollable::Timestamp RemoteConnection::getTimeout() const { - // If there is no pipe return the deadline, we're going to retry, otherwise - // use an infinite timeout. - return mPipeFd == -1 ? mDeadline : Pollable::Timestamp::max(); -} - -void RemoteConnection::receive() { - size_t start = mBuffer.size(); - size_t newSize = start + kReceiveBufferIncrement; - if (newSize > kReceiveBufferMaxSize) { - // We've exceeded the maximum allowed size, drop everything we have so - // far and start over. This is most likely caused by some delay in - // injection or the injection failing in which case keeping old data - // around isn't going to be very useful. - ALOGE("RemoteConnection ran out of buffer space"); - newSize = kReceiveBufferIncrement; - start = 0; - } - mBuffer.resize(newSize); - - while (true) { - int result = ::read(mPipeFd, - mBuffer.data() + start, - mBuffer.size() - start); - if (result < 0) { - if (errno == EINTR) { - continue; - } - ALOGE("RemoteConnection failed to read to forward buffer: %s", - strerror(errno)); - // Return the buffer to its previous size - mBuffer.resize(start); - return; - } else if (result == 0) { - // Nothing received, nothing to write - // Return the buffer to its previous size - mBuffer.resize(start); - ALOGE("RemoteConnection did not receive anything to inject"); - return; - } - // Adjust the buffer size to match everything we recieved - mBuffer.resize(start + static_cast<size_t>(result)); - break; - } - - while (mBuffer.size() >= sizeof(WifiForwardHeader)) { - auto fwd = reinterpret_cast<WifiForwardHeader*>(mBuffer.data()); - if (__le32_to_cpu(fwd->magic) != kWifiForwardMagic) { - // We are not properly aligned, this can happen for the first read - // if the client or server happens to send something that's in the - // middle of a stream. Attempt to find the next packet boundary. - ALOGE("RemoteConnection found incorrect magic, finding next magic"); - uint32_t le32magic = __cpu_to_le32(kWifiForwardMagic); - auto next = reinterpret_cast<unsigned char*>( - ::memmem(mBuffer.data(), mBuffer.size(), - &le32magic, sizeof(le32magic))); - if (next) { - // We've found a possible candidate, erase everything before - size_t length = next - mBuffer.data(); - mBuffer.erase(mBuffer.begin(), mBuffer.begin() + length); - continue; - } else { - // There is no possible candidate, drop everything except the - // last three bytes. The last three bytes could possibly be the - // start of the next magic without actually triggering the - // search above. - if (mBuffer.size() > 3) { - mBuffer.erase(mBuffer.begin(), mBuffer.end() - 3); - } - // In this case there is nothing left to parse so just return - // right away. - return; - } - } - // Check if we support this version - if (fwd->version != kWifiForwardVersion) { - // Unsupported version - if (!mReportedVersionMismatches.test(fwd->version)) { - // Only report these once per version or this might become - // very spammy. - ALOGE("RemoteConnection encountered unknown version %u", - fwd->version); - mReportedVersionMismatches.set(fwd->version); - } - // Drop the magic from the buffer and attempt to find the next magic - mBuffer.erase(mBuffer.begin(), mBuffer.begin() + 4); - continue; - } - // The length according to the wifi forward header - const uint32_t fullLength = __le32_to_cpu(fwd->fullLength); - const uint16_t offset = __le16_to_cpu(fwd->dataOffset); - if (offset < sizeof(WifiForwardHeader) || offset > fullLength) { - // The frame offset is not large enough to go past the header - // or it's outside of the bounds of the length of the frame. - ALOGE("Invalid data offset in header %u, full length is %u", - offset, fullLength); - // Erase the magic and try again - mBuffer.erase(mBuffer.begin(), mBuffer.begin() + 4); - continue; - } - const size_t frameLength = fullLength - offset; - - if (fullLength > mBuffer.size()) { - // We have not received enough data yet, wait for more to arrive. - return; - } - - FrameType type = frameTypeFromByte(fwd->type); - if (frameLength == 0 && type != FrameType::Ack) { - ALOGE("Received empty frame for non-ack frame"); - return; - } - unsigned char* frameData = mBuffer.data() + offset; - if (type == FrameType::Ack) { - FrameInfo info(fwd->transmitter, - __le64_to_cpu(fwd->cookie), - __le32_to_cpu(fwd->flags), - __le32_to_cpu(fwd->channel), - fwd->rates, - __le32_to_cpu(fwd->numRates)); - - if (info.flags() & HWSIM_TX_STAT_ACK) { - mOnAckCallback(info); - } else { - mOnErrorCallback(info); - } - } else if (type == FrameType::Data) { - auto frame = std::make_unique<Frame>(frameData, - frameLength, - fwd->transmitter, - __le64_to_cpu(fwd->cookie), - __le32_to_cpu(fwd->flags), - __le32_to_cpu(fwd->channel), - fwd->rates, - __le32_to_cpu(fwd->numRates)); - mOnFrameCallback(std::move(frame)); - } else { - ALOGE("Received unknown message type %u from remote", - static_cast<uint8_t>(fwd->type)); - } - - mBuffer.erase(mBuffer.begin(), mBuffer.begin() + fullLength); - } -} - -bool RemoteConnection::sendFrame(std::unique_ptr<Frame> frame) { - if (mPipeFd == -1) { - ALOGE("RemoteConnection unable to forward data, pipe not open"); - return false; - } - - WifiForwardHeader header(FrameType::Data, - frame->transmitter(), - frame->size() + sizeof(WifiForwardHeader), - frame->cookie(), - frame->flags(), - frame->channel(), - frame->rates().size(), - frame->rates().data()); -#if 1 - constexpr size_t count = 2; - struct iovec iov[count]; - iov[0].iov_base = &header; - iov[0].iov_len = sizeof(header); - iov[1].iov_base = frame->data(); - iov[1].iov_len = frame->size(); - - size_t totalSize = iov[0].iov_len + iov[1].iov_len; - - size_t current = 0; - for (;;) { - ssize_t written = ::writev(mPipeFd, iov + current, count - current); - if (written < 0) { - ALOGE("RemoteConnection failed to write to pipe: %s", - strerror(errno)); - return false; - } - if (static_cast<size_t>(written) == totalSize) { - // Optimize for most common case, everything was written - break; - } - totalSize -= written; - // Determine how much is left to write after this - while (current < count && static_cast<size_t>(written) >= iov[current].iov_len) { - written -= iov[current++].iov_len; - } - if (current == count) { - break; - } - iov[current].iov_base = - reinterpret_cast<char*>(iov[current].iov_base) + written; - iov[current].iov_len -= written; - } -#else - if (qemu_pipe_write_fully(mPipeFd, &header, sizeof(header))) { - ALOGE("RemoteConnection failed to write to pipe: %s", strerror(errno)); - return false; - } - - if (qemu_pipe_write_fully(mPipeFd, frame->data(), frame->size())) { - ALOGE("RemoteConnection failed to write to pipe: %s", strerror(errno)); - return false; - } -#endif - return true; -} - -bool RemoteConnection::ackFrame(FrameInfo& info, bool success) { - uint32_t flags = info.flags(); - if (success) { - flags |= HWSIM_TX_STAT_ACK; - } - WifiForwardHeader header(FrameType::Ack, - info.transmitter(), - sizeof(WifiForwardHeader), - info.cookie(), - flags, - info.channel(), - info.rates().size(), - info.rates().data()); - - if (qemu_pipe_write_fully(mPipeFd, &header, sizeof(header))) { - ALOGE("RemoteConnection failed to write to pipe: %s", strerror(errno)); - return false; - } - return true; -} diff --git a/network/wifi_forwarder/remote_connection.h b/network/wifi_forwarder/remote_connection.h deleted file mode 100644 index 94c7e36d..00000000 --- a/network/wifi_forwarder/remote_connection.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include "frame.h" -#include "pollable.h" -#include "result.h" - -#include <bitset> -#include <functional> -#include <memory> -#include <vector> - -struct MacAddress; - -class RemoteConnection { -public: - using OnFrameCallback = std::function<void (std::unique_ptr<Frame>)>; - using OnAckCallback = std::function<void (FrameInfo&)>; - using OnErrorCallback = OnAckCallback; - - RemoteConnection(OnFrameCallback onFrameCallback, - OnAckCallback onAckCallback, - OnErrorCallback onErrorCallback); - ~RemoteConnection(); - - Result init(); - - int getFd() const { return mPipeFd; } - Pollable::Timestamp getTimeout() const; - void receive(); - bool sendFrame(std::unique_ptr<Frame> frame); - bool ackFrame(FrameInfo& info, bool success); - -private: - RemoteConnection(const RemoteConnection&) = delete; - RemoteConnection& operator=(const RemoteConnection&) = delete; - - OnFrameCallback mOnFrameCallback; - OnAckCallback mOnAckCallback; - OnErrorCallback mOnErrorCallback; - - Pollable::Timestamp mDeadline = Pollable::Timestamp::max(); - std::vector<unsigned char> mBuffer; - int mPipeFd = -1; - std::bitset<256> mReportedVersionMismatches; -}; - diff --git a/network/wifi_forwarder/result.h b/network/wifi_forwarder/result.h deleted file mode 100644 index 5087e146..00000000 --- a/network/wifi_forwarder/result.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * 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 - * - * http://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. - */ -#pragma once - -#include <stdio.h> -#include <stdarg.h> - -#include <string> - -class Result { -public: - static Result success() { - return Result(true); - } - // Construct a result indicating an error. - static Result error(std::string message) { - return Result(message); - } - static Result error(const char* format, ...) { - char buffer[1024]; - va_list args; - va_start(args, format); - vsnprintf(buffer, sizeof(buffer), format, args); - va_end(args); - buffer[sizeof(buffer) - 1] = '\0'; - return Result(std::string(buffer)); - } - - bool isSuccess() const { return mSuccess; } - bool operator!() const { return !mSuccess; } - - const char* c_str() const { return mMessage.c_str(); } -private: - explicit Result(bool success) : mSuccess(success) { } - explicit Result(std::string message) - : mMessage(message), mSuccess(false) { - } - std::string mMessage; - bool mSuccess; -}; - diff --git a/network/wifi_forwarder/wifi_forwarder.cpp b/network/wifi_forwarder/wifi_forwarder.cpp deleted file mode 100644 index b56c7cdb..00000000 --- a/network/wifi_forwarder/wifi_forwarder.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#include "wifi_forwarder.h" - -#include "frame.h" -#include "log.h" - -static constexpr bool kDebugTraffic = false; -static constexpr bool kDebugBeaconTraffic = false; - -// How many seconds to keep aliases alive for. Since this is used to keep track -// of randomized MAC addresses they will expire after a while. Set the value -// pretty high to ensure that we don't accidentally lose entries just because -// there's not a lot of frames going through. -static constexpr auto kAliasesCacheTimeout = std::chrono::hours(8); - -WifiForwarder::WifiForwarder() - : mAliases(kAliasesCacheTimeout) - , mLocalConnection([this](std::unique_ptr<Frame> frame) { - forwardFrame(std::move(frame), RadioType::Local); - }, - [this](FrameInfo& info) { onAck(info, true); }, - [this](FrameInfo& info) { onAck(info, false); }) - , mRemoteConnection([this](std::unique_ptr<Frame> frame) { - forwardFrame(std::move(frame), RadioType::Remote); - }, - [this](FrameInfo& info) { onAck(info, true); }, - [this](FrameInfo& info) { onAck(info, false); }) { -} - -Result WifiForwarder::init() { - auto now = Pollable::Clock::now(); - Result res = mRemoteConnection.init(); - if (!res) { - // It's OK if this fails, the emulator might not have been started with - // this feature enabled. If it's not enabled we'll try again later. If - // this does not succeed we don't need to perform the rest of the - // initialization either. Just let WiFi work the same as normal. - ALOGE("RemoteConnection failed to initialize: %s", res.c_str()); - mInitDeadline = now + std::chrono::minutes(1); - return Result::success(); - } - - mAliases.setCurrentTime(now); - res = mLocalConnection.init(now); - if (!res) { - return res; - } - mDeadline = now + std::chrono::seconds(1); - return Result::success(); -} - -void WifiForwarder::getPollData(std::vector<pollfd>* fds) const { - int fd = mLocalConnection.getFd(); - if (fd >= 0) { - struct pollfd pfd = { fd, POLLIN, 0 }; - fds->push_back(pfd); - } - fd = mRemoteConnection.getFd(); - if (fd >= 0) { - struct pollfd pfd = { fd, POLLIN, 0 }; - fds->push_back(pfd); - } -} - -Pollable::Timestamp WifiForwarder::getTimeout() const { - if (mRemoteConnection.getFd() == -1) { - return mInitDeadline; - } - return std::min(mLocalConnection.getTimeout(), mDeadline); -} - -bool WifiForwarder::onReadAvailable(int fd, int* /*status*/) { - if (fd == mRemoteConnection.getFd()) { - mRemoteConnection.receive(); - } else if (fd == mLocalConnection.getFd()) { - mLocalConnection.receive(); - } - return true; -} - -bool WifiForwarder::onClose(int /*fd*/, int* /*status*/) { - ALOGE("WifiForwarder socket closed unexpectedly"); - return false; -} - -bool WifiForwarder::onTimeout(Timestamp now, int* /*status*/) { - bool success = true; - if (now >= mInitDeadline) { - Result res = init(); - success = res.isSuccess(); - if (mRemoteConnection.getFd() == -1) { - // Remote connection not set up by init, try again later - mInitDeadline = now + std::chrono::minutes(1); - } - } - mLocalConnection.onTimeout(now); - if (now >= mDeadline) { - mDeadline += std::chrono::seconds(1); - mAliases.setCurrentTime(now); - mAliases.expireEntries(); - } - return success; -} - -const char* WifiForwarder::radioTypeToStr(RadioType type) const { - switch (type) { - case RadioType::Unknown: - return "Unknown"; - case RadioType::Local: - return "Local"; - case RadioType::Remote: - return "Remote"; - } -} - -void WifiForwarder::onAck(FrameInfo& info, bool success) { - RadioType type = mRadios[info.transmitter()]; - if (type == RadioType::Remote) { - if (kDebugTraffic) { - ALOGE("] ACK -] " PRIMAC " [ %" PRIu64 " ] success: %s", - MACARG(info.transmitter()), info.cookie(), - success ? "true" : "false"); - } - if (!mRemoteConnection.ackFrame(info, success)) { - ALOGE("WifiForwarder failed to ack remote frame"); - } - } else if (type == RadioType::Local) { - if (kDebugTraffic) { - ALOGE("> ACK -> " PRIMAC " [ %" PRIu64 " ] success: %s", - MACARG(info.transmitter()), info.cookie(), - success ? "true" : "false"); - } - if (!mLocalConnection.ackFrame(info, success)) { - ALOGE("WifiForwarder failed to ack local frame"); - } - } else { - ALOGE("Unknown transmitter in ack: " PRIMAC, - MACARG(info.transmitter())); - } -} - -void WifiForwarder::forwardFrame(std::unique_ptr<Frame> frame, - RadioType sourceType) { - if (kDebugTraffic) { - if (!frame->isBeacon() || kDebugBeaconTraffic) { - bool isRemote = sourceType == RadioType::Remote; - ALOGE("%c " PRIMAC " -%c " PRIMAC " %s", - isRemote ? '[' : '<', isRemote ? ']' : '>', - MACARG(frame->source()), - MACARG(frame->destination()), - frame->str().c_str()); - } - } - - const MacAddress& source = frame->source(); - const MacAddress& transmitter = frame->transmitter(); - const MacAddress& destination = frame->destination(); - auto& currentType = mRadios[transmitter]; - if (currentType != RadioType::Unknown && currentType != sourceType) { - ALOGE("Replacing type for MAC " PRIMAC " of type %s with type %s, " - "this might indicate duplicate MACs on different emulators", - MACARG(source), radioTypeToStr(currentType), - radioTypeToStr(sourceType)); - } - currentType = sourceType; - mAliases[source] = transmitter; - - bool isMulticast = destination.isMulticast(); - bool sendOnRemote = isMulticast; - for (const auto& radio : mRadios) { - const MacAddress& radioAddress = radio.first; - RadioType radioType = radio.second; - if (radioAddress == transmitter) { - // Don't send back to the transmitter - continue; - } - if (sourceType == RadioType::Remote && radioType == RadioType::Remote) { - // Don't forward frames back to the remote, the remote will have - // taken care of this. - continue; - } - bool forward = false; - if (isMulticast || destination == radioAddress) { - // The frame is either multicast or directly intended for this - // radio. Forward it. - forward = true; - } else { - auto alias = mAliases.find(destination); - if (alias != mAliases.end() && alias->second == radioAddress) { - // The frame is destined for an address that is a known alias - // for this radio. - forward = true; - } - } - uint32_t seq = 0; - if (forward) { - switch (radioType) { - case RadioType::Unknown: - ALOGE("Attempted to forward frame to unknown radio type"); - break; - case RadioType::Local: - if (kDebugTraffic) { - if (!frame->isBeacon() || kDebugBeaconTraffic) { - ALOGE("> " PRIMAC " -> " PRIMAC " %s", - MACARG(frame->source()), - MACARG(frame->destination()), - frame->str().c_str()); - } - } - if (isMulticast) { - // Clone the frame, it might be reused - seq = mLocalConnection.cloneFrame(*frame, radioAddress); - } else { - // This frame has a specific destination, move it - seq = mLocalConnection.transferFrame(std::move(frame), - radioAddress); - // Return so that we don't accidentally reuse the frame. - // This should be safe now because it's a unicast frame - // so it should not be sent to multiple radios. - return; - } - break; - case RadioType::Remote: - sendOnRemote = true; - break; - } - } - } - if (sendOnRemote && sourceType != RadioType::Remote) { - if (kDebugTraffic) { - if (!frame->isBeacon() || kDebugBeaconTraffic) { - ALOGE("] " PRIMAC " -] " PRIMAC " %s", - MACARG(frame->source()), - MACARG(frame->destination()), - frame->str().c_str()); - } - } - // This is either a multicast message or destined for a radio known to - // be a remote. No need to send multiple times to a remote, the remote - // will handle that on its own. - mRemoteConnection.sendFrame(std::move(frame)); - } -} diff --git a/network/wifi_forwarder/wifi_forwarder.h b/network/wifi_forwarder/wifi_forwarder.h deleted file mode 100644 index dfe57d88..00000000 --- a/network/wifi_forwarder/wifi_forwarder.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#pragma once - -#include "cache.h" -#include "frame.h" -#include "local_connection.h" -#include "macaddress.h" -#include "pollable.h" -#include "remote_connection.h" -#include "result.h" - -#include <unordered_map> - -class WifiForwarder : public Pollable { -public: - WifiForwarder(); - virtual ~WifiForwarder() = default; - Result init(); - - // Pollable interface - void getPollData(std::vector<pollfd>* fds) const override; - Timestamp getTimeout() const override; - bool onReadAvailable(int fd, int* status) override; - bool onClose(int fd, int* status) override; - bool onTimeout(Timestamp now, int* status) override; -private: - enum class RadioType { - Unknown, - Local, - Remote - }; - - const char* radioTypeToStr(RadioType type) const; - - void onAck(FrameInfo& info, bool success); - - void forwardFrame(std::unique_ptr<Frame> frame, RadioType sourceType); - - std::unordered_map<MacAddress, RadioType> mRadios; - Cache<MacAddress, MacAddress> mAliases; - LocalConnection mLocalConnection; - RemoteConnection mRemoteConnection; - Pollable::Timestamp mInitDeadline = Pollable::Timestamp::max(); - Pollable::Timestamp mDeadline = Pollable::Timestamp::max(); -}; - diff --git a/overlay/frameworks/base/core/res/res/values/config.xml b/overlay/frameworks/base/core/res/res/values/config.xml index b7e54f5b..39c3c7a2 100644 --- a/overlay/frameworks/base/core/res/res/values/config.xml +++ b/overlay/frameworks/base/core/res/res/values/config.xml @@ -67,4 +67,11 @@ <string-array translatable="false" name="config_ethernet_interfaces"> <item>eth0;11,12,14;;</item> </string-array> + <!-- Specifies priority of automatic time sources. Suggestions from higher entries in the list + take precedence over lower ones. + See com.android.server.timedetector.TimeDetectorStrategy for available sources. --> + <string-array name="config_autoTimeSourcesPriority"> + <item>telephony</item> + <item>network</item> + </string-array> </resources> diff --git a/sepolicy/common/createns.te b/sepolicy/common/createns.te deleted file mode 100644 index 4464ddb7..00000000 --- a/sepolicy/common/createns.te +++ /dev/null @@ -1,15 +0,0 @@ -# Network namespace creation -type createns, domain; -type createns_exec, exec_type, vendor_file_type, file_type; - -init_daemon_domain(createns) - -allow createns self:capability { sys_admin net_raw setuid setgid }; -allow createns varrun_file:dir { add_name search write }; -allow createns varrun_file:file { create mounton open read write }; - -#Allow createns itself to be run by init in its own domain -domain_auto_trans(init, createns_exec, createns); -allow createns goldfish_setup:fd use; - -set_prop(createns, vendor_qemu_prop); diff --git a/sepolicy/common/dhcpclient.te b/sepolicy/common/dhcpclient.te index 8e22a7ac..b28bb51c 100644 --- a/sepolicy/common/dhcpclient.te +++ b/sepolicy/common/dhcpclient.te @@ -5,11 +5,8 @@ type dhcpclient_exec, exec_type, vendor_file_type, file_type; init_daemon_domain(dhcpclient) net_domain(dhcpclient) -allow dhcpclient execns:fd use; - set_prop(dhcpclient, vendor_net_wlan0_prop); set_prop(dhcpclient, vendor_net_eth0_prop); -set_prop(dhcpclient, vendor_net_radio0_prop); allow dhcpclient self:capability { net_admin net_raw sys_module }; allow dhcpclient self:netlink_route_socket { ioctl write nlmsg_write }; allow dhcpclient varrun_file:dir search; diff --git a/sepolicy/common/execns.te b/sepolicy/common/execns.te deleted file mode 100644 index 265fb835..00000000 --- a/sepolicy/common/execns.te +++ /dev/null @@ -1,27 +0,0 @@ -# Network namespace transitions -type execns, domain; -type execns_exec, exec_type, vendor_file_type, file_type; - -init_daemon_domain(execns) - -allow execns varrun_file:dir search; -allow execns varrun_file:file r_file_perms; -allow execns self:capability { sys_admin setuid setgid }; -allow execns nsfs:file { open read }; - -#Allow execns itself to be run by init in its own domain -domain_auto_trans(init, execns_exec, execns); - -# Allow dhcpclient to be run by execns in its own domain -domain_auto_trans(execns, dhcpclient_exec, dhcpclient); - -# Allow hostapd_nohidl to be run by execns in its own domain -domain_auto_trans(execns, hostapd_nohidl_exec, hostapd_nohidl); - -# Allow netmgr to be run by execns in its own domain -domain_auto_trans(execns, netmgr_exec, netmgr); - -# Allow execns to read createns proc file to get the namespace file -allow execns createns:file read; -allow execns createns:dir search; -allow execns createns:lnk_file read; diff --git a/sepolicy/common/file_contexts b/sepolicy/common/file_contexts index e259c3b4..b1aa5ead 100644 --- a/sepolicy/common/file_contexts +++ b/sepolicy/common/file_contexts @@ -29,20 +29,12 @@ /system_ext/bin/init\.qemu-adb-keys\.sh u:object_r:goldfish_system_setup_exec:s0 /vendor/bin/init\.ranchu-core\.sh u:object_r:goldfish_setup_exec:s0 /vendor/bin/init\.ranchu-net\.sh u:object_r:goldfish_setup_exec:s0 -/vendor/bin/init\.wifi\.sh u:object_r:goldfish_setup_exec:s0 /vendor/bin/qemu-adb-keys u:object_r:qemu_adb_keys_exec:s0 /vendor/bin/qemu-device-state u:object_r:qemu_device_state_exec:s0 /vendor/bin/qemu-props u:object_r:qemu_props_exec:s0 /vendor/bin/mac80211_create_radios u:object_r:mac80211_create_radios_exec:s0 -/vendor/bin/createns u:object_r:createns_exec:s0 -/vendor/bin/execns u:object_r:execns_exec:s0 -/vendor/bin/ip u:object_r:goldfish_ip_exec:s0 /vendor/bin/hw/libgoldfish-rild u:object_r:rild_exec:s0 -/vendor/bin/iw u:object_r:goldfish_iw_exec:s0 /vendor/bin/dhcpclient u:object_r:dhcpclient_exec:s0 -/vendor/bin/hostapd_nohidl u:object_r:hostapd_nohidl_exec:s0 -/vendor/bin/netmgr u:object_r:netmgr_exec:s0 -/vendor/bin/wifi_forwarder u:object_r:wifi_forwarder_exec:s0 /vendor/bin/hw/android\.hardware\.bluetooth@1\.1-service\.sim u:object_r:hal_bluetooth_sim_exec:s0 /vendor/bin/hw/android\.hardware\.drm@[0-9]+\.[0-9]+-service\.widevine u:object_r:hal_drm_widevine_exec:s0 diff --git a/sepolicy/common/genfs_contexts b/sepolicy/common/genfs_contexts index bf5fe76a..d0d1c60f 100644 --- a/sepolicy/common/genfs_contexts +++ b/sepolicy/common/genfs_contexts @@ -32,10 +32,14 @@ genfscon sysfs /devices/pci0000:00/0000:00:08.0/virtio5/block/vdf u:object_r:sys # for arm64 virtio block devices genfscon sysfs /devices/platform/a003600.virtio_mmio/virtio2/block/vda/stat u:object_r:sysfs_virtio_block:s0 +genfscon sysfs /devices/platform/a003600.virtio_mmio/virtio2/block/vda/vda1/stat u:object_r:sysfs_virtio_block:s0 +genfscon sysfs /devices/platform/a003600.virtio_mmio/virtio2/block/vda/vda2/stat u:object_r:sysfs_virtio_block:s0 genfscon sysfs /devices/platform/a003800.virtio_mmio/virtio3/block/vdb/stat u:object_r:sysfs_virtio_block:s0 genfscon sysfs /devices/platform/a003a00.virtio_mmio/virtio4/block/vdc/stat u:object_r:sysfs_virtio_block:s0 genfscon sysfs /devices/platform/a003c00.virtio_mmio/virtio5/block/vdd/stat u:object_r:sysfs_virtio_block:s0 +genfscon sysfs /devices/platform/a003c00.virtio_mmio/virtio5/block/vdd/vdd1/stat u:object_r:sysfs_virtio_block:s0 genfscon sysfs /devices/platform/a003e00.virtio_mmio/virtio6/block/vde/stat u:object_r:sysfs_virtio_block:s0 +genfscon sysfs /devices/platform/a003e00.virtio_mmio/virtio6/block/vde/vde1/stat u:object_r:sysfs_virtio_block:s0 # /sys/class/power_supply genfscon sysfs /devices/platform/9020000.goldfish_battery/power_supply u:object_r:sysfs_batteryinfo:s0 diff --git a/sepolicy/common/goldfish_iw.te b/sepolicy/common/goldfish_iw.te deleted file mode 100644 index 734e9f65..00000000 --- a/sepolicy/common/goldfish_iw.te +++ /dev/null @@ -1,6 +0,0 @@ -type goldfish_iw, domain; -type goldfish_iw_exec, exec_type, vendor_file_type, file_type; - -init_daemon_domain(goldfish_iw) -net_domain(goldfish_iw) - diff --git a/sepolicy/common/goldfish_setup.te b/sepolicy/common/goldfish_setup.te index 5ef4d2c1..5ae62ba3 100644 --- a/sepolicy/common/goldfish_setup.te +++ b/sepolicy/common/goldfish_setup.te @@ -14,8 +14,6 @@ allowxperm goldfish_setup self:udp_socket ioctl priv_sock_ioctls; wakelock_use(goldfish_setup); allow goldfish_setup vendor_shell_exec:file { rx_file_perms }; #============= goldfish_setup ============== -allow goldfish_setup goldfish_ip_exec:file execute_no_trans; -allow goldfish_setup goldfish_iw_exec:file execute_no_trans; allow goldfish_setup mac80211_create_radios_exec:file execute_no_trans; # Set system properties to start services @@ -25,25 +23,12 @@ set_prop(goldfish_setup, ctl_default_prop); allow goldfish_setup self:netlink_route_socket { create nlmsg_write setopt bind getattr read write nlmsg_read }; allow goldfish_setup self:netlink_generic_socket create_socket_perms_no_ioctl; allow goldfish_setup self:capability { sys_module sys_admin }; -allow goldfish_setup varrun_file:dir { mounton open read write add_name search remove_name }; -allow goldfish_setup varrun_file:file { mounton getattr create read write open unlink }; -allow goldfish_setup execns_exec:file rx_file_perms; allow goldfish_setup proc_net:file rw_file_perms; allow goldfish_setup proc:file r_file_perms; allow goldfish_setup nsfs:file r_file_perms; allow goldfish_setup system_data_file:dir getattr; set_prop(goldfish_setup, vendor_qemu_prop); get_prop(goldfish_setup, vendor_net_share_prop); -# Allow goldfish_setup to run init.wifi.sh -allow goldfish_setup goldfish_setup_exec:file execute_no_trans; -# iw -allow goldfish_setup sysfs:file { read open }; -# iptables -allow goldfish_setup self:rawip_socket { create getopt setopt }; -# Allow goldfish_setup to read createns proc file to get the namespace file -allow goldfish_setup createns:file { read }; -allow goldfish_setup createns:dir { search }; -allow goldfish_setup createns:lnk_file { read }; # Allow goldfish_setup to copy the hostapd conf template to the vendor data dir allow goldfish_setup hostapd_data_file:file create_file_perms; allow goldfish_setup hostapd_data_file:dir rw_dir_perms; diff --git a/sepolicy/common/hostapd_nohidl.te b/sepolicy/common/hostapd_nohidl.te deleted file mode 100644 index ec058c24..00000000 --- a/sepolicy/common/hostapd_nohidl.te +++ /dev/null @@ -1,17 +0,0 @@ -type hostapd_nohidl, domain; -type hostapd_nohidl_exec, exec_type, vendor_file_type, file_type; - -init_daemon_domain(hostapd_nohidl) -net_domain(hostapd_nohidl) - -allow hostapd_nohidl execns:fd use; -allow hostapd_nohidl hostapd_data_file:file r_file_perms; -allow hostapd_nohidl hostapd_data_file:dir r_dir_perms; -allow hostapd_nohidl self:capability { net_admin net_raw setgid setuid }; -allow hostapd_nohidl self:netlink_generic_socket { bind create getattr read setopt write }; -allow hostapd_nohidl self:netlink_route_socket nlmsg_write; -allow hostapd_nohidl self:packet_socket { create setopt read write }; -allowxperm hostapd_nohidl self:udp_socket ioctl priv_sock_ioctls; - -# hostapd will attempt to search sysfs but it's not needed and will spam the log -dontaudit hostapd_nohidl sysfs_net:dir search; diff --git a/sepolicy/common/netmgr.te b/sepolicy/common/netmgr.te deleted file mode 100644 index 7150cfca..00000000 --- a/sepolicy/common/netmgr.te +++ /dev/null @@ -1,37 +0,0 @@ -# Wifi manager -type netmgr, domain; -type netmgr_exec, exec_type, vendor_file_type, file_type; - -init_daemon_domain(netmgr) -net_domain(netmgr) - -allow netmgr execns:fd use; - -# Set property to indicate bridging is complete -set_prop(netmgr, vendor_net); -# Set ctrl.restart property to restart hostapd when config changes -set_prop(netmgr, ctl_default_prop); -# Modify hostapd config file -allow netmgr hostapd_data_file:file create_file_perms; -allow netmgr hostapd_data_file:dir rw_dir_perms; -# Assign addresses to new interfaces as hostapd brings them up -allow netmgr self:capability { net_raw net_admin }; -allow netmgr self:socket { create }; -allow netmgr self:unix_dgram_socket ioctl; -allow netmgr self:packet_socket { ioctl getopt map }; -allow netmgr self:udp_socket { ioctl }; -allow netmgr proc_net:file { read getattr open }; -allowxperm netmgr self:unix_dgram_socket ioctl { SIOCETHTOOL }; -allowxperm netmgr self:udp_socket ioctl { SIOCSIFFLAGS - SIOCBRADDBR - SIOCBRADDIF - SIOCBRDELIF }; -allowxperm netmgr self:packet_socket ioctl { SIOCGIFINDEX SIOCGIFHWADDR }; - -# Allow netmgr to run ip and modify route table to block unblock traffic -allow netmgr goldfish_ip_exec:file execute_no_trans; -allow netmgr self:netlink_route_socket nlmsg_write; -# Packet socket for wifi forwarding -allow netmgr self:packet_socket { bind create read setopt write }; -allow netmgr self:capability sys_module; -allow netmgr self:vsock_socket create_socket_perms_no_ioctl; diff --git a/sepolicy/common/property_contexts b/sepolicy/common/property_contexts index a776b0de..e15fdb45 100644 --- a/sepolicy/common/property_contexts +++ b/sepolicy/common/property_contexts @@ -1,13 +1,11 @@ vendor.qemu.adb.copykey u:object_r:vendor_qemu_adb_prop:s0 exact bool vendor.qemu.keyboard_layout u:object_r:vendor_qemu_prop:s0 exact string -vendor.qemu.networknamespace u:object_r:vendor_qemu_prop:s0 exact string vendor.qemu.logcat_filter u:object_r:vendor_qemu_prop:s0 exact string vendor.qemu.sf.fake_camera u:object_r:vendor_qemu_prop:s0 exact string vendor.qemu.vport.bluetooth u:object_r:vendor_qemu_prop:s0 exact string vendor.qemu.vport.modem u:object_r:vendor_qemu_prop:s0 exact string vendor.qemu.vport.gnss u:object_r:vendor_qemu_prop:s0 exact string vendor.qemu.timezone u:object_r:vendor_qemu_prop:s0 exact string -vendor.network.bridged u:object_r:vendor_net:s0 exact string vendor.net.wlan0.gw u:object_r:vendor_net_wlan0_prop:s0 exact string vendor.net.wlan0.dns1 u:object_r:vendor_net_wlan0_prop:s0 exact string vendor.net.wlan0.dns2 u:object_r:vendor_net_wlan0_prop:s0 exact string diff --git a/sepolicy/common/wifi_forwarder.te b/sepolicy/common/wifi_forwarder.te deleted file mode 100644 index 536476ba..00000000 --- a/sepolicy/common/wifi_forwarder.te +++ /dev/null @@ -1,11 +0,0 @@ -# Wifi forwarder -type wifi_forwarder, domain; -type wifi_forwarder_exec, exec_type, vendor_file_type, file_type; - -init_daemon_domain(wifi_forwarder) -net_domain(wifi_forwarder) - -allow wifi_forwarder self:capability { net_admin }; -# Generic netlink socket for wifi forwarding -allow wifi_forwarder self:netlink_generic_socket { bind create getattr setopt read write }; -allow wifi_forwarder self:vsock_socket create_socket_perms_no_ioctl; diff --git a/tasks/emu_img_zip.mk b/tasks/emu_img_zip.mk index 9291facd..40b9178d 100644 --- a/tasks/emu_img_zip.mk +++ b/tasks/emu_img_zip.mk @@ -4,6 +4,7 @@ ifeq ($(filter $(TARGET_PRODUCT), qemu_trusty_arm64),) ifeq ($(filter $(MAKECMDGOALS), sdk win_sdk sdk_repo goog_emu_imgs),) emulator_img_source_prop := $(TARGET_OUT_INTERMEDIATES)/source.properties +target_notice_file_txt := $(TARGET_OUT_INTERMEDIATES)/NOTICE.txt $(emulator_img_source_prop): $(PRODUCT_SDK_ADDON_SYS_IMG_SOURCE_PROP) @echo Generate $@ $(hide) mkdir -p $(dir $@) @@ -59,8 +59,6 @@ PRODUCT_PACKAGES += \ libcodec2_goldfish_vp9dec \ libcodec2_goldfish_avcdec \ sh_vendor \ - ip_vendor \ - iw_vendor \ local_time.default \ SdkSetup \ EmulatorRadioConfig \ @@ -198,13 +196,8 @@ PRODUCT_PACKAGES += \ # WiFi: vendor side PRODUCT_PACKAGES += \ mac80211_create_radios \ - createns \ dhcpclient \ - execns \ hostapd \ - hostapd_nohidl \ - netmgr \ - wifi_forwarder \ wpa_supplicant \ PRODUCT_PACKAGES += \ @@ -278,7 +271,6 @@ PRODUCT_COPY_FILES += \ device/generic/goldfish/init.qemu-adb-keys.sh:$(TARGET_COPY_OUT_SYSTEM_EXT)/bin/init.qemu-adb-keys.sh \ device/generic/goldfish/init.ranchu-core.sh:$(TARGET_COPY_OUT_VENDOR)/bin/init.ranchu-core.sh \ device/generic/goldfish/init.ranchu-net.sh:$(TARGET_COPY_OUT_VENDOR)/bin/init.ranchu-net.sh \ - device/generic/goldfish/wifi/init.wifi.sh:$(TARGET_COPY_OUT_VENDOR)/bin/init.wifi.sh \ device/generic/goldfish/init.ranchu.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.ranchu.rc \ device/generic/goldfish/init.system_ext.rc:$(TARGET_COPY_OUT_SYSTEM_EXT)/etc/init/init.system_ext.rc \ device/generic/goldfish/fstab.ranchu:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.ranchu \ diff --git a/wifi/createns/Android.bp b/wifi/createns/Android.bp deleted file mode 100644 index bd6a40fd..00000000 --- a/wifi/createns/Android.bp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) 2020 The Android Open Source Project -// -// 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 -// -// http://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. - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "device_generic_goldfish_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["device_generic_goldfish_license"], -} - -cc_binary { - name: "createns", - srcs: ["createns.cpp"], - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - ], - shared_libs: [ - "libcutils", - "liblog", - ], - proprietary: true, -} diff --git a/wifi/createns/createns.cpp b/wifi/createns/createns.cpp deleted file mode 100644 index 73e2c63e..00000000 --- a/wifi/createns/createns.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#define LOG_TAG "createns" -#include <log/log.h> - -#include <cutils/properties.h> -#include <errno.h> -#include <fcntl.h> -#include <inttypes.h> -#include <sched.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mount.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> - -#include <limits> -#include <string> -#include <vector> - -static const char kNamespacePath[] = "/data/vendor/var/run/netns/"; -static const char kProcNsNet[] = "/proc/self/ns/net"; - -class Fd { -public: - explicit Fd(int fd) : mFd(fd) { } - Fd(const Fd&) = delete; - ~Fd() { - if (mFd != -1) { - ::close(mFd); - mFd = -1; - } - } - - int get() const { return mFd; } - Fd& operator=(const Fd&) = delete; -private: - int mFd; -}; - -static void usage(const char* program) { - ALOGE("%s <namespace>", program); -} - -static bool removeFile(const char* file) { - if (::unlink(file) == -1) { - ALOGE("Failed to unlink file '%s': %s", file, strerror(errno)); - return false; - } - return true; -} - -static std::string getNamespacePath(const char* name) { - size_t len = strlen(name); - if (len == 0) { - ALOGE("Must provide a namespace argument that is not empty"); - return std::string(); - } - - if (std::numeric_limits<size_t>::max() - sizeof(kNamespacePath) < len) { - // The argument is so big the resulting string can't fit in size_t - ALOGE("Namespace argument too long"); - return std::string(); - } - - std::vector<char> nsPath(sizeof(kNamespacePath) + len); - size_t totalSize = strlcpy(nsPath.data(), kNamespacePath, nsPath.size()); - if (totalSize >= nsPath.size()) { - // The resulting string had to be concatenated to fit, this is a logic - // error in the code above that determines the size of the data. - ALOGE("Could not create namespace path"); - return std::string(); - } - totalSize = strlcat(nsPath.data(), name, nsPath.size()); - if (totalSize >= nsPath.size()) { - // The resulting string had to be concatenated to fit, this is a logic - // error in the code above that determines the size of the data. - ALOGE("Could not append to namespace path"); - return std::string(); - } - return nsPath.data(); -} - -static bool writeNamespacePid(const char* name, pid_t pid) { - std::string path = getNamespacePath(name); - if (path.empty()) { - return false; - } - path += ".pid"; - - Fd fd(::open(path.c_str(), - O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, - S_IRUSR | S_IWUSR | S_IRGRP)); - if (fd.get() == -1) { - ALOGE("Unable to create file '%s': %s", path.c_str(), strerror(errno)); - return false; - } - - // In order to safely print a pid_t we use int64_t with a known format - // specifier. Ensure that a pid_t will fit in a pid_t. According to POSIX - // pid_t is signed. - static_assert(sizeof(pid_t) <= sizeof(int64_t), - "pid_t is larger than int64_t"); - char pidString[32]; - int printed = snprintf(pidString, - sizeof(pidString), - "%" PRId64, - static_cast<int64_t>(pid)); - if (printed <= 0) { - ALOGE("Unabled to created PID string for writing"); - removeFile(path.c_str()); - return false; - } - - const char* toPrint = pidString; - int remaining = printed; - for (;;) { - int result = ::write(fd.get(), toPrint, remaining); - if (result < 0) { - if (errno == EINTR) { - continue; - } - ALOGE("Unable to write pid to file %s: %s", - path.c_str(), strerror(errno)); - removeFile(path.c_str()); - return false; - } else if (result < printed) { - remaining -= result; - toPrint += result; - } else { - break; - } - } - return true; -} - -int main(int argc, char* argv[]) { - if (argc != 2) { - usage(argv[0]); - return 1; - } - if (::unshare(CLONE_NEWNET) != 0) { - ALOGE("Failed to create network namespace '%s': %s", - argv[1], - strerror(errno)); - return 1; - } - - std::string path = getNamespacePath(argv[1]); - if (path.empty()) { - return 1; - } - { - // Open and then immediately close the fd - Fd fd(::open(path.c_str(), O_CREAT|O_RDONLY, S_IRUSR | S_IRGRP)); - if (fd.get() == -1) { - ALOGE("Failed to open file %s: %s", path.c_str(), strerror(errno)); - return 1; - } - } - if (::mount(kProcNsNet, path.c_str(), nullptr, MS_BIND, nullptr) != 0) { - ALOGE("Failed to bind %s to %s: %s", - kProcNsNet, - path.c_str(), - strerror(errno)); - // Clean up on failure - removeFile(path.c_str()); - return 1; - } - - if (!writeNamespacePid(argv[1], ::getpid())) { - return 1; - } - property_set("vendor.qemu.networknamespace", "ready"); - - for (;;) { - pause(); - } - - return 0; -} - diff --git a/wifi/execns/Android.bp b/wifi/execns/Android.bp deleted file mode 100644 index 2d780f33..00000000 --- a/wifi/execns/Android.bp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) 2020 The Android Open Source Project -// -// 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 -// -// http://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. - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "device_generic_goldfish_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["device_generic_goldfish_license"], -} - -cc_binary { - name: "execns", - srcs: ["execns.cpp"], - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - ], - shared_libs: [ - "libcutils", - "liblog", - ], - proprietary: true, -} diff --git a/wifi/execns/execns.cpp b/wifi/execns/execns.cpp deleted file mode 100644 index 770d2499..00000000 --- a/wifi/execns/execns.cpp +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * 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 - * - * http://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. - */ - -#define LOG_TAG "execns" -#include <log/log.h> - -#include <errno.h> -#include <fcntl.h> -#include <grp.h> -#include <pwd.h> -#include <sched.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include <string> -#include <vector> - -static bool isTerminal = false; -// Print errors to stderr if running from a terminal, otherwise print to logcat -// This is useful for debugging from a terminal -#define LOGE(...) do { \ - if (isTerminal) { \ - fprintf(stderr, __VA_ARGS__); \ - fprintf(stderr, "\n"); \ - } else { \ - ALOGE(__VA_ARGS__); \ - } \ -} while (0) - -static const char kNetNsDir[] = "/data/vendor/var/run/netns"; - -class FileDescriptor { -public: - explicit FileDescriptor(int fd) : mFd(fd) { } - FileDescriptor(const FileDescriptor&) = delete; - ~FileDescriptor() { - if (mFd != -1) { - close(mFd); - mFd = -1; - } - } - int get() const { return mFd; } - FileDescriptor& operator=(const FileDescriptor&) = delete; -private: - int mFd; -}; - -class File { -public: - explicit File(FILE* file) : mFile(file) { } - File(const File&) = delete; - ~File() { - if (mFile) { - ::fclose(mFile); - mFile = nullptr; - } - } - - FILE* get() const { return mFile; } - File& operator=(const File&) = delete; -private: - FILE* mFile; -}; - -static void printUsage(const char* program) { - LOGE("%s [-u user] [-g group] <namespace> <program> [options...]", program); -} - -static bool isNumericString(const char* str) { - while (isdigit(*str)) { - ++str; - } - return *str == '\0'; -} - -static std::string readNamespacePid(const char* ns) { - char nsPath[PATH_MAX]; - snprintf(nsPath, sizeof(nsPath), "%s/%s.pid", kNetNsDir, ns); - - File file(::fopen(nsPath, "r")); - if (file.get() == nullptr) { - LOGE("Unable to open file %s for namespace %s: %s", - nsPath, ns, strerror(errno)); - return std::string(); - } - - char buffer[32]; - size_t bytesRead = ::fread(buffer, 1, sizeof(buffer), file.get()); - if (bytesRead < sizeof(buffer) && feof(file.get())) { - // Reached end-of-file, null-terminate - buffer[bytesRead] = '\0'; - if (isNumericString(buffer)) { - // File is valid and contains a number, return it - return buffer; - } - LOGE("File %s does not contain a valid pid '%s'", nsPath, buffer); - } else if (ferror(file.get())) { - LOGE("Error reading from file %s: %s", nsPath, strerror(errno)); - } else { - LOGE("Invalid contents of pid file %s", nsPath); - } - return std::string(); -} - -static bool setNetworkNamespace(const char* ns) { - // There is a file in the net namespace dir (/data/vendor/var/run/netns) with - // the name "<namespace>.pid". This file contains the pid of the createns - // process that created the namespace. - // - // To switch network namespace we're going to call setns which requires an - // open file descriptor to /proc/<pid>/ns/net where <pid> refers to a - // process already running in that namespace. So using the pid from the file - // above we can determine which path to use. - std::string pid = readNamespacePid(ns); - if (pid.empty()) { - return false; - } - char nsPath[PATH_MAX]; - snprintf(nsPath, sizeof(nsPath), "/proc/%s/ns/net", pid.c_str()); - - FileDescriptor nsFd(open(nsPath, O_RDONLY | O_CLOEXEC)); - if (nsFd.get() == -1) { - LOGE("Cannot open network namespace '%s' at '%s': %s", - ns, nsPath, strerror(errno)); - return false; - } - - if (setns(nsFd.get(), CLONE_NEWNET) == -1) { - LOGE("Cannot set network namespace '%s': %s", - ns, strerror(errno)); - return false; - } - return true; -} - -static bool changeUser(const char* user) { - struct passwd* pwd = ::getpwnam(user); - if (pwd == nullptr) { - LOGE("Could not find user '%s'", user); - return false; - } - - if (::setuid(pwd->pw_uid) != 0) { - LOGE("Cannot switch to user '%s': %s", user, strerror(errno)); - return false; - } - return true; -} - -static bool changeGroup(const char* group) { - struct group* grp = ::getgrnam(group); - if (grp == nullptr) { - LOGE("Could not find group '%s'", group); - return false; - } - - if (::setgid(grp->gr_gid) != 0) { - LOGE("Cannot switch to group '%s': %s", group, strerror(errno)); - return false; - } - return true; -} - -// Append a formatted string to the end of |buffer|. The total size in |buffer| -// is |size|, including any existing string data. The string to append is -// specified by |fmt| and any additional arguments required by the format -// string. If the function fails it returns -1, otherwise it returns the number -// of characters printed (excluding the terminating NULL). On success the -// string is always null-terminated. -static int sncatf(char* buffer, size_t size, const char* fmt, ...) { - size_t len = strnlen(buffer, size); - if (len >= size) { - // The length exceeds the available size, if len == size then there is - // also a terminating null after len bytes which would then be outside - // the provided buffer. - return -1; - } - - va_list args; - va_start(args, fmt); - int printed = vsnprintf(buffer + len, size - len, fmt, args); - buffer[size - 1] = '\0'; - va_end(args); - return printed; -} - -/** - * Execute a given |command| with |argc| number of parameters that are located - * in |argv|. The first parameter in |argv| is the command that should be run - * followed by its arguments. - */ -static int execCommand( int argc, char** argv) { - if (argc <= 0 || argv == nullptr || argv[0] == nullptr) { - LOGE("No command specified"); - return 1; - } - - std::vector<char*> arguments; - // Place all the arguments in the vector and the terminating null - arguments.insert(arguments.begin(), argv, argv + argc); - arguments.push_back(nullptr); - - char buffer[4096]; - if (execvp(argv[0], arguments.data()) == -1) { - // Save errno in case it gets changed by printing stuff. - int error = errno; - int printed = snprintf(buffer, sizeof(buffer), - "Could not execute command '%s", argv[0]); - if (printed < 0) { - LOGE("Could not execute command: %s", strerror(error)); - return error; - } - for (int i = 1; i < argc; ++i) { - // Be nice to the user and print quotes if there are spaces to - // indicate how we saw it. If there are already single quotes in - // there confusion will ensue. - if (strchr(argv[i], ' ')) { - sncatf(buffer, sizeof(buffer), " \"%s\"", argv[i]); - } else { - sncatf(buffer, sizeof(buffer), " %s", argv[i]); - } - } - sncatf(buffer, sizeof(buffer), "': %s", strerror(error)); - LOGE("%s", buffer); - return error; - } - // execvp never returns unless it fails so this is just to return something. - return 0; -} - -/** - * Enter a given network namespace argv[1] and execute command argv[2] with - * options argv[3..argc-1] in that namespace. - */ -int main(int argc, char* argv[]) { - isTerminal = isatty(STDOUT_FILENO) != 0; - - // Parse parameters - const char* user = nullptr; - const char* group = nullptr; - int nsArg = -1; - int execArg = -1; - for (int i = 1; i < argc; ++i) { - if (::strcmp(argv[i], "-u") == 0) { - if (user || i + 1 >= argc) { - LOGE("Missing argument to option -u"); - return 1; - } - user = argv[++i]; - } else if (::strcmp(argv[i], "-g") == 0) { - if (group || i + 1 >= argc) { - LOGE("Missing argument to option -g"); - return 1; - } - group = argv[++i]; - } else { - // Break on the first non-option and treat it as the namespace name - nsArg = i; - if (i + 1 < argc) { - execArg = i + 1; - } - break; - } - } - - if (nsArg < 0 || execArg < 0) { - // Missing namespace and/or exec arguments - printUsage(argv[0]); - return 1; - } - - // First set the new network namespace for this process - if (!setNetworkNamespace(argv[nsArg])) { - return 1; - } - - // Changing namespace is the privileged operation, so now we can drop - // privileges by changing user and/or group if the user requested it. Note - // that it's important to change group first because it must be done as a - // privileged user. Otherwise an attacker might be able to restore group - // privileges by using the group ID that is saved by setgid when running - // as a non-privileged user. - if (group && !changeGroup(group)) { - return 1; - } - - if (user && !changeUser(user)) { - return 1; - } - - // Now run the command with all the remaining parameters - return execCommand(argc - execArg, &argv[execArg]); -} - diff --git a/wifi/init.wifi.sh b/wifi/init.wifi.sh deleted file mode 100755 index a884c96a..00000000 --- a/wifi/init.wifi.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/vendor/bin/sh - -# Do all the setup required for WiFi. -# The kernel driver mac80211_hwsim has already created two virtual wifi devices -# us. These devices are connected so that everything that's sent on one device -# is recieved on the other and vice versa. This allows us to create a fake -# WiFi network with an access point running inside the guest. Here is the setup -# for that and the basics of how it works. -# -# Create a namespace named router and move eth0 to it. Create a virtual ethernet -# pair of devices and move both one virtual ethernet interface and one virtual -# wifi interface into the router namespace. Then set up NAT networking for those -# interfaces so that traffic flowing through them reach eth0 and eventually the -# host and the internet. The main network namespace will now only see the other -# ends of those pipes and send traffic on them depending on if WiFi or radio is -# used. Finally run hostapd in the network namespace to create an access point -# for the guest to connect to and dnsmasq to serve as a DHCP server for the WiFi -# connection. -# -# main namespace router namespace -# ------- ---------- | --------------- -# | ril |<----->| radio0 |<--+--->| radio0-peer |<-------+ -# ------- ---------- | --------------- | -# | ^ | -# | | | -# | v v -# | ************* -------- -# | * ipv6proxy *<--->| eth0 |<--+ -# | ************* -------- | -# | ^ ^ | -# | | | | -# | v | | -# ------------------ --------- | --------- | | -# | wpa_supplicant |<->| wlan0 |<--+------->| wlan1 |<---------+ | -# ------------------ --------- | --------- | -# | ^ ^ | -# | | | v -# | v v -------- -# | *********** *********** | host | -# | * hostapd * * dnsmasq * -------- -# | *********** *********** -# - -wifi_mac_prefix=`getprop vendor.net.wifi_mac_prefix` -if [ -n "$wifi_mac_prefix" ]; then - /vendor/bin/mac80211_create_radios 2 $wifi_mac_prefix || exit 1 -fi - -NAMESPACE="router" - -# createns will have created a file that contains the process id (pid) of a -# process running in the network namespace. This pid is needed for some commands -# to access the namespace. -PID=$(</data/vendor/var/run/netns/${NAMESPACE}.pid) - -/vendor/bin/ip link set eth0 netns ${PID} - -/vendor/bin/ip link add radio0 type veth peer name radio0-peer netns ${PID} - -# Enable privacy addresses for radio0, this is done by the framework for wlan0 -sysctl -wq net.ipv6.conf.radio0.use_tempaddr=2 - -execns ${NAMESPACE} /vendor/bin/ip link set radio0-peer up - -execns ${NAMESPACE} /vendor/bin/ip link set eth0 up - -/vendor/bin/ip link set radio0 up - -execns ${NAMESPACE} /vendor/bin/ip link set wlan1 up - -/vendor/bin/iw phy phy1 set netns $PID - -setprop ctl.start netmgr - -setprop ctl.start wifi_forwarder - -# If this is a clean boot we need to copy the hostapd configuration file to the -# data partition where netmgr can change it if needed. If it already exists we -# need to preserve the existing settings. -if [ ! -f /data/vendor/wifi/hostapd/hostapd.conf ]; then - cp /vendor/etc/simulated_hostapd.conf /data/vendor/wifi/hostapd/hostapd.conf - chown wifi:wifi /data/vendor/wifi/hostapd/hostapd.conf - chmod 660 /data/vendor/wifi/hostapd/hostapd.conf -fi - -# Start hostapd, the access point software -setprop ctl.start emu_hostapd - -ifconfig radio0 -multicast diff --git a/x86-vendor.mk b/x86-vendor.mk index 3341835f..a8c95cb8 100644 --- a/x86-vendor.mk +++ b/x86-vendor.mk @@ -19,9 +19,6 @@ PRODUCT_SDK_ADDON_COPY_FILES += \ device/generic/goldfish/data/etc/encryptionkey.img:images/x86/encryptionkey.img \ $(EMULATOR_KERNEL_FILE):images/x86/kernel-ranchu-64 -PRODUCT_PACKAGES += \ - emulatorip - PRODUCT_PROPERTY_OVERRIDES += \ ro.crypto.dm_default_key.options_format.version=2 diff --git a/x86_64-vendor.mk b/x86_64-vendor.mk index be16c323..bd7e9930 100644 --- a/x86_64-vendor.mk +++ b/x86_64-vendor.mk @@ -32,10 +32,6 @@ PRODUCT_COPY_FILES += \ device/generic/goldfish/data/media/test/swirl_144x136_mpeg4.mp4:data/media/0/test/CtsMediaTestCases-1.4/swirl_144x136_mpeg4.mp4 \ device/generic/goldfish/data/media/test/swirl_128x128_mpeg4.mp4:data/media/0/test/CtsMediaTestCases-1.4/swirl_128x128_mpeg4.mp4 - -PRODUCT_PACKAGES += \ - emulatorip - PRODUCT_PROPERTY_OVERRIDES += \ ro.crypto.dm_default_key.options_format.version=2 |