void ni_autoip_device_put(ni_autoip_device_t *dev) { ni_assert(dev->users); if (--(dev->users) == 0) ni_autoip_device_free(dev); }
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); }
/* * Free an XML node */ void xml_node_free(xml_node_t *node) { xml_node_t *child; if (!node) return; ni_assert(node->refcount); if (--(node->refcount) != 0) return; while ((child = node->children) != NULL) { node->children = child->next; xml_node_free(child); } if (node->location) xml_location_free(node->location); ni_var_array_destroy(&node->attrs); free(node->cdata); free(node->name); free(node); }
/* * 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; }
dbus_bool_t ni_objectmodel_macvtap_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_macvlan_device_arg(&argv[1], NI_IFTYPE_MACVTAP))) { return ni_dbus_error_invalid_args(error, factory_object->path, method->name); } if (!(dev = __ni_objectmodel_macvlan_newlink(dev, ifname, error))) return FALSE; return ni_objectmodel_netif_factory_result(server, reply, dev, NULL, error); }
/* * 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; }
/* * "Clone" an XML node by incrementing its refcount */ xml_node_t * xml_node_clone_ref(xml_node_t *src) { ni_assert(src->refcount); src->refcount++; return src; }
ni_autoip_device_t * ni_autoip_device_get(ni_autoip_device_t *dev) { ni_assert(dev->users); dev->users++; return dev; }
/* * Refcount handling */ ni_dhcp4_device_t * ni_dhcp4_device_get(ni_dhcp4_device_t *dev) { ni_assert(dev->users); dev->users++; return dev; }
void ni_dhcp4_device_free(ni_dhcp4_device_t *dev) { ni_dhcp4_device_t **pos; ni_assert(dev->users == 0); ni_debug_dhcp("%s: Deleting dhcp4 device with index %u", dev->ifname, dev->link.ifindex); ni_dhcp4_device_drop_buffer(dev); ni_dhcp4_device_drop_lease(dev); ni_dhcp4_device_drop_best_offer(dev); ni_dhcp4_device_close(dev); ni_string_free(&dev->system.ifname); ni_string_free(&dev->ifname); /* Drop existing config and request */ ni_dhcp4_device_set_config(dev, NULL); ni_dhcp4_device_set_request(dev, NULL); for (pos = &ni_dhcp4_active; *pos; pos = &(*pos)->next) { if (*pos == dev) { *pos = dev->next; break; } } free(dev); }
/* * 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); }
/* * Traverse an xml tree, depth first. */ xml_node_t * xml_node_get_next(xml_node_t *top, xml_node_t *cur) { if (cur == NULL) { /* Start at the top node and descend */ cur = top; } else { /* We've already visited this node. Get the * next one. * By default, move right, then down. If there's * no right sibling, move up and repeat. */ /* No next sibling: move up, then right */ if (cur->next == NULL) { if (cur == top || cur->parent == top) return NULL; cur = cur->parent; ni_assert(cur); return cur; } cur = cur->next; } /* depth first */ while (cur->children) cur = cur->children; return cur; }
/* * 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; }
ni_json_t * ni_json_ref(ni_json_t *json) { if (json && json->refcount != -1U) { ni_assert(json->refcount); json->refcount++; } return json; }
static inline void xml_location_shared_release(struct xml_location_shared *sl) { ni_assert(sl->refcount); if (--(sl->refcount) == 0) { free(sl->filename); free(sl); } }
ni_json_pair_t * ni_json_pair_ref(ni_json_pair_t *pair) { if (pair) { ni_assert(pair->refcount); pair->refcount++; } return pair; }
void ni_stringbuf_move(ni_stringbuf_t *dest, ni_stringbuf_t *src) { ni_assert(dest->dynamic == src->dynamic); ni_stringbuf_clear(dest); *dest = *src; src->string = NULL; src->len = 0; }
void xml_node_add_child(xml_node_t *parent, xml_node_t *child) { xml_node_t **tail; ni_assert(child->parent == NULL); tail = __xml_node_list_tail(&parent->children); __xml_node_list_insert(tail, child, parent); }
void ni_shellcmd_free(ni_shellcmd_t *cmd) { if (cmd) { ni_assert(cmd->refcount); cmd->refcount--; if (cmd->refcount == 0) __ni_shellcmd_free(cmd); } }
ni_shellcmd_t * ni_shellcmd_hold(ni_shellcmd_t *cmd) { if (cmd) { ni_assert(cmd->refcount); cmd->refcount++; return cmd; } return NULL; }
/* * Utility functions for starting/stopping the wicked daemon, * and for connecting to it */ int ni_server_background(const char *appname, ni_daemon_close_t close_flags) { const char *piddir = ni_config_piddir(); char pidfilepath[PATH_MAX]; ni_assert(appname != NULL); snprintf(pidfilepath, sizeof(pidfilepath), "%s/%s.pid", piddir, appname); return ni_daemonize(pidfilepath, 0644, close_flags); }
void ni_json_free(ni_json_t *json) { if (!json || json->refcount == -1U) return; ni_assert(json->refcount && json->type); json->refcount--; if (json->refcount != 0) return; switch (json->type) { case NI_JSON_TYPE_BOOL: case NI_JSON_TYPE_INT64: case NI_JSON_TYPE_DOUBLE: json->type = NI_JSON_TYPE_NONE; free(json); break; case NI_JSON_TYPE_STRING: ni_string_free(&json->string_value); json->type = NI_JSON_TYPE_NONE; free(json); break; case NI_JSON_TYPE_OBJECT: ni_json_object_free(json->object_value); json->type = NI_JSON_TYPE_NONE; free(json); break; case NI_JSON_TYPE_ARRAY: ni_json_array_free(json->array_value); json->type = NI_JSON_TYPE_NONE; free(json); break; default: ni_assert(json->type > NI_JSON_TYPE_NULL && json->type <= NI_JSON_TYPE_ARRAY); break; } }
/* * Run all the netif firmware discovery scripts and return their output * as one large buffer. */ static ni_buffer_t * __ni_netconfig_firmware_discovery(const char *root, const char *type, const char *path) { ni_buffer_t *result; ni_config_t *config = ni_global.config; ni_extension_t *ex; ni_assert(config); result = ni_buffer_new_dynamic(1024); for (ex = config->fw_extensions; ex; ex = ex->next) { ni_script_action_t *script; if (ex->c_bindings) ni_warn("builtins specified in a netif-firmware-discovery element: not supported"); for (script = ex->actions; script; script = script->next) { ni_process_t *process; int rv; /* Check if requested to use specific type/name only (e.g. "ibft") */ if (type && !ni_string_eq_nocase(type, script->name)) continue; ni_debug_ifconfig("trying to discover netif config via firmware service \"%s\"", script->name); /* Create an instance of this command */ process = ni_process_new(script->process); /* Add root directory argument if given */ if (root) { ni_string_array_append(&process->argv, "-r"); ni_string_array_append(&process->argv, root); } /* Add firmware type specific path argument if given */ if (type && path) { ni_string_array_append(&process->argv, "-p"); ni_string_array_append(&process->argv, path); } rv = ni_process_run_and_capture_output(process, result); ni_process_free(process); if (rv) { ni_error("unable to discover firmware (script \"%s\")", script->name); ni_buffer_free(result); return NULL; } } } return result; }
static ni_updater_source_t * ni_updater_source_ref(ni_updater_source_t *src) { if (src) { ni_assert(src->users); src->users++; return src; } return NULL; }
/* * Wireless interface config */ ni_wireless_t * ni_wireless_new(ni_netdev_t *dev) { ni_wireless_t *wlan; ni_assert(dev->wireless == NULL); wlan = xcalloc(1, sizeof(ni_wireless_t)); wlan->conf.ap_scan = NI_WIRELESS_AP_SCAN_SUPPLICANT_AUTO; return wlan; }
void ni_client_timer_expires(void *user_data, const ni_timer_t *timer) { int *status; ni_assert(user_data); status = user_data; (void) timer; *status = NI_WICKED_RC_ERROR; ni_error("Operation timeout..."); }
void ni_netconfig_modem_append(ni_netconfig_t *nc, ni_modem_t *modem) { ni_modem_t **tail; ni_assert(!modem->list.prev && !modem->list.next); tail = &nc->modems; while (*tail) tail = &(*tail)->list.next; modem->list.prev = tail; *tail = modem; }
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; }
/* * Obtain an object handle for Wicked.Modem */ ni_dbus_object_t * ni_call_get_modem_list_object(void) { static const ni_dbus_service_t *modem_list_service; ni_dbus_object_t *list_object; if (modem_list_service == NULL) { modem_list_service = ni_objectmodel_service_by_name(NI_OBJECTMODEL_MODEM_LIST_INTERFACE); ni_assert(modem_list_service); } list_object = __ni_call_get_proxy_object(modem_list_service, "Modem"); return list_object; }
static void ni_updater_source_free(ni_updater_source_t *src) { if (src) { ni_assert(src->users); src->users--; if (src->users == 0) { src->seqno = 0; src->lease = NULL; ni_netdev_ref_destroy(&src->d_ref); free(src); } } }