Пример #1
0
/**
* Send a message verdict including the payload
* @arg nlh            netlink messsage header
* @arg msg            queue msg
* @arg payload_data   packet payload data
* @arg payload_len    payload length
* @return 0 on OK or error code
*/
int nfnl_queue_msg_send_verdict_payload(struct nl_sock *nlh,
				const struct nfnl_queue_msg *msg,
				const void *payload_data, unsigned payload_len)
{
	struct nl_msg *nlmsg;
	int err;
	struct iovec iov[3];
	struct nlattr nla;

	nlmsg = nfnl_queue_msg_build_verdict(msg);
	if (nlmsg == NULL)
		return -NLE_NOMEM;

	memset(iov, 0, sizeof(iov));

	iov[0].iov_base = (void *) nlmsg_hdr(nlmsg);
	iov[0].iov_len = nlmsg_hdr(nlmsg)->nlmsg_len;

	nla.nla_type = NFQA_PAYLOAD;
	nla.nla_len = payload_len + sizeof(nla);
	nlmsg_hdr(nlmsg)->nlmsg_len += nla.nla_len;

	iov[1].iov_base = (void *) &nla;
	iov[1].iov_len = sizeof(nla);

	iov[2].iov_base = (void *) payload_data;
	iov[2].iov_len = NLA_ALIGN(payload_len);

	nl_complete_msg(nlh, nlmsg);
	err = nl_send_iovec(nlh, nlmsg, iov, 3);

	nlmsg_free(nlmsg);
	if (err < 0)
		return err;
	return wait_for_ack(nlh);
}
Пример #2
0
/**
 * Send netlink message.
 * @arg sk		Netlink socket.
 * @arg msg		Netlink message to be sent.
 * @arg iov		iovec to be sent.
 * @arg iovlen		number of struct iovec to be sent.
 * @see nl_sendmsg()
 * @return Number of characters sent on success or a negative error code.
 */
int nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, unsigned iovlen)
{
	struct sockaddr_nl *dst;
	struct ucred *creds;
	struct msghdr hdr = {
		.msg_name = (void *) &sk->s_peer,
		.msg_namelen = sizeof(struct sockaddr_nl),
		.msg_iov = iov,
		.msg_iovlen = iovlen,
	};

	/* Overwrite destination if specified in the message itself, defaults
	 * to the peer address of the socket.
	 */
	dst = nlmsg_get_dst(msg);
	if (dst->nl_family == AF_NETLINK)
		hdr.msg_name = dst;

	/* Add credentials if present. */
	creds = nlmsg_get_creds(msg);
	if (creds != NULL) {
		char buf[CMSG_SPACE(sizeof(struct ucred))];
		struct cmsghdr *cmsg;

		hdr.msg_control = buf;
		hdr.msg_controllen = sizeof(buf);

		cmsg = CMSG_FIRSTHDR(&hdr);
		cmsg->cmsg_level = SOL_SOCKET;
		cmsg->cmsg_type = SCM_CREDENTIALS;
		cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
		memcpy(CMSG_DATA(cmsg), creds, sizeof(struct ucred));
	}

	return nl_sendmsg(sk, msg, &hdr);
}



/**
* Send netlink message.
* @arg sk		Netlink socket.
* @arg msg		Netlink message to be sent.
* @see nl_sendmsg()
* @return Number of characters sent on success or a negative error code.
*/
int nl_send(struct nl_sock *sk, struct nl_msg *msg)
{
	struct iovec iov = {
		.iov_base = (void *) nlmsg_hdr(msg),
		.iov_len = nlmsg_hdr(msg)->nlmsg_len,
	};

	return nl_send_iovec(sk, msg, &iov, 1);
}

void nl_complete_msg(struct nl_sock *sk, struct nl_msg *msg)
{
	struct nlmsghdr *nlh;

	nlh = nlmsg_hdr(msg);
	if (nlh->nlmsg_pid == 0)
		nlh->nlmsg_pid = sk->s_local.nl_pid;

	if (nlh->nlmsg_seq == 0)
		nlh->nlmsg_seq = sk->s_seq_next++;

	if (msg->nm_protocol == -1)
		msg->nm_protocol = sk->s_proto;

	nlh->nlmsg_flags |= NLM_F_REQUEST;

	if (!(sk->s_flags & NL_NO_AUTO_ACK))
		nlh->nlmsg_flags |= NLM_F_ACK;
}

void nl_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
{
	nl_complete_msg(sk, msg);
}

