blob: b05144209e4d4a67a542b03dccdb837677a27f09 [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
Tomasz Wasilczyk55f21932019-12-20 09:20:24 -080028namespace android::netdevice {
Tomasz Wasilczyk87329672019-07-12 11:43:00 -070029
30bool exists(std::string ifname) {
31 return nametoindex(ifname) != 0;
32}
33
34static 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) {
chrisweir1173a722020-02-26 14:39:56 -080044 PLOG(ERROR) << "ioctl(" << std::hex << request << std::dec << ") failed";
Tomasz Wasilczyk87329672019-07-12 11:43:00 -070045 return false;
46 }
47
48 return true;
49}
50
51static 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
57std::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
63bool 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
70bool 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
77bool 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
90bool 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
Tomasz Wasilczyk55f21932019-12-20 09:20:24 -080098} // namespace android::netdevice