Beispiel #1
0
/* Process one complete nfnetlink message. */
static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
	struct nfnl_callback *nc;
	struct nfnetlink_subsystem *ss;
	int type, err;

	if (security_netlink_recv(skb, CAP_NET_ADMIN))
		return -EPERM;

	/* All the messages must at least contain nfgenmsg */
	if (nlh->nlmsg_len < NLMSG_SPACE(sizeof(struct nfgenmsg)))
		return 0;

	type = nlh->nlmsg_type;
	ss = nfnetlink_get_subsys(type);
	if (!ss) {
#ifdef CONFIG_KMOD
		/* don't call nfnl_unlock, since it would reenter
		 * with further packet processing */
		__nfnl_unlock();
		request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type));
		nfnl_lock();
		ss = nfnetlink_get_subsys(type);
		if (!ss)
#endif
			return -EINVAL;
	}

	nc = nfnetlink_find_client(type, ss);
	if (!nc)
		return -EINVAL;

	{
		u_int16_t attr_count =
			ss->cb[NFNL_MSG_TYPE(nlh->nlmsg_type)].attr_count;
		struct nfattr *cda[attr_count];

		memset(cda, 0, sizeof(struct nfattr *) * attr_count);

		err = nfnetlink_check_attributes(ss, nlh, cda);
		if (err < 0)
			return err;
		return nc->call(nfnl, skb, nlh, cda);
	}
}
Beispiel #2
0
/* Process one complete nfnetlink message. */
static int nfnetlink_rcv_msg(struct sk_buff *skb,
				    struct nlmsghdr *nlh, int *errp)
{
	struct nfnl_callback *nc;
	struct nfnetlink_subsystem *ss;
	int type, err = 0;

	DEBUGP("entered; subsys=%u, msgtype=%u\n",
		 NFNL_SUBSYS_ID(nlh->nlmsg_type),
		 NFNL_MSG_TYPE(nlh->nlmsg_type));

	if (security_netlink_recv(skb, CAP_NET_ADMIN)) {
		DEBUGP("missing CAP_NET_ADMIN\n");
		*errp = -EPERM;
		return -1;
	}

	/* Only requests are handled by kernel now. */
	if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) {
		DEBUGP("received non-request message\n");
		return 0;
	}

	/* All the messages must at least contain nfgenmsg */
	if (nlh->nlmsg_len < NLMSG_SPACE(sizeof(struct nfgenmsg))) {
		DEBUGP("received message was too short\n");
		return 0;
	}

	type = nlh->nlmsg_type;
	ss = nfnetlink_get_subsys(type);
	if (!ss) {
#ifdef CONFIG_KMOD
		/* don't call nfnl_shunlock, since it would reenter
		 * with further packet processing */
		up(&nfnl_sem);
		request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type));
		nfnl_shlock();
		ss = nfnetlink_get_subsys(type);
		if (!ss)
#endif
			goto err_inval;
	}

	nc = nfnetlink_find_client(type, ss);
	if (!nc) {
		DEBUGP("unable to find client for type %d\n", type);
		goto err_inval;
	}

	{
		u_int16_t attr_count = 
			ss->cb[NFNL_MSG_TYPE(nlh->nlmsg_type)].attr_count;
		struct nfattr *cda[attr_count];

		memset(cda, 0, sizeof(struct nfattr *) * attr_count);
		
		err = nfnetlink_check_attributes(ss, nlh, cda);
		if (err < 0)
			goto err_inval;

		DEBUGP("calling handler\n");
		err = nc->call(nfnl, skb, nlh, cda, errp);
		*errp = err;
		return err;
	}

err_inval:
	DEBUGP("returning -EINVAL\n");
	*errp = -EINVAL;
	return -1;
}