nfnl.c revision 1155370f520cb64657e25153255cf7dc1424317f
1/*
2 * lib/netfilter/nfnl.c		Netfilter Netlink
3 *
4 *	This library is free software; you can redistribute it and/or
5 *	modify it under the terms of the GNU Lesser General Public
6 *	License as published by the Free Software Foundation version 2.1
7 *	of the License.
8 *
9 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
10 * Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
11 * Copyright (c) 2007 Secure Computing Corporation
12 */
13
14/**
15 * @ingroup nlfam
16 * @defgroup nfnl Netfilter Netlink
17 *
18 * @par Message Format
19 * @code
20 *  <------- NLMSG_ALIGN(hlen) ------> <---- NLMSG_ALIGN(len) --->
21 * +----------------------------+- - -+- - - - - - - - - - -+- - -+
22 * |           Header           | Pad |       Payload       | Pad |
23 * |      struct nlmsghdr       |     |                     |     |
24 * +----------------------------+- - -+- - - - - - - - - - -+- - -+
25 * @endcode
26 * @code
27 *  <-------- NFNL_HDRLEN --------->
28 * +--------------------------+- - -+------------+
29 * | Netfilter Netlink Header | Pad | Attributes |
30 * |    struct nfgenmsg       |     |            |
31 * +--------------------------+- - -+------------+
32 * nfnlmsg_attrdata(nfg, hdrlen)-----^
33 * @endcode
34 *
35 * @par 1) Creating a new netfilter netlink message
36 * @code
37 * struct nl_msg *msg;
38 *
39 * // Create a new empty netlink message
40 * msg = nlmsg_alloc();
41 *
42 * // Append the netlink and netfilter netlink message header
43 * hdr = nfnlmsg_put(msg, PID, SEQ, SUBSYS, TYPE, NLM_F_ECHO,
44 *                   FAMILY, RES_ID);
45 *
46 * // Append the attributes.
47 * nla_put_u32(msg, 1, 0x10);
48 *
49 * // Message is ready to be sent.
50 * nl_send_auto_complete(sk, msg);
51 *
52 * // All done? Free the message.
53 * nlmsg_free(msg);
54 * @endcode
55 *
56 * @par 2) Sending of trivial messages
57 * @code
58 * // For trivial messages not requiring any subsys specific header or
59 * // attributes, nfnl_send_simple() may be used to send messages directly.
60 * nfnl_send_simple(sk, SUBSYS, TYPE, 0, FAMILY, RES_ID);
61 * @endcode
62 * @{
63 */
64
65#include <netlink-local.h>
66#include <netlink/netlink.h>
67#include <netlink/netfilter/nfnl.h>
68
69/**
70 * @name Socket Creating
71 * @{
72 */
73
74/**
75 * Create and connect netfilter netlink socket.
76 * @arg sk		Netlink socket.
77 *
78 * Creates a NETLINK_NETFILTER netlink socket, binds the socket and
79 * issues a connection attempt.
80 *
81 * @see nl_connect()
82 *
83 * @return 0 on success or a negative error code.
84 */
85int nfnl_connect(struct nl_sock *sk)
86{
87	return nl_connect(sk, NETLINK_NETFILTER);
88}
89
90/** @} */
91
92/**
93 * @name Sending
94 * @{
95 */
96
97/**
98 * Send trivial netfilter netlink message
99 * @arg sk		Netlink socket.
100 * @arg subsys_id	nfnetlink subsystem
101 * @arg type		nfnetlink message type
102 * @arg flags		message flags
103 * @arg family		nfnetlink address family
104 * @arg res_id		nfnetlink resource id
105 *
106 * @return Newly allocated netlink message or NULL.
107 */
108int nfnl_send_simple(struct nl_sock *sk, uint8_t subsys_id, uint8_t type,
109		     int flags, uint8_t family, uint16_t res_id)
110{
111	struct nfgenmsg hdr = {
112		.nfgen_family = family,
113		.version = NFNETLINK_V0,
114		.res_id = htons(res_id),
115	};
116
117	return nl_send_simple(sk, NFNLMSG_TYPE(subsys_id, type), flags,
118			      &hdr, sizeof(hdr));
119}
120
121/** @} */
122
123/**
124 * @name Message Parsing
125 * @{
126 */
127
128/**
129 * Get netfilter subsystem id from message
130 * @arg nlh	netlink messsage header
131 */
132uint8_t nfnlmsg_subsys(struct nlmsghdr *nlh)
133{
134	return NFNL_SUBSYS_ID(nlh->nlmsg_type);
135}
136
137/**
138 * Get netfilter message type from message
139 * @arg nlh	netlink messsage header
140 */
141uint8_t nfnlmsg_subtype(struct nlmsghdr *nlh)
142{
143	return NFNL_MSG_TYPE(nlh->nlmsg_type);
144}
145
146/**
147 * Get netfilter family from message
148 * @arg nlh	netlink messsage header
149 */
150uint8_t nfnlmsg_family(struct nlmsghdr *nlh)
151{
152	struct nfgenmsg *nfg = nlmsg_data(nlh);
153
154	return nfg->nfgen_family;
155}
156
157/**
158 * Get netfilter resource id from message
159 * @arg nlh	netlink messsage header
160 */
161uint16_t nfnlmsg_res_id(struct nlmsghdr *nlh)
162{
163	struct nfgenmsg *nfg = nlmsg_data(nlh);
164
165	return ntohs(nfg->res_id);
166}
167
168/** @} */
169
170/**
171 * @name Message Building
172 * @{
173 */
174
175static int nfnlmsg_append(struct nl_msg *msg, uint8_t family, uint16_t res_id)
176{
177	struct nfgenmsg *nfg;
178
179	nfg = nlmsg_reserve(msg, sizeof(*nfg), NLMSG_ALIGNTO);
180	if (nfg == NULL)
181		return -NLE_NOMEM;
182
183	nfg->nfgen_family = family;
184	nfg->version = NFNETLINK_V0;
185	nfg->res_id = htons(res_id);
186	NL_DBG(2, "msg %p: Added nfnetlink header family=%d res_id=%d\n",
187	       msg, family, res_id);
188	return 0;
189}
190
191/**
192 * Allocate a new netfilter netlink message
193 * @arg subsys_id	nfnetlink subsystem
194 * @arg type		nfnetlink message type
195 * @arg flags		message flags
196 * @arg family		nfnetlink address family
197 * @arg res_id		nfnetlink resource id
198 *
199 * @return Newly allocated netlink message or NULL.
200 */
201struct nl_msg *nfnlmsg_alloc_simple(uint8_t subsys_id, uint8_t type, int flags,
202				    uint8_t family, uint16_t res_id)
203{
204	struct nl_msg *msg;
205
206	msg = nlmsg_alloc_simple(NFNLMSG_TYPE(subsys_id, type), flags);
207	if (msg == NULL)
208		return NULL;
209
210	if (nfnlmsg_append(msg, family, res_id) < 0)
211		goto nla_put_failure;
212
213	return msg;
214
215nla_put_failure:
216	nlmsg_free(msg);
217	return NULL;
218}
219
220/**
221 * Add netlink and netfilter netlink headers to netlink message
222 * @arg msg		netlink message
223 * @arg pid		netlink process id
224 * @arg seq		sequence number of message
225 * @arg subsys_id	nfnetlink subsystem
226 * @arg type		nfnetlink message type
227 * @arg flags		message flags
228 * @arg family		nfnetlink address family
229 * @arg res_id		nfnetlink resource id
230 */
231int nfnlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq,
232		uint8_t subsys_id, uint8_t type, int flags, uint8_t family,
233		uint16_t res_id)
234{
235	struct nlmsghdr *nlh;
236
237	nlh = nlmsg_put(msg, pid, seq, NFNLMSG_TYPE(subsys_id, type), 0, flags);
238	if (nlh == NULL)
239		return -NLE_MSGSIZE;
240
241	return nfnlmsg_append(msg, family, res_id);
242}
243
244/** @} */
245
246/** @} */
247