Skip to content

Commit

Permalink
dbus: dummy interface dbus service
Browse files Browse the repository at this point in the history
Support for creating dummy network interfaces.
  • Loading branch information
kmroz committed Mar 14, 2014
1 parent 58d9240 commit b22213a
Show file tree
Hide file tree
Showing 6 changed files with 322 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/wicked/objectmodel.h
Expand Up @@ -75,6 +75,7 @@ extern ni_dbus_class_t * ni_objectmodel_class_new(const char *, const ni_dbus_cl
#define NI_OBJECTMODEL_WIRELESS_INTERFACE NI_OBJECTMODEL_INTERFACE ".Wireless"
#define NI_OBJECTMODEL_BRIDGE_INTERFACE NI_OBJECTMODEL_INTERFACE ".Bridge"
#define NI_OBJECTMODEL_MACVLAN_INTERFACE NI_OBJECTMODEL_INTERFACE ".MACVLAN"
#define NI_OBJECTMODEL_DUMMY_INTERFACE NI_OBJECTMODEL_INTERFACE ".Dummy"
#define NI_OBJECTMODEL_VLAN_INTERFACE NI_OBJECTMODEL_INTERFACE ".VLAN"
#define NI_OBJECTMODEL_BONDING_INTERFACE NI_OBJECTMODEL_INTERFACE ".Bond"
#define NI_OBJECTMODEL_TUN_INTERFACE NI_OBJECTMODEL_INTERFACE ".TUN"
Expand Down
1 change: 1 addition & 0 deletions schema/Makefile.am
Expand Up @@ -16,6 +16,7 @@ wicked_schema_files = \
interface.xml \
lldp.xml \
macvlan.xml \
dummy.xml \
ppp.xml \
protocol.xml \
types.xml \
Expand Down
50 changes: 50 additions & 0 deletions schema/dummy.xml
@@ -0,0 +1,50 @@
<!--
-- dummy interface service definition
-->
<service name="dummy" interface="org.opensuse.Network.Dummy"
object-class="netif-dummy">
<description>
This link-layer service is provided by all Dummy devices.
Dummy network interfaces can be used to provide an IP address to any
application/kernel TCP/IP code that needs an IP to function properly.

Dummy devices can be created through the org.opensuse.Network.Dummy.Factory
factory interface.
</description>

<!-- This are the properties used to configure the dummy -->
<define name="configuration" class="dict">
<address type="ethernet-address"/>
</define>

<!-- The same properties are returned in interface state reports -->
<define name="properties" type="dummy:configuration"/>

<method name="changeDevice">
<arguments>
<config type="dummy:configuration">
<meta:mapping document-node="/dummy" skip-unless-present="true" />
</config>
</arguments>
</method>

<method name="deleteDevice">
<!-- no arguments, no return code -->
</method>
</service>

<service name="dummy-factory" interface="org.opensuse.Network.Dummy.Factory"
object-class="netif-list">
<method name="newDevice">
<arguments>
<name type="string"/>
<config type="dummy:configuration">
<meta:mapping document-node="/dummy"/>
</config>
</arguments>
<return>
<!-- this is really an object handle -->
<string/>
</return>
</method>
</service>
1 change: 1 addition & 0 deletions src/Makefile.am
Expand Up @@ -117,6 +117,7 @@ libwicked_dbus_objects_la_SOURCES = \
dbus-objects/ipv6.c \
dbus-objects/lldp.c \
dbus-objects/macvlan.c \
dbus-objects/dummy.c \
dbus-objects/misc.c \
dbus-objects/model.c \
dbus-objects/modem.c \
Expand Down
267 changes: 267 additions & 0 deletions src/dbus-objects/dummy.c
@@ -0,0 +1,267 @@
/*
* DBus encapsulation for dummy interfaces.
*
* Copyright (C) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/> or write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Authors:
* Karol Mroz <kmroz@suse.com>
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <net/if_arp.h>

#include <wicked/netinfo.h>
#include <wicked/logging.h>
#include <wicked/system.h>
#include <wicked/dbus-errors.h>
#include <wicked/dbus-service.h>
#include "model.h"
#include "debug.h"

static ni_netdev_t * __ni_objectmodel_dummy_newlink(ni_netdev_t *, const char *, DBusError *);

static inline ni_netdev_t *
__ni_objectmodel_dummy_device_arg(const ni_dbus_variant_t *dict)
{
return ni_objectmodel_get_netif_argument(dict, NI_IFTYPE_DUMMY,
&ni_objectmodel_dummy_service);
}

static ni_netdev_t *
__ni_objectmodel_dummy_newlink(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error)
{
ni_netconfig_t *nc = ni_global_state_handle(0);
ni_netdev_t *dev_ifp = NULL;
int rv;

if (ni_string_empty(ifname)) {
if (ni_string_empty(cfg_ifp->name) &&
(ifname = ni_netdev_make_name(nc, "dummy"))) {
ni_string_dup(&cfg_ifp->name, ifname);
} else {
dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
"Unable to create dummy interface: "
"name argument missed");
goto out;
}
ifname = NULL;
} else if(!ni_string_eq(cfg_ifp->name, ifname)) {
ni_string_dup(&cfg_ifp->name, ifname);
}

if (cfg_ifp->link.hwaddr.len) {
if (cfg_ifp->link.hwaddr.type == ARPHRD_VOID)
cfg_ifp->link.hwaddr.type = ARPHRD_ETHER;
if (cfg_ifp->link.hwaddr.type != ARPHRD_ETHER ||
cfg_ifp->link.hwaddr.len != ni_link_address_length(ARPHRD_ETHER)) {
dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
"Cannot create dummy interface: "
"invalid ethernet address '%s'",
ni_link_address_print(&cfg_ifp->link.hwaddr));
return NULL;
}
}

if ((rv = ni_system_dummy_create(nc, cfg_ifp, &dev_ifp)) < 0) {
if (rv != -NI_ERROR_DEVICE_EXISTS || dev_ifp == NULL
|| (ifname && dev_ifp && !ni_string_eq(dev_ifp->name, ifname))) {
dbus_set_error(error, DBUS_ERROR_FAILED,
"Unable to create dummy interface: %s",
ni_strerror(rv));
dev_ifp = NULL;
goto out;
}
ni_debug_dbus("dummy interface exists (and name matches)");
}

if (dev_ifp->link.type != NI_IFTYPE_DUMMY) {
dbus_set_error(error, DBUS_ERROR_FAILED,
"Unable to create dummy interface: "
"new interface is of type %s",
ni_linktype_type_to_name(dev_ifp->link.type));
dev_ifp = NULL;
}

out:
if (cfg_ifp)
ni_netdev_put(cfg_ifp);
return dev_ifp;
}

static dbus_bool_t
ni_objectmodel_dummy_newlink(ni_dbus_object_t *factory_object,
const ni_dbus_method_t *method,
unsigned int argc, const ni_dbus_variant_t *argv,
ni_dbus_message_t *reply, DBusError *error)
{
ni_dbus_server_t *server = ni_dbus_object_get_server(factory_object);
ni_netdev_t *dev;
const char *ifname = NULL;

NI_TRACE_ENTER();

ni_assert(argc == 2);
if (!ni_dbus_variant_get_string(&argv[0], &ifname)
|| !(dev = __ni_objectmodel_dummy_device_arg(&argv[1]))) {
return ni_dbus_error_invalid_args(error,
factory_object->path,
method->name);
}

if (!(dev = __ni_objectmodel_dummy_newlink(dev, ifname, error)))
return FALSE;

return ni_objectmodel_netif_factory_result(server, reply, dev, NULL, error);
}

static dbus_bool_t
ni_objectmodel_dummy_change(ni_dbus_object_t *object, const ni_dbus_method_t *method,
unsigned int argc, const ni_dbus_variant_t *argv,
ni_dbus_message_t *reply, DBusError *error)
{
ni_netconfig_t *nc = ni_global_state_handle(0);
ni_netdev_t *dev, *cfg;

/* we've already checked that argv matches our signature */
ni_assert(argc == 1);

if (!(dev = ni_objectmodel_unwrap_netif(object, error)) ||
!(cfg = __ni_objectmodel_dummy_device_arg(&argv[0]))) {
ni_dbus_error_invalid_args(error, object->path, method->name);
return FALSE;
}

cfg->link.ifindex = dev->link.ifindex;
if (ni_string_empty(cfg->name))
ni_string_dup(&cfg->name, dev->name);

if (ni_netdev_device_is_up(dev)) {
ni_debug_objectmodel("Skipping dummy changeDevice call on %s: "
"device is up", dev->name);
return TRUE;
}

if (ni_system_dummy_change(nc, dev, cfg) < 0) {
dbus_set_error(error,
DBUS_ERROR_FAILED,
"Unable to change dummy properties on interface %s",
dev->name);
return FALSE;
}

if (cfg->link.hwaddr.type == ARPHRD_VOID)
cfg->link.hwaddr.type = ARPHRD_ETHER;
if (ni_system_hwaddr_change(nc, dev, &cfg->link.hwaddr) < 0) {
ni_error("Unable to change hwaddr on dummy interface %s",
dev->name);
/* fail? */
}

return TRUE;
}

