blob: 19371e6b745f492765b182da30cb4cfcdc377129 [file] [log] [blame]
Tomasz Wiszkowski4d4bcf02017-09-11 13:34:17 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "common/libs/net/network_interface_manager.h"
17
18#include <arpa/inet.h>
Tomasz Wiszkowski686fe4f2017-09-11 13:32:13 -070019#include <linux/if_addr.h>
Tomasz Wiszkowski4d4bcf02017-09-11 13:34:17 -070020#include <linux/if_link.h>
Tomasz Wiszkowskidb5b8d72017-10-25 10:19:40 -070021#include <linux/netlink.h>
22#include <linux/rtnetlink.h>
Tomasz Wiszkowski719d3152017-10-26 09:58:11 -070023#include <net/if.h>
24
Tomasz Wiszkowski4d4bcf02017-09-11 13:34:17 -070025#include <memory>
26
A. Cody Schuffelen6a16bf92020-02-27 17:53:20 -080027#include "android-base/logging.h"
Tomasz Wiszkowski4d4bcf02017-09-11 13:34:17 -070028#include "common/libs/net/network_interface.h"
29
A. Cody Schuffelen61985ef2020-06-22 22:44:54 +000030namespace cuttlefish {
Tomasz Wiszkowski4d4bcf02017-09-11 13:34:17 -070031namespace {
Tomasz Wiszkowski0e82ef82017-10-26 11:47:57 -070032NetlinkRequest BuildLinkRequest(
Tomasz Wiszkowski686fe4f2017-09-11 13:32:13 -070033 const NetworkInterface& interface) {
Tomasz Wiszkowski0e82ef82017-10-26 11:47:57 -070034 NetlinkRequest request(RTM_SETLINK, 0);
35 request.AddIfInfo(interface.Index(), interface.IsOperational());
Tomasz Wiszkowski686fe4f2017-09-11 13:32:13 -070036 if (!interface.Name().empty()) {
Tomasz Wiszkowski0e82ef82017-10-26 11:47:57 -070037 request.AddString(IFLA_IFNAME, interface.Name());
Tomasz Wiszkowski686fe4f2017-09-11 13:32:13 -070038 }
39
40 return request;
41}
42
Tomasz Wiszkowski0e82ef82017-10-26 11:47:57 -070043NetlinkRequest BuildAddrRequest(
Tomasz Wiszkowski686fe4f2017-09-11 13:32:13 -070044 const NetworkInterface& interface) {
Tomasz Wiszkowski0e82ef82017-10-26 11:47:57 -070045 NetlinkRequest request(RTM_NEWADDR, 0);
Greg Hartman931e97f2017-12-21 22:53:00 -080046 request.AddAddrInfo(interface.Index(), interface.PrefixLength());
47 in_addr_t address{inet_addr(interface.Address().c_str())};
Cody Schuffelenbd13c232018-07-27 19:08:04 -070048 request.AddInt(IFA_LOCAL, address);
49 request.AddInt(IFA_ADDRESS, address);
50 request.AddInt(IFA_BROADCAST,
51 inet_addr(interface.BroadcastAddress().c_str()));
Tomasz Wiszkowski686fe4f2017-09-11 13:32:13 -070052
53 return request;
54}
Tomasz Wiszkowski4d4bcf02017-09-11 13:34:17 -070055} // namespace
56
Tomasz Wiszkowski719d3152017-10-26 09:58:11 -070057std::unique_ptr<NetworkInterfaceManager> NetworkInterfaceManager::New(
58 NetlinkClientFactory* nl_factory) {
59 std::unique_ptr<NetworkInterfaceManager> mgr;
60
61 if (nl_factory == NULL) {
62 nl_factory = NetlinkClientFactory::Default();
Tomasz Wiszkowski4d4bcf02017-09-11 13:34:17 -070063 }
64
Tomasz Wiszkowski719d3152017-10-26 09:58:11 -070065 auto client = nl_factory->New(NETLINK_ROUTE);
66 if (client) {
67 mgr.reset(new NetworkInterfaceManager(std::move(client)));
68 }
69
70 return mgr;
Tomasz Wiszkowski4d4bcf02017-09-11 13:34:17 -070071}
72
73NetworkInterfaceManager::NetworkInterfaceManager(
Tomasz Wiszkowski719d3152017-10-26 09:58:11 -070074 std::unique_ptr<NetlinkClient> nl_client)
75 : nl_client_(std::move(nl_client)) {}
Tomasz Wiszkowski4d4bcf02017-09-11 13:34:17 -070076
Tomasz Wiszkowski719d3152017-10-26 09:58:11 -070077std::unique_ptr<NetworkInterface> NetworkInterfaceManager::Open(
Alistair Strachan8adbea12018-04-05 09:51:31 -070078 const std::string& if_name, const std::string& if_name_alt) {
Tomasz Wiszkowski719d3152017-10-26 09:58:11 -070079 std::unique_ptr<NetworkInterface> iface;
80 // NOTE: do not replace this code with an IOCTL call.
81 // On SELinux enabled Androids, RILD is not permitted to execute an IOCTL
82 // and this call will fail.
Alistair Strachan8adbea12018-04-05 09:51:31 -070083 int32_t index = if_nametoindex(if_name.c_str());
84 if (index == 0) {
85 // Try the alternate name. This will be renamed to our preferred name
86 // by the kernel, because we specify IFLA_IFNAME, but open by index.
87 LOG(ERROR) << "Failed to get interface (" << if_name << ") index, "
88 << "trying alternate.";
89 index = if_nametoindex(if_name_alt.c_str());
90 if (index == 0) {
91 LOG(ERROR) << "Failed to get interface (" << if_name_alt << ") index.";
92 return iface;
93 }
Tomasz Wiszkowski4d4bcf02017-09-11 13:34:17 -070094 }
95
Tomasz Wiszkowski719d3152017-10-26 09:58:11 -070096 iface.reset(new NetworkInterface(index));
97 return iface;
Tomasz Wiszkowski4d4bcf02017-09-11 13:34:17 -070098}
99
Tomasz Wiszkowski4d4bcf02017-09-11 13:34:17 -0700100bool NetworkInterfaceManager::ApplyChanges(const NetworkInterface& iface) {
Tomasz Wiszkowski0e82ef82017-10-26 11:47:57 -0700101 if (!nl_client_->Send(BuildLinkRequest(iface))) return false;
Tomasz Wiszkowski686fe4f2017-09-11 13:32:13 -0700102 // Terminate immediately if interface is down.
103 if (!iface.IsOperational()) return true;
Tomasz Wiszkowski0e82ef82017-10-26 11:47:57 -0700104 return nl_client_->Send(BuildAddrRequest(iface));
Tomasz Wiszkowski4d4bcf02017-09-11 13:34:17 -0700105}
106
A. Cody Schuffelen61985ef2020-06-22 22:44:54 +0000107} // namespace cuttlefish