xref: /aosp_15_r20/bootable/recovery/recovery_ui/ethernet_device.cpp (revision e7c364b630b241adcb6c7726a21055250b91fdac)
1*e7c364b6SAndroid Build Coastguard Worker /*
2*e7c364b6SAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*e7c364b6SAndroid Build Coastguard Worker  *
4*e7c364b6SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*e7c364b6SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*e7c364b6SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*e7c364b6SAndroid Build Coastguard Worker  *
8*e7c364b6SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*e7c364b6SAndroid Build Coastguard Worker  *
10*e7c364b6SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*e7c364b6SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*e7c364b6SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e7c364b6SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*e7c364b6SAndroid Build Coastguard Worker  * limitations under the License.
15*e7c364b6SAndroid Build Coastguard Worker  */
16*e7c364b6SAndroid Build Coastguard Worker 
17*e7c364b6SAndroid Build Coastguard Worker #include <android-base/logging.h>
18*e7c364b6SAndroid Build Coastguard Worker #include <android-base/properties.h>
19*e7c364b6SAndroid Build Coastguard Worker #include <android-base/strings.h>
20*e7c364b6SAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
21*e7c364b6SAndroid Build Coastguard Worker #include <arpa/inet.h>
22*e7c364b6SAndroid Build Coastguard Worker #include <ifaddrs.h>
23*e7c364b6SAndroid Build Coastguard Worker #include <linux/if.h>
24*e7c364b6SAndroid Build Coastguard Worker #include <string.h>
25*e7c364b6SAndroid Build Coastguard Worker #include <sys/ioctl.h>
26*e7c364b6SAndroid Build Coastguard Worker #include <sys/socket.h>
27*e7c364b6SAndroid Build Coastguard Worker #include <sys/types.h>
28*e7c364b6SAndroid Build Coastguard Worker 
29*e7c364b6SAndroid Build Coastguard Worker #include "recovery_ui/device.h"
30*e7c364b6SAndroid Build Coastguard Worker #include "recovery_ui/ethernet_device.h"
31*e7c364b6SAndroid Build Coastguard Worker #include "recovery_ui/ethernet_ui.h"
32*e7c364b6SAndroid Build Coastguard Worker 
33*e7c364b6SAndroid Build Coastguard Worker // Android TV defaults to eth0 for it's interface
EthernetDevice(EthernetRecoveryUI * ui)34*e7c364b6SAndroid Build Coastguard Worker EthernetDevice::EthernetDevice(EthernetRecoveryUI* ui) : EthernetDevice(ui, "eth0") {}
35*e7c364b6SAndroid Build Coastguard Worker 
36*e7c364b6SAndroid Build Coastguard Worker // Allow future users to define the interface as they prefer
EthernetDevice(EthernetRecoveryUI * ui,std::string interface)37*e7c364b6SAndroid Build Coastguard Worker EthernetDevice::EthernetDevice(EthernetRecoveryUI* ui, std::string interface)
38*e7c364b6SAndroid Build Coastguard Worker     : Device(ui), ctl_sock_(socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)), interface_(interface) {
39*e7c364b6SAndroid Build Coastguard Worker   if (ctl_sock_ < 0) {
40*e7c364b6SAndroid Build Coastguard Worker     PLOG(ERROR) << "Failed to open socket";
41*e7c364b6SAndroid Build Coastguard Worker   }
42*e7c364b6SAndroid Build Coastguard Worker }
43*e7c364b6SAndroid Build Coastguard Worker 
PreRecovery()44*e7c364b6SAndroid Build Coastguard Worker void EthernetDevice::PreRecovery() {
45*e7c364b6SAndroid Build Coastguard Worker   SetInterfaceFlags(0, IFF_UP);
46*e7c364b6SAndroid Build Coastguard Worker   SetTitleIPv6LinkLocalAddress(false);
47*e7c364b6SAndroid Build Coastguard Worker }
48*e7c364b6SAndroid Build Coastguard Worker 
PreFastboot()49*e7c364b6SAndroid Build Coastguard Worker void EthernetDevice::PreFastboot() {
50*e7c364b6SAndroid Build Coastguard Worker   android::base::SetProperty("fastbootd.protocol", "tcp");
51*e7c364b6SAndroid Build Coastguard Worker 
52*e7c364b6SAndroid Build Coastguard Worker   if (SetInterfaceFlags(IFF_UP, 0) < 0) {
53*e7c364b6SAndroid Build Coastguard Worker     LOG(ERROR) << "Failed to bring up interface";
54*e7c364b6SAndroid Build Coastguard Worker     return;
55*e7c364b6SAndroid Build Coastguard Worker   }
56*e7c364b6SAndroid Build Coastguard Worker 
57*e7c364b6SAndroid Build Coastguard Worker   SetTitleIPv6LinkLocalAddress(true);
58*e7c364b6SAndroid Build Coastguard Worker }
59*e7c364b6SAndroid Build Coastguard Worker 
SetInterfaceFlags(const unsigned set,const unsigned clr)60*e7c364b6SAndroid Build Coastguard Worker int EthernetDevice::SetInterfaceFlags(const unsigned set, const unsigned clr) {
61*e7c364b6SAndroid Build Coastguard Worker   struct ifreq ifr;
62*e7c364b6SAndroid Build Coastguard Worker 
63*e7c364b6SAndroid Build Coastguard Worker   if (ctl_sock_ < 0) {
64*e7c364b6SAndroid Build Coastguard Worker     return -1;
65*e7c364b6SAndroid Build Coastguard Worker   }
66*e7c364b6SAndroid Build Coastguard Worker 
67*e7c364b6SAndroid Build Coastguard Worker   memset(&ifr, 0, sizeof(struct ifreq));
68*e7c364b6SAndroid Build Coastguard Worker   strncpy(ifr.ifr_name, interface_.c_str(), IFNAMSIZ);
69*e7c364b6SAndroid Build Coastguard Worker   ifr.ifr_name[IFNAMSIZ - 1] = 0;
70*e7c364b6SAndroid Build Coastguard Worker 
71*e7c364b6SAndroid Build Coastguard Worker   if (ioctl(ctl_sock_, SIOCGIFFLAGS, &ifr) < 0) {
72*e7c364b6SAndroid Build Coastguard Worker     PLOG(ERROR) << "Failed to get interface active flags";
73*e7c364b6SAndroid Build Coastguard Worker     return -1;
74*e7c364b6SAndroid Build Coastguard Worker   }
75*e7c364b6SAndroid Build Coastguard Worker   ifr.ifr_flags = (ifr.ifr_flags & (~clr)) | set;
76*e7c364b6SAndroid Build Coastguard Worker 
77*e7c364b6SAndroid Build Coastguard Worker   if (ioctl(ctl_sock_, SIOCSIFFLAGS, &ifr) < 0) {
78*e7c364b6SAndroid Build Coastguard Worker     PLOG(ERROR) << "Failed to set interface active flags";
79*e7c364b6SAndroid Build Coastguard Worker     return -1;
80*e7c364b6SAndroid Build Coastguard Worker   }
81*e7c364b6SAndroid Build Coastguard Worker 
82*e7c364b6SAndroid Build Coastguard Worker   return 0;
83*e7c364b6SAndroid Build Coastguard Worker }
84*e7c364b6SAndroid Build Coastguard Worker 
SetTitleIPv6LinkLocalAddress(const bool interface_up)85*e7c364b6SAndroid Build Coastguard Worker void EthernetDevice::SetTitleIPv6LinkLocalAddress(const bool interface_up) {
86*e7c364b6SAndroid Build Coastguard Worker   auto recovery_ui = reinterpret_cast<EthernetRecoveryUI*>(GetUI());
87*e7c364b6SAndroid Build Coastguard Worker   if (!interface_up) {
88*e7c364b6SAndroid Build Coastguard Worker     recovery_ui->SetIPv6LinkLocalAddress();
89*e7c364b6SAndroid Build Coastguard Worker     return;
90*e7c364b6SAndroid Build Coastguard Worker   }
91*e7c364b6SAndroid Build Coastguard Worker 
92*e7c364b6SAndroid Build Coastguard Worker   struct ifaddrs* ifaddr;
93*e7c364b6SAndroid Build Coastguard Worker   if (getifaddrs(&ifaddr) == -1) {
94*e7c364b6SAndroid Build Coastguard Worker     PLOG(ERROR) << "Failed to get interface addresses";
95*e7c364b6SAndroid Build Coastguard Worker     recovery_ui->SetIPv6LinkLocalAddress();
96*e7c364b6SAndroid Build Coastguard Worker     return;
97*e7c364b6SAndroid Build Coastguard Worker   }
98*e7c364b6SAndroid Build Coastguard Worker 
99*e7c364b6SAndroid Build Coastguard Worker   std::unique_ptr<struct ifaddrs, decltype(&freeifaddrs)> guard{ ifaddr, freeifaddrs };
100*e7c364b6SAndroid Build Coastguard Worker   for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
101*e7c364b6SAndroid Build Coastguard Worker     if (ifa->ifa_addr->sa_family != AF_INET6 || interface_ != ifa->ifa_name) {
102*e7c364b6SAndroid Build Coastguard Worker       continue;
103*e7c364b6SAndroid Build Coastguard Worker     }
104*e7c364b6SAndroid Build Coastguard Worker 
105*e7c364b6SAndroid Build Coastguard Worker     auto current_addr = reinterpret_cast<struct sockaddr_in6*>(ifa->ifa_addr);
106*e7c364b6SAndroid Build Coastguard Worker     if (!IN6_IS_ADDR_LINKLOCAL(&(current_addr->sin6_addr))) {
107*e7c364b6SAndroid Build Coastguard Worker       continue;
108*e7c364b6SAndroid Build Coastguard Worker     }
109*e7c364b6SAndroid Build Coastguard Worker 
110*e7c364b6SAndroid Build Coastguard Worker     char addrstr[INET6_ADDRSTRLEN];
111*e7c364b6SAndroid Build Coastguard Worker     inet_ntop(AF_INET6, reinterpret_cast<const void*>(&current_addr->sin6_addr), addrstr,
112*e7c364b6SAndroid Build Coastguard Worker               INET6_ADDRSTRLEN);
113*e7c364b6SAndroid Build Coastguard Worker     LOG(INFO) << "Our IPv6 link-local address is " << addrstr;
114*e7c364b6SAndroid Build Coastguard Worker     recovery_ui->SetIPv6LinkLocalAddress(addrstr);
115*e7c364b6SAndroid Build Coastguard Worker     return;
116*e7c364b6SAndroid Build Coastguard Worker   }
117*e7c364b6SAndroid Build Coastguard Worker 
118*e7c364b6SAndroid Build Coastguard Worker   recovery_ui->SetIPv6LinkLocalAddress();
119*e7c364b6SAndroid Build Coastguard Worker }
120