/* * Generic lease properties */ static dbus_bool_t __ni_objectmodel_addrconf_generic_get_lease(const ni_dbus_object_t *object, ni_addrconf_mode_t mode, unsigned int addrfamily, ni_dbus_variant_t *dict, DBusError *error) { ni_netdev_t *dev; const ni_addrconf_lease_t *lease; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return FALSE; #if 0 NI_TRACE_ENTER_ARGS("dev=%s, af=%s, mode=%s", dev->name, ni_addrfamily_type_to_name(addrfamily), ni_addrconf_type_to_name(mode)); #endif if (!(lease = ni_netdev_get_lease(dev, addrfamily, mode))) return FALSE; ni_dbus_dict_add_uint32(dict, "state", lease->state); if (lease->flags) ni_dbus_dict_add_uint32(dict, "flags", lease->flags); if (!ni_uuid_is_null(&lease->uuid)) ni_dbus_dict_add_uuid(dict, "uuid", &lease->uuid); return TRUE; }
/* * 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_bool_t ni_objectmodel_pci_describe(const ni_objectmodel_ns_t *ns, const ni_dbus_object_t *object, xml_node_t *parent) { ni_netdev_t *dev; ni_pci_dev_t *pci_dev; xml_node_t *node; char *copy, *s; if (!(dev = ni_objectmodel_unwrap_netif(object, NULL))) return FALSE; if (!(pci_dev = dev->pci_dev)) return FALSE; /* Describe by path */ node = __describe(ns, parent); xml_node_new_element("path", node, pci_dev->path); /* Describe by vendor/device */ node = __describe(ns, parent); xml_node_set_uint_hex(xml_node_new("vendor", node), pci_dev->vendor); xml_node_set_uint_hex(xml_node_new("device", node), pci_dev->device); /* Describe by bridge */ copy = strdup(pci_dev->path); if ((s = strrchr(copy, '/')) != NULL) { *s = '\0'; node = __describe(ns, parent); xml_node_new_element("bridge", node, copy); } free(copy); return TRUE; }
static dbus_bool_t ni_objectmodel_addrconf_static_drop(ni_dbus_object_t *object, unsigned int addrfamily, ni_dbus_message_t *reply, DBusError *error) { ni_addrconf_lease_t *lease = NULL; ni_netdev_t *dev; int rv; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return FALSE; lease = ni_addrconf_lease_new(NI_ADDRCONF_STATIC, addrfamily); lease->state = NI_ADDRCONF_STATE_RELEASED; rv = __ni_system_interface_update_lease(dev, &lease); if (lease) ni_addrconf_lease_free(lease); if (rv < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Error dropping static %s addresses: %s", ni_addrfamily_type_to_name(addrfamily), ni_strerror(rv)); return FALSE; } /* Don't return anything */ return TRUE; }
/* * Identify a device by PCI attributes */ static ni_bool_t ni_objectmodel_pci_match_attr(const ni_dbus_object_t *object, const char *name, const char *value) { ni_netdev_t *dev; ni_pci_dev_t *pci_dev; if (!(dev = ni_objectmodel_unwrap_netif(object, NULL))) return FALSE; if (!(pci_dev = dev->pci_dev)) return FALSE; if (ni_string_eq(name, "path")) return ni_string_eq(pci_dev->path, value); /* Bridge means, we match if the query string is a prefix of the device's path */ if (ni_string_eq(name, "bridge")) { unsigned int len; if (!value) return FALSE; len = strlen(value); return strncmp(pci_dev->path, value, len) == 0 && pci_dev->path[len] == '/'; } if (ni_string_eq(name, "vendor")) return __match_uint(pci_dev->vendor, value); if (ni_string_eq(name, "device")) return __match_uint(pci_dev->device, value); ni_warn("%s: unsupported query attribute %s", __func__, name); return FALSE; }
/* * LLDP.lldpDown */ static dbus_bool_t ni_objectmodel_lldp_down(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; /* we've already checked that argv matches our signature */ ni_assert(argc == 0); if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return FALSE; if (!ni_system_lldp_available(dev)) { ni_error("Cannot disable LLDP for device %s: incompatible layer 2 protocol", dev->name); return TRUE; } if (ni_system_lldp_down(dev) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "failed to stop LLDP agent on device %s", dev->name); return FALSE; } return TRUE; }
/* * 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; }
/* * Helper function to obtain bridge config from dbus object */ static ni_bridge_t * __ni_objectmodel_bridge_handle(const ni_dbus_object_t *object, ni_bool_t write_access, DBusError *error) { ni_netdev_t *dev = ni_objectmodel_unwrap_netif(object, error); ni_bridge_t *bridge; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return NULL; if (!write_access) return dev->bridge; if (!(bridge = ni_netdev_get_bridge(dev))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Error getting bridge handle for interface"); return NULL; } return bridge; }
static dbus_bool_t __ni_objectmodel_team_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); }
/* * Generic functions for static address configuration */ static dbus_bool_t ni_objectmodel_addrconf_static_request(ni_dbus_object_t *object, unsigned int addrfamily, unsigned int argc, const ni_dbus_variant_t *argv, ni_dbus_message_t *reply, DBusError *error) { ni_addrconf_lease_t *lease = NULL; const ni_dbus_variant_t *dict; const char *string_value; ni_netdev_t *dev; ni_address_t *ap; int rv; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return FALSE; if (argc != 1 || !ni_dbus_variant_is_dict(&argv[0])) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "requestLease: expected one dict argument"); return FALSE; } dict = &argv[0]; lease = ni_addrconf_lease_new(NI_ADDRCONF_STATIC, addrfamily); lease->state = NI_ADDRCONF_STATE_GRANTED; ni_uuid_generate(&lease->uuid); if (!__ni_objectmodel_set_address_dict(&lease->addrs, dict, error) || !__ni_objectmodel_set_route_dict(&lease->routes, dict, error) || !__ni_objectmodel_set_resolver_dict(&lease->resolver, dict, error)) { ni_addrconf_lease_free(lease); return FALSE; } if (__ni_objectmodel_get_domain_string(dict, "hostname", &string_value)) ni_string_dup(&lease->hostname, string_value); /* mark all addresses tentative, causing to verify them */ for (ap = lease->addrs; ap; ap = ap->next) ni_address_set_tentative(ap, TRUE); rv = __ni_system_interface_update_lease(dev, &lease); if (lease) ni_addrconf_lease_free(lease); if (rv < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Error configuring static %s addresses: %s", ni_addrfamily_type_to_name(addrfamily), ni_strerror(rv)); return FALSE; } /* Don't return anything. */ return TRUE; }
static dbus_bool_t ni_objectmodel_addrconf_ipv4ll_drop(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; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return FALSE; return ni_objectmodel_addrconf_forward_release(&ipv4ll_forwarder, dev, NULL, reply, error); }
static dbus_bool_t __ni_objectmodel_macvlan_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); }
/* * Helper function to obtain tun config from dbus object */ static void * ni_objectmodel_get_tun(const ni_dbus_object_t *object, ni_bool_t write_access, DBusError *error) { ni_netdev_t *dev; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return NULL; if (!write_access) return dev->tun; return ni_netdev_get_tun(dev); }
static dbus_bool_t ni_objectmodel_gre_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; ni_gre_t *gre; const char *err; /* we've already checked that argv matches our signature */ ni_assert(argc == 1); if (!(dev = ni_objectmodel_unwrap_netif(object, error)) || !(cfg = __ni_objectmodel_gre_device_arg(&argv[0])) || !(ni_netdev_get_gre(dev))) { ni_dbus_error_invalid_args(error, object->path, method->name); return FALSE; } gre = ni_netdev_get_gre(cfg); if ((err = ni_gre_validate(gre))) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "%s", err); 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 gre changeDevice call on %s: " "device is up", dev->name); return TRUE; } if (!ni_string_empty(cfg->link.lowerdev.name) && !ni_objectmodel_bind_netdev_ref_index(cfg->name, "gre tunnel", &cfg->link.lowerdev, nc, error)) return FALSE; if (ni_system_tunnel_change(nc, dev, cfg) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to change gre properties on interface %s", dev->name); return FALSE; } return TRUE; }
/* * 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; }
/* * retrieve an ethtool handle from dbus netif object */ static ni_ethtool_t * ni_objectmodel_ethtool_handle(const ni_dbus_object_t *object, ni_bool_t write_access, DBusError *error) { ni_netdev_t *dev; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return NULL; if (!write_access) return dev->ethtool; return ni_netdev_get_ethtool(dev); }
/* * Helper function to obtain LLDP config from dbus object */ static ni_lldp_t * __ni_objectmodel_lldp_handle(const ni_dbus_object_t *object, ni_bool_t write_access, DBusError *error) { ni_netdev_t *dev; ni_lldp_t *lldp; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return NULL; if (!write_access) return dev->lldp; if (!(lldp = ni_netdev_get_lldp(dev))) dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to get LLDP handle for device %s", dev->name); return lldp; }
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_link_address_is_invalid(&cfg->link.hwaddr) && 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; }
/* * Helper function to obtain team config from dbus object */ static ni_team_t * __ni_objectmodel_team_handle(const ni_dbus_object_t *object, ni_bool_t write_access, DBusError *error) { ni_netdev_t *dev; ni_team_t *team; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return NULL; if (!write_access) return dev->team; if (!(team = ni_netdev_get_team(dev))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Error getting team handle for interface"); return NULL; } return team; }
static dbus_bool_t __ni_objectmodel_gre_set_remote_addr(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; if (__ni_objectmodel_set_hwaddr(argument, &dev->link.hwpeer)) { dev->link.hwpeer.type = ARPHRD_IPGRE; return TRUE; } else { return FALSE; } }
static ni_macvlan_t * ni_objectmodel_macvlan_handle(const ni_dbus_object_t *object, ni_bool_t write_access, DBusError *error) { ni_netdev_t *dev; ni_macvlan_t *macvlan; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return NULL; if (!write_access) return dev->macvlan; if (!(macvlan = ni_netdev_get_macvlan(dev))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Error getting macvlan handle for interface"); return NULL; } return macvlan; }
static dbus_bool_t ni_objectmodel_macvtap_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_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_macvlan_device_arg(&argv[0], NI_IFTYPE_MACVTAP)) || !(ni_netdev_get_macvlan(dev))) { ni_dbus_error_invalid_args(error, object->path, method->name); return FALSE; } return __ni_objectmodel_macvlan_change(cfg, dev, error); }
static dbus_bool_t ni_objectmodel_addrconf_ipv4ll_request(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; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return FALSE; if (argc != 1 || !ni_dbus_variant_is_dict(&argv[0])) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "%s.%s: expected one dict argument", NI_OBJECTMODEL_ADDRCONF_IPV4AUTO_INTERFACE, method->name); return FALSE; } return ni_objectmodel_addrconf_forward_request(&ipv4ll_forwarder, dev, &argv[0], reply, error); }
/* * OVSBridge.shutdown method */ static dbus_bool_t __ni_objectmodel_ovs_bridge_shutdown(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; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return FALSE; NI_TRACE_ENTER_ARGS("dev=%s", dev->name); if (ni_system_ovs_bridge_shutdown(dev) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Error shutting down ovs bridge interface %s", dev->name); return FALSE; } return TRUE; }
/* * 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; }
/* * PPP device properties */ static ni_ppp_config_t * __ni_objectmodel_ppp_handle(const ni_dbus_object_t *object, ni_bool_t write_access, DBusError *error) { ni_netdev_t *dev; ni_ppp_t *ppp; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return NULL; if (!write_access) { if (!dev->ppp) return NULL; return dev->ppp->config; } ppp = ni_netdev_get_ppp(dev); if (!ppp->config) ppp->config = ni_ppp_config_new(); return ppp->config; }
static ni_infiniband_t * __ni_objectmodel_infiniband_handle(const ni_dbus_object_t *object, ni_bool_t write_access, DBusError *error) { ni_netdev_t *dev; ni_infiniband_t *ib; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return NULL; if (!write_access) return dev->infiniband; if (!(ib = ni_netdev_get_infiniband(dev))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Error getting infiniband handle for interface"); return NULL; } return ib; }
/* * Currently only used to pull gre->tunnel data below, but kept around for later expansion. */ static ni_gre_t * ni_objectmodel_get_gre(const ni_dbus_object_t *object, ni_bool_t write_access, DBusError *error) { ni_netdev_t *dev; ni_gre_t *gre; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return NULL; if (!write_access) return dev->gre; if (!(gre = ni_netdev_get_gre(dev))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Error getting gre handle for interface"); return NULL; } return gre; }
/* * Helper function to obtain ppp config from dbus object */ static ni_ppp_t * ni_objectmodel_ppp_handle(const ni_dbus_object_t *object, ni_bool_t write_access, DBusError *error) { ni_netdev_t *dev; ni_ppp_t *ppp; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return NULL; if (!write_access) return dev->ppp; if (!(ppp = ni_netdev_get_ppp(dev))) { if (error) dbus_set_error(error, DBUS_ERROR_FAILED, "Error getting ppp handle for interface %s", dev->name); return NULL; } return ppp; }
/* * PPP.delete method */ static dbus_bool_t ni_objectmodel_ppp_device_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_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *dev; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return FALSE; NI_TRACE_ENTER_ARGS("dev=%s", dev->name); if (ni_system_ppp_delete(nc, dev) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Error deleting ppp interface %s", dev->name); return FALSE; } ni_client_state_drop(dev->link.ifindex); return TRUE; }