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 xml_node_t * __ni_compat_generate_dynamic_addrconf(xml_node_t *ifnode, const char *name, ni_bool_t required, unsigned int update) { xml_node_t *aconf; aconf = xml_node_new(name, ifnode); xml_node_new_element("enabled", aconf, "true"); #if 0 /* This is not yet implemented */ if (!required) xml_node_new_element("optional", aconf, "true"); #endif if (update) { xml_node_t *child = xml_node_new("update", aconf); unsigned int i; for (i = 0; update != 0; ++i, update >>= 1) { if (update & 1) { const char *key = ni_addrconf_update_target_to_name(i); if (key) xml_node_new(key, child); } } } return aconf; }
static xml_node_t * __ni_ifup_generate_match(ni_ifworker_t *w) { xml_node_t *match, *op; unsigned int i; if (!(match = xml_node_new(NI_NANNY_IFPOLICY_MATCH, NULL))) return NULL; if (w->children.count) { op = xml_node_new(NI_NANNY_IFPOLICY_MATCH_COND_OR, match); if (!__ni_ifup_generate_match_dev(op, w)) { xml_node_free(match); return NULL; } for (i = 0; i < w->children.count; i++) { ni_ifworker_t *child = w->children.data[i]; if (!__ni_ifup_generate_match_dev(op, child)) { xml_node_free(match); return NULL; } } } else { if (!__ni_ifup_generate_match_dev(match, w)) { xml_node_free(match); return NULL; } } return match; }
int ni_addrconf_lease_nis_data_to_xml(const ni_addrconf_lease_t *lease, xml_node_t *node) { unsigned int count = 0; unsigned int i, j; ni_nis_info_t *nis; xml_node_t *data; nis = lease->nis; if (!nis) return 1; /* Default domain */ data = xml_node_new("default", NULL); if (!ni_string_empty(nis->domainname)) { count++; xml_node_new_element("domain", data, nis->domainname); } if (nis->default_binding == NI_NISCONF_BROADCAST || nis->default_binding == NI_NISCONF_STATIC) { /* no SLP here */ count++; xml_node_new_element("binding", data, ni_nis_binding_type_to_name(nis->default_binding)); } /* Only in when static binding? */ for (i = 0; i < nis->default_servers.count; ++i) { const char *server = nis->default_servers.data[i]; if (ni_string_empty(server)) continue; count++; xml_node_new_element("server", data, server); } if (count) { xml_node_add_child(node, data); } /* Further domains */ for (i = 0; i < nis->domains.count; ++i) { ni_nis_domain_t *dom = nis->domains.data[i]; if (!dom || ni_string_empty(dom->domainname)) continue; count++; data = xml_node_new("domain", node); xml_node_new_element("domain", data, dom->domainname); if (ni_nis_binding_type_to_name(nis->default_binding)) { xml_node_new_element("binding", data, ni_nis_binding_type_to_name(nis->default_binding)); } for (j = 0; j < dom->servers.count; ++j) { const char *server = dom->servers.data[j]; if (ni_string_empty(server)) continue; xml_node_new_element("server", data, server); } } return count ? 0 : 1; }
static int __ni_dhcp6_lease_ia_data_to_xml(const ni_dhcp6_ia_t *ia, xml_node_t *node) { const char *ia_address = ni_dhcp6_option_name(NI_DHCP6_OPTION_IA_ADDRESS); const char *ia_prefix = ni_dhcp6_option_name(NI_DHCP6_OPTION_IA_PREFIX); const ni_dhcp6_ia_addr_t *iadr; xml_node_t *iadr_node; unsigned int count = 0; char buf[32] = { '\0' }; int ret; switch (ia->type) { case NI_DHCP6_OPTION_IA_TA: xml_node_new_element_uint("interface-id", node, ia->iaid); snprintf(buf, sizeof(buf), "%"PRId64, (int64_t)ia->acquired.tv_sec); xml_node_new_element("acquired", node, buf); break; case NI_DHCP6_OPTION_IA_NA: case NI_DHCP6_OPTION_IA_PD: xml_node_new_element_uint("interface-id", node, ia->iaid); snprintf(buf, sizeof(buf), "%"PRId64, (int64_t)ia->acquired.tv_sec); xml_node_new_element("acquired", node, buf); xml_node_new_element_uint("renewal-time", node, ia->renewal_time); xml_node_new_element_uint("rebind-time", node, ia->rebind_time); break; default: return -1; } for (iadr = ia->addrs; iadr; iadr = iadr->next) { switch (ia->type) { case NI_DHCP6_OPTION_IA_NA: case NI_DHCP6_OPTION_IA_TA: iadr_node = xml_node_new(ia_address, NULL); break; case NI_DHCP6_OPTION_IA_PD: iadr_node = xml_node_new(ia_prefix, NULL); break; default: return -1; } ret = __ni_dhcp6_lease_ia_addr_to_xml(iadr, ia->type, iadr_node); if (ret) { xml_node_free(iadr_node); if (ret < 0) return -1; } else { count++; xml_node_add_child(node, iadr_node); } } __ni_dhcp6_lease_status_to_xml(&ia->status, node); return count == 0 ? 1 : 0; }
void __ni_compat_generate_static_route_metrics(xml_node_t *mnode, const ni_route_t *rp) { ni_string_array_t names = NI_STRING_ARRAY_INIT; xml_node_t *lnode = NULL; unsigned int i; ni_route_metrics_lock_get_names(rp->lock, &names); for (i = 0; i < names.count; ++i) { if (lnode == NULL) lnode = xml_node_new("lock", mnode); xml_node_new(names.data[i], lnode); } if (rp->mtu > 0) { xml_node_new_element("mtu", mnode, ni_sprint_uint(rp->mtu)); } if (rp->window > 0) { xml_node_new_element("window", mnode, ni_sprint_uint(rp->window)); } if (rp->rtt > 0) { xml_node_new_element("rtt", mnode, ni_sprint_uint(rp->rtt)); } if (rp->rttvar > 0) { xml_node_new_element("rttvar", mnode, ni_sprint_uint(rp->rttvar)); } if (rp->ssthresh > 0) { xml_node_new_element("ssthresh", mnode, ni_sprint_uint(rp->ssthresh)); } if (rp->cwnd > 0) { xml_node_new_element("cwnd", mnode, ni_sprint_uint(rp->cwnd)); } if (rp->advmss > 0) { xml_node_new_element("advmss", mnode, ni_sprint_uint(rp->advmss)); } if (rp->reordering > 0) { xml_node_new_element("reordering", mnode, ni_sprint_uint(rp->reordering)); } if (rp->hoplimit > 0) { xml_node_new_element("hoplimit", mnode, ni_sprint_uint(rp->hoplimit)); } if (rp->initcwnd > 0) { xml_node_new_element("initcwnd", mnode, ni_sprint_uint(rp->initcwnd)); } if (rp->features > 0) { xml_node_new_element("features", mnode, ni_sprint_uint(rp->features)); } if (rp->rto_min > 0) { xml_node_new_element("rto-min", mnode, ni_sprint_uint(rp->rto_min)); } if (rp->initrwnd > 0) { xml_node_new_element("initrwnd", mnode, ni_sprint_uint(rp->initrwnd)); } }
static void __ni_compat_generate_static_route_hops(xml_node_t *rnode, const ni_route_nexthop_t *hops, const char *ifname) { const ni_route_nexthop_t *nh; for (nh = hops; nh; nh = nh->next) { xml_node_t *nhnode; if (nh->gateway.ss_family == AF_UNSPEC && !nh->device.name) continue; nhnode = xml_node_new("nexthop", rnode); if (nh->gateway.ss_family != AF_UNSPEC) { xml_node_new_element("gateway", nhnode, ni_sockaddr_print(&nh->gateway)); } if (nh->device.name && !ni_string_eq(ifname, nh->device.name)) { xml_node_new_element("device", nhnode, nh->device.name); } else if (ifname) { xml_node_new_element("device", nhnode, ifname); } if (!hops->next) continue; if (nh->weight > 0) { xml_node_new_element("weight", nhnode, ni_sprint_uint(nh->weight)); } if (nh->realm > 0) { /* Hmm.. */ xml_node_new_element("realm", nhnode, ni_sprint_uint(nh->realm)); } if (nh->flags > 0) { ni_string_array_t names = NI_STRING_ARRAY_INIT; xml_node_t *fnode = NULL; unsigned int i; ni_route_nh_flags_get_names(nh->flags, &names); for (i = 0; i < names.count; ++i) { if (fnode == NULL) fnode = xml_node_new("flags", nhnode); xml_node_new(names.data[i], fnode); } } } }
/* * Apply policy to a virtual (factory) device */ int ni_factory_device_apply_policy(ni_fsm_t *fsm, ni_ifworker_t *w, ni_managed_policy_t *mpolicy) { const char *type_name; ni_fsm_policy_t *policy = mpolicy->fsm_policy; xml_node_t *config = NULL; ni_debug_nanny("%s: configuring factory device using policy %s", w->name, ni_fsm_policy_name(policy)); /* This returns "modem" or "interface" */ type_name = ni_ifworker_type_to_string(w->type); config = xml_node_new(type_name, NULL); xml_node_new_element("name", config, w->name); config = ni_fsm_policy_transform_document(config, &policy, 1); if (config == NULL) { ni_error("%s: error when applying policy to %s document", w->name, type_name); return -1; } ni_debug_nanny("%s: using device config", w->name); xml_node_print_debug(config, 0); ni_ifworker_set_config(w, config, ni_fsm_policy_get_origin(policy)); /* Now do the fandango */ return ni_factory_device_up(fsm, w); }
int ni_dhcp_xml_from_lease(const ni_addrconf_lease_t *lease, xml_node_t *node) { node = xml_node_new("dhcp", node); if (lease->dhcp.serveraddress.s_addr) __ni_dhcp_put_addr(node, "server-address", lease->dhcp.serveraddress); if (lease->dhcp.servername[0]) __ni_dhcp_put_string(node, "server-name", lease->dhcp.servername); if (lease->dhcp.address.s_addr) __ni_dhcp_put_addr(node, "address", lease->dhcp.address); if (lease->dhcp.netmask.s_addr) __ni_dhcp_put_addr(node, "netmask", lease->dhcp.netmask); if (lease->dhcp.broadcast.s_addr) __ni_dhcp_put_addr(node, "broadcast", lease->dhcp.broadcast); if (lease->dhcp.lease_time) __ni_dhcp_put_uint32(node, "lease-time", lease->dhcp.lease_time); if (lease->dhcp.renewal_time) __ni_dhcp_put_uint32(node, "renewal-time", lease->dhcp.renewal_time); if (lease->dhcp.rebind_time) __ni_dhcp_put_uint32(node, "rebind-time", lease->dhcp.rebind_time); if (lease->dhcp.mtu) __ni_dhcp_put_uint16(node, "mtu", lease->dhcp.mtu); return 0; }
/* * Get the state of a dbus object as XML. * We do this by going via the dbus representation, which is a bit of a waste of * time but at least that saves me from writing lots of code, and it makes sure * that we have one canonical mapping. * In fact, this is a lot like doing a Properties.GetAll call... */ static ni_bool_t ni_objectmodel_save_object_state_xml(const ni_dbus_object_t *object, xml_node_t *parent) { const ni_dbus_service_t *service; xml_node_t *object_node; unsigned int i; int rv = TRUE; object_node = xml_node_new("object", parent); xml_node_add_attr(object_node, "path", object->path); for (i = 0; rv && (service = object->interfaces[i]) != NULL; ++i) { ni_dbus_variant_t dict = NI_DBUS_VARIANT_INIT; xml_node_t *prop_node; ni_dbus_variant_init_dict(&dict); rv = ni_dbus_object_get_properties_as_dict(object, service, &dict, NULL); if (rv && dict.array.len != 0) { /* serialize as XML */ prop_node = ni_dbus_xml_deserialize_properties(__ni_objectmodel_schema, service->name, &dict, object_node); if (!prop_node) rv = FALSE; } ni_dbus_variant_destroy(&dict); } return rv; }
static int ni_addrconf_lease_static_data_to_xml(const ni_addrconf_lease_t *lease, xml_node_t *node) { static const struct group_map { const char *name; int (*func)(const ni_addrconf_lease_t *lease, xml_node_t *node); } *g, group_map[] = { { NI_ADDRCONF_LEASE_XML_ADDRS_DATA_NODE, ni_addrconf_lease_addrs_data_to_xml }, { NI_ADDRCONF_LEASE_XML_ROUTES_DATA_NODE, ni_addrconf_lease_routes_data_to_xml }, { NI_ADDRCONF_LEASE_XML_DNS_DATA_NODE, ni_addrconf_lease_dns_data_to_xml }, { NULL, NULL } }; xml_node_t *data; if (!ni_string_empty(lease->hostname)) xml_node_new_element("hostname", node, lease->hostname); for (g = group_map; g && g->name && g->func; ++g) { data = xml_node_new(g->name, NULL); if (g->func(lease, data) == 0) { xml_node_add_child(node, data); } else { xml_node_free(data); } } return 0; }
static int __ni_dhcp6_lease_ia_type_to_xml(const ni_dhcp6_ia_t *ia_list, unsigned ia_type, xml_node_t *node) { const ni_dhcp6_ia_t *ia; xml_node_t *ia_node; const char *ia_name = ni_dhcp6_option_name(ia_type); unsigned int count = 0; int ret; for (ia = ia_list; ia; ia = ia->next) { if (ia->type != ia_type) continue; ia_node = xml_node_new(ia_name, NULL); if ((ret = __ni_dhcp6_lease_ia_data_to_xml(ia, ia_node) == 0)) { xml_node_add_child(node, ia_node); count++; } else { xml_node_free(ia_node); if (ret < 0) return ret; } } return count == 0 ? 1 : 0; }
xml_node_t * xml_node_scan(FILE *fp, const char *location) { xml_reader_t reader; xml_node_t *root = xml_node_new(NULL, NULL); if (xml_reader_init_file(&reader, fp, location) < 0) return NULL; if (reader.shared_location) root->location = xml_location_new(reader.shared_location, reader.lineCount); /* Note! We do not deal with properly formatted XML documents here. * Specifically, we do not expect them to have a document header. */ if (!xml_process_element_nested(&reader, root, 0)) { xml_node_free(root); return NULL; } if (xml_reader_destroy(&reader) < 0) { xml_node_free(root); return NULL; } return root; }
static GNode *xml_build_tree(XMLFile *file, GNode *parent, guint level) { GNode *node = NULL; XMLNode *xmlnode; XMLTag *tag; while (xml_parse_next_tag(file) == 0) { if (file->level < level) break; if (file->level == level) { g_warning("xml_build_tree(): Parse error in %s", file->path); break; } tag = xml_get_current_tag(file); if (!tag) break; xmlnode = xml_node_new(xml_copy_tag(tag), NULL); xmlnode->element = xml_get_element(file); if (!parent) node = g_node_new(xmlnode); else node = g_node_append_data(parent, xmlnode); xml_build_tree(file, node, file->level); if (file->level == 0) break; } return node; }
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; }
/* * Apply policy to a device */ int ni_managed_device_apply_policy(ni_managed_device_t *mdev, ni_managed_policy_t *mpolicy) { ni_ifworker_t *w = mdev->worker; const char *type_name; ni_fsm_policy_t *policy = mpolicy->fsm_policy; xml_node_t *config = NULL; /* If the device is up and running, do not reconfigure unless the policy * has really changed */ switch (mdev->state) { case NI_MANAGED_STATE_STOPPING: case NI_MANAGED_STATE_STOPPED: case NI_MANAGED_STATE_LIMBO: /* Just install the new policy and reconfigure. */ break; case NI_MANAGED_STATE_STARTING: case NI_MANAGED_STATE_RUNNING: case NI_MANAGED_STATE_FAILED: if (mdev->selected_policy == mpolicy && mdev->selected_policy_seq == mpolicy->seqno) { ni_debug_nanny("%s: keep using policy %s", w->name, ni_fsm_policy_name(policy)); return -1; } /* Just install the new policy and reconfigure. */ break; case NI_MANAGED_STATE_BINDING: ni_error("%s(%s): should not get here in state %s", __func__, w->name, ni_managed_state_to_string(mdev->state)); return -1; } ni_debug_nanny("%s: using policy %s", w->name, ni_fsm_policy_name(policy)); /* This returns "modem" or "interface" */ type_name = ni_ifworker_type_to_string(w->type); config = xml_node_new(type_name, NULL); xml_node_new_element("name", config, w->name); config = ni_fsm_policy_transform_document(config, &policy, 1); if (config == NULL) { ni_error("%s: error when applying policy to %s document", w->name, type_name); #if 0 if (mdev->state != NI_MANAGED_STATE_STOPPED) ni_nanny_schedule_recheck(&mdev->nanny->down, w); #endif return -1; } ni_debug_nanny("%s: using device config", w->name); xml_node_print_debug(config, 0); ni_managed_device_set_policy(mdev, mpolicy, config); /* Now do the fandango */ return ni_managed_device_up(mdev, ni_fsm_policy_get_origin(policy)); }
/* * Helper function for creating <name> elements for ns->describe() */ static xml_node_t * __describe(const ni_objectmodel_ns_t *ns, xml_node_t *parent) { xml_node_t *node = xml_node_new("name", parent); xml_node_add_attr(node, "namespace", ns->name); return node; }
xml_node_t * xml_node_new_element_uint(const char *ident, xml_node_t *parent, unsigned int value) { xml_node_t *node = xml_node_new(ident, parent); xml_node_set_uint(node, value); return node; }
/* * XML helper functions */ static xml_node_t * xml_node_create(xml_node_t *parent, const char *name) { xml_node_t *child; if ((child = xml_node_get_child(parent, name)) == NULL) child = xml_node_new(name, parent); return child; }
xml_node_t * ni_addrconf_lease_xml_new_type_node(const ni_addrconf_lease_t *lease, xml_node_t *node) { const char *name = NULL; name = ni_addrconf_lease_xml_new_type_name(lease); return name ? xml_node_new(name, node) : NULL; }
xml_document_t * xml_document_new() { xml_document_t *doc; doc = xcalloc(1, sizeof(*doc)); doc->root = xml_node_new(NULL, NULL); return doc; }
xml_node_t * xml_node_new_element(const char *ident, xml_node_t *parent, const char *cdata) { xml_node_t *node = xml_node_new(ident, parent); if (cdata) xml_node_set_cdata(node, cdata); return node; }
int ni_addrconf_lease_routes_data_to_xml(const ni_addrconf_lease_t *lease, xml_node_t *node) { ni_route_table_t *tab; ni_route_nexthop_t *nh; xml_node_t *route, *hop; ni_route_t *rp; unsigned int count = 0; unsigned int i; /* A very limitted view */ for (tab = lease->routes; tab; tab = tab->next) { if (tab->tid != 254) /* RT_TABLE_MAIN for now */ continue; for (i = 0; i < tab->routes.count; ++i) { if (!(rp = tab->routes.data[i])) continue; route = xml_node_new("route", NULL); if (ni_sockaddr_is_specified(&rp->destination)) { xml_node_new_element("destination", route, ni_sockaddr_prefix_print(&rp->destination, rp->prefixlen)); } for (nh = &rp->nh; nh; nh = nh->next) { if (!ni_sockaddr_is_specified(&nh->gateway)) continue; hop = xml_node_new("nexthop", route); xml_node_new_element("gateway", hop, ni_sockaddr_print(&nh->gateway)); } if (route->children) { xml_node_add_child(node, route); count++; } else { xml_node_free(route); } } } return count ? 0 : 1; }
static xml_node_t * ni_compat_generate_ifcfg(const ni_compat_netdev_t *compat, xml_document_t *doc) { xml_node_t *ifnode, *namenode; ifnode = xml_node_new("interface", doc->root); namenode = xml_node_new("name", ifnode); if (compat->identify.hwaddr.type == NI_IFTYPE_ETHERNET) { xml_node_add_attr(namenode, "namespace", "ethernet"); xml_node_new_element("permanent-address", namenode, ni_link_address_print(&compat->identify.hwaddr)); } else { xml_node_set_cdata(namenode, compat->dev->name); } __ni_compat_generate_ifcfg(ifnode, compat); return ifnode; }
int ni_addrconf_lease_addrs_data_to_xml(const ni_addrconf_lease_t *lease, xml_node_t *node) { unsigned int count = 0; xml_node_t *anode; ni_address_t *ap; for (ap = lease->addrs; ap; ap = ap->next) { if (lease->family != ap->local_addr.ss_family || !ni_sockaddr_is_specified(&ap->local_addr)) continue; count++; anode = xml_node_new("address", node); xml_node_new_element("local", anode, ni_sockaddr_prefix_print (&ap->local_addr, ap->prefixlen)); if (ap->peer_addr.ss_family == ap->family) { xml_node_new_element("peer", anode, ni_sockaddr_print (&ap->peer_addr)); } if (ap->anycast_addr.ss_family == ap->family) { xml_node_new_element("anycast", anode, ni_sockaddr_print (&ap->anycast_addr)); } if (ap->bcast_addr.ss_family == ap->family) { xml_node_new_element("broadcast", anode, ni_sockaddr_print (&ap->bcast_addr)); } if (ap->family == AF_INET && ap->label) xml_node_new_element("label", anode, ap->label); if (ap->ipv6_cache_info.preferred_lft || ap->ipv6_cache_info.valid_lft) { xml_node_t *cnode = xml_node_new("cache-info", anode); xml_node_new_element_uint("preferred-lifetime", cnode, ap->ipv6_cache_info.preferred_lft); xml_node_new_element_uint("valid-lifetime", cnode, ap->ipv6_cache_info.valid_lft); } } return count ? 0 : 1; }
/* * Functions for generating XML */ static ni_bool_t __ni_compat_generate_ethernet(xml_node_t *ifnode, const ni_compat_netdev_t *compat) { const ni_netdev_t *dev = compat->dev; xml_node_t *child; child = xml_node_new("ethernet", ifnode); if (dev->link.hwaddr.len) xml_node_new_element("address", child, ni_link_address_print(&dev->link.hwaddr)); /* generate offload and other information */ return TRUE; }
int ni_dhcp6_lease_data_to_xml(const ni_addrconf_lease_t *lease, xml_node_t *node, const char *ifname) { static const struct group_map { const char *name; int (*func)(const ni_addrconf_lease_t *, xml_node_t *, const char *); } *g, group_map[] = { { NI_ADDRCONF_LEASE_XML_DNS_DATA_NODE, ni_addrconf_lease_dns_data_to_xml }, { NI_ADDRCONF_LEASE_XML_NTP_DATA_NODE, ni_addrconf_lease_ntp_data_to_xml }, { NI_ADDRCONF_LEASE_XML_SIP_DATA_NODE, ni_addrconf_lease_sip_data_to_xml }, { NI_ADDRCONF_LEASE_XML_PTZ_DATA_NODE, ni_addrconf_lease_ptz_data_to_xml }, { NI_ADDRCONF_LEASE_XML_OPTS_DATA_NODE, ni_addrconf_lease_opts_data_to_xml }, { NULL, NULL } }; xml_node_t *data; if (!node || !lease) return -1; if (lease->family != AF_INET6 || lease->type != NI_ADDRCONF_DHCP) return -1; if (__ni_dhcp6_lease_head_to_xml(lease, node) != 0) return -1; if (__ni_dhcp6_lease_ia_type_to_xml(lease->dhcp6.ia_list, NI_DHCP6_OPTION_IA_NA, node) < 0) return -1; if (__ni_dhcp6_lease_ia_type_to_xml(lease->dhcp6.ia_list, NI_DHCP6_OPTION_IA_TA, node) < 0) return -1; if (__ni_dhcp6_lease_ia_type_to_xml(lease->dhcp6.ia_list, NI_DHCP6_OPTION_IA_PD, node) < 0) return -1; if (__ni_dhcp6_lease_boot_to_xml(lease, node) < 0) return -1; for (g = group_map; g && g->name && g->func; ++g) { data = xml_node_new(g->name, NULL); if (g->func(lease, data, ifname) == 0) { xml_node_add_child(node, data); } else { xml_node_free(data); } } return 0; }
int ni_dhcp6_save_duid(const ni_opaque_t *duid, const char *filename) { char path[PATH_MAX]; const char *name = CONFIG_DHCP6_DUID_NODE; ni_opaque_t temp = NI_OPAQUE_INIT; xml_node_t *node; FILE *fp; int rv = -1; if (!duid || !duid->len) { ni_error("BUG: Refusing to save empty duid"); return -1; } if(ni_dhcp6_load_duid(&temp, filename) == 0) return 1; if (!filename) { snprintf(path, sizeof(path), "%s/%s", ni_config_storedir(), CONFIG_DHCP6_DUID_FILE); filename = path; } else { name = "duid"; } if ((node = xml_node_new(name, NULL)) == NULL) { ni_error("Unable to create %s xml node: %m", name); return -1; } ni_duid_format_hex(&node->cdata, duid); if ((fp = fopen(filename, "w")) == NULL) { ni_error("%s: unable to open file for writing: %m", filename); } else if ((rv = xml_node_print(node, fp)) < 0) { ni_error("%s: unable to write %s xml representation", filename, name); } xml_node_free(node); fclose(fp); if(rv < 0) unlink(filename); return rv; }
static int __ni_dhcp6_lease_status_to_xml(const ni_dhcp6_status_t *status, xml_node_t *node) { xml_node_t *snode; if (status->code != NI_DHCP6_STATUS_SUCCESS || !ni_string_empty(status->message)) { snode = xml_node_new("status", node); xml_node_new_element_uint("code", snode, status->code); if (status->message) { xml_node_new_element("message", snode, status->message); } } return 0; }
int __ni_dhcp6_lease_boot_to_xml(const ni_addrconf_lease_t *lease, xml_node_t *node) { xml_node_t *data; unsigned int i; if (ni_string_empty(lease->dhcp6.boot_url) || !lease->dhcp6.boot_params.count) return 1; data = xml_node_new("boot", node); xml_node_new_element("url", data, lease->dhcp6.boot_url); for (i = 0; i < lease->dhcp6.boot_params.count; ++i) { if (ni_string_empty(lease->dhcp6.boot_params.data[i])) continue; xml_node_new_element("param", data, lease->dhcp6.boot_params.data[i]); } return 0; }