1 /*
2 * Copyright (C) 2019 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
17 #include <libnetdevice/libnetdevice.h>
18
19 #include "NetlinkRequest.h"
20 #include "NetlinkSocket.h"
21 #include "common.h"
22
23 #include <android-base/logging.h>
24
25 #include <linux/can.h>
26 #include <net/if.h>
27
28 namespace android::netdevice {
29
exists(std::string ifname)30 bool exists(std::string ifname) {
31 return nametoindex(ifname) != 0;
32 }
33
sendIfreq(unsigned long request,struct ifreq & ifr)34 static bool sendIfreq(unsigned long request, struct ifreq& ifr) {
35 /* For general interfaces it would be socket(AF_INET, SOCK_DGRAM, 0),
36 * but SEPolicy forces us to limit our flexibility here. */
37 base::unique_fd sock(socket(PF_CAN, SOCK_RAW, CAN_RAW));
38 if (!sock.ok()) {
39 LOG(ERROR) << "Can't create socket";
40 return false;
41 }
42
43 if (ioctl(sock.get(), request, &ifr) < 0) {
44 PLOG(ERROR) << "ioctl(" << std::hex << request << std::dec << ") failed";
45 return false;
46 }
47
48 return true;
49 }
50
ifreqFromName(const std::string & ifname)51 static struct ifreq ifreqFromName(const std::string& ifname) {
52 struct ifreq ifr = {};
53 strlcpy(ifr.ifr_name, ifname.c_str(), IF_NAMESIZE);
54 return ifr;
55 }
56
isUp(std::string ifname)57 std::optional<bool> isUp(std::string ifname) {
58 struct ifreq ifr = ifreqFromName(ifname);
59 if (!sendIfreq(SIOCGIFFLAGS, ifr)) return std::nullopt;
60 return ifr.ifr_flags & IFF_UP;
61 }
62
up(std::string ifname)63 bool up(std::string ifname) {
64 struct ifreq ifr = ifreqFromName(ifname);
65 if (!sendIfreq(SIOCGIFFLAGS, ifr)) return false;
66 ifr.ifr_flags |= IFF_UP;
67 return sendIfreq(SIOCSIFFLAGS, ifr);
68 }
69
down(std::string ifname)70 bool down(std::string ifname) {
71 struct ifreq ifr = ifreqFromName(ifname);
72 if (!sendIfreq(SIOCGIFFLAGS, ifr)) return false;
73 ifr.ifr_flags &= ~IFF_UP;
74 return sendIfreq(SIOCSIFFLAGS, ifr);
75 }
76
add(std::string dev,std::string type)77 bool add(std::string dev, std::string type) {
78 NetlinkRequest<struct ifinfomsg> req(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
79 req.addattr(IFLA_IFNAME, dev);
80
81 {
82 auto linkinfo = req.nest(IFLA_LINKINFO);
83 req.addattr(IFLA_INFO_KIND, type);
84 }
85
86 NetlinkSocket sock(NETLINK_ROUTE);
87 return sock.send(req) && sock.receiveAck();
88 }
89
del(std::string dev)90 bool del(std::string dev) {
91 NetlinkRequest<struct ifinfomsg> req(RTM_DELLINK, NLM_F_REQUEST);
92 req.addattr(IFLA_IFNAME, dev);
93
94 NetlinkSocket sock(NETLINK_ROUTE);
95 return sock.send(req) && sock.receiveAck();
96 }
97
98 } // namespace android::netdevice
99