blob: 4bba5f635efef38d244d807cb2ab547cd1d1d01b [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <libnetdevice/libnetdevice.h>
#include "common.h"
#include "ifreqs.h"
#include <android-base/logging.h>
#include <libnetdevice/NetlinkRequest.h>
#include <libnetdevice/NetlinkSocket.h>
#include <linux/can.h>
#include <net/if.h>
namespace android::netdevice {
void useCanSockets(bool yes) {
socketparams::current = yes ? socketparams::can : socketparams::general;
}
bool exists(std::string ifname) {
return nametoindex(ifname) != 0;
}
std::optional<bool> isUp(std::string ifname) {
auto ifr = ifreqs::fromName(ifname);
if (!ifreqs::send(SIOCGIFFLAGS, ifr)) return std::nullopt;
return ifr.ifr_flags & IFF_UP;
}
bool existsAndIsUp(const std::string& ifname) {
return exists(ifname) && isUp(ifname).value_or(false);
}
bool up(std::string ifname) {
auto ifr = ifreqs::fromName(ifname);
if (!ifreqs::send(SIOCGIFFLAGS, ifr)) return false;
ifr.ifr_flags |= IFF_UP;
return ifreqs::send(SIOCSIFFLAGS, ifr);
}
bool down(std::string ifname) {
auto ifr = ifreqs::fromName(ifname);
if (!ifreqs::send(SIOCGIFFLAGS, ifr)) return false;
ifr.ifr_flags &= ~IFF_UP;
return ifreqs::send(SIOCSIFFLAGS, ifr);
}
bool add(std::string dev, std::string type) {
NetlinkRequest<struct ifinfomsg> req(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
req.addattr(IFLA_IFNAME, dev);
{
auto linkinfo = req.nest(IFLA_LINKINFO);
req.addattr(IFLA_INFO_KIND, type);
}
NetlinkSocket sock(NETLINK_ROUTE);
return sock.send(req) && sock.receiveAck();
}
bool del(std::string dev) {
NetlinkRequest<struct ifinfomsg> req(RTM_DELLINK, NLM_F_REQUEST);
req.addattr(IFLA_IFNAME, dev);
NetlinkSocket sock(NETLINK_ROUTE);
return sock.send(req) && sock.receiveAck();
}
std::optional<hwaddr_t> getHwAddr(const std::string& ifname) {
auto ifr = ifreqs::fromName(ifname);
if (!ifreqs::send(SIOCGIFHWADDR, ifr)) return std::nullopt;
hwaddr_t hwaddr;
memcpy(hwaddr.data(), ifr.ifr_hwaddr.sa_data, hwaddr.size());
return hwaddr;
}
bool setHwAddr(const std::string& ifname, hwaddr_t hwaddr) {
auto ifr = ifreqs::fromName(ifname);
// fetch sa_family
if (!ifreqs::send(SIOCGIFHWADDR, ifr)) return false;
memcpy(ifr.ifr_hwaddr.sa_data, hwaddr.data(), hwaddr.size());
return ifreqs::send(SIOCSIFHWADDR, ifr);
}
} // namespace android::netdevice
bool operator==(const android::netdevice::hwaddr_t lhs, const unsigned char rhs[ETH_ALEN]) {
static_assert(lhs.size() == ETH_ALEN);
return 0 == memcmp(lhs.data(), rhs, lhs.size());
}