libnl 1.1.4
log.c
1/*
2 * lib/netfilter/log.c Netfilter Log
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-2006 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 nfnl
16 * @defgroup log Log
17 * @brief
18 * @{
19 */
20
21#include <sys/types.h>
22#include <linux/netfilter/nfnetlink_log.h>
23
24#include <netlink-local.h>
25#include <netlink/attr.h>
26#include <netlink/netfilter/nfnl.h>
27#include <netlink/netfilter/log.h>
28
29static struct nl_cache_ops nfnl_log_ops;
30
31#if __BYTE_ORDER == __BIG_ENDIAN
32static uint64_t ntohll(uint64_t x)
33{
34 return x;
35}
36#elif __BYTE_ORDER == __LITTLE_ENDIAN
37static uint64_t ntohll(uint64_t x)
38{
39 return __bswap_64(x);
40}
41#endif
42
43static struct nla_policy log_policy[NFULA_MAX+1] = {
44 [NFULA_PACKET_HDR] = {
45 .minlen = sizeof(struct nfulnl_msg_packet_hdr)
46 },
47 [NFULA_MARK] = { .type = NLA_U32 },
48 [NFULA_TIMESTAMP] = {
49 .minlen = sizeof(struct nfulnl_msg_packet_timestamp)
50 },
51 [NFULA_IFINDEX_INDEV] = { .type = NLA_U32 },
52 [NFULA_IFINDEX_OUTDEV] = { .type = NLA_U32 },
53 [NFULA_IFINDEX_PHYSINDEV] = { .type = NLA_U32 },
54 [NFULA_IFINDEX_PHYSOUTDEV] = { .type = NLA_U32 },
55 [NFULA_HWADDR] = {
56 .minlen = sizeof(struct nfulnl_msg_packet_hw)
57 },
58 //[NFULA_PAYLOAD]
59 [NFULA_PREFIX] = { .type = NLA_STRING, },
60 [NFULA_UID] = { .type = NLA_U32 },
61 [NFULA_SEQ] = { .type = NLA_U32 },
62 [NFULA_SEQ_GLOBAL] = { .type = NLA_U32 },
63};
64
65struct nfnl_log *nfnlmsg_log_parse(struct nlmsghdr *nlh)
66{
67 struct nfnl_log *log;
68 struct nlattr *tb[NFULA_MAX+1];
69 struct nlattr *attr;
70 int err;
71
72 log = nfnl_log_alloc();
73 if (!log)
74 return NULL;
75
76 log->ce_msgtype = nlh->nlmsg_type;
77
78 err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, NFULA_MAX,
79 log_policy);
80 if (err < 0)
81 goto errout;
82
83 nfnl_log_set_family(log, nfnlmsg_family(nlh));
84
85 attr = tb[NFULA_PACKET_HDR];
86 if (attr) {
87 struct nfulnl_msg_packet_hdr *hdr = nla_data(attr);
88
89 nfnl_log_set_hwproto(log, hdr->hw_protocol);
90 nfnl_log_set_hook(log, hdr->hook);
91 }
92
93 attr = tb[NFULA_MARK];
94 if (attr)
95 nfnl_log_set_mark(log, ntohl(nla_get_u32(attr)));
96
97 attr = tb[NFULA_TIMESTAMP];
98 if (attr) {
99 struct nfulnl_msg_packet_timestamp *timestamp = nla_data(attr);
100 struct timeval tv;
101
102 tv.tv_sec = ntohll(timestamp->sec);
103 tv.tv_usec = ntohll(timestamp->usec);
104 nfnl_log_set_timestamp(log, &tv);
105 }
106
107 attr = tb[NFULA_IFINDEX_INDEV];
108 if (attr)
109 nfnl_log_set_indev(log, ntohl(nla_get_u32(attr)));
110
111 attr = tb[NFULA_IFINDEX_OUTDEV];
112 if (attr)
113 nfnl_log_set_outdev(log, ntohl(nla_get_u32(attr)));
114
115 attr = tb[NFULA_IFINDEX_PHYSINDEV];
116 if (attr)
117 nfnl_log_set_physindev(log, ntohl(nla_get_u32(attr)));
118
119 attr = tb[NFULA_IFINDEX_PHYSOUTDEV];
120 if (attr)
121 nfnl_log_set_physoutdev(log, ntohl(nla_get_u32(attr)));
122
123 attr = tb[NFULA_HWADDR];
124 if (attr) {
125 struct nfulnl_msg_packet_hw *hw = nla_data(attr);
126
127 nfnl_log_set_hwaddr(log, hw->hw_addr, ntohs(hw->hw_addrlen));
128 }
129
130 attr = tb[NFULA_PAYLOAD];
131 if (attr) {
132 err = nfnl_log_set_payload(log, nla_data(attr), nla_len(attr));
133 if (err < 0)
134 goto errout;
135 }
136
137 attr = tb[NFULA_PREFIX];
138 if (attr) {
139 err = nfnl_log_set_prefix(log, nla_data(attr));
140 if (err < 0)
141 goto errout;
142 }
143
144 attr = tb[NFULA_UID];
145 if (attr)
146 nfnl_log_set_uid(log, ntohl(nla_get_u32(attr)));
147
148 attr = tb[NFULA_SEQ];
149 if (attr)
150 nfnl_log_set_seq(log, ntohl(nla_get_u32(attr)));
151
152 attr = tb[NFULA_SEQ_GLOBAL];
153 if (attr)
154 nfnl_log_set_seq_global(log, ntohl(nla_get_u32(attr)));
155
156 return log;
157
158errout:
159 nfnl_log_put(log);
160 return NULL;
161}
162
163static int log_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
164 struct nlmsghdr *nlh, struct nl_parser_param *pp)
165{
166 struct nfnl_log *log;
167 int err;
168
169 log = nfnlmsg_log_parse(nlh);
170 if (log == NULL)
171 goto errout_errno;
172
173 err = pp->pp_cb((struct nl_object *) log, pp);
174 if (err < 0)
175 goto errout;
176
177 err = P_ACCEPT;
178
179errout:
180 nfnl_log_put(log);
181 return err;
182
183errout_errno:
184 err = nl_get_errno();
185 goto errout;
186}
187
188/**
189 * @name Log Commands
190 * @{
191 */
192
193static struct nl_msg *build_log_cmd_msg(uint8_t family, uint16_t queuenum,
194 uint8_t command)
195{
196 struct nl_msg *msg;
197 struct nfulnl_msg_config_cmd cmd;
198
199 msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_ULOG, NFULNL_MSG_CONFIG, 0,
200 family, queuenum);
201 if (msg == NULL)
202 return NULL;
203
204 cmd.command = command;
205 if (nla_put(msg, NFULA_CFG_CMD, sizeof(cmd), &cmd) < 0)
206 goto nla_put_failure;
207
208 return msg;
209
210nla_put_failure:
211 nlmsg_free(msg);
212 return NULL;
213}
214
215static int send_log_msg(struct nl_handle *handle, struct nl_msg *msg)
216{
217 int err;
218
219 err = nl_send_auto_complete(handle, msg);
220 nlmsg_free(msg);
221 if (err < 0)
222 return err;
223
224 return nl_wait_for_ack(handle);
225}
226
227struct nl_msg *nfnl_log_build_bind(uint16_t queuenum)
228{
229 return build_log_cmd_msg(0, queuenum, NFULNL_CFG_CMD_BIND);
230}
231
232int nfnl_log_bind(struct nl_handle *nlh, uint16_t queuenum)
233{
234 struct nl_msg *msg;
235
236 msg = nfnl_log_build_bind(queuenum);
237 if (!msg)
238 return nl_get_errno();
239
240 return send_log_msg(nlh, msg);
241}
242
243struct nl_msg *nfnl_log_build_unbind(uint16_t queuenum)
244{
245 return build_log_cmd_msg(0, queuenum, NFULNL_CFG_CMD_UNBIND);
246}
247
248int nfnl_log_unbind(struct nl_handle *nlh, uint16_t queuenum)
249{
250 struct nl_msg *msg;
251
252 msg = nfnl_log_build_bind(queuenum);
253 if (!msg)
254 return nl_get_errno();
255
256 return send_log_msg(nlh, msg);
257}
258
259struct nl_msg *nfnl_log_build_pf_bind(uint8_t pf)
260{
261 return build_log_cmd_msg(pf, 0, NFULNL_CFG_CMD_PF_BIND);
262}
263
264int nfnl_log_pf_bind(struct nl_handle *nlh, uint8_t pf)
265{
266 struct nl_msg *msg;
267
268 msg = nfnl_log_build_pf_bind(pf);
269 if (!msg)
270 return nl_get_errno();
271
272 return send_log_msg(nlh, msg);
273}
274
275struct nl_msg *nfnl_log_build_pf_unbind(uint8_t pf)
276{
277 return build_log_cmd_msg(pf, 0, NFULNL_CFG_CMD_PF_UNBIND);
278}
279
280int nfnl_log_pf_unbind(struct nl_handle *nlh, uint8_t pf)
281{
282 struct nl_msg *msg;
283
284 msg = nfnl_log_build_pf_unbind(pf);
285 if (!msg)
286 return nl_get_errno();
287
288 return send_log_msg(nlh, msg);
289}
290
291struct nl_msg *nfnl_log_build_mode(uint16_t queuenum, uint8_t copy_mode,
292 uint32_t copy_range)
293{
294 struct nl_msg *msg;
295 struct nfulnl_msg_config_mode mode;
296
297 msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_ULOG, NFULNL_MSG_CONFIG, 0,
298 0, queuenum);
299 if (msg == NULL)
300 return NULL;
301
302 mode.copy_mode = copy_mode;
303 mode.copy_range = htonl(copy_range);
304 if (nla_put(msg, NFULA_CFG_MODE, sizeof(mode), &mode) < 0)
305 goto nla_put_failure;
306
307 return msg;
308
309nla_put_failure:
310 nlmsg_free(msg);
311 return NULL;
312}
313
314int nfnl_log_set_mode(struct nl_handle *nlh, uint16_t queuenum,
315 uint8_t copy_mode, uint32_t copy_range)
316{
317 struct nl_msg *msg;
318
319 msg = nfnl_log_build_mode(queuenum, copy_mode, copy_range);
320 if (!msg)
321 return nl_get_errno();
322 return send_log_msg(nlh, msg);
323}
324
325/** @} */
326
327#define NFNLMSG_LOG_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_ULOG, (type))
328static struct nl_cache_ops nfnl_log_ops = {
329 .co_name = "netfilter/log",
330 .co_hdrsize = NFNL_HDRLEN,
331 .co_msgtypes = {
332 { NFNLMSG_LOG_TYPE(NFULNL_MSG_PACKET), NL_ACT_NEW, "new" },
333 END_OF_MSGTYPES_LIST,
334 },
335 .co_protocol = NETLINK_NETFILTER,
336 .co_msg_parser = log_msg_parser,
337 .co_obj_ops = &log_obj_ops,
338};
339
340static void __init log_init(void)
341{
342 nl_cache_mngt_register(&nfnl_log_ops);
343}
344
345static void __exit log_exit(void)
346{
347 nl_cache_mngt_unregister(&nfnl_log_ops);
348}
349
350/** @} */
void * nla_data(const struct nlattr *nla)
head of payload
Definition: attr.c:151
int nla_put(struct nl_msg *n, int attrtype, int attrlen, const void *data)
Add a netlink attribute to a netlink message.
Definition: attr.c:511
uint32_t nla_get_u32(struct nlattr *nla)
Return payload of u32 attribute.
Definition: attr.c:693
int nla_len(const struct nlattr *nla)
length of payload
Definition: attr.c:160
@ NLA_STRING
character string
Definition: attr.h:41
@ NLA_U32
32bit integer
Definition: attr.h:39
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Definition: cache_mngt.c:261
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
Definition: cache_mngt.c:226
void nlmsg_free(struct nl_msg *n)
Free a netlink message.
Definition: msg.c:656
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, struct nla_policy *policy)
parse attributes of a netlink message
Definition: msg.c:319
uint8_t nfnlmsg_family(struct nlmsghdr *nlh)
Get netfilter family from message.
Definition: nfnl.c:150
struct nl_msg * nfnlmsg_alloc_simple(uint8_t subsys_id, uint8_t type, int flags, uint8_t family, uint16_t res_id)
Allocate a new netfilter netlink message.
Definition: nfnl.c:201
int nl_send_auto_complete(struct nl_handle *handle, struct nl_msg *msg)
Send netlink message and check & extend header values as needed.
Definition: nl.c:373
int nl_wait_for_ack(struct nl_handle *handle)
Wait for ACK.
Definition: nl.c:801
Cache Operations.
Definition: cache-api.h:164
attribute validation policy
Definition: attr.h:73
uint16_t minlen
Minimal length of payload required to be available.
Definition: attr.h:78
Netlink message header.
uint16_t nlmsg_type
Message type (content type)
Netlink socket address.
Definition: netlink-kernel.h:9