• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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