void ni_config_parse_fslocation(ni_config_fslocation_t *fsloc, xml_node_t *node) { const char *attrval; if ((attrval = xml_node_get_attr(node, "path")) != NULL) ni_string_dup(&fsloc->path, attrval); if ((attrval = xml_node_get_attr(node, "mode")) != NULL) ni_parse_uint(attrval, &fsloc->mode, 8); }
ni_bool_t ni_config_parse_addrconf_dhcp4(struct ni_config_dhcp4 *dhcp4, xml_node_t *node) { xml_node_t *child; for (child = node->children; child; child = child->next) { const char *attrval; if (!strcmp(child->name, "vendor-class")) ni_string_dup(&dhcp4->vendor_class, child->cdata); if (!strcmp(child->name, "lease-time") && child->cdata) dhcp4->lease_time = strtoul(child->cdata, NULL, 0); if (!strcmp(child->name, "ignore-server") && (attrval = xml_node_get_attr(child, "ip")) != NULL) ni_string_array_append(&dhcp4->ignore_servers, attrval); if (!strcmp(child->name, "prefer-server") && (attrval = xml_node_get_attr(child, "ip")) != NULL) { ni_server_preference_t *pref; if (dhcp4->num_preferred_servers >= NI_DHCP_SERVER_PREFERENCES_MAX) { ni_warn("config: too many <prefer-server> elements"); continue; } pref = &dhcp4->preferred_server[dhcp4->num_preferred_servers++]; if (ni_sockaddr_parse(&pref->address, attrval, AF_INET) < 0) { ni_error("config: unable to parse <prefer-server ip=\"%s\"", attrval); return FALSE; } pref->weight = 100; if ((attrval = xml_node_get_attr(child, "weight")) != NULL) { if (!strcmp(attrval, "always")) { pref->weight = 100; } else if (!strcmp(attrval, "never")) { pref->weight = -1; } else { pref->weight = strtol(attrval, NULL, 0); if (pref->weight > 100) { pref->weight = 100; ni_warn("preferred dhcp server weight exceeds max, " "clamping to %d", pref->weight); } } } } if (!strcmp(child->name, "allow-update")) ni_config_parse_update_targets(&dhcp4->allow_update, child); } return TRUE; }
ni_bool_t ni_iaid_map_to_vars(const ni_iaid_map_t *map, ni_var_array_t *vars) { xml_node_t *root, *node = NULL; const char *name; if (!vars) return FALSE; if (!(root = ni_iaid_map_root_node(map))) return FALSE; ni_var_array_destroy(vars); while ((node = ni_iaid_map_next_node(root, node))) { if (ni_string_empty(node->cdata)) continue; name = xml_node_get_attr(node, NI_CONFIG_DEFAULT_IAID_DEVICE); if (ni_string_empty(name)) continue; ni_var_array_set(vars, name, node->cdata); } return TRUE; }
ni_bool_t ni_iaid_map_set(ni_iaid_map_t *map, const char *name, unsigned int iaid) { xml_node_t *root, *node = NULL; const char *attr; if (!(root = ni_iaid_map_root_node(map)) || ni_string_empty(name)) return FALSE; while ((node = ni_iaid_map_next_node(root, node))) { attr = xml_node_get_attr(node, NI_CONFIG_DEFAULT_IAID_DEVICE); if (!ni_string_eq(name, attr)) continue; xml_node_set_uint(node, iaid); return TRUE; } if ((node = xml_node_new(NI_CONFIG_DEFAULT_IAID_NODE, root))) { xml_node_add_attr(node, NI_CONFIG_DEFAULT_IAID_DEVICE, name); xml_node_set_uint(node, iaid); return TRUE; } return FALSE; }
static ni_bool_t ni_objectmodel_recover_state_xml(xml_node_t *list, const char **prefix_list) { ni_dbus_object_t *root_object; xml_node_t *object_node; root_object = ni_dbus_server_get_root_object(__ni_objectmodel_server); for (object_node = list->children; object_node; object_node = object_node->next) { ni_dbus_object_t *object; const char *name; if (!ni_string_eq(object_node->name, "object")) { ni_error("%s: not an <object> element", xml_node_location(object_node)); return FALSE; } if (!(name = xml_node_get_attr(object_node, "path"))) { ni_error("%s: <object> lacks path attribute", xml_node_location(object_node)); return FALSE; } if (!(name = ni_dbus_object_get_relative_path(root_object, name))) { ni_error("%s: <object> has invalid path attribute", xml_node_location(object_node)); return FALSE; } if (!(object = ni_dbus_object_lookup(root_object, name))) continue; if (!ni_objectmodel_recover_object_state_xml(object_node, object, prefix_list)) return FALSE; } return TRUE; }
static ni_bool_t ni_iaid_map_node_to_name(const xml_node_t *node, const char **name) { if (!node || !name) return FALSE; *name = xml_node_get_attr(node, NI_CONFIG_DEFAULT_IAID_DEVICE); return !ni_string_empty(*name); }
static void xml_process_pi_node(xml_reader_t *xr, xml_node_t *pi) { const char *attrval; if (!strcmp(pi->name, "xml")) { if ((attrval = xml_node_get_attr(pi, "version")) != NULL && strcmp(attrval, "1.0")) ni_warn("unexpected XML version %s", attrval); if ((attrval = xml_node_get_attr(pi, "encoding")) != NULL && strcasecmp(attrval, "utf8")) { /* TBD: set up iconv to translate from encoding to utf8, and make sure we process all input that way. */ } } }
/* * Another class of extensions helps with updating system files such as resolv.conf * This expects scripts for install, backup and restore (named accordingly). * * <system-updater name="resolver"> * <script name="install" command="/some/crazy/path/to/script install" /> * <script name="backup" command="/some/crazy/path/to/script backup" /> * <script name="restore" command="/some/crazy/path/to/script restore" /> * ... * </system-updater> */ ni_bool_t ni_config_parse_system_updater(ni_extension_t **list, xml_node_t *node) { ni_extension_t *ex; const char *name; if (!(name = xml_node_get_attr(node, "name"))) { ni_error("%s: <%s> element lacks name attribute", node->name, xml_node_location(node)); return FALSE; } ex = ni_extension_new(list, name); /* If the updater has a format type, extract. */ ni_string_dup(&ex->format, xml_node_get_attr(node, "format")); return ni_config_parse_extension(ex, node); }
ni_bool_t xml_node_get_attr_ulong(const xml_node_t *node, const char *name, unsigned long *valp) { const char *value; if (!valp || !(value = xml_node_get_attr(node, name))) return FALSE; if (ni_parse_ulong(value, valp, 10) < 0) return FALSE; return TRUE; }
ni_bool_t xml_node_get_attr_double(const xml_node_t *node, const char *name, double *valp) { const char *value; if (!valp || !(value = xml_node_get_attr(node, name))) return FALSE; if (ni_parse_double(value, valp) < 0) return FALSE; return TRUE; }
static ni_bool_t ni_config_parse_extension(ni_extension_t *ex, xml_node_t *node) { xml_node_t *child; for (child = node->children; child; child = child->next) { if (!strcmp(child->name, "action") || !strcmp(child->name, "script")) { const char *name, *command; if (!(name = xml_node_get_attr(child, "name"))) { ni_error("action element without name attribute"); return FALSE; } if (!(command = xml_node_get_attr(child, "command"))) { ni_error("action element without command attribute"); return FALSE; } if (!ni_extension_script_new(ex, name, command)) return FALSE; } else if (!strcmp(child->name, "builtin")) { const char *name, *library, *symbol; if (!(name = xml_node_get_attr(child, "name"))) { ni_error("builtin element without name attribute"); return FALSE; } if (!(symbol = xml_node_get_attr(child, "symbol"))) { ni_error("action element without command attribute"); return FALSE; } library = xml_node_get_attr(child, "library"); ni_c_binding_new(&ex->c_bindings, name, library, symbol); } else if (!strcmp(child->name, "putenv")) { const char *name, *value; if (!(name = xml_node_get_attr(child, "name"))) { ni_error("%s: <putenv> element without name attribute", xml_node_location(child)); return FALSE; } value = xml_node_get_attr(child, "value"); ni_var_array_set(&ex->environment, name, value); } } return TRUE; }
/* * Object model extensions let you implement parts of a dbus interface separately * from the main wicked body of code; either through a shared library or an * external command/shell script * * <extension interface="org.opensuse.Network.foobar"> * <action name="dbusMethodName" command="/some/shell/scripts some-args"/> * <builtin name="dbusOtherMethodName" library="/usr/lib/libfoo.so" symbol="c_method_impl_name"/> * * <putenv name="WICKED_OBJECT_PATH" value="$object-path"/> * <putenv name="WICKED_INTERFACE_NAME" value="$property:name"/> * <putenv name="WICKED_INTERFACE_INDEX" value="$property:index"/> * </extension> */ ni_bool_t ni_config_parse_objectmodel_extension(ni_extension_t **list, xml_node_t *node) { ni_extension_t *ex; const char *name; if (!(name = xml_node_get_attr(node, "interface"))) { ni_error("%s: <%s> element lacks interface attribute", node->name, xml_node_location(node)); return FALSE; } ex = ni_extension_new(list, name); return ni_config_parse_extension(ex, node); }
/* * @attribute */ static xpath_result_t * __xpath_enode_getattr_evaluate(const xpath_enode_t *op, xpath_result_t *in) { xpath_result_t *result = xpath_result_new(XPATH_STRING); const char *attr_name = op->identifier; unsigned int n; for (n = 0; n < in->count; ++n) { xml_node_t *xn = in->node[n].value.node; const char *attrval; if ((attrval = xml_node_get_attr(xn, attr_name)) != NULL) { xtrace(" found node <%s %s=\"%s\">", xn->name, attr_name, attrval? : ""); xpath_result_append_string(result, attrval); } }
static void extract_net(xmlNodePtr entry, GList ** mail_addrs) { while (entry) { gchar *uri_type = NULL; gchar *mail_addr; if (!xmlStrcmp(entry->name, CXMLCHARP("Uri")) && g_strcmp0(uri_type = xml_node_get_attr(entry, CXMLCHARP("type")), "email") == 0 && (mail_addr = xml_node_get_text(entry)) != NULL) *mail_addrs = g_list_prepend(*mail_addrs, mail_addr); g_free(uri_type); entry = entry->next; } }
/* * XML node matching functions */ ni_bool_t xml_node_match_attrs(const xml_node_t *node, const ni_var_array_t *attrlist) { unsigned int i; ni_var_t *attr; for (i = 0, attr = attrlist->data; i < attrlist->count; ++i, ++attr) { const char *value; value = xml_node_get_attr(node, attr->name); if (attr->value == NULL || value == NULL) { if (attr->value != value) return FALSE; } else if (strcmp(attr->value, value)) { return FALSE; } } return TRUE; }
/* * This specifies sources of client configuration. * * The ifconfig source specifies the type, location and the * priority / load order of the interface configurations. * * <sources> * <ifconfig location="firmware:" /> * <ifconfig location="compat:" /> * <ifconfig location="wicked:/etc/wicked/ifconfig" /> * </sources> * */ static ni_bool_t __ni_config_parse_ifconfig_source(ni_string_array_t *sources, xml_node_t *node) { const char *attrval = NULL; unsigned int i; if ((attrval = xml_node_get_attr(node, "location")) != NULL && *attrval) { const char **p = __ni_ifconfig_source_types; for (i = 0; p[i]; i++) { if (!strncasecmp(attrval, p[i], ni_string_len(p[i]))) { ni_debug_readwrite("%s: Adding ifconfig %s", __func__, attrval); ni_string_array_append(sources, attrval); return TRUE; } } } ni_error("Unknown ifconfig location: %s", attrval); return FALSE; }
ni_bool_t ni_iaid_map_get_iaid(const ni_iaid_map_t *map, const char *name, unsigned int *iaid) { xml_node_t *root, *node = NULL; const char *attr; if (!iaid || ni_string_empty(name)) return FALSE; if (!(root = ni_iaid_map_root_node(map))) return FALSE; while ((node = ni_iaid_map_next_node(root, node))) { attr = xml_node_get_attr(node, NI_CONFIG_DEFAULT_IAID_DEVICE); if (!ni_string_eq(name, attr)) continue; return ni_iaid_map_node_to_iaid(node, iaid); } return FALSE; }
/* XML stuff to extract the data we need from the Rubrica file */ static GSList * extract_cards(xmlNodePtr card) { GSList *addrlist = NULL; while (card) { if (!xmlStrcmp(card->name, CXMLCHARP("Card"))) { LibBalsaAddress *address = libbalsa_address_new(); xmlNodePtr children; address->full_name = xml_node_get_attr(card, CXMLCHARP("name")); children = card->children; while (children) { if (!xmlStrcmp(children->name, CXMLCHARP("Data"))) extract_data(children->children, &address->first_name, &address->last_name, &address->nick_name); else if (!xmlStrcmp(children->name, CXMLCHARP("Work"))) extract_work(children->children, &address->organization); else if (!xmlStrcmp(children->name, CXMLCHARP("Net"))) extract_net(children->children, &address->address_list); children = children->next; } if (address->address_list) addrlist = g_slist_prepend(addrlist, address); else g_object_unref(address); } card = card->next; } return addrlist; }
ni_bool_t ni_iaid_map_del_name(ni_iaid_map_t *map, const char *name) { xml_node_t *root, *node = NULL; const char *attr; if (ni_string_empty(name)) return FALSE; if (!(root = ni_iaid_map_root_node(map))) return FALSE; while ((node = ni_iaid_map_next_node(root, node))) { attr = xml_node_get_attr(node, NI_CONFIG_DEFAULT_IAID_DEVICE); if (!ni_string_eq(name, attr)) continue; xml_node_detach(node); xml_node_free(node); return TRUE; } return FALSE; }
static int __ni_config_parse_dhcp6_class_data(xml_node_t *node, ni_string_array_t *data, const char *parent) { const char *attrval; enum { FORMAT_STR, /* normal string */ FORMAT_HEX, /* XX:XX format */ }; int format = FORMAT_STR; size_t len; if (strcmp(node->name, "class-data")) { ni_error("config: <%s> is not a valid <%s> class-data node", node->name, parent); return -1; } len = ni_string_len(node->cdata); if (len == 0) { ni_warn("config: empty %s <class-data> node", parent); return 0; } if ((attrval = xml_node_get_attr(node, "format")) != NULL) { if (!strcmp(attrval, "hex") || !strcmp(attrval, "mac")) { format = FORMAT_HEX; } else if (!strcmp(attrval, "str") || !strcmp(attrval, "string")) { format = FORMAT_STR; } else { ni_error("config: unknown %s <class-data format=\"%s\"", parent, attrval); return -1; } } if(format == FORMAT_HEX) { unsigned char *buf; /* verify the format early ... */ len = (len / 3) + 1; buf = xcalloc(1, len); if (ni_parse_hex(node->cdata, buf, len) <= 0) { ni_error("config: unable to parse %s hex class-data", parent); free(buf); return -1; } free(buf); ni_string_array_append(data, node->cdata); } else { ni_stringbuf_t buf = NI_STRINGBUF_INIT_DYNAMIC; /* convert to hex-string format */ ni_stringbuf_grow(&buf, (len * 3)); ni_format_hex((unsigned char *)node->cdata, len, buf.string, buf.size); ni_string_array_append(data, buf.string); ni_stringbuf_destroy(&buf); } return 0; }
static int __ni_config_parse_dhcp6_vendor_opt_node(xml_node_t *node, ni_var_array_t *opts, const char *parent) { const char *attrval; const char *code = NULL; enum { FORMAT_STR, /* normal string */ FORMAT_HEX, /* XX:XX format */ }; int format = FORMAT_STR; size_t len; if (strcmp(node->name, "option")) { ni_error("config: <%s> is not a valid <%s> option node", node->name, parent); return -1; } if ((attrval = xml_node_get_attr(node, "code")) != NULL) { char * err; long num; num = strtol(attrval, &err, 0); if (*err != '\0' || num < 0 || num > 0xffff) { ni_error("config: unable to parse %s <option code=\"%s\"", parent, attrval); return -1; } code = attrval; } else { ni_error("config: missed %s <option> without code attribute", parent); return -1; } if ((attrval = xml_node_get_attr(node, "format")) != NULL) { if (!strcmp(attrval, "hex") || !strcmp(attrval, "mac")) { format = FORMAT_HEX; } else if (!strcmp(attrval, "str") || !strcmp(attrval, "string")) { format = FORMAT_STR; } else { ni_error("config: unknown %s <option format=\"%s\"", parent, attrval); return -1; } } len = ni_string_len(node->cdata); if(format == FORMAT_HEX) { unsigned char *buf; /* verify the format early ... */ if (len > 0) { len = (len / 3) + 1; buf = xcalloc(1, len); if (ni_parse_hex(node->cdata, buf, len) <= 0) { ni_error("config: unable to parse %s hex option data", parent); free(buf); return -1; } free(buf); } ni_var_array_set(opts, code, node->cdata); } else { ni_stringbuf_t buf = NI_STRINGBUF_INIT_DYNAMIC; /* convert to hex-string format */ if (len > 0) { ni_stringbuf_grow(&buf, (len * 3)); ni_format_hex((unsigned char *)node->cdata, len, buf.string, buf.size); } ni_var_array_set(opts, code, buf.string); ni_stringbuf_destroy(&buf); } return 0; }
ni_bool_t ni_config_parse_addrconf_dhcp6(struct ni_config_dhcp6 *dhcp6, xml_node_t *node) { xml_node_t *child; for (child = node->children; child; child = child->next) { const char *attrval; if (!strcmp(child->name, "default-duid") && !ni_string_empty(child->cdata)) { ni_string_dup(&dhcp6->default_duid, child->cdata); } else if (!strcmp(child->name, "user-class")) { ni_string_array_destroy(&dhcp6->user_class_data); if (__ni_config_parse_dhcp6_class_data_nodes(child, &dhcp6->user_class_data) < 0) { ni_string_array_destroy(&dhcp6->user_class_data); return FALSE; } if (dhcp6->user_class_data.count == 0) { ni_warn("config: discarding <user-class> without any <class-data>"); } } else if (!strcmp(child->name, "vendor-class") && (attrval = xml_node_get_attr(child, "enterprise-number")) != NULL) { char * err; long num; num = strtol(attrval, &err, 0); if (*err != '\0' || num < 0 || num >= 0xffffffff) { ni_error("config: unable to parse <vendor-class enterprise-number=\"%s\"", attrval); return FALSE; } ni_string_array_destroy(&dhcp6->vendor_class_data); if (__ni_config_parse_dhcp6_class_data_nodes(child, &dhcp6->vendor_class_data) < 0) { ni_string_array_destroy(&dhcp6->vendor_class_data); return FALSE; } if (dhcp6->vendor_class_data.count == 0) { ni_warn("config: discarding <vendor-class> without any <class-data>"); } else { dhcp6->vendor_class_en = num; } } else if (!strcmp(child->name, "vendor-opts") && (attrval = xml_node_get_attr(child, "enterprise-number")) != NULL) { char * err; long num; num = strtol(attrval, &err, 0); if (*err != '\0' || num < 0 || num >= 0xffffffff) { ni_error("config: unable to parse <vendor-class enterprise-number=\"%s\"", attrval); return FALSE; } ni_var_array_destroy(&dhcp6->vendor_opts_data); if (__ni_config_parse_dhcp6_vendor_opts_nodes(child, &dhcp6->vendor_opts_data) < 0) { ni_var_array_destroy(&dhcp6->vendor_opts_data); } if (dhcp6->vendor_opts_data.count == 0) { ni_warn("config: discarding <vendor-opts> without any <option>"); } else { dhcp6->vendor_opts_en = num; } } else if (!strcmp(child->name, "lease-time") && child->cdata) { dhcp6->lease_time = strtoul(child->cdata, NULL, 0); } else if (!strcmp(child->name, "ignore-server") && (attrval = xml_node_get_attr(child, "ip")) != NULL) { ni_string_array_append(&dhcp6->ignore_servers, attrval); } else if (!strcmp(child->name, "prefer-server")) { ni_server_preference_t *pref; const char *id, *ip; ip = xml_node_get_attr(child, "ip"); id = xml_node_get_attr(child, "id"); if (ip == NULL && id == NULL) continue; if (dhcp6->num_preferred_servers >= NI_DHCP_SERVER_PREFERENCES_MAX) { ni_warn("config: too many <prefer-server> elements"); continue; } pref = &dhcp6->preferred_server[dhcp6->num_preferred_servers++]; if (ip && ni_sockaddr_parse(&pref->address, ip, AF_INET6) < 0) { ni_error("config: unable to parse <prefer-server ip=\"%s\"", ip); return FALSE; } if (id) { int len; /* DUID is "opaque", but has 2 bytes type + up to 128 bytes */ if ((len = sizeof(pref->serverid.data)) > 130) len = 130; /* DUID-LL has 2+2 fixed bytes + variable length hwaddress * and seems to be the shortest one I'm aware of ... */ if ((len = ni_parse_hex(id, pref->serverid.data, len)) <= 4) { ni_error("config: unable to parse <prefer-server id=\"%s\"", id); return FALSE; } pref->serverid.len = (size_t)len; } pref->weight = 255; if ((attrval = xml_node_get_attr(child, "weight")) != NULL) { if (!strcmp(attrval, "always")) { pref->weight = 255; } else if (!strcmp(attrval, "never")) { pref->weight = -1; } else { pref->weight = strtol(attrval, NULL, 0); if (pref->weight > 255) { pref->weight = 255; ni_warn("preferred dhcp server weight exceeds max, " "clamping to %d", pref->weight); } } } } else if (!strcmp(child->name, "allow-update")) { ni_config_parse_update_targets(&dhcp6->allow_update, child); } } return TRUE; }
static ni_bool_t ni_dhcp4_tester_req_xml_init(ni_dhcp4_request_t *req, xml_document_t *doc) { xml_node_t *xml, *child; const char *type; xml = xml_document_root(doc); if (xml && !xml->name && xml->children) xml = xml->children; if (!xml || !ni_string_eq(xml->name, "request")) { ni_error("Invalid dhcp4 request xml '%s'", xml ? xml_node_location(xml) : NULL); return FALSE; } type = xml_node_get_attr(xml, "type"); if (ni_string_eq(type, "offer")) { req->dry_run = NI_DHCP4_RUN_OFFER; } else if (ni_string_eq(type, "lease")) { req->dry_run = NI_DHCP4_RUN_LEASE; } for (child = xml->children; child; child = child->next) { if (ni_string_eq(child->name, "uuid")) { if (ni_uuid_parse(&req->uuid, child->cdata) != 0) goto failure; } else if (ni_string_eq(child->name, "acquire-timeout")) { if (ni_parse_uint(child->cdata, &req->acquire_timeout, 10) != 0) goto failure; } else if (ni_string_eq(child->name, "hostname")) { if (!ni_check_domain_name(child->cdata, ni_string_len(child->cdata), 0)) goto failure; ni_string_dup(&req->hostname, child->cdata); } else if (ni_string_eq(child->name, "fqdn")) { const xml_node_t *ptr; for (ptr = child->children; ptr; ptr = ptr->next) { if (ni_string_eq(ptr->name, "enabled")) { ni_bool_t b; if (ni_parse_boolean(ptr->cdata, &b) == 0) ni_tristate_set(&req->fqdn.enabled, b); else if (ni_string_eq(ptr->cdata, "default")) req->fqdn.enabled = NI_TRISTATE_DEFAULT; else goto failure; } else if (ni_string_eq(ptr->name, "update")) { if (!ni_dhcp_fqdn_update_name_to_mode(ptr->cdata, &req->fqdn.update)) goto failure; } else if (ni_string_eq(ptr->name, "encode")) { if (ni_parse_boolean(ptr->cdata, &req->fqdn.encode) != 0) goto failure; } else if (ni_string_eq(ptr->name, "qualify")) { if (ni_parse_boolean(ptr->cdata, &req->fqdn.qualify) != 0) goto failure; } } } else if (ni_string_eq(child->name, "clientid")) { ni_opaque_t duid; if (ni_parse_hex(child->cdata, duid.data, sizeof(duid.data)) <= 0) goto failure; ni_string_dup(&req->clientid, child->cdata); } else if(ni_string_eq(child->name, "start-delay")) { if (ni_parse_uint(child->cdata, &req->start_delay, 10) != 0) goto failure; } else if (ni_string_eq(child->name, "lease-time")) { if (ni_parse_uint(child->cdata, &req->lease_time, 10) != 0) goto failure; } else if (ni_string_eq(child->name, "recover-lease")) { if (ni_parse_boolean(child->cdata, &req->recover_lease) != 0) goto failure; } else if (ni_string_eq(child->name, "release-lease")) { if (ni_parse_boolean(child->cdata, &req->release_lease) != 0) goto failure; } else if (ni_string_eq(child->name, "request-options")) { xml_node_t *opt; for (opt = child->children; opt; opt = opt->next) { if (ni_string_empty(opt->cdata)) continue; ni_string_array_append(&req->request_options, opt->cdata); } } } return TRUE; failure: if (child) { ni_error("Cannot parse dhcp4 request '%s': %s", child->name, xml_node_location(child)); } return FALSE; }
static ni_bool_t ni_ifup_hire_nanny(ni_ifworker_t *w) { xml_node_t *ifcfg = NULL, *policy = NULL; ni_netdev_t *dev; unsigned int i; ni_bool_t rv = FALSE; char *pname; if (!w) return rv; ni_debug_application("%s: hiring nanny", w->name); /* Create a config duplicate for a policy */ ifcfg = xml_node_clone(w->config.node, NULL); if (!ifcfg) goto error; pname = ni_ifpolicy_name_from_ifname(w->name); ni_debug_application("%s: converting config into policy '%s'", w->name, pname); policy = ni_convert_cfg_into_policy_node(ifcfg, __ni_ifup_generate_match(w), pname, w->config.origin); ni_string_free(&pname); if (!policy) { policy = ifcfg; /* Free cloned config*/ goto error; } #if 0 /* Do we need this? */ /* Add link type to match node*/ if (dev) { ni_debug_application("%s: adding link type (%s) to match", w->name, ni_linktype_type_to_name(dev->link.type)); ni_ifpolicy_match_add_link_type(policy, dev->link.type); } ni_debug_application("%s: adding minimum device state (%s) to match", w->name, ni_ifworker_state_name(w->fsm.state)); /* Add minimum device state to match node */ if (!ni_ifpolicy_match_add_min_state(policy, w->fsm.state)) goto error; #endif dev = w->device; if (dev) { ni_debug_application("%s: enabling device for nanny", w->name); if (!ni_nanny_call_device_enable(w->name)) goto error; } ni_debug_application("%s: adding policy %s to nanny", w->name, xml_node_get_attr(policy, NI_NANNY_IFPOLICY_NAME)); if (ni_nanny_addpolicy_node(policy, w->config.origin) <= 0) { ni_nanny_call_device_disable(w->name); goto error; } ni_debug_application("%s: nanny hired!", w->name); ni_ifworker_success(w); /* Append policies for all children in case they contain some special options */ for (i = 0; i < w->children.count; i++) { ni_ifworker_t *child = w->children.data[i]; if (!ni_ifup_hire_nanny(child)) ni_error("%s: unable to apply configuration to nanny", child->name); } rv = TRUE; error: if (!rv) ni_ifworker_fail(w, "%s: unable to apply configuration to nanny", w->name); xml_node_free(policy); return rv; }
ni_bool_t __ni_config_parse(ni_config_t *conf, const char *filename, ni_init_appdata_callback_t *cb, void *appdata) { xml_document_t *doc; xml_node_t *node, *child; ni_debug_wicked("Reading config file %s", filename); doc = xml_document_read(filename); if (!doc) { ni_error("%s: error parsing configuration file", filename); goto failed; } node = xml_node_get_child(doc->root, "config"); if (!node) { ni_error("%s: no <config> element", filename); goto failed; } /* Loop over all elements in the config file */ for (child = node->children; child; child = child->next) { if (strcmp(child->name, "include") == 0) { const char *attrval, *path; if ((attrval = xml_node_get_attr(child, "name")) == NULL) { ni_error("%s: <include> element lacks filename", xml_node_location(child)); goto failed; } if (!(path = ni_config_build_include(filename, attrval))) goto failed; if (!__ni_config_parse(conf, path, cb, appdata)) goto failed; } else if (strcmp(child->name, "use-nanny") == 0) { if (ni_parse_boolean(child->cdata, &conf->use_nanny)) { ni_error("%s: invalid <%s>%s</%s> element value", filename, child->name, child->name, child->cdata); goto failed; } } else if (strcmp(child->name, "piddir") == 0) { ni_config_parse_fslocation(&conf->piddir, child); } else if (strcmp(child->name, "statedir") == 0) { ni_config_parse_fslocation(&conf->statedir, child); } else if (strcmp(child->name, "storedir") == 0) { ni_config_parse_fslocation(&conf->storedir, child); } else if (strcmp(child->name, "dbus") == 0) { const char *attrval; if ((attrval = xml_node_get_attr(child, "name")) != NULL) ni_string_dup(&conf->dbus_name, attrval); if ((attrval = xml_node_get_attr(child, "type")) != NULL) ni_string_dup(&conf->dbus_type, attrval); } else if (strcmp(child->name, "schema") == 0) { const char *attrval; if ((attrval = xml_node_get_attr(child, "name")) != NULL) ni_string_dup(&conf->dbus_xml_schema_file, attrval); } else if (strcmp(child->name, "addrconf") == 0) { xml_node_t *gchild; for (gchild = child->children; gchild; gchild = gchild->next) { if (!strcmp(gchild->name, "default-allow-update")) ni_config_parse_update_targets(&conf->addrconf.default_allow_update, gchild); if (!strcmp(gchild->name, "dhcp4") && !ni_config_parse_addrconf_dhcp4(&conf->addrconf.dhcp4, gchild)) goto failed; if (!strcmp(gchild->name, "dhcp6") && !ni_config_parse_addrconf_dhcp6(&conf->addrconf.dhcp6, gchild)) goto failed; } } else if (strcmp(child->name, "sources") == 0) { if (!ni_config_parse_sources(conf, child)) goto failed; } else if (strcmp(child->name, "extension") == 0 || strcmp(child->name, "dbus-service") == 0) { if (!ni_config_parse_objectmodel_extension(&conf->dbus_extensions, child)) goto failed; } else if (strcmp(child->name, "netif-naming-services") == 0) { if (!ni_config_parse_objectmodel_netif_ns(&conf->ns_extensions, child)) goto failed; } else if (strcmp(child->name, "netif-firmware-discovery") == 0) { if (!ni_config_parse_objectmodel_firmware_discovery(&conf->fw_extensions, child)) goto failed; } else if (strcmp(child->name, "system-updater") == 0) { if (!ni_config_parse_system_updater(&conf->updater_extensions, child)) goto failed; } else if (cb != NULL) { if (!cb(appdata, child)) goto failed; } } if (conf->backupdir.path == NULL) { char pathname[PATH_MAX]; snprintf(pathname, sizeof(pathname), "%s/backup", conf->statedir.path); ni_config_fslocation_init(&conf->backupdir, pathname, 0700); } xml_document_free(doc); return TRUE; failed: if (doc) xml_document_free(doc); return FALSE; }
/* Remove address method */ static LibBalsaABErr libbalsa_address_book_rubrica_modify_address(LibBalsaAddressBook * ab, LibBalsaAddress * address, LibBalsaAddress * newval) { LibBalsaAddressBookRubrica *ab_rubrica = LIBBALSA_ADDRESS_BOOK_RUBRICA(ab); LibBalsaAddressBookText *ab_text = LIBBALSA_ADDRESS_BOOK_TEXT(ab); int fd; xmlDocPtr doc = NULL; xmlNodePtr root_element; xmlNodePtr card; LibBalsaABErr result; gboolean found; /* try to load the current file */ if ((result = lbab_rubrica_load_xml(ab_rubrica, &doc)) != LBABERR_OK) return result; /* check if we have a node with the correct full name */ if (!(root_element = xmlDocGetRootElement(doc)) || xmlStrcmp(root_element->name, CXMLCHARP("Rubrica"))) { xmlFreeDoc(doc); return LBABERR_ADDRESS_NOT_FOUND; } card = root_element->children; found = FALSE; while (card && !found) { if (xmlStrcmp(card->name, CXMLCHARP("Card"))) { gchar *full_name = xml_node_get_attr(card, CXMLCHARP("name")); if (full_name) { found = !g_ascii_strcasecmp(address->full_name, full_name); g_free(full_name); } } } if (!found) { xmlFreeDoc(doc); return LBABERR_ADDRESS_NOT_FOUND; } /* remove the card from the document */ xmlUnlinkNode(card); xmlFreeNode(card); /* add the new card */ if (newval) lbab_insert_address_node(newval, root_element); /* try to open the address book for writing */ if ((fd = open(ab_text->path, O_WRONLY | O_CREAT, 0666)) == -1) { xmlFreeDoc(doc); return LBABERR_CANNOT_WRITE; } if (libbalsa_lock_file(ab_text->path, fd, TRUE, TRUE, FALSE) < 0) { xmlFreeDoc(doc); close(fd); return LBABERR_CANNOT_WRITE; } /* store the document */ if (xmlSaveFormatFileEnc(ab_text->path, doc, "UTF-8", 1) == -1) result = LBABERR_CANNOT_WRITE; else result = LBABERR_OK; libbalsa_unlock_file(ab_text->path, fd, FALSE); close(fd); xmlFreeDoc(doc); ab_text->mtime = 0; /* force re-load upon the next access */ /* done */ return result; }
static ni_bool_t dhcp4_tester_req_xml_init(ni_dhcp4_request_t *req, xml_document_t *doc) { xml_node_t *xml, *child; const char *type; xml = xml_document_root(doc); if (xml && !xml->name && xml->children) xml = xml->children; if (!xml || !ni_string_eq(xml->name, "request")) { ni_error("Invalid dhcp4 request xml '%s'", xml ? xml_node_location(xml) : NULL); return FALSE; } type = xml_node_get_attr(xml, "type"); if (ni_string_eq(type, "offer")) { req->dry_run = NI_DHCP4_RUN_OFFER; } else if (ni_string_eq(type, "lease")) { req->dry_run = NI_DHCP4_RUN_LEASE; } for (child = xml->children; child; child = child->next) { if (ni_string_eq(child->name, "uuid")) { if (ni_uuid_parse(&req->uuid, child->cdata) != 0) goto failure; } else if (ni_string_eq(child->name, "acquire-timeout")) { if (ni_parse_uint(child->cdata, &req->acquire_timeout, 10) != 0) goto failure; } else if (ni_string_eq(child->name, "hostname")) { if (!ni_check_domain_name(child->cdata, ni_string_len(child->cdata), 0)) goto failure; ni_string_dup(&req->hostname, child->cdata); } else if (ni_string_eq(child->name, "clientid")) { ni_opaque_t duid; if (ni_parse_hex(child->cdata, duid.data, sizeof(duid.data)) <= 0) goto failure; ni_string_dup(&req->clientid, child->cdata); } else if(ni_string_eq(child->name, "start-delay")) { if (ni_parse_uint(child->cdata, &req->start_delay, 10) != 0) goto failure; } else if (ni_string_eq(child->name, "lease-time")) { if (ni_parse_uint(child->cdata, &req->lease_time, 10) != 0) goto failure; } else if (ni_string_eq(child->name, "recover-lease")) { if (ni_parse_boolean(child->cdata, &req->recover_lease) != 0) goto failure; } else if (ni_string_eq(child->name, "release-lease")) { if (ni_parse_boolean(child->cdata, &req->release_lease) != 0) goto failure; } } return TRUE; failure: if (child) { ni_error("Cannot parse dhcp4 request '%s': %s", child->name, xml_node_location(child)); } return FALSE; }