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