Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
static int
parse_reply (struct nl_msg *msg, void *arg)
{
	struct nlmsghdr *n = nlmsg_hdr (msg);
	struct nlattr *tb[XFRMA_MAX + 1];
	struct xfrm_userpolicy_info *xpinfo = NULL;

	if (n->nlmsg_type != XFRM_MSG_NEWPOLICY) {
		g_warning ("msg type %d not NEWPOLICY", n->nlmsg_type);
		return NL_SKIP;
	}

	/* Netlink message header is followed by 'struct xfrm_userpolicy_info' and
	 * then the attributes.
	 */

	if (!nlmsg_valid_hdr (n, sizeof (struct xfrm_userpolicy_info))) {
		g_warning ("msg too short");
		return -NLE_MSG_TOOSHORT;
	}

	xpinfo = nlmsg_data (n);
	if (nla_parse (tb, XFRMA_MAX,
	               nlmsg_attrdata (n, sizeof (struct xfrm_userpolicy_info)),
	               nlmsg_attrlen (n, sizeof (struct xfrm_userpolicy_info)),
	               NULL) < 0) {
		g_warning ("failed to parse attributes");
		return NL_SKIP;
	}

	if (tb[XFRMA_TMPL]) {
		int attrlen = nla_len (tb[XFRMA_TMPL]);
		struct xfrm_user_tmpl *list = nla_data (tb[XFRMA_TMPL]);
		int i;

		xfrm_selector_print (&xpinfo->sel);

		for (i = 0; i < attrlen / sizeof (struct xfrm_user_tmpl); i++) {
			struct xfrm_user_tmpl *tmpl = &list[i];
			char buf[INET6_ADDRSTRLEN];

			g_print ("    tmpl ");

			inet_ntop (tmpl->family, (gpointer) &tmpl->saddr, buf, sizeof (buf));
			g_print ("src %s ", buf);

			inet_ntop (tmpl->family, &tmpl->id.daddr, buf, sizeof (buf));
			g_print ("dst %s\n", buf);
		}
	}

	return NL_OK;
}
Esempio n. 4
0
File: genl.c Progetto: Domikk/libnl
/**
 * Validate Generic Netlink message headers
 * @arg nlh		Pointer to Netlink message header
 * @arg hdrlen		Length of user header
 *
 * Verifies the integrity of the Netlink and Generic Netlink headers by
 * enforcing the following requirements:
 *  - Valid Netlink message header (nlmsg_valid_hdr())
 *  - Presence of a complete Generic Netlink header
 *  - At least \c hdrlen bytes of payload included after the generic
 *    netlink header.
 *
 * @return A positive integer (true) if the headers are valid or
 *         0 (false) if not.
 */
int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen)
{
	struct genlmsghdr *ghdr;

	if (!nlmsg_valid_hdr(nlh, GENL_HDRLEN))
		return 0;

	ghdr = nlmsg_data(nlh);
	if (genlmsg_len(ghdr) < NLMSG_ALIGN(hdrlen))
		return 0;

	return 1;
}
Esempio n. 5
0
static int
__ni_rtevent_nduseropt(ni_netconfig_t *nc, const struct sockaddr_nl *nladdr, struct nlmsghdr *h)
{
	struct nduseroptmsg *msg;
	struct nd_opt_hdr *opt;
	ni_netdev_t *dev;

	if (!(msg = ni_rtnl_nduseroptmsg(h, RTM_NEWNDUSEROPT)))
		return -1;

	dev = ni_netdev_by_index(nc, msg->nduseropt_ifindex);
	if (!dev) {
		ni_debug_events("ipv6 nd user option event for unknown device index: %u",
				msg->nduseropt_ifindex);
		return 0;
	}

	if (msg->nduseropt_icmp_type != ND_ROUTER_ADVERT ||
	    msg->nduseropt_icmp_code != 0 ||
	    msg->nduseropt_family    != AF_INET6) {
		ni_debug_events("%s: unknown rtnetlink nd user option message"
				" type %d, code %d, family %d", dev->name,
				msg->nduseropt_icmp_type,
				msg->nduseropt_icmp_code,
				msg->nduseropt_family);
		return 0;
	}

	if (!nlmsg_valid_hdr(h, sizeof(struct nduseroptmsg) + msg->nduseropt_opts_len)) {
		ni_debug_events("%s: invalid rtnetlink nd user radv option length %d",
				dev->name, msg->nduseropt_opts_len);
		return -1;
	}

	opt = (struct nd_opt_hdr *)(msg + 1);

	return __ni_rtevent_process_nd_radv_opts(dev, opt, msg->nduseropt_opts_len);
}