Esempio n. 1
0
static dbus_bool_t
ni_objectmodel_ppp_config_get_ipv6(const ni_dbus_object_t *object, const ni_dbus_property_t *property,
				ni_dbus_variant_t *result, DBusError *error)
{
	const ni_ppp_config_t *conf;
	ni_dbus_variant_t *ipcp;

	if (!(conf = ni_objectmodel_get_ppp_config(object, FALSE, error)))
		return FALSE;

	ni_dbus_dict_add_bool(result, "enabled", conf->ipv6.enabled);
	if (!conf->ipv6.enabled)
		return TRUE;

	if (ni_sockaddr_is_specified(&conf->ipv6.local_ip)) {
		if (!__ni_objectmodel_dict_add_sockaddr(result, "local-ip", &conf->ipv6.local_ip))
			return FALSE;
	}

	if (ni_sockaddr_is_specified(&conf->ipv6.remote_ip)) {
		if (!__ni_objectmodel_dict_add_sockaddr(result, "remote-ip", &conf->ipv6.remote_ip))
			return FALSE;
	}

	if (!(ipcp = ni_dbus_dict_add(result, "ipcp")))
		return FALSE;

	ni_dbus_variant_init_dict(ipcp);
	ni_dbus_dict_add_bool(ipcp, "accept-local", conf->ipv6.ipcp.accept_local);

	return TRUE;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
static dbus_bool_t
ni_objectmodel_ppp_config_get_dns(const ni_dbus_object_t *object, const ni_dbus_property_t *property,
				ni_dbus_variant_t *result, DBusError *error)
{
	const ni_ppp_config_t *conf;

	if (!(conf = ni_objectmodel_get_ppp_config(object, FALSE, error)))
		return FALSE;

	ni_dbus_dict_add_bool(result, "usepeerdns", conf->dns.usepeerdns);

	if (ni_sockaddr_is_specified(&conf->dns.dns1)) {
		if (!__ni_objectmodel_dict_add_sockaddr(result, "dns1", &conf->dns.dns1))
			return FALSE;
	}

	if (ni_sockaddr_is_specified(&conf->dns.dns2)) {
		if (!__ni_objectmodel_dict_add_sockaddr(result, "dns2", &conf->dns.dns2))
			return FALSE;
	}

	return TRUE;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
/*
 * Given a route, look up the lease owning it
 */
ni_addrconf_lease_t *
__ni_netdev_route_to_lease(ni_netdev_t *dev, const ni_route_t *rp, unsigned int minprio)
{
	ni_addrconf_lease_t *lease;
	ni_addrconf_lease_t *found = NULL;
	ni_address_t *ap;
	unsigned int prio;

	if (!dev || !rp)
		return NULL;

	for (lease = dev->leases; lease; lease = lease->next) {
		if (rp->family != lease->family)
			continue;

		if ((prio = ni_addrconf_lease_get_priority(lease)) < minprio)
			continue;

		/* First, check if this is an interface route */
		for (ap = lease->addrs; ap; ap = ap->next) {
			if (ni_sockaddr_is_specified(&rp->nh.gateway))
				continue;
			if (rp->prefixlen != ap->prefixlen)
				continue;
			if (!ni_sockaddr_prefix_match(ap->prefixlen,
				&rp->destination, &ap->local_addr))
				continue;

			if (!found || prio > ni_addrconf_lease_get_priority(found))
				found = lease;
		}

		if (__ni_lease_owns_route(lease, rp)) {
			if (!found || prio > ni_addrconf_lease_get_priority(found))
				found = lease;
		}
	}

	return found;
}
Esempio n. 6
0
/*
 * Callback from addrconf supplicant whenever it acquired, released or lost a lease.
 *
 * FIXME SECURITY:
 * Is it good enough to check for the sender interface to avoid that someone is sending
 * us spoofed lease messages?!
 */
void
ni_objectmodel_addrconf_signal_handler(ni_dbus_connection_t *conn, ni_dbus_message_t *msg, void *user_data)
{
	ni_dbus_addrconf_forwarder_t *forwarder = user_data;
	const char *signal_name = dbus_message_get_member(msg);
	ni_netdev_t *ifp;
	ni_addrconf_lease_t *lease = NULL;
	ni_dbus_variant_t argv[16];
	ni_uuid_t uuid = NI_UUID_INIT;
	ni_event_t ifevent;
	int argc, optind = 0;

	memset(argv, 0, sizeof(argv));
	argc = ni_dbus_message_get_args_variants(msg, argv, 16);
	if (argc < 0) {
		ni_error("%s: cannot parse arguments for signal %s", __func__, signal_name);
		goto done;
	}

	ifp = ni_objectmodel_addrconf_path_to_device(dbus_message_get_path(msg));
	if (ifp == NULL) {
		ni_debug_dbus("%s: received signal %s for unknown interface %s", __func__,
				signal_name, dbus_message_get_path(msg));
		goto done;
	}

	lease = ni_addrconf_lease_new(forwarder->addrconf, forwarder->addrfamily);

	if (argc != 1 && argc != 2) {
		ni_warn("%s: ignoring %s event from %s: bad number of arguments (%u)",
				__func__, signal_name, dbus_message_get_path(msg), argc);
		goto done;
	}

	if (argc == 2 && !ni_dbus_variant_get_uuid(&argv[optind++], &uuid)) {
		ni_debug_dbus("%s: unable to parse uuid argument", __func__);
		goto done;
	}

	if (!ni_objectmodel_set_addrconf_lease(lease, &argv[optind++])) {
		ni_error("%s: unable to parse lease argument received from %s", __func__,
				dbus_message_get_sender(msg));
		goto done;
	}

	ni_debug_dbus("received signal %s for interface %s (ifindex %d), lease %s:%s, uuid=%s, update=0x%x, flags=0x%x",
			signal_name, ifp->name, ifp->link.ifindex,
			ni_addrfamily_type_to_name(lease->family),
			ni_addrconf_type_to_name(lease->type),
			ni_uuid_print(&uuid), lease->update, lease->flags);
	if (!strcmp(signal_name, NI_OBJECTMODEL_LEASE_ACQUIRED_SIGNAL)) {
		if (lease->state != NI_ADDRCONF_STATE_GRANTED) {
			ni_error("%s: unexpected lease state in signal %s", __func__, signal_name);
			goto done;
		}

		ifevent = NI_EVENT_ADDRESS_ACQUIRED;

		if (!__ni_addrconf_should_update(lease->update, NI_ADDRCONF_UPDATE_DEFAULT_ROUTE)) {
			ni_route_table_t *tab;
			ni_route_t *rp;
			unsigned int i;

			for (tab = lease->routes; tab; tab = tab->next) {
				for (i = 0; i < tab->routes.count; ++i) {
					if (!(rp = tab->routes.data[i]))
						continue;

					if (ni_sockaddr_is_specified(&rp->destination))
						continue;

					if (ni_route_array_delete(&tab->routes, i))
						i--;
				}
			}
		}
	} else if (!strcmp(signal_name, NI_OBJECTMODEL_LEASE_RELEASED_SIGNAL)) {
		lease->state = NI_ADDRCONF_STATE_RELEASED;
		ifevent = NI_EVENT_ADDRESS_RELEASED;
	} else if (!strcmp(signal_name, NI_OBJECTMODEL_LEASE_LOST_SIGNAL)) {
		lease->state = NI_ADDRCONF_STATE_FAILED;
		ifevent = NI_EVENT_ADDRESS_LOST;
	} else {
		/* Ignore unknown signal */
		goto done;
	}

	/*
	 * The following call updates the system with the information given in
	 * the lease. This includes setting all addresses, as well as updating
	 * resolver and hostname, if provided.
	 * When a lease is dropped, we either fall back to the config information
	 * from the next best lease, or if there is none, we restore the original
	 * system settings.
	 *
	 * Note, lease may be NULL after this, as the interface object
	 * takes ownership of it.
	 */
	__ni_system_interface_update_lease(ifp, &lease);

	/* Potentially, there's a client somewhere waiting for that event.
	 * We use the UUID that's passed back and forth to make sure we
	 * really match the event we were expecting to match.
	 */
	{
		ni_dbus_object_t *object;

		object = ni_objectmodel_get_netif_object(__ni_objectmodel_server, ifp);
		if (object)
			ni_objectmodel_send_netif_event(__ni_objectmodel_server, object,
					ifevent, ni_uuid_is_null(&uuid)? NULL : &uuid);
	}

done:
	while (argc--)
		ni_dbus_variant_destroy(&argv[argc]);
	if (lease)
		ni_addrconf_lease_free(lease);
}
Esempio n. 7
0
/*
 * Install information from a lease, and remember that we did
 */
static ni_bool_t
ni_system_updater_install(ni_updater_t *updater, const ni_addrconf_lease_t *lease, const char *ifname)
{
	ni_string_array_t arguments = NI_STRING_ARRAY_INIT;
	const char *statedir = NULL;
	char *file = NULL;
	ni_bool_t result = FALSE;
	int rv = 0;

	ni_debug_ifconfig("Updating system %s settings from %s/%s lease",
					ni_updater_name(updater->kind),
					ni_addrconf_type_to_name(lease->type),
					ni_addrfamily_type_to_name(lease->family));

	if (!updater->proc_install)
		return TRUE;

	if (!ifname || (!updater->have_backup && !ni_system_updater_backup(updater, ifname)))
		return FALSE;

	ni_string_array_append(&arguments, "-i");
	ni_string_array_append(&arguments, ifname);

	ni_string_array_append(&arguments, "-t");
	ni_string_array_append(&arguments, ni_addrconf_type_to_name(lease->type));

	ni_string_array_append(&arguments, "-f");
	ni_string_array_append(&arguments, ni_addrfamily_type_to_name(lease->family));

	switch (updater->kind) {
	case NI_ADDRCONF_UPDATER_GENERIC:
		switch (updater->format) {
		case NI_ADDRCONF_UPDATER_FORMAT_INFO:
			ni_leaseinfo_dump(NULL, lease, ifname, NULL);
			if (!(file = ni_leaseinfo_path(ifname, lease->type, lease->family))) {
				ni_error("Unable to determine leaseinfo file path.");
				goto done;
			}
			ni_string_array_append(&arguments, file);
			break;

		default:
			ni_error("Unsupported %s updater data format.",
				ni_updater_name(updater->kind));
			goto done;
		}

		ni_string_array_append(&arguments,
				ni_updater_format_name(updater->format));
		break;

	case NI_ADDRCONF_UPDATER_RESOLVER:
		statedir = ni_extension_statedir(ni_updater_name(updater->kind));
		if (!statedir) {
			ni_error("failed to get %s statedir", ni_updater_name(updater->kind));
			goto done;
		}
		ni_string_printf(&file, "%s/resolv.conf.%s.%s.%s",
				statedir, ifname,
				ni_addrconf_type_to_name(lease->type),
				ni_addrfamily_type_to_name(lease->family));
		ni_string_array_append(&arguments, file);

		if ((rv = ni_resolver_write_resolv_conf(file, lease->resolver, NULL)) < 0) {
			ni_error("failed to write resolver info to file: %s",
					ni_strerror(rv));
			goto done;
		}
		break;

	case NI_ADDRCONF_UPDATER_HOSTNAME:
		if (!ni_string_empty(lease->hostname)) {
			ni_string_array_append(&arguments, lease->hostname);
		} else {
			const ni_address_t *ap;
			char *name = NULL;
			unsigned int count;

			/* bnc#861476 workaround */
			if (!can_try_reverse_lookup(lease))
				goto done;

			for (count = 0, ap = lease->addrs; ap; ap = ap->next) {
				if (!ni_sockaddr_is_specified(&ap->local_addr))
					continue;

				if (!ni_resolve_reverse_timed(&ap->local_addr,
						&name, NI_UPDATER_REVERSE_TIMEOUT))
					break;

				ni_info("Unable to resolve %s to hostname",
					ni_sockaddr_print(&ap->local_addr));

				if (++count >= NI_UPDATER_REVERSE_MAX_CNT)
					break;
			}

			if (ni_string_empty(name)) {
				ni_note("Skipping hostname update, none available");
				goto done;
			}
			ni_string_array_append(&arguments, name);
			ni_string_free(&name);
		}
		break;

	default:
		ni_error("cannot install new %s settings - file format not understood",
				ni_updater_name(updater->kind));
		goto done;
	}

	if (!ni_system_updater_run(updater->proc_install, &arguments)) {
		ni_error("failed to install %s settings", ni_updater_name(updater->kind));
		goto done;
	}

	result = TRUE;

	switch (updater->kind) {
	case NI_ADDRCONF_UPDATER_RESOLVER:
		if (ni_global.other_event)
			ni_global.other_event(NI_EVENT_RESOLVER_UPDATED);
		break;

	case NI_ADDRCONF_UPDATER_HOSTNAME:
		if (ni_global.other_event)
			ni_global.other_event(NI_EVENT_HOSTNAME_UPDATED);
		break;

	case NI_ADDRCONF_UPDATER_GENERIC:
		if (ni_global.other_event)
			ni_global.other_event(NI_EVENT_GENERIC_UPDATED);
		break;

	default:
		break;
	}

done:
	if (file)
		free(file);
	ni_string_array_destroy(&arguments);

	return result;
}
Esempio n. 8
0
File: compat.c Progetto: mchf/wicked
void
__ni_compat_generate_static_route(xml_node_t *aconf, const ni_route_t *rp, const char *ifname)
{
	xml_node_t *rnode, *mnode, *knode;
	char *tmp = NULL;
	const char *ptr;

	rnode = xml_node_new("route", aconf);

	if (rp->destination.ss_family != AF_UNSPEC && rp->prefixlen != 0) {
		xml_node_new_element("destination", rnode,
			ni_sockaddr_prefix_print(&rp->destination, rp->prefixlen));
	}

	__ni_compat_generate_static_route_hops(rnode, &rp->nh, ifname);

	knode = NULL;
	if (rp->table != RT_TABLE_UNSPEC && rp->table != RT_TABLE_MAIN) {
		if (!(ptr = ni_route_table_type_to_name(rp->table)))
			ptr = ni_sprint_uint(rp->table);
		if (knode == NULL)
			knode = xml_node_new("kern", rnode);
		xml_node_new_element("table", knode, ptr);
	}
	if (rp->type != RTN_UNSPEC && rp->type != RTN_UNICAST) {
		if (!(ptr = ni_route_type_type_to_name(rp->type)))
			ptr = ni_sprint_uint(rp->type);
		if (knode == NULL)
			knode = xml_node_new("kern", rnode);
		xml_node_new_element("type", knode, ptr);
	}
	if (rp->scope != RT_SCOPE_UNIVERSE) {
		if (!(ptr = ni_route_scope_type_to_name(rp->scope)))
			ptr = ni_sprint_uint(rp->scope);
		if (knode == NULL)
			knode = xml_node_new("kern", rnode);
		xml_node_new_element("scope", knode, ptr);
	}
	if (rp->protocol != RTPROT_UNSPEC && rp->protocol != RTPROT_BOOT) {
		if (!(ptr = ni_route_protocol_type_to_name(rp->protocol)))
			ptr = ni_sprint_uint(rp->protocol);
		if (knode == NULL)
			knode = xml_node_new("kern", rnode);
		xml_node_new_element("protocol", knode, ptr);
	}

	if (rp->priority > 0) {
		xml_node_new_element("priority", rnode, ni_sprint_uint(rp->priority));
	}
	if (ni_sockaddr_is_specified(&rp->pref_src)) {
		xml_node_new_element("source", rnode, ni_sockaddr_print(&rp->pref_src));
	}
	if (rp->realm > 0) {
		/* Hmm */
		xml_node_new_element("realm", rnode, ni_sprint_uint(rp->realm));
	}
	if (rp->mark > 0 && ni_string_printf(&tmp, "0x%02x", rp->mark)) {
		xml_node_new_element("mark", rnode, tmp);
		ni_string_free(&tmp);
	}
	if (rp->flags > 0) {
		ni_string_array_t names = NI_STRING_ARRAY_INIT;
		xml_node_t *fnode = NULL;
		unsigned int i;

		ni_route_flags_get_names(rp->flags, &names);
		for (i = 0; i < names.count; ++i) {
			if (fnode == NULL)
				fnode = xml_node_new("flags", rnode);
			xml_node_new(names.data[i], fnode);
		}
	}
	if (rp->tos > 0 && ni_string_printf(&tmp, "0x%02x", rp->tos)) {
		xml_node_new_element("tos", rnode, tmp);
		ni_string_free(&tmp);
	}

	mnode = xml_node_new("metrics", NULL);
	__ni_compat_generate_static_route_metrics(mnode, rp);
	if (mnode->children || mnode->attrs.count || mnode->cdata)
		xml_node_add_child(rnode, mnode);
	else
		xml_node_free(mnode);
}