/**
 * Automatically complete and send a netlink message
 * @arg sk		Netlink socket.
 * @arg msg		Netlink message to be sent.
 *
 * This function takes a netlink message and passes it on to
 * nl_auto_complete() for completion.
 *
 * Checks the netlink message \c nlh for completness and extends it
 * as required before sending it out. Checked fields include pid,
 * sequence nr, and flags.
 *
 * @see nl_send()
 * @return Number of characters sent or a negative error code.
 */
int nl_send_auto(struct nl_sock *sk, struct nl_msg *msg)
{
	struct nl_cb *cb = sk->s_cb;

	nl_complete_msg(sk, msg);

	if (cb->cb_send_ow)
		return cb->cb_send_ow(sk, msg);
	else
		return nl_send(sk, msg);
}

int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
{
	return nl_send_auto(sk, msg);
}

/**
 * Send netlink message and wait for response (sync request-response)
 * @arg sk		Netlink socket
 * @arg msg		Netlink message to be sent
 *
 * This function takes a netlink message and sends it using nl_send_auto().
 * It will then wait for the response (ACK or error message) to be
 * received. Threfore this function will block until the operation has
 * been completed.
 *
 * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause
 *       this function to return immediately after sending. In this case,
 *       it is the responsibility of the caller to handle any eventual
 *       error messages returned.
 *
 * @see nl_send_auto().
 *
 * @return 0 on success or a negative error code.
 */
int nl_send_sync(struct nl_sock *sk, struct nl_msg *msg)
{
	int err;

	err = nl_send_auto(sk, msg);
	nlmsg_free(msg);
	if (err < 0)
		return err;

	return wait_for_ack(sk);
}
Пример #3
0
/**
 * Transmit Netlink message (taking IO vector)
 * @arg sk		Netlink socket (required)
 * @arg msg		Netlink message to be sent (required)
 * @arg iov		IO vector to be sent (required)
 * @arg iovlen		Number of struct iovec to be sent (required)
 *
 * This function is identical to nl_send() except that instead of taking a
 * `struct nl_msg` object it takes an IO vector. Please see the description
 * of `nl_send()`.
 *
 * @callback This function triggers the `NL_CB_MSG_OUT` callback.
 *
 * @see nl_send()
 *
 * @return Number of bytes sent on success or a negative error code.
 *
 * @lowlevel
 */
int nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, unsigned iovlen)
{
    struct sockaddr_nl *dst;
    struct ucred *creds;
    struct msghdr hdr = {
        .msg_name = (void *) &sk->s_peer,
        .msg_namelen = sizeof(struct sockaddr_nl),
        .msg_iov = iov,
        .msg_iovlen = iovlen,
    };

    /* Overwrite destination if specified in the message itself, defaults
     * to the peer address of the socket.
     */
    dst = nlmsg_get_dst(msg);
    if (dst->nl_family == AF_NETLINK)
        hdr.msg_name = dst;

    /* Add credentials if present. */
    creds = nlmsg_get_creds(msg);
    if (creds != NULL) {
        char buf[CMSG_SPACE(sizeof(struct ucred))];
        struct cmsghdr *cmsg;

        hdr.msg_control = buf;
        hdr.msg_controllen = sizeof(buf);

        cmsg = CMSG_FIRSTHDR(&hdr);
        cmsg->cmsg_level = SOL_SOCKET;
        cmsg->cmsg_type = SCM_CREDENTIALS;
        cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
        memcpy(CMSG_DATA(cmsg), creds, sizeof(struct ucred));
    }

    return nl_sendmsg(sk, msg, &hdr);
}

