0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-20 12:12:15 +02:00

sitnl: implement net_iface_new and net_iface_del

These two new methods can be used to create and delete a tun or an
ovpn-dco interface via RTNL API.

Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
Signed-off-by: Lev Stipakov <lev@openvpn.net>
This commit is contained in:
Antonio Quartulli 2020-04-21 15:22:57 +02:00 committed by Lev Stipakov
parent bca2a06c29
commit 648234cc68
2 changed files with 126 additions and 0 deletions

View File

@ -831,6 +831,80 @@ err:
return ret; return ret;
} }
/**
* @brief Add new interface (similar to ip link add)
*
* @param iface interface name
* @param type interface link type (for example "ovpn-dco")
* @return int 0 on success, negative error code on error
*/
static int
net_iface_new(const std::string& iface, const std::string& type)
{
struct sitnl_link_req req = { };
struct rtattr *tail = NULL;
int ret = -1;
if (iface.empty())
{
OPENVPN_LOG(__func__ << ": passed empty interface");
return -EINVAL;
}
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
req.n.nlmsg_type = RTM_NEWLINK;
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_IFNAME, iface.c_str(),
iface.length() + 1);
tail = NLMSG_TAIL(&req.n);
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_INFO_KIND, type.c_str(),
type.length() + 1);
tail->rta_len = (uint8_t *)NLMSG_TAIL(&req.n) - (uint8_t *)tail;
req.i.ifi_family = AF_PACKET;
req.i.ifi_index = 0;
OPENVPN_LOG(__func__ << ": add " << iface << " type " << type);
ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
err:
return ret;
}
static int
net_iface_del(const std::string& iface)
{
struct sitnl_link_req req = { };
int ifindex;
if (iface.empty())
{
OPENVPN_LOG(__func__ << ": passed empty interface");
return -EINVAL;
}
ifindex = if_nametoindex(iface.c_str());
if (ifindex == 0)
{
OPENVPN_LOG(__func__ << ": rtnl: cannot get ifindex for " << iface
<< ": " << strerror(errno));
return -ENOENT;
}
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
req.n.nlmsg_flags = NLM_F_REQUEST;
req.n.nlmsg_type = RTM_DELLINK;
req.i.ifi_family = AF_PACKET;
req.i.ifi_index = ifindex;
OPENVPN_LOG(__func__ << ": idel " << iface);
return sitnl_send(&req.n, 0, 0, NULL, NULL);
}
static int static int
net_iface_up(std::string& iface, bool up) net_iface_up(std::string& iface, bool up)
{ {

View File

@ -431,6 +431,58 @@ namespace openvpn {
R_ADD_ALL=R_ADD_SYS|R_ADD_DCO, R_ADD_ALL=R_ADD_SYS|R_ADD_DCO,
}; };
/**
* @brief Add new interface
*
* @param os output stream to where error message is written
* @param dev interface name
* @param type interface link type (such as "ovpn-dco")
* @return int 0 on success, negative error code on error
*/
inline int iface_new(std::ostringstream& os, const std::string& dev, const std::string& type)
{
int ret = -1;
if (dev.empty())
{
os << "Error: can't call NetlinkLinkNew with no interface" << std::endl;
return ret;
}
if (type.empty())
{
os << "Error: can't call NetlinkLinkNew with no interfacei type" << std::endl;
return ret;
}
ret = SITNL::net_iface_new(dev, type);
if (ret)
{
os << "Error while executing NetlinkLinkNew " << dev << ": " << ret << std::endl;
}
return ret;
}
inline int iface_del(std::ostringstream& os, const std::string& dev)
{
int ret = -1;
if (dev.empty())
{
os << "Error: can't call NetlinkLinkDel with no interface" << std::endl;
return ret;
}
ret = SITNL::net_iface_del(dev);
if (ret)
{
os << "Error while executing NetlinkLinkDel " << dev << ": " << ret << std::endl;
}
return ret;
}
/*inline IPv4::Addr cvt_pnr_ip_v4(const std::string& hexaddr) /*inline IPv4::Addr cvt_pnr_ip_v4(const std::string& hexaddr)
{ {
BufferAllocated v(4, BufferAllocated::CONSTRUCT_ZERO); BufferAllocated v(4, BufferAllocated::CONSTRUCT_ZERO);