コード例 #1
0
ファイル: nm-ip6-manager.c プロジェクト: binli/NetworkManager
static NMIP6Device *
process_nduseropt (NMIP6Manager *manager, struct nl_msg *msg)
{
	NMIP6Device *device;
	struct nduseroptmsg *ndmsg;
	struct nd_opt_hdr *opt;
	guint opts_len;
	gboolean changed = FALSE;

	nm_log_dbg (LOGD_IP6, "processing netlink nduseropt message");

	ndmsg = (struct nduseroptmsg *) NLMSG_DATA (nlmsg_hdr (msg));

	if (!nlmsg_valid_hdr (nlmsg_hdr (msg), sizeof (*ndmsg)) ||
	    nlmsg_datalen (nlmsg_hdr (msg)) <
		(ndmsg->nduseropt_opts_len + sizeof (*ndmsg))) {
		nm_log_dbg (LOGD_IP6, "ignoring invalid nduseropt message");
		return NULL;
	}

	if (ndmsg->nduseropt_family != AF_INET6 ||
		ndmsg->nduseropt_icmp_type != ND_ROUTER_ADVERT ||
		ndmsg->nduseropt_icmp_code != 0) {
		nm_log_dbg (LOGD_IP6, "ignoring non-Router Advertisement message");
		return NULL;
	}

	device = nm_ip6_manager_get_device (manager, ndmsg->nduseropt_ifindex);
	if (!device) {
		nm_log_dbg (LOGD_IP6, "ignoring message for unknown device");
		return NULL;
	}

	opt = (struct nd_opt_hdr *) (ndmsg + 1);
	opts_len = ndmsg->nduseropt_opts_len;

	while (opts_len >= sizeof (struct nd_opt_hdr)) {
		size_t nd_opt_len = opt->nd_opt_len;

		if (nd_opt_len == 0 || opts_len < (nd_opt_len << 3))
			break;

		switch (opt->nd_opt_type) {
		case ND_OPT_RDNSS:
			changed = process_nduseropt_rdnss (device, opt);
			break;
		case ND_OPT_DNSSL:
			changed = process_nduseropt_dnssl (device, opt);
			break;
		}

		opts_len -= opt->nd_opt_len << 3;
		opt = (struct nd_opt_hdr *) ((uint8_t *) opt + (opt->nd_opt_len << 3));
	}

	if (changed)
		return device;
	else
		return NULL;
}
コード例 #2
0
ファイル: nm-ip6-manager.c プロジェクト: binli/NetworkManager
static NMIP6Device *
process_prefix (NMIP6Manager *manager, struct nl_msg *msg)
{
	struct prefixmsg *pmsg;
	NMIP6Device *device;

	/* We don't care about the prefix itself, but if we receive a
	 * router advertisement telling us to use DHCP, we might not
	 * get any RTM_NEWADDRs or RTM_NEWROUTEs, so this is our only
	 * way to notice immediately that an RA was received.
	 */

	nm_log_dbg (LOGD_IP6, "processing netlink new prefix message");

	if (!nlmsg_valid_hdr (nlmsg_hdr (msg), sizeof(*pmsg))) {
		nm_log_dbg (LOGD_IP6, "ignoring invalid prefix message");
		return NULL;
	}

	pmsg = (struct prefixmsg *) NLMSG_DATA (nlmsg_hdr (msg));
	device = nm_ip6_manager_get_device (manager, pmsg->prefix_ifindex);

	if (!device || device->addrconf_complete) {
		nm_log_dbg (LOGD_IP6, "(%s): ignoring unknown or completed device",
		            device ? device->iface : "(none)");
		return NULL;
	}

	return device;
}
コード例 #3
0
static NMIP6Device *
process_address_change (NMIP6Manager *manager, struct nl_msg *msg)
{
	NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager);
	NMIP6Device *device;
	struct nlmsghdr *hdr;
	struct rtnl_addr *rtnladdr;
	int old_size;

	hdr = nlmsg_hdr (msg);
	rtnladdr = NULL;
	nl_msg_parse (msg, ref_object, &rtnladdr);
	if (!rtnladdr) {
		nm_log_dbg (LOGD_IP6, "error processing netlink new/del address message");
		return NULL;
	}

	device = nm_ip6_manager_get_device (manager, rtnl_addr_get_ifindex (rtnladdr));

	old_size = nl_cache_nitems (priv->addr_cache);
	nl_cache_include (priv->addr_cache, (struct nl_object *)rtnladdr, NULL, NULL);

	/* The kernel will re-notify us of automatically-added addresses
	 * every time it gets another router advertisement. We only want
	 * to notify higher levels if we actually changed something.
	 */
	nm_log_dbg (LOGD_IP6, "(%s): address cache size: %d -> %d:",
		    device_get_iface (device), old_size, nl_cache_nitems (priv->addr_cache));
	dump_address_change (device, hdr, rtnladdr);
	rtnl_addr_put (rtnladdr);
	if (nl_cache_nitems (priv->addr_cache) == old_size)
		return NULL;

	return device;
}
コード例 #4
0
ファイル: nm-ip6-manager.c プロジェクト: binli/NetworkManager
static NMIP6Device *
process_newlink (NMIP6Manager *manager, struct nl_msg *msg)
{
	struct nlmsghdr *hdr = nlmsg_hdr (msg);
	struct ifinfomsg *ifi;
	NMIP6Device *device;
	struct nlattr *tb[IFLA_MAX + 1];
	struct nlattr *pi[IFLA_INET6_MAX + 1];
	int err;

	/* FIXME: we have to do this manually for now since libnl doesn't yet
	 * support the IFLA_PROTINFO attribute of NEWLINK messages.  When it does,
	 * we can get rid of this function and just grab IFLA_PROTINFO from
	 * nm_ip6_device_sync_from_netlink(), then get the IFLA_INET6_FLAGS out of
	 * the PROTINFO.
	 */
	err = nlmsg_parse (hdr, sizeof (*ifi), tb, IFLA_MAX, link_policy);
	if (err < 0) {
		nm_log_dbg (LOGD_IP6, "ignoring invalid newlink netlink message "
				      "while parsing PROTINFO attribute");
		return NULL;
	}

	ifi = nlmsg_data (hdr);
	if (ifi->ifi_family != AF_INET6) {
		nm_log_dbg (LOGD_IP6, "ignoring netlink message family %d", ifi->ifi_family);
		return NULL;
	}

	device = nm_ip6_manager_get_device (manager, ifi->ifi_index);
	if (!device || device->addrconf_complete) {
		nm_log_dbg (LOGD_IP6, "(%s): ignoring unknown or completed device",
		            device ? device->iface : "(none)");
		return NULL;
	}

	if (!tb[IFLA_PROTINFO]) {
		nm_log_dbg (LOGD_IP6, "(%s): message had no PROTINFO attribute", device->iface);
		return NULL;
	}

	err = nla_parse_nested (pi, IFLA_INET6_MAX, tb[IFLA_PROTINFO], link_prot_policy);
	if (err < 0) {
		nm_log_dbg (LOGD_IP6, "(%s): error parsing PROTINFO flags", device->iface);
		return NULL;
	}
	if (!pi[IFLA_INET6_FLAGS]) {
		nm_log_dbg (LOGD_IP6, "(%s): message had no PROTINFO flags", device->iface);
		return NULL;
	}

	device->ra_flags = nla_get_u32 (pi[IFLA_INET6_FLAGS]);
	nm_log_dbg (LOGD_IP6, "(%s): got IPv6 flags 0x%X", device->iface, device->ra_flags);

	return device;
}
コード例 #5
0
static NMIP6Device *
process_route_change (NMIP6Manager *manager, struct nl_msg *msg)
{
	NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager);
	NMIP6Device *device;
	struct nlmsghdr *hdr;
	struct rtnl_route *rtnlroute;
	int old_size;

	hdr = nlmsg_hdr (msg);
	rtnlroute = NULL;
	nl_msg_parse (msg, ref_object, &rtnlroute);
	if (!rtnlroute) {
		nm_log_dbg (LOGD_IP6, "error processing netlink new/del route message");
		return NULL;
	}

	/* Cached/cloned routes are created by the kernel for specific operations
	 * and aren't part of the interface's permanent routing configuration.
	 */
	if (rtnl_route_get_flags (rtnlroute) & RTM_F_CLONED) {
		rtnl_route_put (rtnlroute);
		return NULL;
	}

	device = nm_ip6_manager_get_device (manager, rtnl_route_get_oif (rtnlroute));

	old_size = nl_cache_nitems (priv->route_cache);
	nl_cache_include (priv->route_cache, (struct nl_object *)rtnlroute, NULL, NULL);

	/* As above in process_address_change */
	nm_log_dbg (LOGD_IP6, "(%s): route cache size: %d -> %d:",
		    device_get_iface (device), old_size, nl_cache_nitems (priv->route_cache));
	dump_route_change (device, hdr, rtnlroute);
	rtnl_route_put (rtnlroute);
	if (nl_cache_nitems (priv->route_cache) == old_size)
		return NULL;

	return device;
}
コード例 #6
0
ファイル: nm-ip6-manager.c プロジェクト: binli/NetworkManager
static NMIP6Device *
process_route (NMIP6Manager *manager, struct nl_msg *msg)
{
	NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager);
	NMIP6Device *device;
	struct rtnl_route *rtnlroute;
	int old_size;

	nm_log_dbg (LOGD_IP6, "processing netlink new/del route message");

	rtnlroute = NULL;
	nl_msg_parse (msg, ref_object, &rtnlroute);
	if (!rtnlroute) {
		nm_log_dbg (LOGD_IP6, "error processing netlink new/del route message");
		return NULL;
	}

	device = nm_ip6_manager_get_device (manager, rtnl_route_get_oif (rtnlroute));
	if (!device) {
		nm_log_dbg (LOGD_IP6, "ignoring message for unknown device");
		rtnl_route_put (rtnlroute);
		return NULL;
	}

	old_size = nl_cache_nitems (priv->route_cache);
	nl_cache_include (priv->route_cache, (struct nl_object *)rtnlroute, NULL, NULL);
	rtnl_route_put (rtnlroute);

	/* As above in process_addr */
	if (nl_cache_nitems (priv->route_cache) == old_size) {
		nm_log_dbg (LOGD_IP6, "(%s): route cache unchanged, ignoring message",
		            device->iface);
		return NULL;
	}

	return device;
}