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> 19 #include <linux/if_addr.h> 20 #include <linux/if_link.h> 21 #include <linux/netlink.h> 22 #include <linux/rtnetlink.h> 23 #include <net/if.h> 24 25 #include <memory> 26 27 #include "common/libs/glog/logging.h" 28 #include "common/libs/net/network_interface.h" 29 30 namespace cvd { 31 namespace { 32 NetlinkRequest BuildLinkRequest( 33 const NetworkInterface& interface) { 34 NetlinkRequest request(RTM_SETLINK, 0); 35 request.AddIfInfo(interface.Index(), interface.IsOperational()); 36 if (!interface.Name().empty()) { 37 request.AddString(IFLA_IFNAME, interface.Name()); 38 } 39 40 return request; 41 } 42 43 NetlinkRequest BuildAddrRequest( 44 const NetworkInterface& interface) { 45 NetlinkRequest request(RTM_NEWADDR, 0); 46 request.AddAddrInfo(interface.Index(), interface.PrefixLength()); 47 in_addr_t address{inet_addr(interface.Address().c_str())}; 48 request.AddInt32(IFA_LOCAL, address); 49 request.AddInt32(IFA_ADDRESS, address); 50 request.AddInt32(IFA_BROADCAST, 51 inet_addr(interface.BroadcastAddress().c_str())); 52 53 return request; 54 } 55 } // namespace 56 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(); 63 } 64 65 auto client = nl_factory->New(NETLINK_ROUTE); 66 if (client) { 67 mgr.reset(new NetworkInterfaceManager(std::move(client))); 68 } 69 70 return mgr; 71 } 72 73 NetworkInterfaceManager::NetworkInterfaceManager( 74 std::unique_ptr<NetlinkClient> nl_client) 75 : nl_client_(std::move(nl_client)) {} 76 77 std::unique_ptr<NetworkInterface> NetworkInterfaceManager::Open( 78 const std::string& if_name, const std::string& if_name_alt) { 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. 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 } 94 } 95 96 iface.reset(new NetworkInterface(index)); 97 return iface; 98 } 99 100 bool NetworkInterfaceManager::ApplyChanges(const NetworkInterface& iface) { 101 if (!nl_client_->Send(BuildLinkRequest(iface))) return false; 102 // Terminate immediately if interface is down. 103 if (!iface.IsOperational()) return true; 104 return nl_client_->Send(BuildAddrRequest(iface)); 105 } 106 107 } // namespace cvd 108