Tomasz Wiszkowski | 4d4bcf0 | 2017-09-11 13:34:17 -0700 | [diff] [blame] | 1 | /* |
| 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 Wiszkowski | 686fe4f | 2017-09-11 13:32:13 -0700 | [diff] [blame] | 19 | #include <linux/if_addr.h> |
Tomasz Wiszkowski | 4d4bcf0 | 2017-09-11 13:34:17 -0700 | [diff] [blame] | 20 | #include <linux/if_link.h> |
Tomasz Wiszkowski | db5b8d7 | 2017-10-25 10:19:40 -0700 | [diff] [blame] | 21 | #include <linux/netlink.h> |
| 22 | #include <linux/rtnetlink.h> |
Tomasz Wiszkowski | 719d315 | 2017-10-26 09:58:11 -0700 | [diff] [blame] | 23 | #include <net/if.h> |
| 24 | |
Tomasz Wiszkowski | 4d4bcf0 | 2017-09-11 13:34:17 -0700 | [diff] [blame] | 25 | #include <memory> |
| 26 | |
A. Cody Schuffelen | 6a16bf9 | 2020-02-27 17:53:20 -0800 | [diff] [blame] | 27 | #include "android-base/logging.h" |
Tomasz Wiszkowski | 4d4bcf0 | 2017-09-11 13:34:17 -0700 | [diff] [blame] | 28 | #include "common/libs/net/network_interface.h" |
| 29 | |
A. Cody Schuffelen | 61985ef | 2020-06-22 22:44:54 +0000 | [diff] [blame] | 30 | namespace cuttlefish { |
Tomasz Wiszkowski | 4d4bcf0 | 2017-09-11 13:34:17 -0700 | [diff] [blame] | 31 | namespace { |
Tomasz Wiszkowski | 0e82ef8 | 2017-10-26 11:47:57 -0700 | [diff] [blame] | 32 | NetlinkRequest BuildLinkRequest( |
Tomasz Wiszkowski | 686fe4f | 2017-09-11 13:32:13 -0700 | [diff] [blame] | 33 | const NetworkInterface& interface) { |
Tomasz Wiszkowski | 0e82ef8 | 2017-10-26 11:47:57 -0700 | [diff] [blame] | 34 | NetlinkRequest request(RTM_SETLINK, 0); |
| 35 | request.AddIfInfo(interface.Index(), interface.IsOperational()); |
Tomasz Wiszkowski | 686fe4f | 2017-09-11 13:32:13 -0700 | [diff] [blame] | 36 | if (!interface.Name().empty()) { |
Tomasz Wiszkowski | 0e82ef8 | 2017-10-26 11:47:57 -0700 | [diff] [blame] | 37 | request.AddString(IFLA_IFNAME, interface.Name()); |
Tomasz Wiszkowski | 686fe4f | 2017-09-11 13:32:13 -0700 | [diff] [blame] | 38 | } |
| 39 | |
| 40 | return request; |
| 41 | } |
| 42 | |
Tomasz Wiszkowski | 0e82ef8 | 2017-10-26 11:47:57 -0700 | [diff] [blame] | 43 | NetlinkRequest BuildAddrRequest( |
Tomasz Wiszkowski | 686fe4f | 2017-09-11 13:32:13 -0700 | [diff] [blame] | 44 | const NetworkInterface& interface) { |
Tomasz Wiszkowski | 0e82ef8 | 2017-10-26 11:47:57 -0700 | [diff] [blame] | 45 | NetlinkRequest request(RTM_NEWADDR, 0); |
Greg Hartman | 931e97f | 2017-12-21 22:53:00 -0800 | [diff] [blame] | 46 | request.AddAddrInfo(interface.Index(), interface.PrefixLength()); |
| 47 | in_addr_t address{inet_addr(interface.Address().c_str())}; |
Cody Schuffelen | bd13c23 | 2018-07-27 19:08:04 -0700 | [diff] [blame] | 48 | request.AddInt(IFA_LOCAL, address); |
| 49 | request.AddInt(IFA_ADDRESS, address); |
| 50 | request.AddInt(IFA_BROADCAST, |
| 51 | inet_addr(interface.BroadcastAddress().c_str())); |
Tomasz Wiszkowski | 686fe4f | 2017-09-11 13:32:13 -0700 | [diff] [blame] | 52 | |
| 53 | return request; |
| 54 | } |
Tomasz Wiszkowski | 4d4bcf0 | 2017-09-11 13:34:17 -0700 | [diff] [blame] | 55 | } // namespace |
| 56 | |
Tomasz Wiszkowski | 719d315 | 2017-10-26 09:58:11 -0700 | [diff] [blame] | 57 | std::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 Wiszkowski | 4d4bcf0 | 2017-09-11 13:34:17 -0700 | [diff] [blame] | 63 | } |
| 64 | |
Tomasz Wiszkowski | 719d315 | 2017-10-26 09:58:11 -0700 | [diff] [blame] | 65 | auto client = nl_factory->New(NETLINK_ROUTE); |
| 66 | if (client) { |
| 67 | mgr.reset(new NetworkInterfaceManager(std::move(client))); |
| 68 | } |
| 69 | |
| 70 | return mgr; |
Tomasz Wiszkowski | 4d4bcf0 | 2017-09-11 13:34:17 -0700 | [diff] [blame] | 71 | } |
| 72 | |
| 73 | NetworkInterfaceManager::NetworkInterfaceManager( |
Tomasz Wiszkowski | 719d315 | 2017-10-26 09:58:11 -0700 | [diff] [blame] | 74 | std::unique_ptr<NetlinkClient> nl_client) |
| 75 | : nl_client_(std::move(nl_client)) {} |
Tomasz Wiszkowski | 4d4bcf0 | 2017-09-11 13:34:17 -0700 | [diff] [blame] | 76 | |
Tomasz Wiszkowski | 719d315 | 2017-10-26 09:58:11 -0700 | [diff] [blame] | 77 | std::unique_ptr<NetworkInterface> NetworkInterfaceManager::Open( |
Alistair Strachan | 8adbea1 | 2018-04-05 09:51:31 -0700 | [diff] [blame] | 78 | const std::string& if_name, const std::string& if_name_alt) { |
Tomasz Wiszkowski | 719d315 | 2017-10-26 09:58:11 -0700 | [diff] [blame] | 79 | 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 Strachan | 8adbea1 | 2018-04-05 09:51:31 -0700 | [diff] [blame] | 83 | 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 Wiszkowski | 4d4bcf0 | 2017-09-11 13:34:17 -0700 | [diff] [blame] | 94 | } |
| 95 | |
Tomasz Wiszkowski | 719d315 | 2017-10-26 09:58:11 -0700 | [diff] [blame] | 96 | iface.reset(new NetworkInterface(index)); |
| 97 | return iface; |
Tomasz Wiszkowski | 4d4bcf0 | 2017-09-11 13:34:17 -0700 | [diff] [blame] | 98 | } |
| 99 | |
Tomasz Wiszkowski | 4d4bcf0 | 2017-09-11 13:34:17 -0700 | [diff] [blame] | 100 | bool NetworkInterfaceManager::ApplyChanges(const NetworkInterface& iface) { |
Tomasz Wiszkowski | 0e82ef8 | 2017-10-26 11:47:57 -0700 | [diff] [blame] | 101 | if (!nl_client_->Send(BuildLinkRequest(iface))) return false; |
Tomasz Wiszkowski | 686fe4f | 2017-09-11 13:32:13 -0700 | [diff] [blame] | 102 | // Terminate immediately if interface is down. |
| 103 | if (!iface.IsOperational()) return true; |
Tomasz Wiszkowski | 0e82ef8 | 2017-10-26 11:47:57 -0700 | [diff] [blame] | 104 | return nl_client_->Send(BuildAddrRequest(iface)); |
Tomasz Wiszkowski | 4d4bcf0 | 2017-09-11 13:34:17 -0700 | [diff] [blame] | 105 | } |
| 106 | |
A. Cody Schuffelen | 61985ef | 2020-06-22 22:44:54 +0000 | [diff] [blame] | 107 | } // namespace cuttlefish |