144d362409d5469aed47d19e7908d19bd194493aThomas Graf/*
244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/netfilter/nfnl.c		Netfilter Netlink
344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
444d362409d5469aed47d19e7908d19bd194493aThomas Graf *	This library is free software; you can redistribute it and/or
544d362409d5469aed47d19e7908d19bd194493aThomas Graf *	modify it under the terms of the GNU Lesser General Public
644d362409d5469aed47d19e7908d19bd194493aThomas Graf *	License as published by the Free Software Foundation version 2.1
744d362409d5469aed47d19e7908d19bd194493aThomas Graf *	of the License.
844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
1044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
1144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Copyright (c) 2007 Secure Computing Corporation
1244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1344d362409d5469aed47d19e7908d19bd194493aThomas Graf
1444d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup nfnl Netfilter Netlink
1644d362409d5469aed47d19e7908d19bd194493aThomas Graf *
1744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par Message Format
1844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code
1944d362409d5469aed47d19e7908d19bd194493aThomas Graf *  <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) --->
2044d362409d5469aed47d19e7908d19bd194493aThomas Graf * +----------------------------+- - -+- - - - - - - - - - -+- - -+
2144d362409d5469aed47d19e7908d19bd194493aThomas Graf * |           Header           | Pad |       Payload       | Pad |
2244d362409d5469aed47d19e7908d19bd194493aThomas Graf * |      struct nlmsghdr       |     |                     |     |
2344d362409d5469aed47d19e7908d19bd194493aThomas Graf * +----------------------------+- - -+- - - - - - - - - - -+- - -+
2444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode
2544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code
2644d362409d5469aed47d19e7908d19bd194493aThomas Graf *  <-------- NFNL_HDRLEN --------->
2744d362409d5469aed47d19e7908d19bd194493aThomas Graf * +--------------------------+- - -+------------+
2844d362409d5469aed47d19e7908d19bd194493aThomas Graf * | Netfilter Netlink Header | Pad | Attributes |
2944d362409d5469aed47d19e7908d19bd194493aThomas Graf * |    struct nfgenmsg       |     |            |
3044d362409d5469aed47d19e7908d19bd194493aThomas Graf * +--------------------------+- - -+------------+
3144d362409d5469aed47d19e7908d19bd194493aThomas Graf * nfnlmsg_attrdata(nfg, hdrlen)-----^
3244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode
3344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
3444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par 1) Creating a new netfilter netlink message
3544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code
3644d362409d5469aed47d19e7908d19bd194493aThomas Graf * struct nl_msg *msg;
3744d362409d5469aed47d19e7908d19bd194493aThomas Graf *
3844d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Create a new empty netlink message
3944d362409d5469aed47d19e7908d19bd194493aThomas Graf * msg = nlmsg_alloc();
4044d362409d5469aed47d19e7908d19bd194493aThomas Graf *
4144d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Append the netlink and netfilter netlink message header
4244d362409d5469aed47d19e7908d19bd194493aThomas Graf * hdr = nfnlmsg_put(msg, PID, SEQ, SUBSYS, TYPE, NLM_F_ECHO,
4344d362409d5469aed47d19e7908d19bd194493aThomas Graf *                   FAMILY, RES_ID);
4444d362409d5469aed47d19e7908d19bd194493aThomas Graf *
4544d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Append the attributes.
4644d362409d5469aed47d19e7908d19bd194493aThomas Graf * nla_put_u32(msg, 1, 0x10);
4744d362409d5469aed47d19e7908d19bd194493aThomas Graf *
4844d362409d5469aed47d19e7908d19bd194493aThomas Graf * // Message is ready to be sent.
491155370f520cb64657e25153255cf7dc1424317fThomas Graf * nl_send_auto_complete(sk, msg);
5044d362409d5469aed47d19e7908d19bd194493aThomas Graf *
5144d362409d5469aed47d19e7908d19bd194493aThomas Graf * // All done? Free the message.
5244d362409d5469aed47d19e7908d19bd194493aThomas Graf * nlmsg_free(msg);
5344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode
5444d362409d5469aed47d19e7908d19bd194493aThomas Graf *
5544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @par 2) Sending of trivial messages
5644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code
5744d362409d5469aed47d19e7908d19bd194493aThomas Graf * // For trivial messages not requiring any subsys specific header or
5844d362409d5469aed47d19e7908d19bd194493aThomas Graf * // attributes, nfnl_send_simple() may be used to send messages directly.
591155370f520cb64657e25153255cf7dc1424317fThomas Graf * nfnl_send_simple(sk, SUBSYS, TYPE, 0, FAMILY, RES_ID);
6044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode
6144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
6244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
6344d362409d5469aed47d19e7908d19bd194493aThomas Graf
6444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h>
6544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h>
6644d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netfilter/nfnl.h>
6744d362409d5469aed47d19e7908d19bd194493aThomas Graf
6844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
6944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Socket Creating
7044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
7144d362409d5469aed47d19e7908d19bd194493aThomas Graf */
7244d362409d5469aed47d19e7908d19bd194493aThomas Graf
7344d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
7444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Create and connect netfilter netlink socket.
751155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket.
7644d362409d5469aed47d19e7908d19bd194493aThomas Graf *
7744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Creates a NETLINK_NETFILTER netlink socket, binds the socket and
7844d362409d5469aed47d19e7908d19bd194493aThomas Graf * issues a connection attempt.
7944d362409d5469aed47d19e7908d19bd194493aThomas Graf *
8044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @see nl_connect()
8144d362409d5469aed47d19e7908d19bd194493aThomas Graf *
8244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code.
8344d362409d5469aed47d19e7908d19bd194493aThomas Graf */
841155370f520cb64657e25153255cf7dc1424317fThomas Grafint nfnl_connect(struct nl_sock *sk)
8544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
861155370f520cb64657e25153255cf7dc1424317fThomas Graf	return nl_connect(sk, NETLINK_NETFILTER);
8744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
8844d362409d5469aed47d19e7908d19bd194493aThomas Graf
8944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
9044d362409d5469aed47d19e7908d19bd194493aThomas Graf
9144d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
9244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Sending
9344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
9444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
9544d362409d5469aed47d19e7908d19bd194493aThomas Graf
9644d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
9744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Send trivial netfilter netlink message
981155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket.
9944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg subsys_id	nfnetlink subsystem
10044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg type		nfnetlink message type
10144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags		message flags
10244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg family		nfnetlink address family
10344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg res_id		nfnetlink resource id
10444d362409d5469aed47d19e7908d19bd194493aThomas Graf *
10544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Newly allocated netlink message or NULL.
10644d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1071155370f520cb64657e25153255cf7dc1424317fThomas Grafint nfnl_send_simple(struct nl_sock *sk, uint8_t subsys_id, uint8_t type,
10844d362409d5469aed47d19e7908d19bd194493aThomas Graf		     int flags, uint8_t family, uint16_t res_id)
10944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
11044d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfgenmsg hdr = {
11144d362409d5469aed47d19e7908d19bd194493aThomas Graf		.nfgen_family = family,
11244d362409d5469aed47d19e7908d19bd194493aThomas Graf		.version = NFNETLINK_V0,
11344d362409d5469aed47d19e7908d19bd194493aThomas Graf		.res_id = htons(res_id),
11444d362409d5469aed47d19e7908d19bd194493aThomas Graf	};
11544d362409d5469aed47d19e7908d19bd194493aThomas Graf
1161155370f520cb64657e25153255cf7dc1424317fThomas Graf	return nl_send_simple(sk, NFNLMSG_TYPE(subsys_id, type), flags,
11744d362409d5469aed47d19e7908d19bd194493aThomas Graf			      &hdr, sizeof(hdr));
11844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
11944d362409d5469aed47d19e7908d19bd194493aThomas Graf
12044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
12144d362409d5469aed47d19e7908d19bd194493aThomas Graf
12244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
12344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Message Parsing
12444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
12544d362409d5469aed47d19e7908d19bd194493aThomas Graf */
12644d362409d5469aed47d19e7908d19bd194493aThomas Graf
12744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
12844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get netfilter subsystem id from message
12944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg nlh	netlink messsage header
13044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
13144d362409d5469aed47d19e7908d19bd194493aThomas Grafuint8_t nfnlmsg_subsys(struct nlmsghdr *nlh)
13244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
13344d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NFNL_SUBSYS_ID(nlh->nlmsg_type);
13444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
13544d362409d5469aed47d19e7908d19bd194493aThomas Graf
13644d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
13744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get netfilter message type from message
13844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg nlh	netlink messsage header
13944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
14044d362409d5469aed47d19e7908d19bd194493aThomas Grafuint8_t nfnlmsg_subtype(struct nlmsghdr *nlh)
14144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
14244d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NFNL_MSG_TYPE(nlh->nlmsg_type);
14344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
14444d362409d5469aed47d19e7908d19bd194493aThomas Graf
14544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
14644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get netfilter family from message
14744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg nlh	netlink messsage header
14844d362409d5469aed47d19e7908d19bd194493aThomas Graf */
14944d362409d5469aed47d19e7908d19bd194493aThomas Grafuint8_t nfnlmsg_family(struct nlmsghdr *nlh)
15044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
15144d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfgenmsg *nfg = nlmsg_data(nlh);
15244d362409d5469aed47d19e7908d19bd194493aThomas Graf
15344d362409d5469aed47d19e7908d19bd194493aThomas Graf	return nfg->nfgen_family;
15444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
15544d362409d5469aed47d19e7908d19bd194493aThomas Graf
15644d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
15744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get netfilter resource id from message
15844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg nlh	netlink messsage header
15944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
16044d362409d5469aed47d19e7908d19bd194493aThomas Grafuint16_t nfnlmsg_res_id(struct nlmsghdr *nlh)
16144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
16244d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfgenmsg *nfg = nlmsg_data(nlh);
16344d362409d5469aed47d19e7908d19bd194493aThomas Graf
16444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return ntohs(nfg->res_id);
16544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
16644d362409d5469aed47d19e7908d19bd194493aThomas Graf
16744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
16844d362409d5469aed47d19e7908d19bd194493aThomas Graf
16944d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
17044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Message Building
17144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
17244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
17344d362409d5469aed47d19e7908d19bd194493aThomas Graf
17444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int nfnlmsg_append(struct nl_msg *msg, uint8_t family, uint16_t res_id)
17544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
17644d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nfgenmsg *nfg;
17744d362409d5469aed47d19e7908d19bd194493aThomas Graf
17844d362409d5469aed47d19e7908d19bd194493aThomas Graf	nfg = nlmsg_reserve(msg, sizeof(*nfg), NLMSG_ALIGNTO);
17944d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (nfg == NULL)
1808a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_NOMEM;
18144d362409d5469aed47d19e7908d19bd194493aThomas Graf
18244d362409d5469aed47d19e7908d19bd194493aThomas Graf	nfg->nfgen_family = family;
18344d362409d5469aed47d19e7908d19bd194493aThomas Graf	nfg->version = NFNETLINK_V0;
18444d362409d5469aed47d19e7908d19bd194493aThomas Graf	nfg->res_id = htons(res_id);
18544d362409d5469aed47d19e7908d19bd194493aThomas Graf	NL_DBG(2, "msg %p: Added nfnetlink header family=%d res_id=%d\n",
18644d362409d5469aed47d19e7908d19bd194493aThomas Graf	       msg, family, res_id);
18744d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
18844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
18944d362409d5469aed47d19e7908d19bd194493aThomas Graf
19044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
19144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocate a new netfilter netlink message
19244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg subsys_id	nfnetlink subsystem
19344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg type		nfnetlink message type
19444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags		message flags
19544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg family		nfnetlink address family
19644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg res_id		nfnetlink resource id
19744d362409d5469aed47d19e7908d19bd194493aThomas Graf *
19844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Newly allocated netlink message or NULL.
19944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
20044d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_msg *nfnlmsg_alloc_simple(uint8_t subsys_id, uint8_t type, int flags,
20144d362409d5469aed47d19e7908d19bd194493aThomas Graf				    uint8_t family, uint16_t res_id)
20244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
20344d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_msg *msg;
20444d362409d5469aed47d19e7908d19bd194493aThomas Graf
20544d362409d5469aed47d19e7908d19bd194493aThomas Graf	msg = nlmsg_alloc_simple(NFNLMSG_TYPE(subsys_id, type), flags);
20644d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (msg == NULL)
20744d362409d5469aed47d19e7908d19bd194493aThomas Graf		return NULL;
20844d362409d5469aed47d19e7908d19bd194493aThomas Graf
20944d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (nfnlmsg_append(msg, family, res_id) < 0)
21044d362409d5469aed47d19e7908d19bd194493aThomas Graf		goto nla_put_failure;
21144d362409d5469aed47d19e7908d19bd194493aThomas Graf
21244d362409d5469aed47d19e7908d19bd194493aThomas Graf	return msg;
21344d362409d5469aed47d19e7908d19bd194493aThomas Graf
21444d362409d5469aed47d19e7908d19bd194493aThomas Grafnla_put_failure:
21544d362409d5469aed47d19e7908d19bd194493aThomas Graf	nlmsg_free(msg);
21644d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NULL;
21744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
21844d362409d5469aed47d19e7908d19bd194493aThomas Graf
21944d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
22044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Add netlink and netfilter netlink headers to netlink message
22144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg msg		netlink message
22244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg pid		netlink process id
22344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg seq		sequence number of message
22444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg subsys_id	nfnetlink subsystem
22544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg type		nfnetlink message type
22644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags		message flags
22744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg family		nfnetlink address family
22844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg res_id		nfnetlink resource id
22944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
23044d362409d5469aed47d19e7908d19bd194493aThomas Grafint nfnlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq,
23144d362409d5469aed47d19e7908d19bd194493aThomas Graf		uint8_t subsys_id, uint8_t type, int flags, uint8_t family,
23244d362409d5469aed47d19e7908d19bd194493aThomas Graf		uint16_t res_id)
23344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
23444d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nlmsghdr *nlh;
23544d362409d5469aed47d19e7908d19bd194493aThomas Graf
23644d362409d5469aed47d19e7908d19bd194493aThomas Graf	nlh = nlmsg_put(msg, pid, seq, NFNLMSG_TYPE(subsys_id, type), 0, flags);
23744d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (nlh == NULL)
2388a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_MSGSIZE;
23944d362409d5469aed47d19e7908d19bd194493aThomas Graf
24044d362409d5469aed47d19e7908d19bd194493aThomas Graf	return nfnlmsg_append(msg, family, res_id);
24144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
24244d362409d5469aed47d19e7908d19bd194493aThomas Graf
24344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
24444d362409d5469aed47d19e7908d19bd194493aThomas Graf
24544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
246