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:
parent
bca2a06c29
commit
648234cc68
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user