/* * ethtool.changeDevice method */ static dbus_bool_t ni_objectmodel_ethtool_setup(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, *cfg; /* we've already checked that argv matches our signature */ ni_assert(argc == 1); if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return FALSE; if (!(cfg = ni_objectmodel_ethtool_request_arg(&argv[0]))) { ni_dbus_error_invalid_args(error, object->path, method->name); return FALSE; } if (ni_system_ethtool_setup(NULL, dev, cfg) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "failed to apply ethtool settings"); ni_netdev_put(cfg); return FALSE; } ni_netdev_put(cfg); return TRUE; }
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", 0))) { 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; }
/* * PPP.changeDevice method */ static dbus_bool_t ni_objectmodel_ppp_device_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 *ifp, *cfg; dbus_bool_t rv = FALSE; /* we've already checked that argv matches our signature */ ni_assert(argc == 1); if (!(ifp = ni_objectmodel_unwrap_netif(object, error))) return FALSE; if (!(cfg = ni_objectmodel_ppp_device_arg(&argv[0]))) { ni_dbus_error_invalid_args(error, object->path, method->name); goto out; } if (ni_system_ppp_setup(nc, ifp, cfg) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "failed to set up ppp device"); goto out; } rv = TRUE; out: if (cfg) ni_netdev_put(cfg); return rv; }
/* * Create a new ppp interface */ static dbus_bool_t ni_objectmodel_ppp_device_new(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, *cfg; const char *ifname = NULL; if (argc != 2) goto error; if (!ni_dbus_variant_get_string(&argv[0], &ifname)) goto error; if (!(cfg = ni_objectmodel_ppp_device_arg(&argv[1]))) goto error; dev = ni_objectmodel_ppp_device_create(cfg, ifname, error); ni_netdev_put(cfg); if (dev) return ni_objectmodel_netif_factory_result(server, reply, dev, NULL, error); else return FALSE; error: return ni_dbus_error_invalid_args(error, factory_object->path, method->name); }
/* * Create a new PPP interface * We're given two arguments, the interface name and the <ppp> configuration data. * However, we ignore all the config data at this point and just create the * device. The configuration data is consumed by a subsequent call to changeDevice * (where we build a config file from it). */ dbus_bool_t ni_objectmodel_ppp_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, __get_device_arg_fn_t get_device_arg_fn) { ni_dbus_server_t *server = ni_dbus_object_get_server(factory_object); const char *ifname = NULL; ni_netdev_t *dev, *dev_cfg; NI_TRACE_ENTER(); ni_assert(argc == 2); if (!ni_dbus_variant_get_string(&argv[0], &ifname)) return ni_dbus_error_invalid_args(error, factory_object->path, method->name); if (!(dev_cfg = get_device_arg_fn(&argv[1], error))) return FALSE; dev = __ni_objectmodel_ppp_newlink(dev_cfg, ifname, error); ni_netdev_put(dev_cfg); if (dev == NULL) return FALSE; return ni_objectmodel_netif_factory_result(server, reply, dev, NULL, error); }
static dbus_bool_t __ni_objectmodel_tuntap_newlink(ni_iftype_t iftype, 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); const char *ifname = NULL; ni_netdev_t *dev; ni_netdev_t *cfg; NI_TRACE_ENTER(); ni_assert(argc == 2); if (!ni_dbus_variant_get_string(&argv[0], &ifname) || !(cfg = __ni_objectmodel_tuntap_device_arg(&argv[1], iftype))) { return ni_dbus_error_invalid_args(error, factory_object->path, method->name); } ni_string_dup(&cfg->name, ifname); dev = __ni_objectmodel_tuntap_create(cfg, error); ni_netdev_put(cfg); if (!dev) return FALSE; return ni_objectmodel_netif_factory_result(server, reply, dev, NULL, error); }
static ni_netdev_t * __ni_objectmodel_team_newlink(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error) { ni_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *new_ifp = NULL; int rv; ni_netdev_get_team(cfg_ifp); if (ifname == NULL && !(ifname = ni_netdev_make_name(nc, "team", 0))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create team interface - too many interfaces"); goto out; } 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 team interface: invalid ethernet address '%s'", ni_link_address_print(&cfg_ifp->link.hwaddr)); goto out; } } if ((rv = ni_system_team_create(nc, cfg_ifp, &new_ifp)) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create team interface '%s'", cfg_ifp->name); new_ifp = NULL; goto out; #if 0 if (rv != -NI_ERROR_DEVICE_EXISTS && (ifname != NULL && strcmp(ifname, new_ifp->name))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create team interface: %s", ni_strerror(rv)); goto out; } ni_debug_dbus("Bonding interface exists (and name matches)"); #endif } if (new_ifp->link.type != NI_IFTYPE_TEAM) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create team interface: new interface is of type %s", ni_linktype_type_to_name(new_ifp->link.type)); new_ifp = NULL; } out: if (cfg_ifp) ni_netdev_put(cfg_ifp); return new_ifp; }
void ni_compat_netdev_free(ni_compat_netdev_t *compat) { ni_netdev_put(compat->dev); /* FIXME: clean up the rest */ free(compat); }
/* * Functions for handling lists of interfaces */ void __ni_netdev_list_destroy(ni_netdev_t **list) { ni_netdev_t *dev; while ((dev = *list) != NULL) { *list = dev->next; ni_netdev_put(dev); } }
void ni_netconfig_device_remove(ni_netconfig_t *nc, ni_netdev_t *dev) { ni_netdev_t **pos, *cur; for (pos = &nc->interfaces; (cur = *pos) != NULL; pos = &cur->next) { if (cur == dev) { *pos = cur->next; ni_netdev_put(cur); return; } } }
/* * Infiniband(Child).changeDevice method */ static dbus_bool_t ni_objectmodel_ib_setup(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 *ifp, *cfg; dbus_bool_t rv = FALSE; /* we've already checked that argv matches our signature */ if (argc != 1 || !(ifp = ni_objectmodel_unwrap_netif(object, error))) return FALSE; if (ifp->link.type == NI_IFTYPE_INFINIBAND) { cfg = __ni_objectmodel_ibparent_device_arg(&argv[0]); } else if (ifp->link.type == NI_IFTYPE_INFINIBAND_CHILD) { cfg = __ni_objectmodel_ibchild_device_arg(&argv[0]); } else { cfg = NULL; } if (!cfg) { ni_dbus_error_invalid_args(error, object->path, method->name); goto out; } /* when <infiniband/> node is empty (defaults only), skip setup */ if (cfg->infiniband) { const char *err; if ((err = ni_infiniband_validate(ifp->link.type, cfg->infiniband, &cfg->link.lowerdev))) { dbus_set_error(error, DBUS_ERROR_FAILED, "%s", err); goto out; } if (ni_system_infiniband_setup(nc, ifp, cfg) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "failed to configure infiniband device %s", ifp->name); goto out; } } rv = TRUE; out: if (cfg) ni_netdev_put(cfg); return rv; }
static ni_netdev_t * __ni_objectmodel_tun_newlink(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error) { ni_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *new_ifp = NULL; const ni_tun_t *tun; const char *err; int rv; /* There's nothing in the device argument that we could use. */ ni_debug_dbus("TUN.newDevice(name=%s)", ifname); if (ifname == NULL && !(ifname = ni_netdev_make_name(nc, "tun", 0))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create tun - too many interfaces"); goto out; } tun = ni_netdev_get_tun(cfg_ifp); if ((err = ni_tun_validate(tun))) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "%s", err); goto out; } if ((rv = ni_system_tun_create(nc, ifname, tun, &new_ifp)) < 0) { if (rv != -NI_ERROR_DEVICE_EXISTS || new_ifp == NULL || (ifname && new_ifp && !ni_string_eq(new_ifp->name, ifname))) { ni_dbus_set_error_from_code(error, rv, "unable to create TUN interface %s", ifname); new_ifp = NULL; goto out; } ni_debug_dbus("TUN interface exists (and name matches)"); } if (new_ifp->link.type != NI_IFTYPE_TUN) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create TUN interface: new interface is of type %s", ni_linktype_type_to_name(new_ifp->link.type)); new_ifp = NULL; } out: if (cfg_ifp) ni_netdev_put(cfg_ifp); return new_ifp; }
static dbus_bool_t ni_objectmodel_ib_newchild(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 *cfg, *dev; const char *ifname = NULL; NI_TRACE_ENTER(); if (argc != 2 || !ni_dbus_variant_get_string(&argv[0], &ifname) || !ifname || !(cfg = __ni_objectmodel_ibchild_device_arg(&argv[1]))) { return ni_dbus_error_invalid_args(error, factory_object->path, method->name); } if (!(dev = __ni_objectmodel_ib_newchild(cfg, ifname, error))) { ni_netdev_put(cfg); return FALSE; } ni_netdev_put(cfg); return ni_objectmodel_netif_factory_result(server, reply, dev, NULL, error); }
static ni_netdev_t * __ni_objectmodel_bond_newlink(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error) { ni_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *new_ifp = NULL; const ni_bonding_t *bond; int rv; bond = ni_netdev_get_bonding(cfg_ifp); if (ifname == NULL && !(ifname = ni_netdev_make_name(nc, "bond", 0))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create bonding interface - too many interfaces"); goto out; } ni_string_dup(&cfg_ifp->name, ifname); if ((rv = ni_system_bond_create(nc, cfg_ifp->name, bond, &new_ifp)) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create bonding interface '%s'", cfg_ifp->name); new_ifp = NULL; goto out; #if 0 if (rv != -NI_ERROR_DEVICE_EXISTS && (ifname != NULL && strcmp(ifname, new_ifp->name))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create bonding interface: %s", ni_strerror(rv)); goto out; } ni_debug_dbus("Bonding interface exists (and name matches)"); #endif } if (new_ifp->link.type != NI_IFTYPE_BOND) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create bonding interface: new interface is of type %s", ni_linktype_type_to_name(new_ifp->link.type)); new_ifp = NULL; } out: if (cfg_ifp) ni_netdev_put(cfg_ifp); return new_ifp; }
/* * LLDP.lldpUp */ static dbus_bool_t ni_objectmodel_lldp_up(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, *cfg; dbus_bool_t rv = FALSE; /* we've already checked that argv matches our signature */ ni_assert(argc == 1); if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return FALSE; ni_debug_lldp("ni_objectmodel_lldp_up(%s -> %s)", object->path, dev->name); if (!ni_system_lldp_available(dev)) { ni_error("Cannot enable LLDP for device %s: incompatible layer 2 protocol", dev->name); return TRUE; } if (!(cfg = __ni_objectmodel_protocol_arg(&argv[0], &ni_objectmodel_lldp_service))) { ni_dbus_error_invalid_args(error, object->path, method->name); goto out; } if (cfg->lldp && !__ni_objectmodel_lldp_verify(object, method, dev, cfg->lldp, error)) goto out; if (ni_system_lldp_up(dev, cfg->lldp) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "failed to set up LLDP on device %s", dev->name); goto out; } rv = TRUE; out: if (cfg) ni_netdev_put(cfg); return rv; }
/* * Common helper function to extract some specific properties of device info from a dbus dict */ static ni_netdev_t * __ni_objectmodel_protocol_arg(const ni_dbus_variant_t *dict, const ni_dbus_service_t *service) { ni_dbus_object_t *dev_object; ni_netdev_t *dev; dbus_bool_t rv; dev = ni_netdev_new(NULL, 0); dev->link.type = NI_IFTYPE_ETHERNET; dev_object = ni_objectmodel_wrap_netif(dev); rv = ni_dbus_object_set_properties_from_dict(dev_object, service, dict, NULL); ni_dbus_object_free(dev_object); if (!rv) { ni_netdev_put(dev); dev = NULL; } return dev; }
static ni_netdev_t * __ni_objectmodel_ovs_bridge_newlink(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error) { ni_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *new_ifp = NULL; int rv; ni_netdev_get_ovs_bridge(cfg_ifp); if (ifname == NULL && !(ifname = ni_netdev_make_name(nc, "ovsbr", 0))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create ovs bridge interface - too many interfaces"); goto out; } ni_string_dup(&cfg_ifp->name, ifname); if ((rv = ni_system_ovs_bridge_create(nc, cfg_ifp, &new_ifp)) < 0) { if (rv != -NI_ERROR_DEVICE_EXISTS || new_ifp == NULL || (ifname && new_ifp && !ni_string_eq(ifname, new_ifp->name))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create OVS bridge device: %s", ni_strerror(rv)); new_ifp = NULL; goto out; } ni_debug_dbus("OVS bridge device %s exists (and with correct type)", ifname); } if (new_ifp->link.type != NI_IFTYPE_OVS_BRIDGE) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create ovs bridge interface: new interface is of type %s", ni_linktype_type_to_name(new_ifp->link.type)); new_ifp = NULL; } out: if (cfg_ifp) ni_netdev_put(cfg_ifp); return new_ifp; }
static ni_netdev_t * __ni_objectmodel_bridge_newlink(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error) { ni_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *new_ifp = NULL; const ni_bridge_t *bridge; int rv; bridge = ni_netdev_get_bridge(cfg_ifp); if (ifname == NULL && !(ifname = ni_netdev_make_name(nc, "br", 0))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create bridging interface - too many interfaces"); goto out; } ni_string_dup(&cfg_ifp->name, ifname); if ((rv = ni_system_bridge_create(nc, cfg_ifp->name, bridge, &new_ifp)) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create bridging interface: %s", ni_strerror(rv)); new_ifp = NULL; goto out; } if (new_ifp->link.type != NI_IFTYPE_BRIDGE) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create bridging interface: new interface is of type %s", ni_linktype_type_to_name(new_ifp->link.type)); new_ifp = NULL; } out: if (cfg_ifp) ni_netdev_put(cfg_ifp); return new_ifp; }
static ni_netdev_t * __ni_objectmodel_macvlan_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; const ni_macvlan_t *macvlan; const char *err; const char *cfg_ifp_iftype = NULL; int rv; cfg_ifp_iftype = ni_linktype_type_to_name(cfg_ifp->link.type); if (ni_string_empty(cfg_ifp->link.lowerdev.name)) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Incomplete arguments: need a lower device name"); return NULL; } else if (!ni_netdev_ref_bind_ifindex(&cfg_ifp->link.lowerdev, nc)) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Unable to find %s lower device %s by name", cfg_ifp_iftype, cfg_ifp->link.lowerdev.name); return NULL; } macvlan = ni_netdev_get_macvlan(cfg_ifp); if ((err = ni_macvlan_validate(macvlan))) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "%s", err); goto out; } if (ni_string_empty(ifname)) { if (ni_string_empty(cfg_ifp->name) && (ifname = ni_netdev_make_name( nc, cfg_ifp_iftype, 0))) { ni_string_dup(&cfg_ifp->name, ifname); } else { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Unable to create %s interface: " "name argument missed", cfg_ifp_iftype); goto out; } ifname = NULL; } else if(!ni_string_eq(cfg_ifp->name, ifname)) { ni_string_dup(&cfg_ifp->name, ifname); } if (ni_string_eq(cfg_ifp->name, cfg_ifp->link.lowerdev.name)) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Cannot create %s interface: " "macvlan name %s equal with lower device name", cfg_ifp_iftype, cfg_ifp->name); return NULL; } 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 %s interface: " "invalid ethernet address '%s'", cfg_ifp_iftype, ni_link_address_print(&cfg_ifp->link.hwaddr)); return NULL; } } if ((rv = ni_system_macvlan_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 %s interface: %s", cfg_ifp_iftype, ni_strerror(rv)); dev_ifp = NULL; goto out; } ni_debug_dbus("%s interface exists (and name matches)", cfg_ifp_iftype); } if (dev_ifp->link.type != cfg_ifp->link.type) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create %s interface: " "new interface is of type %s", cfg_ifp_iftype, 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 ni_netdev_t * __ni_objectmodel_gre_create(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error) { ni_netconfig_t *nc = ni_global_state_handle(0); ni_gre_t *gre = NULL; ni_netdev_t *dev = NULL; const char *err = NULL; int rv; gre = ni_netdev_get_gre(cfg_ifp); if ((err = ni_gre_validate(gre))) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "%s", err); goto out; } if (ni_string_empty(ifname)) { if (ni_string_empty(cfg_ifp->name) && (ifname = ni_netdev_make_name(nc, "gre", 1))) { ni_string_dup(&cfg_ifp->name, ifname); } else { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Unable to create gre tunnel: " "name argument missed"); goto out; } ifname = NULL; } else if(!ni_string_eq(cfg_ifp->name, ifname)) { ni_string_dup(&cfg_ifp->name, ifname); } if (!ni_string_empty(cfg_ifp->link.lowerdev.name) && !ni_objectmodel_bind_netdev_ref_index(cfg_ifp->name, "gre tunnel", &cfg_ifp->link.lowerdev, nc, error)) goto out; if (cfg_ifp->link.hwaddr.len) { if (cfg_ifp->link.hwaddr.type == ARPHRD_VOID) cfg_ifp->link.hwaddr.type = ARPHRD_IPGRE; if (cfg_ifp->link.hwaddr.type != ARPHRD_IPGRE || cfg_ifp->link.hwaddr.len != ni_link_address_length(ARPHRD_IPGRE)) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Cannot create gre tunnel interface: " "invalid local address '%s'", ni_link_address_print(&cfg_ifp->link.hwaddr)); return NULL; } } if (cfg_ifp->link.hwpeer.len) { if (cfg_ifp->link.hwpeer.type == ARPHRD_VOID) cfg_ifp->link.hwpeer.type = ARPHRD_IPGRE; if (cfg_ifp->link.hwpeer.type != ARPHRD_IPGRE || cfg_ifp->link.hwpeer.len != ni_link_address_length(ARPHRD_IPGRE)) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Cannot create gre tunnel interface: " "invalid remote address '%s'", ni_link_address_print(&cfg_ifp->link.hwpeer)); return NULL; } } if ((rv = ni_system_tunnel_create(nc, cfg_ifp, &dev, NI_IFTYPE_GRE) < 0)) { if (rv != -NI_ERROR_DEVICE_EXISTS || dev == NULL || (ifname && dev && !ni_string_eq(dev->name, ifname))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create gre tunnel: %s", cfg_ifp->name); dev = NULL; goto out; } ni_debug_dbus("gre tunnel exists (and name matches)"); } if (dev->link.type != NI_IFTYPE_GRE) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create gre tunnel: " "new interface is of type %s", ni_linktype_type_to_name(dev->link.type)); dev = NULL; } out: if (cfg_ifp) ni_netdev_put(cfg_ifp); return dev; }