static dbus_bool_t
ni_objectmodel_dummy_delete(ni_dbus_object_t *object, const ni_dbus_method_t *method,
unsigned int argc, const ni_dbus_variant_t *argv,
ni_dbus_message_t *reply, DBusError *error)
{
ni_netdev_t *dev;
int rv;

if (!(dev = ni_objectmodel_unwrap_netif(object, error)))
return FALSE;

NI_TRACE_ENTER_ARGS("dev=%s", dev->name);

if ((rv = ni_system_dummy_delete(dev)) < 0) {
dbus_set_error(error, DBUS_ERROR_FAILED,
"Error deleting dummy interface %s: %s",
dev->name, ni_strerror(rv));
return FALSE;
}

ni_dbus_object_free(object);

return TRUE;
}


/*
* Helper functions to obtain dummy config from dbus object.
*/

static dbus_bool_t
__ni_objectmodel_dummy_get_address(const ni_dbus_object_t *object,
const ni_dbus_property_t *property,
ni_dbus_variant_t *result,
DBusError *error)
{
ni_netdev_t *dev;

if (!(dev = ni_objectmodel_unwrap_netif(object, error)))
return FALSE;
return __ni_objectmodel_get_hwaddr(result, &dev->link.hwaddr);
}

static dbus_bool_t
__ni_objectmodel_dummy_set_address(ni_dbus_object_t *object,
const ni_dbus_property_t *property,
const ni_dbus_variant_t *argument,
DBusError *error)
{
ni_netdev_t *dev;

if (!(dev = ni_objectmodel_unwrap_netif(object, error)))
return FALSE;
return __ni_objectmodel_set_hwaddr(argument, &dev->link.hwaddr);
}

