blob: 827f8f3905204302fb8553fb1c911cd8e946e13e [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
Tomasz Wasilczykad107412020-05-29 16:32:43 -070030namespace socketparams {
31
32struct Params {
33 int domain;
34 int type;
35 int protocol;
36};
37
38static constexpr Params general = {AF_INET, SOCK_DGRAM, 0};
39static constexpr Params can = {PF_CAN, SOCK_RAW, CAN_RAW};
40
41static Params current = general;
42
43} // namespace socketparams
44
45void useCanSockets(bool yes) {
46 socketparams::current = yes ? socketparams::can : socketparams::general;
47}
48
Tomasz Wasilczyk87329672019-07-12 11:43:00 -070049bool exists(std::string ifname) {
50 return nametoindex(ifname) != 0;
51}
52
53static bool sendIfreq(unsigned long request, struct ifreq& ifr) {
Tomasz Wasilczykad107412020-05-29 16:32:43 -070054 base::unique_fd sock(socket(socketparams::current.domain, socketparams::current.type,
55 socketparams::current.protocol));
Tomasz Wasilczyk87329672019-07-12 11:43:00 -070056 if (!sock.ok()) {
57 LOG(ERROR) << "Can't create socket";
58 return false;
59 }
60
61 if (ioctl(sock.get(), request, &ifr) < 0) {
chrisweir1173a722020-02-26 14:39:56 -080062 PLOG(ERROR) << "ioctl(" << std::hex << request << std::dec << ") failed";
Tomasz Wasilczyk87329672019-07-12 11:43:00 -070063 return false;
64 }
65
66 return true;
67}
68
69static struct ifreq ifreqFromName(const std::string& ifname) {
70 struct ifreq ifr = {};
71 strlcpy(ifr.ifr_name, ifname.c_str(), IF_NAMESIZE);
72 return ifr;
73}
74
75std::optional<bool> isUp(std::string ifname) {
76 struct ifreq ifr = ifreqFromName(ifname);
77 if (!sendIfreq(SIOCGIFFLAGS, ifr)) return std::nullopt;
78 return ifr.ifr_flags & IFF_UP;
79}
80
Tomasz Wasilczykad107412020-05-29 16:32:43 -070081bool existsAndIsUp(const std::string& ifname) {
82 return exists(ifname) && isUp(ifname).value_or(false);
83}
84
Tomasz Wasilczyk87329672019-07-12 11:43:00 -070085bool up(std::string ifname) {
86 struct ifreq ifr = ifreqFromName(ifname);
87 if (!sendIfreq(SIOCGIFFLAGS, ifr)) return false;
88 ifr.ifr_flags |= IFF_UP;
89 return sendIfreq(SIOCSIFFLAGS, ifr);
90}
91
92bool down(std::string ifname) {
93 struct ifreq ifr = ifreqFromName(ifname);
94 if (!sendIfreq(SIOCGIFFLAGS, ifr)) return false;
95 ifr.ifr_flags &= ~IFF_UP;
96 return sendIfreq(SIOCSIFFLAGS, ifr);
97}
98
99bool add(std::string dev, std::string type) {
100 NetlinkRequest<struct ifinfomsg> req(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
101 req.addattr(IFLA_IFNAME, dev);
102
103 {
104 auto linkinfo = req.nest(IFLA_LINKINFO);
105 req.addattr(IFLA_INFO_KIND, type);
106 }
107
108 NetlinkSocket sock(NETLINK_ROUTE);
109 return sock.send(req) && sock.receiveAck();
110}
111
112bool del(std::string dev) {
113 NetlinkRequest<struct ifinfomsg> req(RTM_DELLINK, NLM_F_REQUEST);
114 req.addattr(IFLA_IFNAME, dev);
115
116 NetlinkSocket sock(NETLINK_ROUTE);
117 return sock.send(req) && sock.receiveAck();
118}
119
Tomasz Wasilczyk55f21932019-12-20 09:20:24 -0800120} // namespace android::netdevice