platform: support creation of TUN/TAP devices
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <dlfcn.h>
|
||||
#include <netinet/icmp6.h>
|
||||
@@ -4235,6 +4236,66 @@ link_vlan_change (NMPlatform *platform,
|
||||
return do_change_link (platform, ifindex, nlmsg) == NM_PLATFORM_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
tun_add (NMPlatform *platform, const char *name, gboolean tap,
|
||||
gint64 owner, gint64 group, gboolean pi, gboolean vnet_hdr,
|
||||
gboolean multi_queue, NMPlatformLink *out_link)
|
||||
{
|
||||
const NMPObject *obj;
|
||||
struct ifreq ifr = { };
|
||||
int fd;
|
||||
|
||||
_LOGD ("link: add %s '%s' owner %" G_GINT64_FORMAT " group %" G_GINT64_FORMAT,
|
||||
tap ? "tap" : "tun", name, owner, group);
|
||||
|
||||
fd = open ("/dev/net/tun", O_RDWR);
|
||||
if (fd < 0)
|
||||
return FALSE;
|
||||
|
||||
strncpy (ifr.ifr_name, name, IFNAMSIZ);
|
||||
ifr.ifr_flags = tap ? IFF_TAP : IFF_TUN;
|
||||
|
||||
if (!pi)
|
||||
ifr.ifr_flags |= IFF_NO_PI;
|
||||
if (vnet_hdr)
|
||||
ifr.ifr_flags |= IFF_VNET_HDR;
|
||||
if (multi_queue)
|
||||
ifr.ifr_flags |= NM_IFF_MULTI_QUEUE;
|
||||
|
||||
if (ioctl (fd, TUNSETIFF, &ifr)) {
|
||||
close (fd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (owner >= 0 && owner < G_MAXINT32) {
|
||||
if (ioctl (fd, TUNSETOWNER, (uid_t) owner)) {
|
||||
close (fd);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (group >= 0 && group < G_MAXINT32) {
|
||||
if (ioctl (fd, TUNSETGROUP, (gid_t) group)) {
|
||||
close (fd);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ioctl (fd, TUNSETPERSIST, 1)) {
|
||||
close (fd);
|
||||
return FALSE;
|
||||
}
|
||||
do_request_link (platform, 0, name, TRUE);
|
||||
obj = nmp_cache_lookup_link_full (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache,
|
||||
0, name, FALSE,
|
||||
tap ? NM_LINK_TYPE_TAP : NM_LINK_TYPE_TUN,
|
||||
NULL, NULL);
|
||||
if (out_link && obj)
|
||||
*out_link = obj->link;
|
||||
|
||||
return !!obj;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
link_enslave (NMPlatform *platform, int master, int slave)
|
||||
{
|
||||
@@ -5444,6 +5505,8 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
|
||||
platform_class->vlan_add = vlan_add;
|
||||
platform_class->link_vlan_change = link_vlan_change;
|
||||
|
||||
platform_class->tun_add = tun_add;
|
||||
|
||||
platform_class->infiniband_partition_add = infiniband_partition_add;
|
||||
|
||||
platform_class->wifi_get_capabilities = wifi_get_capabilities;
|
||||
|
@@ -1531,6 +1531,44 @@ nm_platform_vlan_add (NMPlatform *self,
|
||||
return NM_PLATFORM_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_platform_tun_add:
|
||||
* @self: platform instance
|
||||
* @name: new interface name
|
||||
* @tap: whether the interface is a TAP
|
||||
* @owner: interface owner or -1
|
||||
* @group: interface group or -1
|
||||
* @pi: whether to clear the IFF_NO_PI flag
|
||||
* @vnet_hdr: whether to set the IFF_VNET_HDR flag
|
||||
* @multi_queue: whether to set the IFF_MULTI_QUEUE flag
|
||||
* @out_link: on success, the link object
|
||||
*
|
||||
* Create a TUN or TAP interface.
|
||||
*/
|
||||
NMPlatformError
|
||||
nm_platform_tun_add (NMPlatform *self, const char *name, gboolean tap,
|
||||
gint64 owner, gint64 group, gboolean pi, gboolean vnet_hdr,
|
||||
gboolean multi_queue, NMPlatformLink *out_link)
|
||||
{
|
||||
NMPlatformError plerr;
|
||||
|
||||
_CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG);
|
||||
|
||||
g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG);
|
||||
g_return_val_if_fail (klass->tun_add, NM_PLATFORM_ERROR_BUG);
|
||||
|
||||
plerr = _link_add_check_existing (self, name, tap ? NM_LINK_TYPE_TAP : NM_LINK_TYPE_TUN, out_link);
|
||||
if (plerr != NM_PLATFORM_ERROR_SUCCESS)
|
||||
return plerr;
|
||||
|
||||
_LOGD ("link: adding %s '%s' owner %" G_GINT64_FORMAT " group %" G_GINT64_FORMAT,
|
||||
tap ? "tap" : "tun", name, owner, group);
|
||||
if (!klass->tun_add (self, name, tap, owner, group, pi, vnet_hdr, multi_queue, out_link))
|
||||
return NM_PLATFORM_ERROR_UNSPECIFIED;
|
||||
return NM_PLATFORM_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
nm_platform_master_set_option (NMPlatform *self, int ifindex, const char *option, const char *value)
|
||||
{
|
||||
@@ -1844,13 +1882,10 @@ nm_platform_tun_get_properties_ifname (NMPlatform *self, const char *ifname, NMP
|
||||
|
||||
flags = _nm_utils_ascii_str_to_int64 (val, 16, 0, G_MAXINT64, 0);
|
||||
if (!errno) {
|
||||
#ifndef IFF_MULTI_QUEUE
|
||||
const int IFF_MULTI_QUEUE = 0x0100;
|
||||
#endif
|
||||
props->mode = ((flags & (IFF_TUN | IFF_TAP)) == IFF_TUN) ? "tun" : "tap";
|
||||
props->no_pi = !!(flags & IFF_NO_PI);
|
||||
props->vnet_hdr = !!(flags & IFF_VNET_HDR);
|
||||
props->multi_queue = !!(flags & IFF_MULTI_QUEUE);
|
||||
props->multi_queue = !!(flags & NM_IFF_MULTI_QUEUE);
|
||||
} else
|
||||
success = FALSE;
|
||||
g_free (val);
|
||||
|
@@ -61,6 +61,8 @@ typedef struct _NMPlatform NMPlatform;
|
||||
#define NM_IN6_ADDR_GEN_MODE_NONE 1 /* IN6_ADDR_GEN_MODE_NONE */
|
||||
#define NM_IN6_ADDR_GEN_MODE_STABLE_PRIVACY 2 /* IN6_ADDR_GEN_MODE_STABLE_PRIVACY */
|
||||
|
||||
#define NM_IFF_MULTI_QUEUE 0x0100 /* IFF_MULTI_QUEUE */
|
||||
|
||||
typedef enum { /*< skip >*/
|
||||
|
||||
/* dummy value, to enforce that the enum type is signed and has a size
|
||||
@@ -525,6 +527,9 @@ typedef struct {
|
||||
|
||||
gboolean (*infiniband_partition_add) (NMPlatform *, int parent, int p_key, NMPlatformLink *out_link);
|
||||
|
||||
gboolean (*tun_add) (NMPlatform *platform, const char *name, gboolean tap, gint64 owner, gint64 group, gboolean pi,
|
||||
gboolean vnet_hdr, gboolean multi_queue, NMPlatformLink *out_link);
|
||||
|
||||
gboolean (*wifi_get_capabilities) (NMPlatform *, int ifindex, NMDeviceWifiCapabilities *caps);
|
||||
gboolean (*wifi_get_bssid) (NMPlatform *, int ifindex, guint8 *bssid);
|
||||
GByteArray *(*wifi_get_ssid) (NMPlatform *, int ifindex);
|
||||
@@ -728,6 +733,9 @@ gboolean nm_platform_link_vlan_change (NMPlatform *self,
|
||||
gsize n_egress_map);
|
||||
|
||||
|
||||
NMPlatformError nm_platform_tun_add (NMPlatform *self, const char *name, gboolean tap, gint64 owner, gint64 group, gboolean pi,
|
||||
gboolean vnet_hdr, gboolean multi_queue, NMPlatformLink *out_link);
|
||||
|
||||
NMPlatformError nm_platform_infiniband_partition_add (NMPlatform *self, int parent, int p_key, NMPlatformLink *out_link);
|
||||
gboolean nm_platform_infiniband_get_properties (NMPlatform *self, int ifindex, int *parent, int *p_key, const char **mode);
|
||||
|
||||
|
Reference in New Issue
Block a user