#define DUMMY_HWADDR_PROPERTY(dbus_name, rw) \
__NI_DBUS_PROPERTY(DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING, \
dbus_name, __ni_objectmodel_dummy, rw)

const ni_dbus_property_t ni_objectmodel_dummy_property_table[] = {
DUMMY_HWADDR_PROPERTY(address, RO),
{ NULL }
};

static ni_dbus_method_t ni_objectmodel_dummy_methods[] = {
{ "changeDevice", "a{sv}", ni_objectmodel_dummy_change },
{ "deleteDevice", "", ni_objectmodel_dummy_delete },
{ NULL }
};

static ni_dbus_method_t ni_objectmodel_dummy_factory_methods[] = {
{ "newDevice", "sa{sv}", ni_objectmodel_dummy_newlink },

{ NULL }
};

ni_dbus_service_t ni_objectmodel_dummy_factory_service = {
.name = NI_OBJECTMODEL_DUMMY_INTERFACE ".Factory",
.methods = ni_objectmodel_dummy_factory_methods,
};

ni_dbus_service_t ni_objectmodel_dummy_service = {
.name = NI_OBJECTMODEL_DUMMY_INTERFACE,
.methods = ni_objectmodel_dummy_methods,
.properties = ni_objectmodel_dummy_property_table,
};
2 changes: 2 additions & 0 deletions src/dbus-objects/model.h
Expand Up @@ -93,6 +93,8 @@ extern ni_dbus_service_t ni_objectmodel_vlan_service;
extern ni_dbus_service_t ni_objectmodel_vlan_factory_service;
extern ni_dbus_service_t ni_objectmodel_macvlan_service;
extern ni_dbus_service_t ni_objectmodel_macvlan_factory_service;
extern ni_dbus_service_t ni_objectmodel_dummy_service;
extern ni_dbus_service_t ni_objectmodel_dummy_factory_service;
extern ni_dbus_service_t ni_objectmodel_tun_service;
extern ni_dbus_service_t ni_objectmodel_tun_factory_service;
extern ni_dbus_service_t ni_objectmodel_ppp_base_service;
Expand Down

0 comments on commit b22213a

Please sign in to comment.