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*>(¤t_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