/**
 * Transmit Netlink message
 * @arg sk		Netlink socket (required)
 * @arg msg		Netlink message (required)
 *
 * Transmits the Netlink message `msg` over the Netlink socket using the
 * `sendmsg()` system call. This function is based on `nl_send_iovec()` but
 * takes care of initializing a `struct iovec` based on the `msg` object.
 *
 * The message is addressed to the peer as specified in the socket by either
 * the nl_socket_set_peer_port() or nl_socket_set_peer_groups() function.
 * The peer address can be overwritten by specifying an address in the `msg`
 * object using nlmsg_set_dst().
 *
 * If present in the `msg`, credentials set by the nlmsg_set_creds() function
 * are added to the control buffer of the message.
 *
 * @par Overwriting Capability:
 * Calls to this function can be overwritten by providing an alternative using
 * the nl_cb_overwrite_send() function.
 *
 * @callback This function triggers the `NL_CB_MSG_OUT` callback.
 *
 * @attention
 * Unlike `nl_send_auto()`, this function does *not* finalize the message in
 * terms of automatically adding needed flags or filling out port numbers.
 *
 * @see nl_send_auto()
 * @see nl_send_iovec()
 * @see nl_socket_set_peer_port()
 * @see nl_socket_set_peer_groups()
 * @see nlmsg_set_dst()
 * @see nlmsg_set_creds()
 * @see nl_cb_overwrite_send()
 *
 * @return Number of bytes sent on success or a negative error code.
*/
int nl_send(struct nl_sock *sk, struct nl_msg *msg)
{
    struct nl_cb *cb = sk->s_cb;

    if (cb->cb_send_ow)
        return cb->cb_send_ow(sk, msg);
    else {
        struct iovec iov = {
            .iov_base = (void *) nlmsg_hdr(msg),
            .iov_len = nlmsg_hdr(msg)->nlmsg_len,
        };

        return nl_send_iovec(sk, msg, &iov, 1);
    }
}

/**
 * Finalize Netlink message
 * @arg sk		Netlink socket (required)
 * @arg msg		Netlink message (required)
 *
 * This function finalizes a Netlink message by completing the message with
 * desirable flags and values depending on the socket configuration.
 *
 *  - If not yet filled out, the source address of the message (`nlmsg_pid`)
 *    will be set to the local port number of the socket.
 *  - If not yet specified, the next available sequence number is assigned
 *    to the message (`nlmsg_seq`).
 *  - If not yet specified, the protocol field of the message will be set to
 *    the protocol field of the socket.
 *  - The `NLM_F_REQUEST` Netlink message flag will be set.
 *  - The `NLM_F_ACK` flag will be set if Auto-ACK mode is enabled on the
 *    socket.
 */
void nl_complete_msg(struct nl_sock *sk, struct nl_msg *msg)
{
    struct nlmsghdr *nlh;

    nlh = nlmsg_hdr(msg);
    if (nlh->nlmsg_pid == NL_AUTO_PORT)
        nlh->nlmsg_pid = nl_socket_get_local_port(sk);

    if (nlh->nlmsg_seq == NL_AUTO_SEQ)
        nlh->nlmsg_seq = sk->s_seq_next++;

    if (msg->nm_protocol == -1)
        msg->nm_protocol = sk->s_proto;

    nlh->nlmsg_flags |= NLM_F_REQUEST;

    if (!(sk->s_flags & NL_NO_AUTO_ACK))
        nlh->nlmsg_flags |= NLM_F_ACK;
}

/**
 * Finalize and transmit Netlink message
 * @arg sk		Netlink socket (required)
 * @arg msg		Netlink message (required)
 *
 * Finalizes the message by passing it to `nl_complete_msg()` and transmits it
 * by passing it to `nl_send()`.
 *
 * @callback This function triggers the `NL_CB_MSG_OUT` callback.
 *
 * @see nl_complete_msg()
 * @see nl_send()
 *
 * @return Number of bytes sent or a negative error code.
 */
int nl_send_auto(struct nl_sock *sk, struct nl_msg *msg)
{
    nl_complete_msg(sk, msg);

    return nl_send(sk, msg);
}

/**
 * Finalize and transmit Netlink message and wait for ACK or error message
 * @arg sk		Netlink socket (required)
 * @arg msg		Netlink message (required)
 *
 * Passes the `msg` to `nl_send_auto()` to finalize and transmit it. Frees the
 * message and waits (sleeps) for the ACK or error message to be received.
 *
 * @attention
 * Disabling Auto-ACK (nl_socket_disable_auto_ack()) will cause this function
 * to return immediately after transmitting the message. However, the peer may
 * still be returning an error message in response to the request. It is the
 * responsibility of the caller to handle such messages.
 *
 * @callback This function triggers the `NL_CB_MSG_OUT` callback.
 *
 * @attention
 * This function frees the `msg` object after transmitting it by calling
 * `nlmsg_free()`.
 *
 * @see nl_send_auto().
 * @see nl_wait_for_ack()
 *
 * @return 0 on success or a negative error code.
 */
int nl_send_sync(struct nl_sock *sk, struct nl_msg *msg)
{
    int err;

    err = nl_send_auto(sk, msg);
    nlmsg_free(msg);
    if (err < 0)
        return err;

    return wait_for_ack(sk);
}
Пример #4
0
/**
 * @deprecated Please use nl_complete_msg()
 */
void nl_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
{
    nl_complete_msg(sk, msg);
}